fixed comments

This commit is contained in:
Dan Percic 2021-11-15 22:34:47 +02:00
parent bf0e1631b7
commit 9b9c025be5
16 changed files with 103 additions and 148 deletions

View File

@ -1,32 +1,34 @@
<div *ngFor="let comment of annotation.comments; trackBy: trackBy" class="comment">
<div class="comment-details-wrapper">
<div [matTooltipPosition]="'above'" [matTooltip]="comment.date | date: 'exactDate'" class="small-label">
<strong> {{ comment.user | name }} </strong>
{{ comment.date | date: 'sophisticatedDate' }}
<ng-container *ngIf="file$ | async as file">
<div *ngFor="let comment of annotation.comments; trackBy: trackBy" class="comment">
<div class="comment-details-wrapper">
<div [matTooltipPosition]="'above'" [matTooltip]="comment.date | date: 'exactDate'" class="small-label">
<strong> {{ comment.user | name }} </strong>
{{ comment.date | date: 'sophisticatedDate' }}
</div>
<div class="comment-actions">
<iqser-circle-button
(action)="deleteComment(comment)"
*ngIf="permissionsService.canDeleteComment(comment, file)"
[iconSize]="10"
[size]="20"
class="pointer"
icon="iqser:trash"
></iqser-circle-button>
</div>
</div>
<div class="comment-actions">
<iqser-circle-button
(action)="deleteComment(comment)"
*ngIf="permissionsService.canDeleteComment(comment, filesMapService.get(dossierId, fileId))"
[iconSize]="10"
[size]="20"
class="pointer"
icon="iqser:trash"
></iqser-circle-button>
</div>
<div>{{ comment.text }}</div>
</div>
<div>{{ comment.text }}</div>
</div>
<iqser-input-with-action
(action)="addComment($event)"
*ngIf="permissionsService.canAddComment(filesMapService.get(dossierId, fileId))"
[placeholder]="'comments.add-comment' | translate"
autocomplete="off"
icon="iqser:collapse"
width="full"
></iqser-input-with-action>
<iqser-input-with-action
(action)="addComment($event)"
*ngIf="permissionsService.canAddComment(file)"
[placeholder]="'comments.add-comment' | translate"
autocomplete="off"
icon="iqser:collapse"
width="full"
></iqser-input-with-action>
</ng-container>
<div (click)="toggleExpandComments($event)" class="all-caps-label pointer hide-comments" translate="comments.hide-comments"></div>

View File

