From a9849a8edb0b49e86c72595945407f25b5beade6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adina=20=C8=9Aeudan?= Date: Wed, 21 Oct 2020 01:28:28 +0300 Subject: [PATCH 1/3] Assign project members --- apps/red-ui/src/app/app.module.ts | 128 +++++++------- .../project-members-dialog.component.html | 20 +++ .../project-members-dialog.component.scss | 4 + .../project-members-dialog.component.ts | 57 +++++++ .../project-overview-screen.component.html | 27 +-- .../project-overview-screen.component.scss | 5 + .../project-overview-screen.component.ts | 157 +++++++++--------- apps/red-ui/src/app/user/user.service.ts | 43 +++-- apps/red-ui/src/assets/styles/red-list.scss | 8 + apps/red-ui/src/assets/styles/red-theme.scss | 1 + 10 files changed, 283 insertions(+), 167 deletions(-) create mode 100644 apps/red-ui/src/app/screens/project-overview-screen/project-members-dialog/project-members-dialog.component.html create mode 100644 apps/red-ui/src/app/screens/project-overview-screen/project-members-dialog/project-members-dialog.component.scss create mode 100644 apps/red-ui/src/app/screens/project-overview-screen/project-members-dialog/project-members-dialog.component.ts create mode 100644 apps/red-ui/src/assets/styles/red-list.scss diff --git a/apps/red-ui/src/app/app.module.ts b/apps/red-ui/src/app/app.module.ts index a99349460..4de33a1c0 100644 --- a/apps/red-ui/src/app/app.module.ts +++ b/apps/red-ui/src/app/app.module.ts @@ -1,60 +1,62 @@ -import {BrowserModule} from '@angular/platform-browser'; -import {APP_INITIALIZER, NgModule} from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; +import { APP_INITIALIZER, NgModule } from '@angular/core'; -import {AppComponent} from './app.component'; -import {ActivatedRoute, Router, RouterModule} from '@angular/router'; -import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; -import {FormsModule, ReactiveFormsModule} from '@angular/forms'; -import {HTTP_INTERCEPTORS, HttpClient, HttpClientModule} from '@angular/common/http'; -import {BaseScreenComponent} from './screens/base-screen/base-screen.component'; -import {ProjectListingScreenComponent} from './screens/project-listing-screen/project-listing-screen.component'; -import {ProjectOverviewScreenComponent} from './screens/project-overview-screen/project-overview-screen.component'; -import {MatToolbarModule} from '@angular/material/toolbar'; -import {ApiModule} from '@redaction/red-ui-http'; -import {ApiPathInterceptorService} from './interceptor/api-path-interceptor.service'; -import {MatButtonModule} from '@angular/material/button'; -import {TranslateLoader, TranslateModule} from '@ngx-translate/core'; -import {TranslateHttpLoader} from '@ngx-translate/http-loader'; -import {MatMenuModule} from '@angular/material/menu'; -import {languageInitializer} from './i18n/language.initializer'; -import {LanguageService} from './i18n/language.service'; -import {MatIconModule} from '@angular/material/icon'; -import {IconsModule} from './icons/icons.module'; -import {AddEditProjectDialogComponent} from './screens/project-listing-screen/add-edit-project-dialog/add-edit-project-dialog.component'; -import {MatDialogModule} from '@angular/material/dialog'; -import {MatSnackBarModule} from '@angular/material/snack-bar'; -import {MatTooltipModule} from '@angular/material/tooltip'; -import {ConfirmationDialogComponent} from './common/confirmation-dialog/confirmation-dialog.component'; -import {FilePreviewScreenComponent} from './screens/file/file-preview-screen/file-preview-screen.component'; -import {PdfViewerComponent} from './screens/file/pdf-viewer/pdf-viewer.component'; -import {MatTabsModule} from '@angular/material/tabs'; -import {MatButtonToggleModule} from '@angular/material/button-toggle'; -import {NgpSortModule} from 'ngp-sort-pipe'; -import {MatFormFieldModule} from '@angular/material/form-field'; -import {MatSelectModule} from '@angular/material/select'; -import {MatSidenavModule} from '@angular/material/sidenav'; -import {FileDetailsDialogComponent} from './screens/file/file-preview-screen/file-details-dialog/file-details-dialog.component'; -import {ToastrModule} from 'ngx-toastr'; -import {ServiceWorkerModule} from '@angular/service-worker'; -import {environment} from '../environments/environment'; -import {ProjectDetailsDialogComponent} from './screens/project-overview-screen/project-details-dialog/project-details-dialog.component'; -import {AuthModule} from './auth/auth.module'; -import {FileUploadModule} from './upload/file-upload.module'; -import {FullPageLoadingIndicatorComponent} from './utils/full-page-loading-indicator/full-page-loading-indicator.component'; -import {MatProgressSpinnerModule} from '@angular/material/progress-spinner'; -import {InitialsAvatarComponent} from './common/initials-avatar/initials-avatar.component'; -import {StatusBarComponent} from './components/status-bar/status-bar.component'; -import {LogoComponent} from './logo/logo.component'; -import {CompositeRouteGuard} from './utils/composite-route.guard'; -import {AppStateGuard} from './state/app-state.guard'; -import {SimpleDoughnutChartComponent} from './components/simple-doughnut-chart/simple-doughnut-chart.component'; -import {ManualRedactionDialogComponent} from './screens/file/manual-redaction-dialog/manual-redaction-dialog.component'; -import {MatCheckboxModule} from '@angular/material/checkbox'; -import {MatSlideToggleModule} from '@angular/material/slide-toggle'; -import {AnnotationIconComponent} from './components/annotation-icon/annotation-icon.component'; -import {AuthGuard} from "./auth/auth.guard"; -import {AuthErrorComponent} from './screens/auth-error/auth-error.component'; -import {RedRoleGuard} from "./auth/red-role.guard"; +import { AppComponent } from './app.component'; +import { ActivatedRoute, Router, RouterModule } from '@angular/router'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { HTTP_INTERCEPTORS, HttpClient, HttpClientModule } from '@angular/common/http'; +import { BaseScreenComponent } from './screens/base-screen/base-screen.component'; +import { ProjectListingScreenComponent } from './screens/project-listing-screen/project-listing-screen.component'; +import { ProjectOverviewScreenComponent } from './screens/project-overview-screen/project-overview-screen.component'; +import { MatToolbarModule } from '@angular/material/toolbar'; +import { ApiModule } from '@redaction/red-ui-http'; +import { ApiPathInterceptorService } from './interceptor/api-path-interceptor.service'; +import { MatButtonModule } from '@angular/material/button'; +import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { TranslateHttpLoader } from '@ngx-translate/http-loader'; +import { MatMenuModule } from '@angular/material/menu'; +import { languageInitializer } from './i18n/language.initializer'; +import { LanguageService } from './i18n/language.service'; +import { MatIconModule } from '@angular/material/icon'; +import { IconsModule } from './icons/icons.module'; +import { AddEditProjectDialogComponent } from './screens/project-listing-screen/add-edit-project-dialog/add-edit-project-dialog.component'; +import { MatDialogModule } from '@angular/material/dialog'; +import { MatSnackBarModule } from '@angular/material/snack-bar'; +import { MatTooltipModule } from '@angular/material/tooltip'; +import { ConfirmationDialogComponent } from './common/confirmation-dialog/confirmation-dialog.component'; +import { FilePreviewScreenComponent } from './screens/file/file-preview-screen/file-preview-screen.component'; +import { PdfViewerComponent } from './screens/file/pdf-viewer/pdf-viewer.component'; +import { MatTabsModule } from '@angular/material/tabs'; +import { MatButtonToggleModule } from '@angular/material/button-toggle'; +import { NgpSortModule } from 'ngp-sort-pipe'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatSelectModule } from '@angular/material/select'; +import { MatSidenavModule } from '@angular/material/sidenav'; +import { FileDetailsDialogComponent } from './screens/file/file-preview-screen/file-details-dialog/file-details-dialog.component'; +import { ToastrModule } from 'ngx-toastr'; +import { ServiceWorkerModule } from '@angular/service-worker'; +import { environment } from '../environments/environment'; +import { ProjectDetailsDialogComponent } from './screens/project-overview-screen/project-details-dialog/project-details-dialog.component'; +import { AuthModule } from './auth/auth.module'; +import { FileUploadModule } from './upload/file-upload.module'; +import { FullPageLoadingIndicatorComponent } from './utils/full-page-loading-indicator/full-page-loading-indicator.component'; +import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; +import { InitialsAvatarComponent } from './common/initials-avatar/initials-avatar.component'; +import { StatusBarComponent } from './components/status-bar/status-bar.component'; +import { LogoComponent } from './logo/logo.component'; +import { CompositeRouteGuard } from './utils/composite-route.guard'; +import { AppStateGuard } from './state/app-state.guard'; +import { SimpleDoughnutChartComponent } from './components/simple-doughnut-chart/simple-doughnut-chart.component'; +import { ManualRedactionDialogComponent } from './screens/file/manual-redaction-dialog/manual-redaction-dialog.component'; +import { MatCheckboxModule } from '@angular/material/checkbox'; +import { MatSlideToggleModule } from '@angular/material/slide-toggle'; +import { AnnotationIconComponent } from './components/annotation-icon/annotation-icon.component'; +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 { MatListModule } from '@angular/material/list'; export function HttpLoaderFactory(httpClient: HttpClient) { return new TranslateHttpLoader(httpClient, '/assets/i18n/', '.json'); @@ -72,6 +74,7 @@ export function HttpLoaderFactory(httpClient: HttpClient) { PdfViewerComponent, FileDetailsDialogComponent, ProjectDetailsDialogComponent, + ProjectMembersDialogComponent, FullPageLoadingIndicatorComponent, InitialsAvatarComponent, StatusBarComponent, @@ -79,7 +82,7 @@ export function HttpLoaderFactory(httpClient: HttpClient) { SimpleDoughnutChartComponent, ManualRedactionDialogComponent, AnnotationIconComponent, - AuthErrorComponent, + AuthErrorComponent ], imports: [ BrowserModule, @@ -156,9 +159,10 @@ export function HttpLoaderFactory(httpClient: HttpClient) { MatSelectModule, MatSidenavModule, FileUploadModule, - ServiceWorkerModule.register('ngsw-worker.js', {enabled: environment.production}), + ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production }), MatProgressSpinnerModule, - MatCheckboxModule + MatCheckboxModule, + MatListModule ], providers: [{ provide: HTTP_INTERCEPTORS, @@ -181,12 +185,12 @@ export class AppModule { queryParams: { 'state': null, 'session_state': null, - 'code': null, + 'code': null }, queryParamsHandling: 'merge' - }) + }); } - }) + }); } } diff --git a/apps/red-ui/src/app/screens/project-overview-screen/project-members-dialog/project-members-dialog.component.html b/apps/red-ui/src/app/screens/project-overview-screen/project-members-dialog/project-members-dialog.component.html new file mode 100644 index 000000000..2c5d8e95e --- /dev/null +++ b/apps/red-ui/src/app/screens/project-overview-screen/project-members-dialog/project-members-dialog.component.html @@ -0,0 +1,20 @@ +
+
+ +
+ +
+ + + +

