Skip to content

Commit

Permalink
Added a filter to the team building dialog
Browse files Browse the repository at this point in the history
  • Loading branch information
sauterl committed May 22, 2024
1 parent 4740fb9 commit cded493
Show file tree
Hide file tree
Showing 12 changed files with 165 additions and 10 deletions.
18 changes: 18 additions & 0 deletions frontend/src/app/services/pipes/not-in-list-filter.pipe.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
name: 'notInListFilter'
})
export class NotInListFilterPipe implements PipeTransform {

transform(list: any[], filter: any): any[] {
if(!list){
return [];
}
if(!filter){
return list;
}
return list.filter(it => it != filter);
}

}
5 changes: 4 additions & 1 deletion frontend/src/app/services/services.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { OrderByPipe } from './pipes/order-by.pipe';
import { FilterNotInPipe } from './pipes/filter-not-in.pipe';
import { UnderscoreWordBreakPipe } from './pipes/underscore-wordbreak.pipe';
import { SubmissionsOfPipe } from './pipes/submissions-of.pipe';
import { NotInListFilterPipe } from './pipes/not-in-list-filter.pipe';

/**
* Provides the {@link AppConfig} reference.
Expand Down Expand Up @@ -59,7 +60,8 @@ export function initializeApiConfig(appConfig: AppConfig) {
OrderByPipe,
FilterNotInPipe,
UnderscoreWordBreakPipe,
SubmissionsOfPipe
SubmissionsOfPipe,
NotInListFilterPipe
],
declarations: [
RoundPipePipe,
Expand All @@ -81,6 +83,7 @@ export function initializeApiConfig(appConfig: AppConfig) {
FilterNotInPipe,
UnderscoreWordBreakPipe,
SubmissionsOfPipe,
NotInListFilterPipe,
],
providers: [
AuthenticationService,
Expand Down
16 changes: 16 additions & 0 deletions frontend/src/app/shared/search-box/search-box.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<button *ngIf="!searchBoxActive" type="button" mat-icon-button
aria-label="Search"
matTooltip="Search"
(click)="searchBoxActive = true">
<mat-icon>search</mat-icon>
</button>
<mat-form-field *ngIf="searchBoxActive" style="display: flex; flex-direction: row; justify-content: space-between; align-items: center;">
<mat-icon matIconPrefix>search</mat-icon>
<input matInput type="text" placeholder="Search" [(ngModel)]="filter" (ngModelChange)="onTextChanged()" />
<button type="button" matSuffix mat-icon-button
aria-label="Clear and close."
matTooltip="Clear and close."
(click)="onFilterClear()">
<mat-icon>close</mat-icon>
</button>
</mat-form-field>
Empty file.
27 changes: 27 additions & 0 deletions frontend/src/app/shared/search-box/search-box.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Component, EventEmitter, OnInit, Output } from "@angular/core";

@Component({
selector: 'app-search-box',
templateUrl: './search-box.component.html',
styleUrls: ['./search-box.component.scss']
})
export class SearchBoxComponent{
// Source: https://angular-htpgvx.stackblitz.io
@Output() filterChanged = new EventEmitter<string>();
public searchBoxActive = false;
filter: string;

onFilterClear(){
this.filter = '';
this.searchBoxActive = false;
this.filterChanged.emit(this.filter);
}

onTextChanged(){
this.filterChanged.emit(this.filter);
}

public clear(){
this.onFilterClear();
}
}
9 changes: 7 additions & 2 deletions frontend/src/app/shared/shared.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ import { ServerInfoComponent } from './server-info/server-info.component';
import { TargetMediaViewerComponent } from './target-media-viewer/target-media-viewer.component';
import { MediaItemViewerComponent } from './media-item-viewer/media-item-viewer.component';
import { InformationDialogComponent } from './information-dialog/information-dialog.component';
import { SearchBoxComponent } from './search-box/search-box.component';
import { MatInputModule } from "@angular/material/input";
import { FormsModule } from "@angular/forms";

@NgModule({
declarations: [
Expand All @@ -31,6 +34,7 @@ import { InformationDialogComponent } from './information-dialog/information-dia
TargetMediaViewerComponent,
MediaItemViewerComponent,
InformationDialogComponent,
SearchBoxComponent,
],
exports: [
BackButtonComponent,
Expand All @@ -42,8 +46,9 @@ import { InformationDialogComponent } from './information-dialog/information-dia
UploadJsonButtonComponent,
ActionableDynamicTable,
TargetMediaViewerComponent,
MediaItemViewerComponent
MediaItemViewerComponent,
SearchBoxComponent
],
imports: [CommonModule, MatButtonModule, ServicesModule, MatIconModule, MatTooltipModule, MatDialogModule, MatTableModule]
imports: [CommonModule, MatButtonModule, ServicesModule, MatIconModule, MatTooltipModule, MatDialogModule, MatTableModule, MatInputModule, FormsModule]
})
export class SharedModule {}
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,16 @@ <h1 mat-dialog-title>Add team</h1>
<h3>Users in Team
<mat-icon matTooltip="To add users to this team, drag'n'drop them from the available users list. To remove users from this team, dragn'n'drop them to the available users list.">help</mat-icon>
</h3>
<app-search-box #memberFilter (filterChanged)="onMemberFilterChanged($event)"></app-search-box>
<div
cdkDropList
#memberList="cdkDropList"
[cdkDropListData]="form.get('users').value"
id="memberList"
[cdkDropListData]="form.get('users').value | userListFilter: memberFilterText"
[cdkDropListConnectedTo]="[userList]"
class="member-list"
(cdkDropListDropped)="drop($event)">
<mat-card class="member-list-item-border member-list-item" *ngFor="let user of form.get('users').value" cdkDrag>
<mat-card class="member-list-item-border member-list-item" *ngFor="let user of (form.get('users').value | userListFilter: memberFilterText)" cdkDrag>
<mat-card-content>{{user.username}}</mat-card-content>
</mat-card>
</div>
Expand All @@ -71,14 +73,16 @@ <h3>Users in Team
<h3>Users Available
<mat-icon matTooltip="To add users to the team, drag'n'drop them from this list. To remove users from the team, dragn'n'drop them to the this list.">help</mat-icon>
</h3>
<app-search-box #userFilter (filterChanged)="onAvailalbeFilterChanged($event)"></app-search-box>
<div
cdkDropList
#userList="cdkDropList"
[cdkDropListData]="users"
id="userList"
[cdkDropListData]="users | userListFilter: availableFilterText"
[cdkDropListConnectedTo]="[memberList]"
class="member-list"
(cdkDropListDropped)="drop($event)">
<mat-card class="member-list-item-border member-list-item" *ngFor="let user of users" cdkDrag>
<mat-card class="member-list-item-border member-list-item" *ngFor="let user of (users|userListFilter: availableFilterText)" cdkDrag>
<mat-card-content>{{user.username}}</mat-card-content>
</mat-card>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
min-height: 48px;
background: rgba(74,74,74, 0.84);
border-radius: 4px;
overflow: hidden;
overflow: auto;
display: block;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { COMMA, ENTER } from "@angular/cdk/keycodes";
import { MatChipInput, MatChipInputEvent } from "@angular/material/chips";
import { TemplateBuilderService } from "../../template-builder.service";
import { CdkDragDrop, moveItemInArray, transferArrayItem } from "@angular/cdk/drag-drop";
import { SearchBoxComponent } from "../../../../shared/search-box/search-box.component";

@Component({
selector: 'app-team-builder-dialog',
Expand All @@ -20,9 +21,13 @@ export class TeamBuilderDialogComponent {
form: FormGroup;
separatorKeyCodes: number[] = [ENTER, COMMA];
@ViewChild('userInput') userInput: ElementRef<HTMLInputElement>
@ViewChild('memberFilter') memberFilter: SearchBoxComponent
@ViewChild('userFilter') userFilter: SearchBoxComponent

logoName = '';
users: ApiUser[];
memberFilterText: string;
availableFilterText: string;
availableUsers: Observable<ApiUser[]>;
colorPalette = [
'#BF0000',
Expand Down Expand Up @@ -97,13 +102,27 @@ export class TeamBuilderDialogComponent {
}

public drop(event: CdkDragDrop<ApiUser[]>){
let prevList = event.previousContainer.data;
let newList = event.container.data;
if(event.previousContainer === event.container){
moveItemInArray(event.container.data, event.previousIndex, event.currentIndex)
}else{
transferArrayItem(event.previousContainer.data, event.container.data, event.previousIndex, event.currentIndex)
if(event.previousContainer.id === "memberList"){
prevList = this.form.get('users').value;
newList = this.users;
}else{
newList = this.form.get('users').value;
prevList = this.users;
}
let prevIdx = prevList.indexOf(event.previousContainer.data[event.previousIndex])
let currIdx = newList.indexOf(event.container.data[event.currentIndex])
transferArrayItem(prevList, newList, prevIdx, currIdx)
}
this.memberFilter?.clear()
this.userFilter?.clear();
}


/**
* Removes the selected user from the list of users.
*
Expand Down Expand Up @@ -163,6 +182,16 @@ export class TeamBuilderDialogComponent {
} as ApiTeam;
}

onMemberFilterChanged(filter: string){
console.log(`MEMBER: was: ${this.memberFilterText} is: ${filter}`)
this.memberFilterText = filter;
}

onAvailalbeFilterChanged(filter: string){
console.log(`AVAIL: was: ${this.availableFilterText} is: ${filter}`)
this.availableFilterText= filter;
}

/**
* Closes the dialog without saving.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Pipe, PipeTransform } from '@angular/core';
import { ApiUser } from "../../../../../../openapi";

/**
* A pipe enabling the filtering of a list of [ApiUser]s based on their username.
*/
@Pipe({
name: 'userListFilter'
})
export class UserListFilterPipe implements PipeTransform {

transform(list: ApiUser[], filter: string): ApiUser[] {
if(!list){
// Catch no / empty list;
return [];
}
if(!filter){
// Catch no / empty filter provided
return list;
}else{
return list.filter(user => {
return user.username.toLowerCase().includes(filter.toLowerCase())
});
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Pipe, PipeTransform } from '@angular/core';
import { ApiUser } from "../../../../../../openapi";

/**
* Simple filter which filters a list of [ApiUser]s based on whether they are present in another list.
*/
@Pipe({
name: 'userListInOtherFilter'
})
export class UserListInOtherFilterPipe implements PipeTransform {

transform(list: ApiUser[], other: ApiUser[]): ApiUser[] {
if(!list){
return [];
}
if(!other){
return list;
}
return list.filter(it => !other.includes(it))
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ import { ColorPickerModule } from "ngx-color-picker";
import {CdkDrag, CdkDropList} from '@angular/cdk/drag-drop';
import { MatCardModule } from "@angular/material/card";
import { ViewersListComponent } from './viewers-list/viewers-list.component';
import { UserListFilterPipe } from './team-builder-dialog/user-list-filter.pipe';
import { UserListInOtherFilterPipe } from './team-builder-dialog/user-list-in-other-filter.pipe';


@NgModule({
Expand All @@ -69,7 +71,9 @@ import { ViewersListComponent } from './viewers-list/viewers-list.component';
QueryDescriptionExternalVideoFormFieldComponent,
QueryDescriptionExternalImageFormFieldComponent,
TeamBuilderDialogComponent,
ViewersListComponent
ViewersListComponent,
UserListFilterPipe,
UserListInOtherFilterPipe
],
imports: [
CommonModule,
Expand Down

0 comments on commit cded493

Please sign in to comment.