@ -1,5 +1,5 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, HostBinding, Input, ViewChild } from '@angular/core';
import { IComment } from '@red/domain';
import { File, IComment } from '@red/domain';
import { ManualAnnotationService } from '../../services/manual-annotation.service';
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
import { UserService } from '@services/user.service';
@ -7,6 +7,7 @@ import { PermissionsService } from '@services/permissions.service';
import { InputWithActionComponent, trackBy } from '@iqser/common-ui';
import { FilesMapService } from '@services/entity-services/files-map.service';
import { ActivatedRoute } from '@angular/router';
import { Observable } from 'rxjs';
@Component({
selector: 'redaction-comments',
@ -17,8 +18,7 @@ import { ActivatedRoute } from '@angular/router';
export class CommentsComponent {
@Input() annotation: AnnotationWrapper;
readonly trackBy = trackBy();
readonly fileId: string;
readonly dossierId: string;
readonly file$: Observable<File>;
@HostBinding('class.hidden') private _hidden = true;
@ViewChild(InputWithActionComponent) private readonly _input: InputWithActionComponent;
@ -30,8 +30,9 @@ export class CommentsComponent {
readonly filesMapService: FilesMapService,
activatedRoute: ActivatedRoute,
) {
this.fileId = activatedRoute.snapshot.paramMap.get('fileId');
this.dossierId = activatedRoute.snapshot.paramMap.get('dossierId');
const fileId = activatedRoute.snapshot.paramMap.get('fileId');
const dossierId = activatedRoute.snapshot.paramMap.get('dossierId');
this.file$ = filesMapService.watch$(dossierId, fileId);
}
addComment(value: string): void {

View File

@ -28,15 +28,19 @@
[canAdd]="false"
[canRemove]="true"
[largeSpacing]="true"
[memberIds]="selectedReviewersList"
[memberIds]="selectedReviewers$ | async"
[perLine]="13"
[unremovableMembers]="[selectedOwnerId]"
></redaction-team-members>
<pre *ngIf="selectedReviewersList.length === 0" [innerHTML]="'assign-dossier-owner.dialog.no-reviewers' | translate" class="info"></pre>
<pre
*ngIf="(selectedReviewers$ | async).length === 0"
[innerHTML]="'assign-dossier-owner.dialog.no-reviewers' | translate"
class="info"
></pre>
<iqser-input-with-action
(valueChange)="setMembersSelectOptions()"
(valueChange)="setMembersSelectOptions($event)"
[(value)]="searchQuery"
[placeholder]="'assign-dossier-owner.dialog.search' | translate"
[width]="560"

View File

@ -1,9 +1,11 @@
import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core';
import { UserService } from '@services/user.service';
import { Toaster } from '@iqser/common-ui';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { DossiersService } from '@services/entity-services/dossiers.service';
import { Dossier, IDossier, IDossierRequest } from '@red/domain';
import { AutoUnsubscribe } from '@iqser/common-ui';
import { EditDossierSectionInterface } from '../../dialogs/edit-dossier-dialog/edit-dossier-section.interface';
import { BehaviorSubject } from 'rxjs';
@Component({
selector: 'redaction-team-members-manager',
@ -11,7 +13,7 @@ import { Dossier, IDossier, IDossierRequest } from '@red/domain';
styleUrls: ['./team-members-manager.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class TeamMembersManagerComponent implements OnInit {
export class TeamMembersManagerComponent extends AutoUnsubscribe implements EditDossierSectionInterface, OnInit, OnDestroy {
teamForm: FormGroup;
searchQuery = '';
@ -19,16 +21,17 @@ export class TeamMembersManagerComponent implements OnInit {
@Output() readonly save = new EventEmitter<IDossier>();
readonly ownersSelectOptions = this.userService.managerUsers.map(m => m.id);
selectedReviewersList: string[] = [];
membersSelectOptions: string[] = [];
changed = false;
selectedReviewers$ = new BehaviorSubject<string[]>([]);
constructor(
readonly userService: UserService,
private readonly _toaster: Toaster,
private readonly _formBuilder: FormBuilder,
private readonly _dossiersService: DossiersService,
) {}
) {
super();
}
get selectedOwnerId(): string {
return this.teamForm.get('owner').value;
@ -46,6 +49,10 @@ export class TeamMembersManagerComponent implements OnInit {
return this.teamForm.valid;
}
get disabled() {
return !this.userService.currentUser.isManager;
}
isOwner(userId: string): boolean {
return userId === this.selectedOwnerId;
}
@ -113,9 +120,9 @@ export class TeamMembersManagerComponent implements OnInit {
this._loadData();
}
setMembersSelectOptions(): void {
setMembersSelectOptions(value = this.searchQuery): void {
this.membersSelectOptions = this.userService.eligibleUsers
.filter(user => this.userService.getNameForId(user.id).toLowerCase().includes(this.searchQuery.toLowerCase()))
.filter(user => this.userService.getNameForId(user.id).toLowerCase().includes(value.toLowerCase()))
.filter(user => this.selectedOwnerId !== user.id)
.map(user => user.id);
}
@ -136,7 +143,8 @@ export class TeamMembersManagerComponent implements OnInit {
}
private _setSelectedReviewersList() {
this.selectedReviewersList = this.selectedMembersList.filter(m => this.selectedApproversList.indexOf(m) === -1);
const selectedReviewers = this.selectedMembersList.filter(m => this.selectedApproversList.indexOf(m) === -1);
this.selectedReviewers$.next(selectedReviewers);
}
private _loadData() {
@ -145,7 +153,7 @@ export class TeamMembersManagerComponent implements OnInit {
approvers: [[...this.dossier?.approverIds]],
members: [[...this.dossier?.memberIds]],
});
this.teamForm.get('owner').valueChanges.subscribe(owner => {
this.addSubscription = this.teamForm.get('owner').valueChanges.subscribe(owner => {
if (!this.isApprover(owner)) {
this.toggleApprover(owner);
}

View File

@ -22,7 +22,6 @@ class DialogData {
})
export class AssignReviewerApproverDialogComponent {
usersForm: FormGroup;
searchForm: FormGroup;
constructor(
readonly userService: UserService,
@ -71,15 +70,13 @@ export class AssignReviewerApproverDialogComponent {
}
async save() {
const selectedUser = this.selectedSingleUser;
try {
if (this.data.mode === 'reviewer') {
await this._filesService
.setReviewerFor(
this.data.files.map(f => f.fileId),
this._dossiersService.activeDossierId,
selectedUser,
this.selectedSingleUser,
)
.toPromise();
} else {
@ -87,7 +84,7 @@ export class AssignReviewerApproverDialogComponent {
.setUnderApprovalFor(
this.data.files.map(f => f.fileId),
this._dossiersService.activeDossierId,
selectedUser,
this.selectedSingleUser,
)
.toPromise();
}

View File

@ -37,11 +37,11 @@
[dossier]="dossier"
></redaction-edit-dossier-dictionary>
<redaction-edit-dossier-team-members
(updateDossier)="updatedDossier()"
<redaction-team-members-manager
(save)="updatedDossier()"
*ngIf="activeNav === 'members'"
[dossier]="dossier"
></redaction-edit-dossier-team-members>
></redaction-team-members-manager>
<redaction-edit-dossier-attributes
(updateDossier)="updatedDossier()"
@ -69,7 +69,8 @@
(click)="save(true)"
[disabled]="activeComponent?.disabled || !activeComponent?.changed"
[label]="'edit-dossier-dialog.actions.save-and-close' | translate"
[type]="iconButtonTypes.dark">
[type]="iconButtonTypes.dark"
>
</iqser-icon-button>
<div (click)="revert()" class="all-caps-label cancel" translate="edit-dossier-dialog.actions.revert"></div>

View File

@ -6,13 +6,13 @@ import { EditDossierDownloadPackageComponent } from './download-package/edit-dos
import { EditDossierSectionInterface } from './edit-dossier-section.interface';
import { IconButtonTypes, Toaster } from '@iqser/common-ui';
import { EditDossierDictionaryComponent } from './dictionary/edit-dossier-dictionary.component';
import { EditDossierTeamMembersComponent } from './team-members/edit-dossier-team-members.component';
import { EditDossierAttributesComponent } from './attributes/edit-dossier-attributes.component';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { EditDossierDeletedDocumentsComponent } from './deleted-documents/edit-dossier-deleted-documents.component';
import { AppStateService } from '@state/app-state.service';
import { DossiersService } from '@services/entity-services/dossiers.service';
import { TeamMembersManagerComponent } from '../../components/team-members-manager/team-members-manager.component';
type Section = 'dossierInfo' | 'downloadPackage' | 'dossierDictionary' | 'members' | 'dossierAttributes' | 'deletedDocuments';
@ -29,7 +29,7 @@ export class EditDossierDialogComponent {
@ViewChild(EditDossierGeneralInfoComponent) generalInfoComponent: EditDossierGeneralInfoComponent;
@ViewChild(EditDossierDownloadPackageComponent) downloadPackageComponent: EditDossierDownloadPackageComponent;
@ViewChild(EditDossierDictionaryComponent) dictionaryComponent: EditDossierDictionaryComponent;
@ViewChild(EditDossierTeamMembersComponent) membersComponent: EditDossierTeamMembersComponent;
@ViewChild(TeamMembersManagerComponent) membersComponent: TeamMembersManagerComponent;
@ViewChild(EditDossierAttributesComponent) attributesComponent: EditDossierAttributesComponent;
@ViewChild(EditDossierDeletedDocumentsComponent) deletedDocumentsComponent: EditDossierDeletedDocumentsComponent;

View File

@ -1 +0,0 @@
<redaction-team-members-manager (save)="updateDossier.emit()" [dossier]="dossier"></redaction-team-members-manager>

View File

@ -1,38 +0,0 @@
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output, ViewChild } from '@angular/core';
import { Dossier } from '@red/domain';
import { EditDossierSectionInterface } from '../edit-dossier-section.interface';
import { TeamMembersManagerComponent } from '../../../components/team-members-manager/team-members-manager.component';
import { UserService } from '@services/user.service';
@Component({
selector: 'redaction-edit-dossier-team-members',
templateUrl: './edit-dossier-team-members.component.html',
styleUrls: ['./edit-dossier-team-members.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class EditDossierTeamMembersComponent implements EditDossierSectionInterface {
readonly currentUser = this._userService.currentUser;
@Input() dossier: Dossier;
@Output() readonly updateDossier = new EventEmitter();
@ViewChild(TeamMembersManagerComponent) managerComponent: TeamMembersManagerComponent;
constructor(private readonly _userService: UserService) {}
get changed() {
return this.managerComponent.changed;
}
get disabled() {
return !this.currentUser.isManager;
}
async save() {
await this.managerComponent.saveMembers();
}
revert() {
this.managerComponent.revert();
}
}

View File

@ -27,7 +27,6 @@ import { EditDossierDialogComponent } from './dialogs/edit-dossier-dialog/edit-d
import { EditDossierGeneralInfoComponent } from './dialogs/edit-dossier-dialog/general-info/edit-dossier-general-info.component';
import { EditDossierDownloadPackageComponent } from './dialogs/edit-dossier-dialog/download-package/edit-dossier-download-package.component';
import { EditDossierDictionaryComponent } from './dialogs/edit-dossier-dialog/dictionary/edit-dossier-dictionary.component';
import { EditDossierTeamMembersComponent } from './dialogs/edit-dossier-dialog/team-members/edit-dossier-team-members.component';
import { TeamMembersManagerComponent } from './components/team-members-manager/team-members-manager.component';
import { ChangeLegalBasisDialogComponent } from './dialogs/change-legal-basis-dialog/change-legal-basis-dialog.component';
import { PageExclusionComponent } from './components/page-exclusion/page-exclusion.component';
@ -68,7 +67,6 @@ const components = [
EditDossierGeneralInfoComponent,
EditDossierDownloadPackageComponent,
EditDossierDictionaryComponent,
EditDossierTeamMembersComponent,
EditDossierAttributesComponent,
TeamMembersManagerComponent,
PageExclusionComponent,

View File

@ -1,4 +1,4 @@
<ng-container *ngIf="areSomeFilesSelected" (longPress)="forceReanalysisAction($event)" redactionLongPress>
<ng-container (longPress)="forceReanalysisAction($event)" *ngIf="listingService.selectedLength$ | async" redactionLongPress>
<iqser-circle-button
(action)="delete()"
*ngIf="canDelete"

View File

@ -1,11 +1,11 @@
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
import { AppStateService } from '@state/app-state.service';
import { PermissionsService } from '@services/permissions.service';
import { Dossier, File } from '@red/domain';
import { FileActionService } from '../../../../shared/services/file-action.service';
import { Observable } from 'rxjs';
import { DossiersDialogService } from '../../../../services/dossiers-dialog.service';
import { CircleButtonTypes, ConfirmationDialogInput, EntitiesService, ListingService, LoadingService } from '@iqser/common-ui';
import { CircleButtonTypes, ConfirmationDialogInput, ListingService, LoadingService } from '@iqser/common-ui';
import { TranslateService } from '@ngx-translate/core';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { LongPressEvent } from '@shared/directives/long-press.directive';
@ -17,6 +17,7 @@ import { ReanalysisService } from '@services/reanalysis.service';
selector: 'redaction-dossier-overview-bulk-actions',
templateUrl: './dossier-overview-bulk-actions.component.html',
styleUrls: ['./dossier-overview-bulk-actions.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class DossierOverviewBulkActionsComponent {
readonly circleButtonTypes = CircleButtonTypes;
@ -35,34 +36,21 @@ export class DossierOverviewBulkActionsComponent {
private readonly _fileActionService: FileActionService,
private readonly _loadingService: LoadingService,
private readonly _translateService: TranslateService,
private readonly _entitiesService: EntitiesService<File>,
private readonly _listingService: ListingService<File>,
readonly listingService: ListingService<File>,
private readonly _userPreferenceService: UserPreferenceService,
) {}
get selectedFiles(): File[] {
return this._listingService.selected;
}
get areAllFilesSelected() {
const allFilesCount = this._entitiesService.all.length;
return allFilesCount !== 0 && this.selectedFiles.length === allFilesCount;
}
get areSomeFilesSelected() {
return this.selectedFiles.length > 0;
return this.listingService.selected;
}
get allSelectedFilesCanBeAssignedIntoSameState() {
if (this.areSomeFilesSelected) {
const allFilesAreUnderReviewOrUnassigned = this.selectedFiles.reduce(
(acc, file) => acc && (file.isUnderReview || file.isUnassigned),
true,
);
const allFilesAreUnderApproval = this.selectedFiles.reduce((acc, file) => acc && file.isUnderApproval, true);
return allFilesAreUnderReviewOrUnassigned || allFilesAreUnderApproval;
}
return false;
const allFilesAreUnderReviewOrUnassigned = this.selectedFiles.reduce(
(acc, file) => acc && (file.isUnderReview || file.isUnassigned),
true,
);
const allFilesAreUnderApproval = this.selectedFiles.reduce((acc, file) => acc && file.isUnderApproval, true);
return allFilesAreUnderReviewOrUnassigned || allFilesAreUnderApproval;
}
get canAssignToSelf() {
@ -83,31 +71,27 @@ export class DossierOverviewBulkActionsComponent {
}
get canDelete() {
return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canDeleteFile(file), true);
return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canDeleteFile(file, this.dossier), true);
}
get canReanalyse() {
return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canReanalyseFile(file), true);
return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canReanalyseFile(file, this.dossier), true);
}
get canOcr() {
return this.selectedFiles.reduce((acc, file) => acc && file.canBeOCRed, true);
}
get files() {
return this.selectedFiles.map(file => file.status);
}
get canSetToUnderReview() {
return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canSetUnderReview(file), true);
return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canSetUnderReview(file, this.dossier), true);
}
get canSetToUnderApproval() {
return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canSetUnderApproval(file), true);
return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canSetUnderApproval(file, this.dossier), true);
}
get isReadyForApproval() {
return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.isReadyForApproval(file), true);
return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.isReadyForApproval(file, this.dossier), true);
}
get canApprove() {

View File

@ -1,7 +1,6 @@
<div>
<redaction-simple-doughnut-chart
*ngIf="dossiersChartData$ | async as config"
[config]="config"
[config]="dossiersChartData$ | async"
[radius]="80"
[strokeWidth]="15"
[subtitle]="'dossier-listing.stats.charts.dossiers' | translate"

View File

@ -239,17 +239,17 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD
this.assignTooltip = this.file.isUnderApproval ? _('dossier-overview.assign-approver') : _('dossier-overview.assign-reviewer');
this.buttonType = this.isFilePreview ? CircleButtonTypes.default : CircleButtonTypes.dark;
this.toggleTooltip = this._toggleTooltip;
const dossier = this.dossiersService.find(this.file.dossierId);
this.showUndoApproval = this.permissionsService.canUndoApproval(this.file) && !this.isDossierOverviewWorkflow;
this.showUnderReview = this.permissionsService.canSetUnderReview(this.file) && !this.isDossierOverviewWorkflow;
this.showUnderReview = this.permissionsService.canSetUnderReview(this.file, dossier) && !this.isDossierOverviewWorkflow;
this.showUnderApproval = this.permissionsService.canSetUnderApproval(this.file) && !this.isDossierOverviewWorkflow;
this.showApprove = this.permissionsService.isReadyForApproval(this.file) && !this.isDossierOverviewWorkflow;
this.showApprove = this.permissionsService.isReadyForApproval(this.file, dossier) && !this.isDossierOverviewWorkflow;
this.canToggleAnalysis = this.permissionsService.canToggleAnalysis(this.file);
const dossier = this.dossiersService.find(this.file.dossierId);
this.canToggleAnalysis = this.permissionsService.canToggleAnalysis(this.file, dossier);
this.showDelete = this.permissionsService.canDeleteFile(this.file, dossier);
this.showOCR = this.file.canBeOCRed;
this.canReanalyse = this.permissionsService.canReanalyseFile(this.file);
this.canReanalyse = this.permissionsService.canReanalyseFile(this.file, dossier);
this.showStatusBar = this.file.isWorkable && this.isDossierOverviewList;

View File

@ -13,20 +13,20 @@ export class PermissionsService {
return this._dossiersService.activeDossier;
}
isReviewerOrApprover(file: File): boolean {
return this.isFileReviewer(file) || this.isApprover(this._getDossier(file));
isReviewerOrApprover(file: File, dossier: Dossier): boolean {
return this.isFileReviewer(file) || this.isApprover(dossier);
}
displayReanalyseBtn(dossier: Dossier): boolean {
return this.isApprover(dossier);
}
canToggleAnalysis(file: File): boolean {
return this.isReviewerOrApprover(file) && ['UNASSIGNED', 'UNDER_REVIEW', 'UNDER_APPROVAL'].includes(file.status);
canToggleAnalysis(file: File, dossier: Dossier): boolean {
return this.isReviewerOrApprover(file, dossier) && ['UNASSIGNED', 'UNDER_REVIEW', 'UNDER_APPROVAL'].includes(file.status);
}
canReanalyseFile(file: File): boolean {
return this.isReviewerOrApprover(file) || file.isUnassigned || (file.isError && file.isUnassigned);
canReanalyseFile(file: File, dossier: Dossier): boolean {
return this.isReviewerOrApprover(file, dossier) || file.isUnassigned || (file.isError && file.isUnassigned);
}
isFileReviewer(file: File): boolean {
@ -74,16 +74,16 @@ export class PermissionsService {
return (file.isUnderReview || file.isUnderApproval) && (this.isFileReviewer(file) || this.isApprover(dossier));
}
canSetUnderReview(file: File): boolean {
return file?.isUnderApproval && this.isApprover(this._getDossier(file));
canSetUnderReview(file: File, dossier: Dossier = this._dossiersService.activeDossier): boolean {
return file?.isUnderApproval && this.isApprover(dossier);
}
isReadyForApproval(file: File): boolean {
return this.canSetUnderReview(file);
isReadyForApproval(file: File, dossier: Dossier = this._dossiersService.activeDossier): boolean {
return this.canSetUnderReview(file, dossier);
}
canSetUnderApproval(file: File): boolean {
return file?.isUnderReview && this.isReviewerOrApprover(file);
canSetUnderApproval(file: File, dossier: Dossier = this._dossiersService.activeDossier): boolean {
return file?.isUnderReview && this.isReviewerOrApprover(file, dossier);
}
isOwner(dossier: Dossier, user = this._userService.currentUser): boolean {