Assign project owner
This commit is contained in:
parent
ee037c63ac
commit
6bebc5409d
@ -55,8 +55,9 @@ import { AnnotationIconComponent } from './components/annotation-icon/annotation
|
||||
import { AuthGuard } from './auth/auth.guard';
|
||||
import { AuthErrorComponent } from './screens/auth-error/auth-error.component';
|
||||
import { RedRoleGuard } from './auth/red-role.guard';
|
||||
import { ProjectMembersDialogComponent } from './screens/project-overview-screen/project-members-dialog/project-members-dialog.component';
|
||||
import { AssignProjectMembersDialogComponent } from './screens/project-overview-screen/project-members-dialog/assign-project-members-dialog.component';
|
||||
import { MatListModule } from '@angular/material/list';
|
||||
import { AssignOwnerDialogComponent } from './components/project-members-dialog/assign-owner-dialog.component';
|
||||
|
||||
export function HttpLoaderFactory(httpClient: HttpClient) {
|
||||
return new TranslateHttpLoader(httpClient, '/assets/i18n/', '.json');
|
||||
@ -74,7 +75,8 @@ export function HttpLoaderFactory(httpClient: HttpClient) {
|
||||
PdfViewerComponent,
|
||||
FileDetailsDialogComponent,
|
||||
ProjectDetailsDialogComponent,
|
||||
ProjectMembersDialogComponent,
|
||||
AssignProjectMembersDialogComponent,
|
||||
AssignOwnerDialogComponent,
|
||||
FullPageLoadingIndicatorComponent,
|
||||
InitialsAvatarComponent,
|
||||
StatusBarComponent,
|
||||
|
||||
@ -0,0 +1,21 @@
|
||||
<section class="dialog">
|
||||
<div [translate]="'assign-' + data.type + '-owner.dialog.title.label'"
|
||||
class="dialog-header heading-l">
|
||||
</div>
|
||||
|
||||
<div class="dialog-content">
|
||||
<mat-list class="list-50vh">
|
||||
<ng-container *ngFor="let user of userService.allUsers">
|
||||
<mat-list-item class="pointer" [class.owner]="isOwner(user)"
|
||||
(click)="assignOwner(user)"
|
||||
*ngIf="userService.isManager(user)">
|
||||
{{ userService.getNameForId(user.userId) }}
|
||||
</mat-list-item>
|
||||
</ng-container>
|
||||
</mat-list>
|
||||
</div>
|
||||
|
||||
<button (click)="dialogRef.close()" class="dialog-close" mat-icon-button>
|
||||
<mat-icon svgIcon="red:close"></mat-icon>
|
||||
</button>
|
||||
</section>
|
||||
@ -0,0 +1,5 @@
|
||||
@import "../../../assets/styles/red-variables";
|
||||
|
||||
.owner {
|
||||
background-color: rgba($primary, 0.1);
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { Project, ProjectControllerService, User } from '@redaction/red-ui-http';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { AppStateService } from '../../state/app-state.service';
|
||||
import { UserService } from '../../user/user.service';
|
||||
import { NotificationService, NotificationType } from '../../notification/notification.service';
|
||||
|
||||
class DialogData {
|
||||
type: 'file' | 'project';
|
||||
projectId?: string;
|
||||
fileId?: string;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-project-details-dialog',
|
||||
templateUrl: './assign-owner-dialog.component.html',
|
||||
styleUrls: ['./assign-owner-dialog.component.scss']
|
||||
})
|
||||
export class AssignOwnerDialogComponent {
|
||||
private project: Project;
|
||||
public memberIds: string[];
|
||||
|
||||
constructor(private readonly _projectControllerService: ProjectControllerService,
|
||||
private readonly _notificationService: NotificationService,
|
||||
public readonly userService: UserService,
|
||||
private readonly _appStateService: AppStateService,
|
||||
public dialogRef: MatDialogRef<AssignOwnerDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: DialogData) {
|
||||
this._loadData();
|
||||
}
|
||||
|
||||
public isOwner(user: User) {
|
||||
return this.data.type === 'project' ? this.project.ownerId === user.userId : false;
|
||||
}
|
||||
|
||||
public assignOwner(user: User) {
|
||||
if (this.data.type === 'project') {
|
||||
this._projectControllerService.assignProjectOwner(this.project.projectId, user.userId).subscribe(() => {
|
||||
this._notificationService.showToastNotification('Successfully assigned ' + this.userService.getNameForId(user.userId) + ' to project: ' + this.project.projectName);
|
||||
}, error => {
|
||||
this._notificationService.showToastNotification('Failed: ' + error.error.message, null, NotificationType.ERROR);
|
||||
}).add(() => this._reloadProject());
|
||||
} else if (this.data.type === 'file') {
|
||||
console.log('not implemented yet');
|
||||
}
|
||||
}
|
||||
|
||||
private _loadData() {
|
||||
if (this.data.type === 'project') {
|
||||
this.project = this._appStateService.getProjectById(this.data.projectId).project;
|
||||
}
|
||||
}
|
||||
|
||||
private _reloadProject() {
|
||||
this._appStateService.addOrUpdateProject(this.project).then(() => {
|
||||
this._loadData();
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -69,7 +69,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<redaction-initials-avatar [username]="user.name"
|
||||
<redaction-initials-avatar [username]="_userService.getNameForId(pw.project.ownerId)"
|
||||
color="lightgray-red"
|
||||
withName="true"
|
||||
></redaction-initials-avatar>
|
||||
@ -81,18 +81,18 @@
|
||||
</div>
|
||||
|
||||
<div class="action-buttons">
|
||||
<button mat-icon-button color="accent" (click)="deleteProject($event,pw.project)"
|
||||
<button mat-icon-button color="accent" (click)="openDeleteProjectDialog($event,pw.project)"
|
||||
[matTooltip]="'project-listing.delete.action.label'|translate">
|
||||
<mat-icon svgIcon="red:trash"></mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button color="accent" (click)="showDetailsDialog($event,pw)"
|
||||
<button mat-icon-button color="accent" (click)="openDetailsDialog($event,pw)"
|
||||
[matTooltip]="'project-listing.report.action.label'|translate">
|
||||
<mat-icon svgIcon="red:report"></mat-icon>
|
||||
</button>
|
||||
<!-- <button mat-icon-button (click)="editProject($event,pw.project)">-->
|
||||
<!-- <mat-icon svgIcon="red:edit"></mat-icon>-->
|
||||
<!-- </button>-->
|
||||
<button color="accent" (click)="assignProjectPeople($event,pw.project)" mat-icon-button
|
||||
<button color="accent" (click)="openAssignProjectOwnerDialog($event,pw.project)" mat-icon-button
|
||||
[matTooltip]="'project-listing.assign.action.label'|translate">
|
||||
<mat-icon svgIcon="red:assign"></mat-icon>
|
||||
</button>
|
||||
|
||||
@ -1,16 +1,17 @@
|
||||
import {Component, OnInit} from '@angular/core';
|
||||
import {Project, ProjectControllerService} from '@redaction/red-ui-http';
|
||||
import {MatDialog} from '@angular/material/dialog';
|
||||
import {AddEditProjectDialogComponent} from './add-edit-project-dialog/add-edit-project-dialog.component';
|
||||
import {ConfirmationDialogComponent} from '../../common/confirmation-dialog/confirmation-dialog.component';
|
||||
import {TranslateService} from '@ngx-translate/core';
|
||||
import {NotificationService} from '../../notification/notification.service';
|
||||
import {AppStateService, ProjectWrapper} from '../../state/app-state.service';
|
||||
import {UserService} from '../../user/user.service';
|
||||
import {ProjectDetailsDialogComponent} from '../project-overview-screen/project-details-dialog/project-details-dialog.component';
|
||||
import {DoughnutChartConfig} from '../../components/simple-doughnut-chart/simple-doughnut-chart.component';
|
||||
import {SortingOption} from '../../utils/types';
|
||||
import {groupBy} from "../../utils/functions";
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Project, ProjectControllerService } from '@redaction/red-ui-http';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { AddEditProjectDialogComponent } from './add-edit-project-dialog/add-edit-project-dialog.component';
|
||||
import { ConfirmationDialogComponent } from '../../common/confirmation-dialog/confirmation-dialog.component';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { NotificationService } from '../../notification/notification.service';
|
||||
import { AppStateService, ProjectWrapper } from '../../state/app-state.service';
|
||||
import { UserService } from '../../user/user.service';
|
||||
import { ProjectDetailsDialogComponent } from '../project-overview-screen/project-details-dialog/project-details-dialog.component';
|
||||
import { DoughnutChartConfig } from '../../components/simple-doughnut-chart/simple-doughnut-chart.component';
|
||||
import { SortingOption } from '../../utils/types';
|
||||
import { groupBy } from '../../utils/functions';
|
||||
import { AssignOwnerDialogComponent } from '../../components/project-members-dialog/assign-owner-dialog.component';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-project-listing-screen',
|
||||
@ -21,8 +22,8 @@ export class ProjectListingScreenComponent implements OnInit {
|
||||
public projectsChartData: DoughnutChartConfig [] = [];
|
||||
public documentsChartData: DoughnutChartConfig [] = [];
|
||||
public sortingOptions: SortingOption[] = [
|
||||
{label: 'project-listing.sorting.recent.label', order: 'desc', column: 'projectDate'},
|
||||
{label: 'project-listing.sorting.alphabetically.label', order: 'asc', column: 'project.projectName'}
|
||||
{ label: 'project-listing.sorting.recent.label', order: 'desc', column: 'projectDate' },
|
||||
{ label: 'project-listing.sorting.alphabetically.label', order: 'asc', column: 'project.projectName' }
|
||||
];
|
||||
public sortingOption: SortingOption = this.sortingOptions[0];
|
||||
|
||||
@ -35,25 +36,49 @@ export class ProjectListingScreenComponent implements OnInit {
|
||||
private readonly _dialog: MatDialog) {
|
||||
}
|
||||
|
||||
get user() {
|
||||
return this._userService.user;
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.appStateService.reset();
|
||||
this.projectsChartData = [
|
||||
{value: this.activeProjects, color: 'ACTIVE', label: 'active'},
|
||||
{value: this.inactiveProjects, color: 'DELETED', label: 'archived'}
|
||||
{ value: this.activeProjects, color: 'ACTIVE', label: 'active' },
|
||||
{ value: this.inactiveProjects, color: 'DELETED', label: 'archived' }
|
||||
];
|
||||
const groups = groupBy(this.appStateService.aggregatedFiles, 'status');
|
||||
this.documentsChartData = [];
|
||||
for (const key of Object.keys(groups)) {
|
||||
this.documentsChartData.push({value: groups[key].length, color: key, label: key});
|
||||
this.documentsChartData.push({ value: groups[key].length, color: key, label: key });
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
openAddProjectDialog(project?: Project): void {
|
||||
public get user() {
|
||||
return this._userService.user;
|
||||
}
|
||||
|
||||
public get totalPages() {
|
||||
return this.appStateService.totalAnalysedPages;
|
||||
}
|
||||
|
||||
public get totalPeople() {
|
||||
return this.appStateService.totalPeople;
|
||||
}
|
||||
|
||||
public get activeProjects() {
|
||||
return this.appStateService.allProjects.reduce((i, p) => i + (p.project.status === Project.StatusEnum.ACTIVE ? 1 : 0), 0);
|
||||
}
|
||||
|
||||
public get inactiveProjects() {
|
||||
return this.appStateService.allProjects.length - this.activeProjects;
|
||||
}
|
||||
|
||||
public documentCount(project: ProjectWrapper) {
|
||||
return project.files.length;
|
||||
}
|
||||
|
||||
public userCount(project: ProjectWrapper) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public openAddProjectDialog(project?: Project): void {
|
||||
this._dialog.open(AddEditProjectDialogComponent, {
|
||||
width: '400px',
|
||||
maxWidth: '90vw',
|
||||
@ -61,12 +86,7 @@ export class ProjectListingScreenComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
editProject($event: MouseEvent, project: Project) {
|
||||
$event.stopPropagation();
|
||||
this.openAddProjectDialog(project);
|
||||
}
|
||||
|
||||
deleteProject($event: MouseEvent, project: Project) {
|
||||
public openDeleteProjectDialog($event: MouseEvent, project: Project) {
|
||||
$event.stopPropagation();
|
||||
const dialogRef = this._dialog.open(ConfirmationDialogComponent, {
|
||||
width: '400px',
|
||||
@ -80,7 +100,7 @@ export class ProjectListingScreenComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
showDetailsDialog($event: MouseEvent, project: ProjectWrapper) {
|
||||
public openDetailsDialog($event: MouseEvent, project: ProjectWrapper) {
|
||||
$event.stopPropagation();
|
||||
this._dialog.open(ProjectDetailsDialogComponent, {
|
||||
width: '600px',
|
||||
@ -89,34 +109,12 @@ export class ProjectListingScreenComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
get totalPages() {
|
||||
return this.appStateService.totalAnalysedPages;
|
||||
}
|
||||
|
||||
get totalPeople(){
|
||||
return this.appStateService.totalPeople;
|
||||
}
|
||||
|
||||
documentCount(project: ProjectWrapper) {
|
||||
return project.files.length;
|
||||
}
|
||||
|
||||
userCount(project: ProjectWrapper) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
get activeProjects() {
|
||||
return this.appStateService.allProjects.reduce((i, p) => i + (p.project.status === Project.StatusEnum.ACTIVE ? 1 : 0), 0);
|
||||
}
|
||||
|
||||
get inactiveProjects() {
|
||||
return this.appStateService.allProjects.length - this.activeProjects;
|
||||
}
|
||||
|
||||
assignProjectPeople($event: MouseEvent, project: Project) {
|
||||
public openAssignProjectOwnerDialog($event: MouseEvent, project: Project) {
|
||||
$event.stopPropagation();
|
||||
this._projectControllerService.assignProjectOwner(project.projectId, this._userService.user.id).subscribe(() => {
|
||||
this._notificationService.showToastNotification("Successfully assigned " + this.user.name + " to project: " + project.projectName);
|
||||
})
|
||||
this._dialog.open(AssignOwnerDialogComponent, {
|
||||
width: '400px',
|
||||
maxWidth: '90vw',
|
||||
data: { type: 'project', projectId: project.projectId }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,10 +5,12 @@
|
||||
</div>
|
||||
|
||||
<div class="dialog-content">
|
||||
<mat-selection-list [(ngModel)]="memberIds" (selectionChange)="selectionChange($event)" color="primary">
|
||||
<mat-selection-list class="list-50vh" color="primary"
|
||||
[(ngModel)]="memberIds"
|
||||
(selectionChange)="selectionChange($event)">
|
||||
<ng-container *ngFor="let user of userService.allUsers">
|
||||
<mat-list-option *ngIf="userService.isManager(user) || userService.isUser(user)" [value]="user.userId" checkboxPosition="before">
|
||||
<p matLine>{{ userService.getNameForId(user.userId) }}</p>
|
||||
{{ userService.getNameForId(user.userId) }}
|
||||
</mat-list-option>
|
||||
</ng-container>
|
||||
</mat-selection-list>
|
||||
@ -8,10 +8,10 @@ import { NotificationService, NotificationType } from '../../../notification/not
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-project-details-dialog',
|
||||
templateUrl: './project-members-dialog.component.html',
|
||||
styleUrls: ['./project-members-dialog.component.scss']
|
||||
templateUrl: './assign-project-members-dialog.component.html',
|
||||
styleUrls: ['./assign-project-members-dialog.component.scss']
|
||||
})
|
||||
export class ProjectMembersDialogComponent {
|
||||
export class AssignProjectMembersDialogComponent {
|
||||
private _project: Project;
|
||||
public memberIds: string[];
|
||||
|
||||
@ -19,8 +19,7 @@ export class ProjectMembersDialogComponent {
|
||||
private readonly _notificationService: NotificationService,
|
||||
public readonly userService: UserService,
|
||||
private readonly _appStateService: AppStateService,
|
||||
public dialogRef: MatDialogRef<ProjectMembersDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public projectDetails: ProjectWrapper) {
|
||||
public dialogRef: MatDialogRef<AssignProjectMembersDialogComponent>) {
|
||||
this._loadProject();
|
||||
}
|
||||
|
||||
@ -1,4 +0,0 @@
|
||||
mat-selection-list {
|
||||
overflow-y: scroll;
|
||||
max-height: 50vh;
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
import { ChangeDetectorRef, Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
|
||||
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import {
|
||||
FileStatus,
|
||||
@ -21,8 +21,8 @@ import { AddEditProjectDialogComponent } from '../project-listing-screen/add-edi
|
||||
import { UserService } from '../../user/user.service';
|
||||
import { SortingOption } from '../../utils/types';
|
||||
import { DoughnutChartConfig } from '../../components/simple-doughnut-chart/simple-doughnut-chart.component';
|
||||
import {groupBy} from "../../utils/functions";
|
||||
import { ProjectMembersDialogComponent } from './project-members-dialog/project-members-dialog.component';
|
||||
import { groupBy } from '../../utils/functions';
|
||||
import { AssignProjectMembersDialogComponent } from './project-members-dialog/assign-project-members-dialog.component';
|
||||
|
||||
|
||||
@Component({
|
||||
@ -86,8 +86,8 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy {
|
||||
return this._userService.user;
|
||||
}
|
||||
|
||||
public get members() {
|
||||
return this.activeProject.memberIds.map(m => this._userService.getName(this._userService.getUserById(m)))
|
||||
public get members() {
|
||||
return this.activeProject.memberIds.map(m => this._userService.getName(this._userService.getUserById(m)));
|
||||
}
|
||||
|
||||
public get ownerName() {
|
||||
@ -104,7 +104,7 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy {
|
||||
const groups = groupBy(this.appStateService.activeProject.files, 'status');
|
||||
this.documentsChartData = [];
|
||||
for (const key of Object.keys(groups)) {
|
||||
this.documentsChartData.push({value: groups[key].length, color: key, label: key});
|
||||
this.documentsChartData.push({ value: groups[key].length, color: key, label: key });
|
||||
}
|
||||
}
|
||||
|
||||
@ -162,7 +162,7 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
public openAssignProjectMembersDialog() {
|
||||
this._dialog.open(ProjectMembersDialogComponent, {
|
||||
this._dialog.open(AssignProjectMembersDialogComponent, {
|
||||
width: '400px',
|
||||
maxWidth: '90vw',
|
||||
autoFocus: false
|
||||
@ -196,15 +196,15 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy {
|
||||
this._uploadStatusOverlayService.openStatusOverlay();
|
||||
}
|
||||
|
||||
public canOpenFile(fileStatus: FileStatus): boolean {
|
||||
public canOpenFile(fileStatus: FileStatus): boolean {
|
||||
// TODO check correct condition for this
|
||||
return fileStatus === 'PROCESSING' || fileStatus === 'REVIEWED' || true;
|
||||
}
|
||||
|
||||
public assignPeopleToFile($event: MouseEvent, fileStatus: FileStatus) {
|
||||
$event.stopPropagation();
|
||||
this._statusControllerService.assignProjectOwner1(this.appStateService.activeProjectId, fileStatus.fileId, this.user.id).subscribe(()=>{
|
||||
this._notificationService.showToastNotification("Successfully assigned " + this.user.name + " to file: " + fileStatus.filename);
|
||||
this._statusControllerService.assignProjectOwner1(this.appStateService.activeProjectId, fileStatus.fileId, this.user.id).subscribe(() => {
|
||||
this._notificationService.showToastNotification('Successfully assigned ' + this.user.name + ' to file: ' + fileStatus.filename);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -82,6 +82,10 @@ export class AppStateService {
|
||||
return this._appState.totalDocuments;
|
||||
}
|
||||
|
||||
public getProjectById(id: string) {
|
||||
return this.allProjects.find(project => project.project.projectId === id);
|
||||
}
|
||||
|
||||
async loadAllProjects() {
|
||||
const projects = await this._projectControllerService.getProjects().toPromise();
|
||||
if (projects) {
|
||||
|
||||
@ -6,3 +6,8 @@
|
||||
font-size: 13px !important;
|
||||
line-height: 16px !important;
|
||||
}
|
||||
|
||||
.list-50vh {
|
||||
overflow-y: scroll;
|
||||
max-height: 50vh;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user