{{ userService.getNameForId(user.userId) }}

+
+
+
+
+ + +
diff --git a/apps/red-ui/src/app/screens/project-overview-screen/project-members-dialog/project-members-dialog.component.scss b/apps/red-ui/src/app/screens/project-overview-screen/project-members-dialog/project-members-dialog.component.scss new file mode 100644 index 000000000..705f562e1 --- /dev/null +++ b/apps/red-ui/src/app/screens/project-overview-screen/project-members-dialog/project-members-dialog.component.scss @@ -0,0 +1,4 @@ +mat-selection-list { + overflow-y: scroll; + max-height: 50vh; +} diff --git a/apps/red-ui/src/app/screens/project-overview-screen/project-members-dialog/project-members-dialog.component.ts b/apps/red-ui/src/app/screens/project-overview-screen/project-members-dialog/project-members-dialog.component.ts new file mode 100644 index 000000000..db14679bb --- /dev/null +++ b/apps/red-ui/src/app/screens/project-overview-screen/project-members-dialog/project-members-dialog.component.ts @@ -0,0 +1,57 @@ +import { Component, Inject } from '@angular/core'; +import { Project, ProjectControllerService } from '@redaction/red-ui-http'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { AppStateService, ProjectWrapper } from '../../../state/app-state.service'; +import { UserService } from '../../../user/user.service'; +import { MatSelectionListChange } from '@angular/material/list'; +import { NotificationService, NotificationType } from '../../../notification/notification.service'; + +@Component({ + selector: 'redaction-project-details-dialog', + templateUrl: './project-members-dialog.component.html', + styleUrls: ['./project-members-dialog.component.scss'] +}) +export class ProjectMembersDialogComponent { + 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, + @Inject(MAT_DIALOG_DATA) public projectDetails: ProjectWrapper) { + this._loadProject(); + } + + private _loadProject() { + this._project = this._appStateService.activeProject.project; + this.memberIds = [...this._project.memberIds]; + } + + private _reloadProject() { + this._appStateService.addOrUpdateProject(this._project).then(() => { + this._loadProject(); + }); + } + + public selectionChange($event: MatSelectionListChange) { + const userId = $event.option.value; + const selected = $event.option.selected; + const userName = this.userService.getNameForId(userId); + + if (selected) { + this._projectControllerService.addMembersToProject({ memberIds: [userId] }, this._project.projectId).subscribe(() => { + this._notificationService.showToastNotification('Successfully assigned ' + userName + ' to project: ' + this._project.projectName); + }, error => { + this._notificationService.showToastNotification('Failed: ' + error.error.message, null, NotificationType.ERROR); + }).add(() => this._reloadProject()); + } else { + this._projectControllerService.deleteMembersToProject({ memberIds: [userId] }, this._project.projectId).subscribe(() => { + this._notificationService.showToastNotification('Successfully removed ' + userName + ' from project: ' + this._project.projectName); + }, error => { + this._notificationService.showToastNotification('Failed: ' + error.error.message, null, NotificationType.ERROR); + }).add(() => this._reloadProject()); + } + } +} diff --git a/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.html b/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.html index e03aa8716..d2502aa14 100644 --- a/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.html +++ b/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.html @@ -1,5 +1,5 @@
+ [routerLink]="canOpenFile(fileStatus.status) ? ['/ui/projects/'+activeProject.projectId+'/file/'+fileStatus.fileId] : []">
{{ fileStatus.filename }}
@@ -77,7 +77,7 @@
@@ -88,7 +88,7 @@
- @@ -110,13 +110,13 @@
- - -
@@ -141,7 +141,7 @@
-
-
+
- - - +
+
+
+
+
diff --git a/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.scss b/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.scss index 11cad4cba..0a91f19ab 100644 --- a/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.scss +++ b/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.scss @@ -8,6 +8,11 @@ min-width: 60px; } +.header-flex-end { + display: flex; + justify-content: flex-end; +} + .table-item { .needs-work { display: flex; diff --git a/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.ts b/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.ts index a6d6ed2c3..60e65ad1f 100644 --- a/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.ts +++ b/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.ts @@ -22,6 +22,7 @@ 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'; @Component({ @@ -30,10 +31,7 @@ import {groupBy} from "../../utils/functions"; styleUrls: ['./project-overview-screen.component.scss'] }) export class ProjectOverviewScreenComponent implements OnInit, OnDestroy { - @ViewChild('dropzoneComponent', { static: true }) - dropZoneComponent; - - dragActive = false; + private _fileStatusInterval; public sortingOptions: SortingOption[] = [ { label: 'project-overview.sorting.recent.label', order: 'desc', column: 'lastUpdated' }, @@ -42,12 +40,8 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy { { label: 'project-overview.sorting.number-of-analyses.label', order: 'desc', column: 'numberOfAnalyses' } ]; public sortingOption: SortingOption = this.sortingOptions[0]; - public documentsChartData: DoughnutChartConfig[] = []; - projectId: string; - private _fileStatusInterval; - constructor(public readonly appStateService: AppStateService, private readonly _changeDetectorRef: ChangeDetectorRef, private readonly _activatedRoute: ActivatedRoute, @@ -64,15 +58,10 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy { private readonly _fileUploadControllerService: FileUploadControllerService, private readonly _projectControllerService: ProjectControllerService) { this._activatedRoute.params.subscribe(params => { - this.projectId = params.projectId; - this.appStateService.activateProject(this.projectId); + this.appStateService.activateProject(params.projectId); }); } - get user() { - return this._userService.user; - } - ngOnInit(): void { this._fileDropOverlayService.initFileDropHandling(); this._calculateChartConfig(); @@ -81,7 +70,45 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy { }, 5000); } - deleteFile($event: MouseEvent, fileStatus: FileStatus) { + ngOnDestroy(): void { + this._fileDropOverlayService.cleanupFileDropHandling(); + if (this._fileStatusInterval) { + this._fileStatusInterval = null; + clearInterval(this._fileStatusInterval); + } + } + + public get activeProject() { + return this.appStateService.activeProject.project; + } + + public get user() { + return this._userService.user; + } + + public get members() { + return this.activeProject.memberIds.map(m => this._userService.getName(this._userService.getUserById(m))) + } + + public get ownerName() { + return this._userService.getNameForId(this.activeProject.ownerId); + } + + private _getFileStatus() { + this.appStateService.reloadActiveProjectFiles().then(() => { + this._calculateChartConfig(); + }); + } + + private _calculateChartConfig() { + 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}); + } + } + + public openDeleteFileDialog($event: MouseEvent, fileStatus: FileStatus) { $event.stopPropagation(); const dialogRef = this._dialog.open(ConfirmationDialogComponent, { width: '400px', @@ -100,7 +127,7 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy { }); } - showDetailsDialog($event: MouseEvent) { + public openDetailsDialog($event: MouseEvent) { $event.stopPropagation(); this._dialog.open(ProjectDetailsDialogComponent, { width: '600px', @@ -109,57 +136,7 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy { }); } - ngOnDestroy(): void { - this._fileDropOverlayService.cleanupFileDropHandling(); - if (this._fileStatusInterval) { - this._fileStatusInterval = null; - clearInterval(this._fileStatusInterval); - } - } - - reanalyseFile($event: MouseEvent, fileStatus: FileStatus) { - $event.stopPropagation(); - this._reanalysisControllerService.reanalyzeFile(this.appStateService.activeProject.project.projectId, fileStatus.fileId).subscribe(() => { - this._getFileStatus(); - }); - } - - private _getFileStatus() { - this.appStateService.reloadActiveProjectFiles().then(() => { - this._calculateChartConfig(); - }); - } - - private _calculateChartConfig() { - 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}); - } - } - - fileId(index, item) { - return item.fileId; - } - - uploadFiles(files: FileList | File[]) { - - const uploadFiles: FileUploadModel[] = []; - for (let i = 0; i < files.length; i++) { - const file = files[i]; - uploadFiles.push({ - file: file, - progress: 0, - completed: false, - error: null - }); - } - - this._fileUploadService.uploadFiles(uploadFiles); - this._uploadStatusOverlayService.openStatusOverlay(); - } - - editProject($event: MouseEvent) { + public openEditProjectDialog($event: MouseEvent) { $event.stopPropagation(); this._dialog.open(AddEditProjectDialogComponent, { width: '400px', @@ -168,7 +145,7 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy { }); } - deleteProject($event: MouseEvent) { + public openDeleteProjectDialog($event: MouseEvent) { $event.stopPropagation(); const dialogRef = this._dialog.open(ConfirmationDialogComponent, { width: '400px', @@ -184,24 +161,54 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy { }); } + public openAssignProjectMembersDialog() { + this._dialog.open(ProjectMembersDialogComponent, { + width: '400px', + maxWidth: '90vw', + autoFocus: false + }); + } - canOpenFile(fileStatus: FileStatus): boolean { + public reanalyseFile($event: MouseEvent, fileStatus: FileStatus) { + $event.stopPropagation(); + this._reanalysisControllerService.reanalyzeFile(this.appStateService.activeProject.project.projectId, fileStatus.fileId).subscribe(() => { + this._getFileStatus(); + }); + } + + public fileId(index, item) { + return item.fileId; + } + + public uploadFiles(files: FileList | File[]) { + const uploadFiles: FileUploadModel[] = []; + for (let i = 0; i < files.length; i++) { + const file = files[i]; + uploadFiles.push({ + file: file, + progress: 0, + completed: false, + error: null + }); + } + + this._fileUploadService.uploadFiles(uploadFiles); + this._uploadStatusOverlayService.openStatusOverlay(); + } + + public canOpenFile(fileStatus: FileStatus): boolean { // TODO check correct condition for this return fileStatus === 'PROCESSING' || fileStatus === 'REVIEWED' || true; } - assignPeopleToFile($event: MouseEvent, fileStatus: FileStatus) { + 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); }); } - getMembers(){ - return this.appStateService.activeProject.project.memberIds.map(m => this._userService.getName(this._userService.getUserById(m))) - } - - getUsername(fileStatus: FileStatus) { + public getFileOwnerUsername(fileStatus: FileStatus) { return undefined; } } diff --git a/apps/red-ui/src/app/user/user.service.ts b/apps/red-ui/src/app/user/user.service.ts index a1ab79e39..94f0de68a 100644 --- a/apps/red-ui/src/app/user/user.service.ts +++ b/apps/red-ui/src/app/user/user.service.ts @@ -1,8 +1,8 @@ -import {Injectable} from "@angular/core"; -import {KeycloakService} from "keycloak-angular"; -import {KeycloakProfile} from "keycloak-js"; -import jwt_decode from "jwt-decode"; -import {User, UserControllerService} from "@redaction/red-ui-http"; +import { Injectable } from '@angular/core'; +import { KeycloakService } from 'keycloak-angular'; +import { KeycloakProfile } from 'keycloak-js'; +import jwt_decode from 'jwt-decode'; +import { User, UserControllerService } from '@redaction/red-ui-http'; export class UserWrapper { @@ -10,21 +10,21 @@ export class UserWrapper { } get name() { - return this._currentUser.firstName + " " + this._currentUser.lastName; + return this._currentUser.firstName + ' ' + this._currentUser.lastName; } get isManager() { - return this.roles.indexOf("RED_MANAGER") >= 0; + return this.roles.indexOf('RED_MANAGER') >= 0; } get isUser() { - return this.roles.indexOf("RED_USER") >= 0; + return this.roles.indexOf('RED_USER') >= 0; } get isAdmin() { - return this.roles.indexOf("RED_ADMIn") >= 0; + return this.roles.indexOf('RED_ADMIN') >= 0; } get hasAnyREDRoles() { @@ -37,11 +37,11 @@ export class UserWrapper { providedIn: 'root' }) export class UserService { - private _currentUser: UserWrapper; private _allUsers: User[]; - constructor(private readonly _keycloakService: KeycloakService, private readonly _userControllerService: UserControllerService) { + constructor(private readonly _keycloakService: KeycloakService, + private readonly _userControllerService: UserControllerService) { } logout() { @@ -65,7 +65,6 @@ export class UserService { return allUsers; } - async loadCurrentUser() { const token = await this._keycloakService.getToken(); const decoded = jwt_decode(token); @@ -77,15 +76,25 @@ export class UserService { return this._currentUser; } - getUserById(id: string) { return this._allUsers.find(u => u.userId === id); } + getNameForId(userId: string) { + return this.getName(this.getUserById(userId)); + } + getName(user?: User) { - if (user) { - return user.firstName + " " + user.lastName; - } - return undefined; + return user ? + (user.firstName && user.lastName ? `${user.firstName} ${user.lastName}` : user.username) : + undefined; + } + + isManager(user: User) { + return user.roles.indexOf('RED_MANAGER') >= 0; + } + + isUser(user: User) { + return user.roles.indexOf('RED_USER') >= 0; } } diff --git a/apps/red-ui/src/assets/styles/red-list.scss b/apps/red-ui/src/assets/styles/red-list.scss new file mode 100644 index 000000000..df3a3919f --- /dev/null +++ b/apps/red-ui/src/assets/styles/red-list.scss @@ -0,0 +1,8 @@ +@import "red-variables"; + +.mat-list-item { + font-family: Inter, sans-serif; + color: $grey-1 !important; + font-size: 13px !important; + line-height: 16px !important; +} diff --git a/apps/red-ui/src/assets/styles/red-theme.scss b/apps/red-ui/src/assets/styles/red-theme.scss index 61e61229d..74b2b37d5 100644 --- a/apps/red-ui/src/assets/styles/red-theme.scss +++ b/apps/red-ui/src/assets/styles/red-theme.scss @@ -9,6 +9,7 @@ @import "red-input"; @import "red-button"; @import "red-select"; +@import "red-list"; @import "red-checkbox"; @import "red-toggle"; @import "red-menu"; From ee037c63ac38956cf06e0b55a8e403517fbe71e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adina=20=C8=9Aeudan?= Date: Wed, 21 Oct 2020 01:36:12 +0300 Subject: [PATCH 2/3] Fix clearInterval --- .../project-overview-screen.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.ts b/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.ts index 60e65ad1f..b4b0964ca 100644 --- a/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.ts +++ b/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.ts @@ -73,8 +73,8 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy { ngOnDestroy(): void { this._fileDropOverlayService.cleanupFileDropHandling(); if (this._fileStatusInterval) { - this._fileStatusInterval = null; clearInterval(this._fileStatusInterval); + this._fileStatusInterval = null; } } From 6bebc5409d073ef09e08826d110f1b51d97a1e03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adina=20=C8=9Aeudan?= Date: Wed, 21 Oct 2020 02:26:23 +0300 Subject: [PATCH 3/3] Assign project owner --- apps/red-ui/src/app/app.module.ts | 6 +- .../assign-owner-dialog.component.html | 21 ++++ .../assign-owner-dialog.component.scss | 5 + .../assign-owner-dialog.component.ts | 59 +++++++++ .../project-listing-screen.component.html | 8 +- .../project-listing-screen.component.ts | 114 +++++++++--------- ...ign-project-members-dialog.component.html} | 6 +- ...sign-project-members-dialog.component.scss | 0 ...ssign-project-members-dialog.component.ts} | 9 +- .../project-members-dialog.component.scss | 4 - .../project-overview-screen.component.ts | 20 +-- .../red-ui/src/app/state/app-state.service.ts | 4 + apps/red-ui/src/assets/styles/red-list.scss | 5 + 13 files changed, 176 insertions(+), 85 deletions(-) create mode 100644 apps/red-ui/src/app/components/project-members-dialog/assign-owner-dialog.component.html create mode 100644 apps/red-ui/src/app/components/project-members-dialog/assign-owner-dialog.component.scss create mode 100644 apps/red-ui/src/app/components/project-members-dialog/assign-owner-dialog.component.ts rename apps/red-ui/src/app/screens/project-overview-screen/project-members-dialog/{project-members-dialog.component.html => assign-project-members-dialog.component.html} (72%) create mode 100644 apps/red-ui/src/app/screens/project-overview-screen/project-members-dialog/assign-project-members-dialog.component.scss rename apps/red-ui/src/app/screens/project-overview-screen/project-members-dialog/{project-members-dialog.component.ts => assign-project-members-dialog.component.ts} (88%) delete mode 100644 apps/red-ui/src/app/screens/project-overview-screen/project-members-dialog/project-members-dialog.component.scss diff --git a/apps/red-ui/src/app/app.module.ts b/apps/red-ui/src/app/app.module.ts index 4de33a1c0..faacea368 100644 --- a/apps/red-ui/src/app/app.module.ts +++ b/apps/red-ui/src/app/app.module.ts @@ -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, diff --git a/apps/red-ui/src/app/components/project-members-dialog/assign-owner-dialog.component.html b/apps/red-ui/src/app/components/project-members-dialog/assign-owner-dialog.component.html new file mode 100644 index 000000000..9423d219d --- /dev/null +++ b/apps/red-ui/src/app/components/project-members-dialog/assign-owner-dialog.component.html @@ -0,0 +1,21 @@ +
+
+
+ +
+ + + + {{ userService.getNameForId(user.userId) }} + + + +
+ + +
diff --git a/apps/red-ui/src/app/components/project-members-dialog/assign-owner-dialog.component.scss b/apps/red-ui/src/app/components/project-members-dialog/assign-owner-dialog.component.scss new file mode 100644 index 000000000..6914bc08f --- /dev/null +++ b/apps/red-ui/src/app/components/project-members-dialog/assign-owner-dialog.component.scss @@ -0,0 +1,5 @@ +@import "../../../assets/styles/red-variables"; + +.owner { + background-color: rgba($primary, 0.1); +} diff --git a/apps/red-ui/src/app/components/project-members-dialog/assign-owner-dialog.component.ts b/apps/red-ui/src/app/components/project-members-dialog/assign-owner-dialog.component.ts new file mode 100644 index 000000000..8abc46d65 --- /dev/null +++ b/apps/red-ui/src/app/components/project-members-dialog/assign-owner-dialog.component.ts @@ -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, + @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(); + }); + } +} diff --git a/apps/red-ui/src/app/screens/project-listing-screen/project-listing-screen.component.html b/apps/red-ui/src/app/screens/project-listing-screen/project-listing-screen.component.html index 25d2e89bb..c90a8fc62 100644 --- a/apps/red-ui/src/app/screens/project-listing-screen/project-listing-screen.component.html +++ b/apps/red-ui/src/app/screens/project-listing-screen/project-listing-screen.component.html @@ -69,7 +69,7 @@
- @@ -81,18 +81,18 @@
- - - diff --git a/apps/red-ui/src/app/screens/project-listing-screen/project-listing-screen.component.ts b/apps/red-ui/src/app/screens/project-listing-screen/project-listing-screen.component.ts index 8247f709c..f1eaf8942 100644 --- a/apps/red-ui/src/app/screens/project-listing-screen/project-listing-screen.component.ts +++ b/apps/red-ui/src/app/screens/project-listing-screen/project-listing-screen.component.ts @@ -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 } + }); } } diff --git a/apps/red-ui/src/app/screens/project-overview-screen/project-members-dialog/project-members-dialog.component.html b/apps/red-ui/src/app/screens/project-overview-screen/project-members-dialog/assign-project-members-dialog.component.html similarity index 72% rename from apps/red-ui/src/app/screens/project-overview-screen/project-members-dialog/project-members-dialog.component.html rename to apps/red-ui/src/app/screens/project-overview-screen/project-members-dialog/assign-project-members-dialog.component.html index 2c5d8e95e..b9eec293f 100644 --- a/apps/red-ui/src/app/screens/project-overview-screen/project-members-dialog/project-members-dialog.component.html +++ b/apps/red-ui/src/app/screens/project-overview-screen/project-members-dialog/assign-project-members-dialog.component.html @@ -5,10 +5,12 @@
- + -

