Edit project team members
This commit is contained in:
parent
dbf0d6cc8b
commit
b845d0e520
@ -18,15 +18,6 @@
|
||||
>
|
||||
</redaction-circle-button>
|
||||
|
||||
<redaction-circle-button
|
||||
(action)="openAssignProjectOwnerDialog($event, project)"
|
||||
*ngIf="permissionsService.isManager()"
|
||||
icon="red:assign"
|
||||
tooltip="project-listing.assign.action"
|
||||
type="dark-bg"
|
||||
>
|
||||
</redaction-circle-button>
|
||||
|
||||
<redaction-circle-button
|
||||
(action)="reanalyseProject($event, project)"
|
||||
*ngIf="permissionsService.displayReanalyseBtn(project)"
|
||||
|
||||
@ -25,12 +25,6 @@ export class ProjectListingActionsComponent {
|
||||
private readonly _fileManagementControllerService: FileManagementControllerService
|
||||
) {}
|
||||
|
||||
openAssignProjectOwnerDialog($event: MouseEvent, project: ProjectWrapper) {
|
||||
this._dialogService.openAssignProjectMembersAndOwnerDialog($event, project, (pw: ProjectWrapper) => {
|
||||
this.actionPerformed.emit(pw);
|
||||
});
|
||||
}
|
||||
|
||||
openDeleteProjectDialog($event: MouseEvent, project: ProjectWrapper) {
|
||||
this._dialogService.openDeleteProjectDialog($event, project, () => {
|
||||
this.actionPerformed.emit();
|
||||
|
||||
@ -0,0 +1,57 @@
|
||||
<form (submit)="saveMembers()" [formGroup]="teamForm">
|
||||
<div class="red-input-group w-300">
|
||||
<mat-form-field floatLabel="always">
|
||||
<mat-label>{{ 'assign-project-owner.dialog.single-user' | translate }}</mat-label>
|
||||
<mat-select formControlName="owner">
|
||||
<mat-option *ngFor="let userId of ownersSelectOptions" [value]="userId">
|
||||
{{ userService.getNameForId(userId) }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div [translate]="'assign-project-owner.dialog.approvers'" class="all-caps-label mt-16"></div>
|
||||
<redaction-team-members
|
||||
(remove)="toggleSelected($event)"
|
||||
[canAdd]="false"
|
||||
[canRemove]="true"
|
||||
[largeSpacing]="true"
|
||||
[memberIds]="selectedApproversList"
|
||||
[perLine]="13"
|
||||
[unremovableMembers]="[selectedOwnerId]"
|
||||
></redaction-team-members>
|
||||
|
||||
<pre *ngIf="selectedApproversList.length === 0" [innerHTML]="'assign-project-owner.dialog.no-approvers' | translate" class="info"></pre>
|
||||
|
||||
<div [translate]="'assign-project-owner.dialog.reviewers'" class="all-caps-label mt-16"></div>
|
||||
<redaction-team-members
|
||||
(remove)="toggleSelected($event)"
|
||||
[canAdd]="false"
|
||||
[canRemove]="true"
|
||||
[largeSpacing]="true"
|
||||
[memberIds]="selectedReviewersList"
|
||||
[perLine]="13"
|
||||
[unremovableMembers]="[selectedOwnerId]"
|
||||
></redaction-team-members>
|
||||
|
||||
<pre *ngIf="selectedReviewersList.length === 0" [innerHTML]="'assign-project-owner.dialog.no-reviewers' | translate" class="info"></pre>
|
||||
|
||||
<redaction-search-input
|
||||
[form]="searchForm"
|
||||
[placeholder]="'assign-project-owner.dialog.search' | translate"
|
||||
[width]="560"
|
||||
class="search-container"
|
||||
></redaction-search-input>
|
||||
|
||||
<div class="members-list">
|
||||
<div (click)="!isOwner(userId) && toggleSelected(userId)" *ngFor="let userId of membersSelectOptions" [class.selected]="isMemberSelected(userId)">
|
||||
<redaction-initials-avatar [userId]="userId" [withName]="true" size="large"></redaction-initials-avatar>
|
||||
<div class="actions">
|
||||
<div (click)="toggleApprover(userId, $event)" *ngIf="!isOwner(userId)" class="make-approver">
|
||||
<redaction-round-checkbox [active]="isApprover(userId)" class="mr-8"></redaction-round-checkbox>
|
||||
<span [translate]="'assign-project-owner.dialog.make-approver'"></span>
|
||||
</div>
|
||||
<mat-icon *ngIf="!isOwner(userId)" svgIcon="red:check"></mat-icon>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@ -1,9 +1,5 @@
|
||||
@import '../../../../../assets/styles/red-mixins';
|
||||
|
||||
.no-padding-bottom {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.search-container {
|
||||
margin-top: 16px;
|
||||
}
|
||||
@ -14,8 +10,6 @@ redaction-team-members {
|
||||
}
|
||||
|
||||
.members-list {
|
||||
max-height: 220px;
|
||||
height: 220px;
|
||||
margin-top: 16px;
|
||||
overflow-y: hidden;
|
||||
width: 587px;
|
||||
@ -58,6 +52,7 @@ redaction-team-members {
|
||||
&.selected,
|
||||
&:hover {
|
||||
background-color: $grey-2;
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
}
|
||||
@ -1,115 +1,102 @@
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { ProjectControllerService, StatusControllerService } from '@redaction/red-ui-http';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||
import { Project, ProjectControllerService, StatusControllerService } from '@redaction/red-ui-http';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { NotificationService, NotificationType } from '@services/notification.service';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
|
||||
import { ProjectWrapper } from '@state/model/project.wrapper';
|
||||
|
||||
class DialogData {
|
||||
project?: ProjectWrapper;
|
||||
files?: FileStatusWrapper[];
|
||||
ignoreChanged?: boolean;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-project-details-dialog',
|
||||
templateUrl: './assign-owner-dialog.component.html',
|
||||
styleUrls: ['./assign-owner-dialog.component.scss']
|
||||
selector: 'redaction-team-members-manager',
|
||||
templateUrl: './team-members-manager.component.html',
|
||||
styleUrls: ['./team-members-manager.component.scss']
|
||||
})
|
||||
export class AssignOwnerDialogComponent {
|
||||
usersForm: FormGroup;
|
||||
export class TeamMembersManagerComponent implements OnInit {
|
||||
teamForm: FormGroup;
|
||||
searchForm: FormGroup;
|
||||
|
||||
@Input() projectWrapper: ProjectWrapper;
|
||||
|
||||
@Output() save = new EventEmitter<Project>();
|
||||
|
||||
constructor(
|
||||
readonly userService: UserService,
|
||||
private readonly _projectControllerService: ProjectControllerService,
|
||||
private readonly _notificationService: NotificationService,
|
||||
private readonly _formBuilder: FormBuilder,
|
||||
private readonly _statusControllerService: StatusControllerService,
|
||||
private readonly _appStateService: AppStateService,
|
||||
public dialogRef: MatDialogRef<AssignOwnerDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: DialogData
|
||||
) {
|
||||
this._loadData();
|
||||
}
|
||||
private readonly _appStateService: AppStateService
|
||||
) {}
|
||||
|
||||
get selectedSingleUser(): string {
|
||||
return this.usersForm.get('singleUser').value;
|
||||
get selectedOwnerId(): string {
|
||||
return this.teamForm.get('owner').value;
|
||||
}
|
||||
|
||||
get selectedApproversList(): string[] {
|
||||
return this.usersForm.get('approvers').value;
|
||||
return this.teamForm.get('approvers').value;
|
||||
}
|
||||
|
||||
get selectedReviewersList(): string[] {
|
||||
return this.selectedUsersList.filter((m) => this.selectedApproversList.indexOf(m) === -1);
|
||||
return this.selectedMembersList.filter((m) => this.selectedApproversList.indexOf(m) === -1);
|
||||
}
|
||||
|
||||
get selectedUsersList(): string[] {
|
||||
return this.usersForm.get('members').value;
|
||||
get selectedMembersList(): string[] {
|
||||
return this.teamForm.get('members').value;
|
||||
}
|
||||
|
||||
get singleUsersSelectOptions() {
|
||||
get ownersSelectOptions() {
|
||||
return this.userService.managerUsers.map((m) => m.userId);
|
||||
}
|
||||
|
||||
get multiUsersSelectOptions() {
|
||||
get membersSelectOptions() {
|
||||
const searchQuery = this.searchForm.get('query').value;
|
||||
return this.userService.eligibleUsers
|
||||
.filter((user) => this.userService.getNameForId(user.userId).toLowerCase().includes(searchQuery.toLowerCase()))
|
||||
.filter((user) => this.selectedSingleUser !== user.userId)
|
||||
.filter((user) => this.selectedOwnerId !== user.userId)
|
||||
.map((user) => user.userId);
|
||||
}
|
||||
|
||||
get valid(): boolean {
|
||||
return this.teamForm.valid;
|
||||
}
|
||||
|
||||
get changed(): boolean {
|
||||
if (this.data.ignoreChanged) {
|
||||
if (this.projectWrapper.ownerId !== this.selectedOwnerId) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.data.project.ownerId !== this.selectedSingleUser) {
|
||||
return true;
|
||||
}
|
||||
const initialMembers = this.projectWrapper.memberIds.sort();
|
||||
const currentMembers = this.selectedMembersList.sort();
|
||||
|
||||
const initialMembers = this.data.project.memberIds.sort();
|
||||
const currentMembers = this.selectedUsersList.sort();
|
||||
|
||||
const initialApprovers = this.data.project.approverIds.sort();
|
||||
const initialApprovers = this.projectWrapper.approverIds.sort();
|
||||
const currentApprovers = this.selectedApproversList.sort();
|
||||
|
||||
if (this._compareLists(initialMembers, currentMembers) || this._compareLists(initialApprovers, currentApprovers)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return this._compareLists(initialMembers, currentMembers) || this._compareLists(initialApprovers, currentApprovers);
|
||||
}
|
||||
|
||||
isOwner(userId: string): boolean {
|
||||
return userId === this.selectedSingleUser;
|
||||
return userId === this.selectedOwnerId;
|
||||
}
|
||||
|
||||
async saveUsers() {
|
||||
async saveMembers() {
|
||||
let result;
|
||||
try {
|
||||
const ownerId = this.selectedSingleUser;
|
||||
const memberIds = this.selectedUsersList;
|
||||
const ownerId = this.selectedOwnerId;
|
||||
const memberIds = this.selectedMembersList;
|
||||
const approverIds = this.selectedApproversList;
|
||||
const pw = Object.assign({}, this.data.project);
|
||||
const pw = Object.assign({}, this.projectWrapper);
|
||||
pw.project.memberIds = memberIds;
|
||||
pw.project.approverIds = approverIds;
|
||||
pw.project.ownerId = ownerId;
|
||||
result = await this._appStateService.addOrUpdateProject(pw.project);
|
||||
this.save.emit(result);
|
||||
} catch (error) {
|
||||
this._notificationService.showToastNotification('Failed: ' + error.error ? error.error.message : error, null, NotificationType.ERROR);
|
||||
}
|
||||
|
||||
this.dialogRef.close(result);
|
||||
}
|
||||
|
||||
isMemberSelected(userId: string): boolean {
|
||||
return this.selectedUsersList.indexOf(userId) !== -1;
|
||||
return this.selectedMembersList.indexOf(userId) !== -1;
|
||||
}
|
||||
|
||||
isApprover(userId: string): boolean {
|
||||
@ -135,29 +122,36 @@ export class AssignOwnerDialogComponent {
|
||||
|
||||
toggleSelected(userId: string) {
|
||||
if (this.isMemberSelected(userId)) {
|
||||
this.selectedUsersList.splice(this.selectedUsersList.indexOf(userId), 1);
|
||||
this.selectedMembersList.splice(this.selectedMembersList.indexOf(userId), 1);
|
||||
|
||||
if (this.isApprover(userId)) {
|
||||
this.selectedApproversList.splice(this.selectedApproversList.indexOf(userId), 1);
|
||||
}
|
||||
} else {
|
||||
this.selectedUsersList.push(userId);
|
||||
this.selectedMembersList.push(userId);
|
||||
}
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
this._loadData();
|
||||
}
|
||||
|
||||
revert() {
|
||||
this._loadData();
|
||||
}
|
||||
|
||||
private _loadData() {
|
||||
const project = this.data.project;
|
||||
this.usersForm = this._formBuilder.group({
|
||||
singleUser: [project?.ownerId, Validators.required],
|
||||
approvers: [[...project?.approverIds]],
|
||||
members: [[...project?.memberIds]]
|
||||
this.teamForm = this._formBuilder.group({
|
||||
owner: [this.projectWrapper?.ownerId, Validators.required],
|
||||
approvers: [[...this.projectWrapper?.approverIds]],
|
||||
members: [[...this.projectWrapper?.memberIds]]
|
||||
});
|
||||
this.searchForm = this._formBuilder.group({
|
||||
query: ['']
|
||||
});
|
||||
this.usersForm.get('singleUser').valueChanges.subscribe((singleUser) => {
|
||||
if (!this.isApprover(singleUser)) {
|
||||
this.toggleApprover(singleUser);
|
||||
this.teamForm.get('owner').valueChanges.subscribe((owner) => {
|
||||
if (!this.isApprover(owner)) {
|
||||
this.toggleApprover(owner);
|
||||
}
|
||||
// If it is an approver, it is already a member, no need to check
|
||||
});
|
||||
@ -1,77 +0,0 @@
|
||||
<section class="dialog">
|
||||
<div [translate]="'assign-project-owner.dialog.title'" class="dialog-header heading-l"></div>
|
||||
|
||||
<form (submit)="saveUsers()" [formGroup]="usersForm">
|
||||
<div class="dialog-content no-padding-bottom">
|
||||
<div class="red-input-group w-300">
|
||||
<mat-form-field floatLabel="always">
|
||||
<mat-label>{{ 'assign-project-owner.dialog.single-user' | translate }}</mat-label>
|
||||
<mat-select formControlName="singleUser">
|
||||
<mat-option *ngFor="let userId of singleUsersSelectOptions" [value]="userId">
|
||||
{{ userService.getNameForId(userId) }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div [translate]="'assign-project-owner.dialog.approvers'" class="all-caps-label mt-16"></div>
|
||||
<redaction-team-members
|
||||
(remove)="toggleSelected($event)"
|
||||
[canAdd]="false"
|
||||
[canRemove]="true"
|
||||
[largeSpacing]="true"
|
||||
[memberIds]="selectedApproversList"
|
||||
[perLine]="13"
|
||||
[unremovableMembers]="[selectedSingleUser]"
|
||||
></redaction-team-members>
|
||||
|
||||
<pre *ngIf="selectedApproversList.length === 0" [innerHTML]="'assign-project-owner.dialog.no-approvers' | translate" class="info"></pre>
|
||||
|
||||
<div [translate]="'assign-project-owner.dialog.reviewers'" class="all-caps-label mt-16"></div>
|
||||
<redaction-team-members
|
||||
(remove)="toggleSelected($event)"
|
||||
[canAdd]="false"
|
||||
[canRemove]="true"
|
||||
[largeSpacing]="true"
|
||||
[memberIds]="selectedReviewersList"
|
||||
[perLine]="13"
|
||||
[unremovableMembers]="[selectedSingleUser]"
|
||||
></redaction-team-members>
|
||||
|
||||
<pre *ngIf="selectedReviewersList.length === 0" [innerHTML]="'assign-project-owner.dialog.no-reviewers' | translate" class="info"></pre>
|
||||
|
||||
<redaction-search-input
|
||||
[form]="searchForm"
|
||||
[placeholder]="'assign-project-owner.dialog.search' | translate"
|
||||
[width]="560"
|
||||
class="search-container"
|
||||
></redaction-search-input>
|
||||
|
||||
<div class="members-list">
|
||||
<div
|
||||
(click)="!isOwner(userId) && toggleSelected(userId)"
|
||||
*ngFor="let userId of multiUsersSelectOptions"
|
||||
[class.selected]="isMemberSelected(userId)"
|
||||
>
|
||||
<redaction-initials-avatar [userId]="userId" [withName]="true" size="large"></redaction-initials-avatar>
|
||||
<div class="actions">
|
||||
<div *ngIf="!isOwner(userId)" (click)="toggleApprover(userId, $event)" class="make-approver">
|
||||
<redaction-round-checkbox [active]="isApprover(userId)" class="mr-8"></redaction-round-checkbox>
|
||||
<span [translate]="'assign-project-owner.dialog.make-approver'"></span>
|
||||
</div>
|
||||
<mat-icon *ngIf="!isOwner(userId)" svgIcon="red:check"></mat-icon>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dialog-actions">
|
||||
<button [disabled]="!usersForm.valid || !changed" color="primary" mat-flat-button type="submit">
|
||||
{{ 'assign-project-owner.dialog.save' | translate }}
|
||||
</button>
|
||||
|
||||
<div [translate]="'assign-project-owner.dialog.cancel'" class="all-caps-label pointer cancel" mat-dialog-close></div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<redaction-circle-button class="dialog-close" icon="red:close" mat-dialog-close></redaction-circle-button>
|
||||
</section>
|
||||
@ -1,70 +0,0 @@
|
||||
@import '../../../../../assets/styles/red-mixins';
|
||||
|
||||
.no-padding-bottom {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.search-container {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
redaction-team-members {
|
||||
margin-top: -4px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.members-list {
|
||||
max-height: 220px;
|
||||
height: 220px;
|
||||
margin-top: 16px;
|
||||
overflow-y: hidden;
|
||||
width: 587px;
|
||||
|
||||
&:hover {
|
||||
overflow-y: auto;
|
||||
@include scroll-bar;
|
||||
}
|
||||
|
||||
> div {
|
||||
margin-bottom: 2px;
|
||||
padding: 3px 5px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
transition: background-color ease-in-out 0.1s;
|
||||
width: 560px;
|
||||
box-sizing: border-box;
|
||||
|
||||
.make-approver {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: none;
|
||||
position: absolute;
|
||||
right: 13px;
|
||||
top: 0;
|
||||
height: 38px;
|
||||
align-items: center;
|
||||
|
||||
mat-icon {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
margin-left: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
&.selected,
|
||||
&:hover {
|
||||
background-color: $grey-2;
|
||||
.actions {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.info {
|
||||
margin-top: 4px;
|
||||
}
|
||||
@ -30,7 +30,7 @@ export class EditProjectDictionaryComponent implements EditProjectSectionInterfa
|
||||
}
|
||||
|
||||
get disabled() {
|
||||
return !this._permissionsService.isAdmin();
|
||||
return !this.canEdit;
|
||||
}
|
||||
|
||||
save() {
|
||||
|
||||
@ -13,7 +13,16 @@
|
||||
</redaction-side-nav>
|
||||
<div>
|
||||
<div class="content">
|
||||
<div [translate]="'edit-project-dialog.nav-items.' + (activeNavItem.title || activeNavItem.key)" class="heading"></div>
|
||||
<div class="heading">
|
||||
{{ 'edit-project-dialog.nav-items.' + (activeNavItem.title || activeNavItem.key) | translate }}
|
||||
|
||||
<div *ngIf="activeNav === 'dossier-dictionary'" class="small-label stats-subtitle">
|
||||
<div>
|
||||
<mat-icon svgIcon="red:entries"></mat-icon>
|
||||
{{ 'edit-project-dialog.dictionary.entries' | translate: { length: (projectWrapper.type?.entries || []).length } }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<redaction-edit-project-general-info
|
||||
(updateProject)="updatedProject($event)"
|
||||
@ -33,6 +42,9 @@
|
||||
[projectWrapper]="projectWrapper"
|
||||
>
|
||||
</redaction-edit-project-dictionary>
|
||||
|
||||
<redaction-edit-project-team-members (updateProject)="updatedProject($event)" *ngIf="activeNav === 'members'" [projectWrapper]="projectWrapper">
|
||||
</redaction-edit-project-team-members>
|
||||
</div>
|
||||
|
||||
<div class="dialog-actions">
|
||||
|
||||
@ -27,5 +27,9 @@
|
||||
|
||||
redaction-edit-project-dictionary {
|
||||
display: block;
|
||||
height: calc(100% - 44px);
|
||||
height: calc(100% - 74px);
|
||||
}
|
||||
|
||||
.stats-subtitle {
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@ import { EditProjectSectionInterface } from './edit-project-section.interface';
|
||||
import { NotificationService, NotificationType } from '../../../../services/notification.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { EditProjectDictionaryComponent } from './dictionary/edit-project-dictionary.component';
|
||||
import { EditProjectTeamMembersComponent } from './team-members/edit-project-team-members.component';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-edit-project-dialog',
|
||||
@ -19,9 +20,9 @@ export class EditProjectDialogComponent {
|
||||
navItems: { key: string; title?: string }[] = [
|
||||
{ key: 'dossier-info', title: 'general-info' },
|
||||
{ key: 'download-package', title: 'choose-download' },
|
||||
{ key: 'dossier-dictionary', title: 'dossier-dictionary' }
|
||||
{ key: 'dossier-dictionary', title: 'dossier-dictionary' },
|
||||
{ key: 'members', title: 'team-members' }
|
||||
// TODO:
|
||||
// { key: 'members' },
|
||||
// { key: 'project-attributes' },
|
||||
// { key: 'report-attributes' }
|
||||
];
|
||||
@ -31,6 +32,7 @@ export class EditProjectDialogComponent {
|
||||
@ViewChild(EditProjectGeneralInfoComponent) generalInfoComponent: EditProjectGeneralInfoComponent;
|
||||
@ViewChild(EditProjectDownloadPackageComponent) downloadPackageComponent: EditProjectDownloadPackageComponent;
|
||||
@ViewChild(EditProjectDictionaryComponent) dictionaryComponent: EditProjectDictionaryComponent;
|
||||
@ViewChild(EditProjectTeamMembersComponent) membersComponent: EditProjectTeamMembersComponent;
|
||||
|
||||
constructor(
|
||||
private readonly _appStateService: AppStateService,
|
||||
@ -52,7 +54,8 @@ export class EditProjectDialogComponent {
|
||||
return {
|
||||
'dossier-info': this.generalInfoComponent,
|
||||
'download-package': this.downloadPackageComponent,
|
||||
'dossier-dictionary': this.dictionaryComponent
|
||||
'dossier-dictionary': this.dictionaryComponent,
|
||||
members: this.membersComponent
|
||||
}[this.activeNav];
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1 @@
|
||||
<redaction-team-members-manager (save)="updatedProject($event)" [projectWrapper]="projectWrapper"></redaction-team-members-manager>
|
||||
@ -0,0 +1,40 @@
|
||||
import { Component, EventEmitter, Input, Output, ViewChild } from '@angular/core';
|
||||
import { AppStateService } from '../../../../../state/app-state.service';
|
||||
import { ProjectWrapper } from '../../../../../state/model/project.wrapper';
|
||||
import { EditProjectSectionInterface } from '../edit-project-section.interface';
|
||||
import { PermissionsService } from '../../../../../services/permissions.service';
|
||||
import { TeamMembersManagerComponent } from '../../../components/team-members-manager/team-members-manager.component';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-edit-project-team-members',
|
||||
templateUrl: './edit-project-team-members.component.html',
|
||||
styleUrls: ['./edit-project-team-members.component.scss']
|
||||
})
|
||||
export class EditProjectTeamMembersComponent implements EditProjectSectionInterface {
|
||||
@Input() projectWrapper: ProjectWrapper;
|
||||
@Output() updateProject = new EventEmitter<any>();
|
||||
|
||||
@ViewChild(TeamMembersManagerComponent) managerComponent: TeamMembersManagerComponent;
|
||||
|
||||
constructor(private readonly _appStateService: AppStateService, private readonly _permissionsService: PermissionsService) {}
|
||||
|
||||
get changed() {
|
||||
return this.managerComponent.changed;
|
||||
}
|
||||
|
||||
get disabled() {
|
||||
return !this._permissionsService.isManager();
|
||||
}
|
||||
|
||||
async save() {
|
||||
await this.managerComponent.saveMembers();
|
||||
}
|
||||
|
||||
updatedProject($event) {
|
||||
this.updateProject.emit($event);
|
||||
}
|
||||
|
||||
revert() {
|
||||
this.managerComponent.revert();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
<section class="dialog">
|
||||
<div [translate]="'assign-project-owner.dialog.title'" class="dialog-header heading-l"></div>
|
||||
|
||||
<div class="dialog-content no-padding-bottom">
|
||||
<redaction-team-members-manager (save)="save($event)" [projectWrapper]="data.projectWrapper"></redaction-team-members-manager>
|
||||
</div>
|
||||
<div class="dialog-actions">
|
||||
<button (click)="managerComponent.saveMembers()" [disabled]="!managerComponent.valid || !managerComponent.changed" color="primary" mat-flat-button>
|
||||
{{ 'assign-project-owner.dialog.save' | translate }}
|
||||
</button>
|
||||
|
||||
<div [translate]="'assign-project-owner.dialog.cancel'" class="all-caps-label pointer cancel" mat-dialog-close></div>
|
||||
</div>
|
||||
|
||||
<redaction-circle-button class="dialog-close" icon="red:close" mat-dialog-close></redaction-circle-button>
|
||||
</section>
|
||||
@ -0,0 +1,8 @@
|
||||
.no-padding-bottom {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
::ng-deep redaction-team-members-manager .members-list {
|
||||
max-height: 220px;
|
||||
height: 220px;
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
import { Component, Inject, ViewChild } from '@angular/core';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { NotificationService } from '@services/notification.service';
|
||||
import { ProjectWrapper } from '@state/model/project.wrapper';
|
||||
import { TeamMembersManagerComponent } from '../../components/team-members-manager/team-members-manager.component';
|
||||
|
||||
class DialogData {
|
||||
projectWrapper?: ProjectWrapper;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-team-members-dialog',
|
||||
templateUrl: './team-members-dialog.component.html',
|
||||
styleUrls: ['./team-members-dialog.component.scss']
|
||||
})
|
||||
export class TeamMembersDialogComponent {
|
||||
@ViewChild(TeamMembersManagerComponent, { static: true }) managerComponent: TeamMembersManagerComponent;
|
||||
|
||||
constructor(
|
||||
private readonly _notificationService: NotificationService,
|
||||
private readonly _appStateService: AppStateService,
|
||||
public dialogRef: MatDialogRef<TeamMembersDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: DialogData
|
||||
) {}
|
||||
|
||||
async save(result) {
|
||||
this.dialogRef.close(result);
|
||||
}
|
||||
}
|
||||
@ -4,7 +4,6 @@ import { ProjectListingScreenComponent } from './screens/project-listing-screen/
|
||||
import { ProjectOverviewScreenComponent } from './screens/project-overview-screen/project-overview-screen.component';
|
||||
import { FilePreviewScreenComponent } from './screens/file-preview-screen/file-preview-screen.component';
|
||||
import { AddProjectDialogComponent } from './dialogs/add-project-dialog/add-project-dialog.component';
|
||||
import { AssignOwnerDialogComponent } from './dialogs/assign-owner-dialog/assign-owner-dialog.component';
|
||||
import { AssignReviewerApproverDialogComponent } from './dialogs/assign-reviewer-approver-dialog/assign-reviewer-approver-dialog.component';
|
||||
import { ManualAnnotationDialogComponent } from './dialogs/manual-redaction-dialog/manual-annotation-dialog.component';
|
||||
import { ForceRedactionDialogComponent } from './dialogs/force-redaction-dialog/force-redaction-dialog.component';
|
||||
@ -42,13 +41,16 @@ import { EditProjectGeneralInfoComponent } from './dialogs/edit-project-dialog/g
|
||||
import { EditProjectDownloadPackageComponent } from './dialogs/edit-project-dialog/download-package/edit-project-download-package.component';
|
||||
import { UserPreferenceControllerService } from '@redaction/red-ui-http';
|
||||
import { EditProjectDictionaryComponent } from './dialogs/edit-project-dialog/dictionary/edit-project-dictionary.component';
|
||||
import { EditProjectTeamMembersComponent } from './dialogs/edit-project-dialog/team-members/edit-project-team-members.component';
|
||||
import { TeamMembersManagerComponent } from './components/team-members-manager/team-members-manager.component';
|
||||
import { TeamMembersDialogComponent } from './dialogs/team-members-dialog/team-members-dialog.component';
|
||||
|
||||
const screens = [ProjectListingScreenComponent, ProjectOverviewScreenComponent, FilePreviewScreenComponent];
|
||||
|
||||
const dialogs = [
|
||||
AddProjectDialogComponent,
|
||||
EditProjectDialogComponent,
|
||||
AssignOwnerDialogComponent,
|
||||
TeamMembersDialogComponent,
|
||||
ManualAnnotationDialogComponent,
|
||||
ForceRedactionDialogComponent,
|
||||
RemoveAnnotationsDialogComponent,
|
||||
@ -76,6 +78,8 @@ const components = [
|
||||
EditProjectGeneralInfoComponent,
|
||||
EditProjectDownloadPackageComponent,
|
||||
EditProjectDictionaryComponent,
|
||||
EditProjectTeamMembersComponent,
|
||||
TeamMembersManagerComponent,
|
||||
|
||||
...screens,
|
||||
...dialogs
|
||||
|
||||
@ -177,7 +177,7 @@ export class ProjectListingScreenComponent extends BaseListingComponent<ProjectW
|
||||
}
|
||||
|
||||
openAssignProjectOwnerDialog($event: MouseEvent, project: ProjectWrapper) {
|
||||
this._dialogService.openAssignProjectMembersAndOwnerDialog($event, project);
|
||||
this._dialogService.openAssignTeamMembersDialog($event, project);
|
||||
}
|
||||
|
||||
actionPerformed() {
|
||||
|
||||
@ -46,13 +46,6 @@
|
||||
<!-- tooltip="project-overview.header-actions.delete"-->
|
||||
<!-- tooltipPosition="below"-->
|
||||
<!-- ></redaction-circle-button>-->
|
||||
<redaction-circle-button
|
||||
(action)="openAssignProjectMembersDialog()"
|
||||
*ngIf="permissionsService.isManager()"
|
||||
icon="red:assign"
|
||||
tooltip="project-overview.header-actions.assign"
|
||||
tooltipPosition="below"
|
||||
></redaction-circle-button>
|
||||
|
||||
<redaction-file-download-btn [file]="allEntities" [project]="activeProject" tooltipPosition="below"></redaction-file-download-btn>
|
||||
|
||||
@ -170,8 +163,8 @@
|
||||
<div
|
||||
*cdkVirtualFor="let fileStatus of displayedEntities | sortBy: sortingOption.order:sortingOption.column; trackBy: fileId"
|
||||
[class.disabled]="fileStatus.isExcluded"
|
||||
[class.pointer]="permissionsService.canOpenFile(fileStatus)"
|
||||
[class.last-opened]="isLastOpenedFile(fileStatus)"
|
||||
[class.pointer]="permissionsService.canOpenFile(fileStatus)"
|
||||
[routerLink]="fileLink(fileStatus)"
|
||||
class="table-item"
|
||||
>
|
||||
@ -265,8 +258,8 @@
|
||||
<redaction-project-details
|
||||
#projectDetailsComponent
|
||||
(filtersChanged)="filtersChanged($event)"
|
||||
(openDossierDictionaryDialog)="openDossierDictionaryDialog()"
|
||||
(openAssignProjectMembersDialog)="openAssignProjectMembersDialog()"
|
||||
(openDossierDictionaryDialog)="openDossierDictionaryDialog()"
|
||||
(toggleCollapse)="toggleCollapsedDetails()"
|
||||
[filters]="detailsContainerFilters"
|
||||
></redaction-project-details>
|
||||
|
||||
@ -241,7 +241,7 @@ export class ProjectOverviewScreenComponent extends BaseListingComponent<FileSta
|
||||
}
|
||||
|
||||
openAssignProjectMembersDialog(): void {
|
||||
this._dialogService.openAssignProjectMembersAndOwnerDialog(null, this.activeProject, () => {
|
||||
this._dialogService.openAssignTeamMembersDialog(null, this.activeProject, () => {
|
||||
this.reloadProjects();
|
||||
});
|
||||
}
|
||||
|
||||
@ -20,11 +20,11 @@ import { ManualRedactionEntryWrapper } from '@models/file/manual-redaction-entry
|
||||
import { ManualAnnotationService } from './manual-annotation.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { ManualAnnotationDialogComponent } from '../dialogs/manual-redaction-dialog/manual-annotation-dialog.component';
|
||||
import { AssignOwnerDialogComponent } from '../dialogs/assign-owner-dialog/assign-owner-dialog.component';
|
||||
import { DossierDictionaryDialogComponent } from '../dialogs/dossier-dictionary-dialog/dossier-dictionary-dialog.component';
|
||||
import { EditProjectDialogComponent } from '../dialogs/edit-project-dialog/edit-project-dialog.component';
|
||||
import { FileStatusWrapper } from '../../../models/file/file-status.wrapper';
|
||||
import { AssignReviewerApproverDialogComponent } from '../dialogs/assign-reviewer-approver-dialog/assign-reviewer-approver-dialog.component';
|
||||
import { TeamMembersDialogComponent } from '../dialogs/team-members-dialog/team-members-dialog.component';
|
||||
|
||||
const dialogConfig = {
|
||||
width: '662px',
|
||||
@ -175,11 +175,11 @@ export class ProjectsDialogService {
|
||||
return ref;
|
||||
}
|
||||
|
||||
openAssignProjectMembersAndOwnerDialog($event: MouseEvent, project: ProjectWrapper, cb?: Function): MatDialogRef<AssignOwnerDialogComponent> {
|
||||
openAssignTeamMembersDialog($event: MouseEvent, projectWrapper: ProjectWrapper, cb?: Function): MatDialogRef<TeamMembersDialogComponent> {
|
||||
$event?.stopPropagation();
|
||||
const ref = this._dialog.open(AssignOwnerDialogComponent, {
|
||||
const ref = this._dialog.open(TeamMembersDialogComponent, {
|
||||
...dialogConfig,
|
||||
data: { project: project }
|
||||
data: { projectWrapper }
|
||||
});
|
||||
ref.afterClosed().subscribe((result) => {
|
||||
if (cb) {
|
||||
|
||||
@ -100,9 +100,6 @@
|
||||
"reanalyse": {
|
||||
"action": "Analysieren Sie das gesamte Dossier"
|
||||
},
|
||||
"assign": {
|
||||
"action": "Eigentümer zuweisen"
|
||||
},
|
||||
"download-files": {
|
||||
"action": "Laden Sie redigierte Dateien herunter"
|
||||
},
|
||||
@ -199,7 +196,6 @@
|
||||
"header-actions": {
|
||||
"edit": "Bearbeiten",
|
||||
"delete": "Löschen",
|
||||
"assign": "Eigentümer zuweisen",
|
||||
"upload-document": "Dokument hochladen",
|
||||
"download-redacted-files": "Laden Sie redigierte Dateien herunter"
|
||||
},
|
||||
|
||||
@ -100,9 +100,6 @@
|
||||
"reanalyse": {
|
||||
"action": "Analyze entire dossier"
|
||||
},
|
||||
"assign": {
|
||||
"action": "Assign Owner & Members"
|
||||
},
|
||||
"download-files": {
|
||||
"action": "Download Redacted Files"
|
||||
},
|
||||
@ -175,6 +172,8 @@
|
||||
"choose-download": "Choose what is included at download:",
|
||||
"dictionary": "Dictionary",
|
||||
"dossier-dictionary": "Dossier Dictionary",
|
||||
"members": "Members",
|
||||
"team-members": "Team Members",
|
||||
"project-attributes": "Dossier Attributes",
|
||||
"report-attributes": "Report Attributes"
|
||||
},
|
||||
@ -196,6 +195,9 @@
|
||||
"template": "Dossier Template"
|
||||
}
|
||||
},
|
||||
"dictionary": {
|
||||
"entries": "{{length}} entries"
|
||||
},
|
||||
"unsaved-changes": "You have unsaved changes. Save or revert before changing the tab.",
|
||||
"change-successful": "Project was updated."
|
||||
},
|
||||
@ -236,7 +238,6 @@
|
||||
"header-actions": {
|
||||
"edit": "Edit",
|
||||
"delete": "Delete",
|
||||
"assign": "Assign Owner & Members",
|
||||
"upload-document": "Upload Document",
|
||||
"download-redacted-files": "Download Redacted Files"
|
||||
},
|
||||
|
||||
@ -76,6 +76,7 @@ pre {
|
||||
opacity: 0.7;
|
||||
font-size: 11px;
|
||||
line-height: 14px;
|
||||
font-weight: initial;
|
||||
}
|
||||
|
||||
.link-action {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user