diff --git a/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.html b/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.html index 26570bb7ce2df2392043a9fd69dafb73a221ce30..ca5ba1bf6c30db63d84ed5797f1aab5f8c6fe8bf 100644 --- a/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.html +++ b/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.html @@ -338,7 +338,8 @@ matTooltip="{{'topic-cloud-dialog.keyword-counter' | translate}}"></mat-icon> <p [ngClass]="{'animation-blink': searchMode}" matTooltip="{{'topic-cloud-dialog.keyword-counter' | translate}}"> - {{searchMode ? filteredKeywords.length : keywords.size}}</p> + {{searchMode ? filteredKeywords.length : + selectedTabIndex === 0 ? keywords.size : blacklistKeywords.length}}</p> </div> <div class="margin-left vertical-center"> <button [ngClass]="{'animation-blink': sortMode!=='alphabetic'}" mat-icon-button [matMenuTriggerFor]="sortMenu"> @@ -365,73 +366,144 @@ </button> </mat-menu> - <mat-card class="color-surface" - *ngIf="(keywords.size === 0 || (searchMode && filteredKeywords.length === 0))&&!isLoading"> - <p class="color-on-surface" fxLayoutAlign="center"> - {{'topic-cloud-dialog.no-keywords-note' | translate}} - </p> - </mat-card> - - <mat-accordion> - <div *ngFor="let keyword of (searchMode ? filteredKeywords : getValues()); let i = index"> - <mat-expansion-panel class="color-surface" (opened)="panelOpenState = true" - (closed)="panelOpenState = edit = false" [attr.data-index]="i" - *ngIf="(blacklistIncludesKeyword(keyword.keyword) && isCreatorOrMod) || !blacklistIncludesKeyword(keyword.keyword)" - matTooltip="{{blacklistIncludesKeyword(keyword.keyword)?'Blacklist: ':''}}{{'topic-cloud-dialog.'+(keyword.keywordType === 2?'Keyword-from-both':(keyword.keywordType === 0?'keyword-from-spacy':'keyword-from-questioner')) | translate}}"> - <mat-expansion-panel-header class="color-surface"> - <mat-panel-title [ngClass]="{'red': blacklistIncludesKeyword(keyword.keyword)}"> - {{profanityFilter ? keyword.keywordWithoutProfanity : keyword.keyword}} - </mat-panel-title> - <mat-panel-description [ngClass]="{'red': blacklistIncludesKeyword(keyword.keyword)}"> - {{keyword.comments.length}} - {{'topic-cloud-dialog.question-count-' + (keyword.comments.length > 1 ? 'plural' : 'singular') | translate}} - </mat-panel-description> - </mat-expansion-panel-header> - <div *ngFor="let question of keyword.comments"> - <mat-divider></mat-divider> - <app-topic-dialog-comment [question]="question.body" [keyword]="keyword.keyword" - [maxShowedCharachters]="140" - [profanityFilter]="profanityFilter" - [languageSpecific]="censorLanguageSpecificCheck" - [partialWords]="censorPartialWordsCheck" - [language]="question.language"></app-topic-dialog-comment> + + <mat-tab-group [selectedIndex]="selectedTabIndex" (selectedIndexChange)="changeTabIndex()" animationDuration="0ms" mat-stretch-tabs mat-align-tabs="center"> + <mat-tab label="{{'topic-cloud-dialog.keywords' | translate}}"> + <mat-card class="color-surface" + *ngIf="(keywords.size === 0 || (searchMode && filteredKeywords.length === 0))&&!isLoading"> + <p class="color-on-surface" fxLayoutAlign="center"> + {{'topic-cloud-dialog.no-keywords-note' | translate}} + </p> + </mat-card> + <mat-accordion> + <div *ngFor="let keyword of (searchMode ? filteredKeywords : getValues()); let i = index"> + <mat-expansion-panel class="color-surface" (opened)="panelOpenState = true" + (closed)="panelOpenState = edit = false" [attr.data-index]="i" + *ngIf="(blacklistIncludesKeyword(keyword.keyword) && isCreatorOrMod) || !blacklistIncludesKeyword(keyword.keyword)" + matTooltip="{{'topic-cloud-dialog.'+(keyword.keywordType === 2?'Keyword-from-both':(keyword.keywordType === 0?'keyword-from-spacy':'keyword-from-questioner')) | translate}}"> + <mat-expansion-panel-header class="color-surface"> + <mat-panel-title> + {{profanityFilter ? keyword.keywordWithoutProfanity : keyword.keyword}} + </mat-panel-title> + <mat-panel-description> + {{keyword.comments.length}} + {{'topic-cloud-dialog.question-count-' + (keyword.comments.length > 1 ? 'plural' : 'singular') | translate}} + </mat-panel-description> + </mat-expansion-panel-header> + <div *ngFor="let question of keyword.comments"> + <mat-divider></mat-divider> + <app-topic-dialog-comment [question]="question.body" [keyword]="keyword.keyword" + [maxShowedCharachters]="140" + [profanityFilter]="profanityFilter" + [languageSpecific]="censorLanguageSpecificCheck" + [partialWords]="censorPartialWordsCheck" + [language]="question.language"></app-topic-dialog-comment> + </div> + + <div *ngIf="isCreatorOrMod"> + <!-- Only visible when not editing --> + <div *ngIf="!edit" align="end"> + <mat-divider></mat-divider> + <button class="margin-right" mat-icon-button style="align-self:flex-end;" (click)="editKeyword(i)"> + <mat-icon class="primary" matTooltip="{{'topic-cloud-dialog.edit' | translate}}">edit</mat-icon> + </button> + <button class="margin-right" mat-icon-button style="align-self:flex-end;" + (click)="openConfirmDialog('delete-message','delete',keyword)"> + <mat-icon class="red" matTooltip="{{'topic-cloud-dialog.delete' | translate}}">delete</mat-icon> + </button> + </div> + + <!-- Only visible when editing --> + <div *ngIf="edit"> + <mat-divider></mat-divider> + <mat-form-field> + <mat-label>{{'topic-cloud-dialog.edit-keyword-tip' | translate}}</mat-label> + <input matInput id="{{'edit-input'+i}}" [(ngModel)]="newKeyword"> + </mat-form-field> + <!-- TODO: textinput and buttons in one row --> + <div align="end"> + <button mat-raised-button class="redBackground margin-right" + (click)="cancelEdit()">{{'topic-cloud-dialog.cancel' | translate}}</button> + <button mat-raised-button class="primaryBackground" + [disabled]="!newKeyword || newKeyword.toLowerCase() === keyword.keyword.toLowerCase()" + (click)="confirmEdit(keyword)"> + {{'topic-cloud-dialog.save' | translate}} + </button> + </div> + </div> + </div> + </mat-expansion-panel> </div> + </mat-accordion> + </mat-tab> - <div *ngIf="isCreatorOrMod"> - <!-- Only visible when not editing --> - <div *ngIf="!edit" align="end"> - <mat-divider></mat-divider> - <button class="margin-right" mat-icon-button style="align-self:flex-end;" (click)="editKeyword(i)"> - <mat-icon class="primary" matTooltip="{{'topic-cloud-dialog.edit' | translate}}">edit</mat-icon> - </button> - <button class="margin-right" mat-icon-button style="align-self:flex-end;" - (click)="openConfirmDialog('delete-message','delete',keyword)"> - <mat-icon class="red" matTooltip="{{'topic-cloud-dialog.delete' | translate}}">delete</mat-icon> - </button> - </div> - - <!-- Only visible when editing --> - <div *ngIf="edit"> - <mat-divider></mat-divider> - <mat-form-field> - <mat-label>{{'topic-cloud-dialog.edit-keyword-tip' | translate}}</mat-label> - <input matInput id="{{'edit-input'+i}}" [(ngModel)]="newKeyword"> - </mat-form-field> - <!-- TODO: textinput and buttons in one row --> - <div align="end"> - <button mat-raised-button class="redBackground margin-right" - (click)="cancelEdit()">{{'topic-cloud-dialog.cancel' | translate}}</button> - <button mat-raised-button class="primaryBackground" - [disabled]="!newKeyword || newKeyword.toLowerCase() === keyword.keyword.toLowerCase()" - (click)="confirmEdit(keyword)"> - {{'topic-cloud-dialog.save' | translate}} - </button> + <mat-tab *ngIf="isCreatorOrMod"> + <ng-template mat-tab-label> + <label [ngClass]="{'animation-blink': blacklistIsActive}" + matTooltip="{{'topic-cloud-dialog.blacklist-is'+(blacklistIsActive?'':'-not')+'-active' | translate}}">Blacklist</label> + </ng-template> + <mat-card class="color-surface" + *ngIf="(blacklistKeywords.length === 0 || (searchMode && filteredKeywords.length === 0))&&!isLoading"> + <p class="color-on-surface" fxLayoutAlign="center"> + {{'topic-cloud-dialog.no-keywords-note' | translate}} + </p> + </mat-card> + <mat-accordion> + <div *ngFor="let keyword of (searchMode ? filteredKeywords : blacklistKeywords); let i = index"> + <mat-expansion-panel class="color-surface" (opened)="panelOpenState = true" + (closed)="panelOpenState = edit = false" [attr.data-index]="i" + matTooltip="{{'topic-cloud-dialog.'+(keyword.keywordType === 2?'Keyword-from-both':(keyword.keywordType === 0?'keyword-from-spacy':'keyword-from-questioner')) | translate}}"> + <mat-expansion-panel-header class="color-surface"> + <mat-panel-title> + {{keyword.keyword}} + </mat-panel-title> + <mat-panel-description> + {{keyword.comments.length}} + {{'topic-cloud-dialog.question-count-' + (keyword.comments.length > 1 ? 'plural' : 'singular') | translate}} + </mat-panel-description> + </mat-expansion-panel-header> + <div *ngFor="let question of keyword.comments"> + <mat-divider></mat-divider> + <app-topic-dialog-comment [question]="question.body" [keyword]="keyword.keyword" [maxShowedCharachters]="140" + [profanityFilter]="profanityFilter" [languageSpecific]="censorLanguageSpecificCheck" + [partialWords]="censorPartialWordsCheck" + [language]="question.language"></app-topic-dialog-comment> + </div> + <div> + <!-- Only visible when not editing --> + <div *ngIf="!edit" align="end"> + <mat-divider></mat-divider> + <button class="margin-right" mat-icon-button style="align-self:flex-end;" (click)="editKeyword(i)"> + <mat-icon class="primary" matTooltip="{{'topic-cloud-dialog.edit' | translate}}">edit</mat-icon> + </button> + <button class="margin-right" mat-icon-button style="align-self:flex-end;" + (click)="openConfirmDialog('delete-message','delete',keyword)"> + <mat-icon class="red" matTooltip="{{'topic-cloud-dialog.delete' | translate}}">delete</mat-icon> + </button> + </div> + + <!-- Only visible when editing --> + <div *ngIf="edit"> + <mat-divider></mat-divider> + <mat-form-field> + <mat-label>{{'topic-cloud-dialog.edit-keyword-tip' | translate}}</mat-label> + <input matInput id="{{'edit-input'+i}}" [(ngModel)]="newKeyword"> + </mat-form-field> + + <div align="end"> + <button mat-raised-button class="redBackground margin-right" + (click)="cancelEdit()">{{'topic-cloud-dialog.cancel' | translate}}</button> + <button mat-raised-button class="primaryBackground" + (click)="confirmEdit(keyword)">{{'topic-cloud-dialog.save' + | translate}}</button> + </div> + </div> </div> - </div> + </mat-expansion-panel> </div> - </mat-expansion-panel> - </div> - </mat-accordion> + </mat-accordion> + </mat-tab> + </mat-tab-group> </div> </mat-dialog-content> <app-dialog-action-buttons diff --git a/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.ts b/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.ts index 567ceb523fdf44be9903eaa078f3ecab4b1b224b..db3d258cf2c1e2f6f26e8e0e8c1fb2efbf9bec66 100644 --- a/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.ts +++ b/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.ts @@ -59,6 +59,7 @@ export class TopicCloudAdministrationComponent implements OnInit, OnDestroy { minUpvotes: string; startDate: string; endDate: string; + selectedTabIndex = 0; keywords: Map<string, Keyword> = new Map<string, Keyword>(); private topicCloudAdminData: TopicCloudAdminData; @@ -67,6 +68,7 @@ export class TopicCloudAdministrationComponent implements OnInit, OnDestroy { private censorLanguageSpecificCheck: boolean; private testProfanityWord: string = undefined; private testProfanityLanguage = 'de'; + private blacklistKeywords = []; constructor( @Inject(MAT_DIALOG_DATA) public data: Data, @@ -85,9 +87,15 @@ export class TopicCloudAdministrationComponent implements OnInit, OnDestroy { } ngOnInit(): void { - this.topicCloudAdminService.getBlacklistIsActive().subscribe(isActive => this.blacklistIsActive = isActive); + this.topicCloudAdminService.getBlacklistIsActive().subscribe(isActive => { + this.blacklistIsActive = isActive; + this.refreshKeywords(); + }); this.deviceType = localStorage.getItem('deviceType'); - this.blacklistSubscription = this.topicCloudAdminService.getBlacklist().subscribe(list => this.blacklist = list); + this.blacklistSubscription = this.topicCloudAdminService.getBlacklist().subscribe(list => { + this.blacklist = list; + this.refreshKeywords(); + }); this.profanitywordlist = this.profanityFilterService.getProfanityListFromStorage(); this.profanitylistSubscription = this.profanityFilterService.getCustomProfanityList().subscribe(list => { this.profanitywordlist = list; @@ -101,6 +109,13 @@ export class TopicCloudAdministrationComponent implements OnInit, OnDestroy { this.initializeKeywords(); } + changeTabIndex() { + this.selectedTabIndex = this.selectedTabIndex === 0 ? 1 : 0; + if (this.searchMode) { + this.searchKeyword(); + } + } + getValues(): Keyword[] { return [...this.keywords.values()]; } @@ -116,6 +131,7 @@ export class TopicCloudAdministrationComponent implements OnInit, OnDestroy { } refreshKeywords() { + this.blacklistKeywords = []; this.keywords = new Map<string, Keyword>(); this.roomDataService.currentRoomData.forEach(comment => { this.pushInKeywords(comment); @@ -157,14 +173,20 @@ export class TopicCloudAdministrationComponent implements OnInit, OnDestroy { _keywordType = includedFromQuestioner ? KeywordType.fromQuestioner : KeywordType.fromSpacy; } } - this.keywords.set(_keyword.lemma, { + const entry = { keyword: _keyword.lemma, keywordDeps: new Set<string>(_keyword.dep), keywordType: _keywordType, keywordWithoutProfanity: this.getKeywordWithoutProfanity(_keyword.lemma, comment.language), comments: [comment], vote: comment.score - } as Keyword); + }; + + if (this.blacklistIncludesKeyword(_keyword.lemma) && this.blacklistIsActive) { + this.blacklistKeywords.push(entry); + } else { + this.keywords.set(_keyword.lemma, entry as Keyword); + } } }); } @@ -455,10 +477,16 @@ export class TopicCloudAdministrationComponent implements OnInit, OnDestroy { if (!this.searchedKeyword) { this.searchMode = false; } else { - const entries = [...this.keywords.entries()]; - this.filteredKeywords = entries.filter(([_, keyword]) => + if (this.selectedTabIndex === 0) { + const entries = [...this.keywords.entries()]; + this.filteredKeywords = entries.filter(([_, keyword]) => keyword.keyword.toLowerCase().includes(this.searchedKeyword.toLowerCase()) - ).map(e => e[1]); + ).map(e => e[1]); + } else { + this.filteredKeywords = this.blacklistKeywords.filter(keyword => + keyword.keyword.toLowerCase().includes(this.searchedKeyword.toLowerCase()) + ); + } this.searchMode = true; } } diff --git a/src/assets/i18n/creator/de.json b/src/assets/i18n/creator/de.json index 4a790c3bb5552bb61a6e0d60917527eaf2b7e5a7..f2d6548f65c0ed3efab17db7df1d258cedd07aca 100644 --- a/src/assets/i18n/creator/de.json +++ b/src/assets/i18n/creator/de.json @@ -424,6 +424,9 @@ "topic-requirement-upvotes": "Minimale Anzahl Up-Votes", "topic-requirement-begin-datetime": "Beginn der Zeitspanne", "topic-requirement-end-datetime": "Ende der Zeitspanne", + "keywords": "Stichwörter", + "blacklist-is-active": "Die Blacklist wird verborgen", + "blacklist-is-not-active": "Die Blacklist wird nicht verborgen", "topic-requirement-reset": "Zurücksetzen" }, "topic-cloud-confirm-dialog": { diff --git a/src/assets/i18n/creator/en.json b/src/assets/i18n/creator/en.json index 87f14a56684556dfca75914a4d9657b98b45a2c2..a7290cce09b4a10c5bba6212de125835ce4db2e9 100644 --- a/src/assets/i18n/creator/en.json +++ b/src/assets/i18n/creator/en.json @@ -432,6 +432,9 @@ "topic-requirement-upvotes": "Minimum number of upvotes", "topic-requirement-begin-datetime": "Earliest comment", "topic-requirement-end-datetime": "Last comment", + "keywords": "Keywords", + "blacklist-is-active": "The blacklist is hidden", + "blacklist-is-not-active": "The blacklist is not hidden", "topic-requirement-reset": "Reset" }, "topic-cloud-confirm-dialog":{ diff --git a/src/assets/i18n/participant/de.json b/src/assets/i18n/participant/de.json index 187ecce9e070aa2367594f4b22ee56c66c8e24df..f0bc0e6e8e41e43df2ac077e5ba0e9fa73fdf607 100644 --- a/src/assets/i18n/participant/de.json +++ b/src/assets/i18n/participant/de.json @@ -308,6 +308,7 @@ "topic-requirement-upvotes": "Minimale Anzahl Up-Votes", "topic-requirement-begin-datetime": "Beginn der Zeitspanne", "topic-requirement-end-datetime": "Ende der Zeitspanne", + "keywords": "Stichwörter", "topic-requirement-reset": "Zurücksetzen" }, "dialog-comment": { diff --git a/src/assets/i18n/participant/en.json b/src/assets/i18n/participant/en.json index 012260e357b8a19fddedf3fdc24d9bfe2bb2ac2a..196ab889901a5b49e6560b6c20ac7e307e5e7dee 100644 --- a/src/assets/i18n/participant/en.json +++ b/src/assets/i18n/participant/en.json @@ -314,6 +314,7 @@ "topic-requirement-upvotes": "Minimum number of upvotes", "topic-requirement-begin-datetime": "Earliest comment", "topic-requirement-end-datetime": "Last comment", + "keywords": "Keywords", "topic-requirement-reset": "Reset" }, "dialog-comment":{