{{ userService.getNameForId(user.userId) }}

+ {{ userService.getNameForId(user.userId) }}
diff --git a/apps/red-ui/src/app/screens/project-overview-screen/project-members-dialog/assign-project-members-dialog.component.scss b/apps/red-ui/src/app/screens/project-overview-screen/project-members-dialog/assign-project-members-dialog.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/apps/red-ui/src/app/screens/project-overview-screen/project-members-dialog/project-members-dialog.component.ts b/apps/red-ui/src/app/screens/project-overview-screen/project-members-dialog/assign-project-members-dialog.component.ts similarity index 88% rename from apps/red-ui/src/app/screens/project-overview-screen/project-members-dialog/project-members-dialog.component.ts rename to apps/red-ui/src/app/screens/project-overview-screen/project-members-dialog/assign-project-members-dialog.component.ts index db14679bb..272784e9a 100644 --- a/apps/red-ui/src/app/screens/project-overview-screen/project-members-dialog/project-members-dialog.component.ts +++ b/apps/red-ui/src/app/screens/project-overview-screen/project-members-dialog/assign-project-members-dialog.component.ts @@ -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, - @Inject(MAT_DIALOG_DATA) public projectDetails: ProjectWrapper) { + public dialogRef: MatDialogRef) { this._loadProject(); } diff --git a/apps/red-ui/src/app/screens/project-overview-screen/project-members-dialog/project-members-dialog.component.scss b/apps/red-ui/src/app/screens/project-overview-screen/project-members-dialog/project-members-dialog.component.scss deleted file mode 100644 index 705f562e1..000000000 --- a/apps/red-ui/src/app/screens/project-overview-screen/project-members-dialog/project-members-dialog.component.scss +++ /dev/null @@ -1,4 +0,0 @@ -mat-selection-list { - overflow-y: scroll; - max-height: 50vh; -} diff --git a/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.ts b/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.ts index b4b0964ca..f152acbe2 100644 --- a/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.ts +++ b/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.ts @@ -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); }); } diff --git a/apps/red-ui/src/app/state/app-state.service.ts b/apps/red-ui/src/app/state/app-state.service.ts index 66b63dd97..8d7e78a02 100644 --- a/apps/red-ui/src/app/state/app-state.service.ts +++ b/apps/red-ui/src/app/state/app-state.service.ts @@ -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) { diff --git a/apps/red-ui/src/assets/styles/red-list.scss b/apps/red-ui/src/assets/styles/red-list.scss index df3a3919f..c476f677c 100644 --- a/apps/red-ui/src/assets/styles/red-list.scss +++ b/apps/red-ui/src/assets/styles/red-list.scss @@ -6,3 +6,8 @@ font-size: 13px !important; line-height: 16px !important; } + +.list-50vh { + overflow-y: scroll; + max-height: 50vh; +}