diff --git a/apps/red-ui/src/app/dialogs/assign-owner-dialog/assign-owner-dialog.component.ts b/apps/red-ui/src/app/dialogs/assign-owner-dialog/assign-owner-dialog.component.ts index 93ea9a9ec..e93a7a232 100644 --- a/apps/red-ui/src/app/dialogs/assign-owner-dialog/assign-owner-dialog.component.ts +++ b/apps/red-ui/src/app/dialogs/assign-owner-dialog/assign-owner-dialog.component.ts @@ -1,20 +1,16 @@ import { Component, Inject } from '@angular/core'; -import { - FileStatus, - Project, - ProjectControllerService, - StatusControllerService -} from '@redaction/red-ui-http'; +import { Project, ProjectControllerService, StatusControllerService } 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'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { FileStatusWrapper } from '../../screens/file/model/file-status.wrapper'; class DialogData { type: 'file' | 'project'; project?: Project; - file?: FileStatus; + file?: FileStatusWrapper; } @Component({ @@ -76,13 +72,14 @@ export class AssignOwnerDialogComponent { const reviewerId = this.usersForm.get('singleUser').value; await this._statusControllerService - .assignProjectOwner1( + .assignProjectOwner( this._appStateService.activeProjectId, this.data.file.fileId, reviewerId ) .toPromise(); this.data.file.currentReviewer = reviewerId; + this.data.file.reviewerName = this.userService.getNameForId(reviewerId); this._notificationService.showToastNotification( 'Successfully assigned ' + this.userService.getNameForId(reviewerId) + diff --git a/apps/red-ui/src/app/dialogs/file-details-dialog/file-details-dialog.component.ts b/apps/red-ui/src/app/dialogs/file-details-dialog/file-details-dialog.component.ts index 909ed8aa9..428be1548 100644 --- a/apps/red-ui/src/app/dialogs/file-details-dialog/file-details-dialog.component.ts +++ b/apps/red-ui/src/app/dialogs/file-details-dialog/file-details-dialog.component.ts @@ -1,7 +1,7 @@ import { Component, Inject, OnInit } from '@angular/core'; -import { FileStatus } from '@redaction/red-ui-http'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { AppStateService } from '../../state/app-state.service'; +import { FileStatusWrapper } from '../../screens/file/model/file-status.wrapper'; @Component({ selector: 'redaction-file-details-dialog', @@ -12,7 +12,7 @@ export class FileDetailsDialogComponent implements OnInit { constructor( private readonly _appStateService: AppStateService, public dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) public fileStatus: FileStatus + @Inject(MAT_DIALOG_DATA) public fileStatus: FileStatusWrapper ) {} ngOnInit(): void {} diff --git a/apps/red-ui/src/app/icons/icons.module.ts b/apps/red-ui/src/app/icons/icons.module.ts index 08912aece..81d515fe0 100644 --- a/apps/red-ui/src/app/icons/icons.module.ts +++ b/apps/red-ui/src/app/icons/icons.module.ts @@ -43,7 +43,9 @@ export class IconsModule { 'trash', 'user', 'check-alt', - 'page' + 'page', + 'upload', + 'undo' ]; for (const icon of icons) { diff --git a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.html b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.html index c50069ead..f5fb56949 100644 --- a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.html +++ b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.html @@ -56,6 +56,24 @@ > + @@ -64,7 +82,7 @@ - + +
+ + + + +
@@ -114,9 +118,21 @@ > + +
-
-
- - {{ fileStatus.numberOfPages }} -
-
@@ -212,6 +222,11 @@ >
+
+ + {{ fileStatus.numberOfPages }} +
+
+
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 a94a1dd50..928a58786 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 @@ -13,10 +13,10 @@ } .grid-container { - grid-template-columns: 3fr 2fr 1fr 2fr auto; + grid-template-columns: 3fr 2fr 1fr 1fr 2fr auto; &.bulk-select { - grid-template-columns: auto 3fr 2fr 1fr 2fr auto; + grid-template-columns: auto 3fr 2fr 1fr 1fr 2fr auto; } .table-item { @@ -29,7 +29,7 @@ } .extend-cols { - grid-column-end: span 3; + grid-column-end: span 4; align-items: flex-end; } @@ -45,6 +45,23 @@ gap: 4px; } + .pages { + display: flex; + flex-direction: row; + align-items: center; + justify-content: flex-start; + gap: 4px; + opacity: 0.7; + color: $grey-1; + font-size: 11px; + letter-spacing: 0; + line-height: 14px; + .mat-icon { + width: 10px; + height: 10px; + } + } + .status-container { align-items: flex-end; } 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 188363483..f5b9de127 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 @@ -21,7 +21,7 @@ import { FilterModel } from '../../common/filter/model/filter.model'; import * as moment from 'moment'; import { SortingComponent, SortingOption } from '../../components/sorting/sorting.component'; import { ProjectDetailsComponent } from './project-details/project-details.component'; -import { ActiveToast } from 'ngx-toastr'; +import { FileStatusWrapper } from '../file/model/file-status.wrapper'; @Component({ selector: 'redaction-project-overview-screen', @@ -36,7 +36,7 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy { public peopleFilters: FilterModel[]; public addedDateFilters: FilterModel[]; - public displayedFiles: FileStatus[] = []; + public displayedFiles: FileStatusWrapper[] = []; @ViewChild('projectDetailsComponent', { static: true }) private _projectDetailsComponent: ProjectDetailsComponent; @@ -85,17 +85,17 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy { return this.userService.user; } - public isPending(fileStatus: FileStatus) { - return fileStatus.status === FileStatus.StatusEnum.UNPROCESSED; + public isPending(fileStatusWrapper: FileStatusWrapper) { + return fileStatusWrapper.status === FileStatus.StatusEnum.UNPROCESSED; } - public isError(fileStatus: FileStatus) { - return fileStatus.status === FileStatus.StatusEnum.ERROR; + public isError(fileStatusWrapper: FileStatusWrapper) { + return fileStatusWrapper.status === FileStatus.StatusEnum.ERROR; } - public isProcessing(fileStatus: FileStatus) { + public isProcessing(fileStatusWrapper: FileStatusWrapper) { return [FileStatus.StatusEnum.REPROCESS, FileStatus.StatusEnum.PROCESSING].includes( - fileStatus.status + fileStatusWrapper.status ); } @@ -157,9 +157,10 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy { this._computeAllFilters(); this._filterFiles(); this._projectDetailsComponent.calculateChartConfig(); + this._changeDetectorRef.detectChanges(); } - public toggleFileSelected($event: MouseEvent, file: FileStatus) { + public toggleFileSelected($event: MouseEvent, file: FileStatusWrapper) { $event.stopPropagation(); const idx = this._selectedFileIds.indexOf(file.fileId); if (idx === -1) { @@ -186,35 +187,38 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy { ); } - public isFileSelected(file: FileStatus) { + public isFileSelected(file: FileStatusWrapper) { return this._selectedFileIds.indexOf(file.fileId) !== -1; } - public openDeleteFileDialog($event: MouseEvent, fileStatus: FileStatus) { + public openDeleteFileDialog($event: MouseEvent, fileStatusWrapper: FileStatusWrapper) { this._dialogService.openDeleteFileDialog( $event, - fileStatus.projectId, - fileStatus.fileId, + fileStatusWrapper.projectId, + fileStatusWrapper.fileId, () => { this._calculateData(); } ); } - downloadFileRedactionReport($event: MouseEvent, file: FileStatus) { + downloadFileRedactionReport($event: MouseEvent, file: FileStatusWrapper) { $event.stopPropagation(); this.appStateService.downloadFileRedactionReport(file); } - public assignReviewer($event: MouseEvent, file: FileStatus) { + public assignReviewer($event: MouseEvent, file: FileStatusWrapper) { $event.stopPropagation(); this._fileActionService.assignProjectReviewer(file, () => this.reloadProjects()); } - public reanalyseFile($event: MouseEvent, fileStatus: FileStatus) { + public reanalyseFile($event: MouseEvent, fileStatusWrapper: FileStatusWrapper) { $event.stopPropagation(); this._reanalysisControllerService - .reanalyzeFile(this.appStateService.activeProject.project.projectId, fileStatus.fileId) + .reanalyzeFile( + this.appStateService.activeProject.project.projectId, + fileStatusWrapper.fileId + ) .subscribe(() => { this.reloadProjects(); }); @@ -240,11 +244,11 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy { this._uploadStatusOverlayService.openStatusOverlay(); } - public canOpenFile(fileStatus: FileStatus): boolean { + public canOpenFile(fileStatusWrapper: FileStatusWrapper): boolean { return ( - !this.isError(fileStatus) && - !this.isProcessing(fileStatus) && - this.appStateService.isReviewerOrOwner(fileStatus) + !this.isError(fileStatusWrapper) && + !this.isProcessing(fileStatusWrapper) && + this.appStateService.isReviewerOrOwner(fileStatusWrapper) ); } @@ -253,7 +257,7 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy { } private _computeAllFilters() { - const allDistinctFileStatus = new Set(); + const allDistinctFileStatusWrapper = new Set(); const allDistinctPeople = new Set(); const allDistinctAddedDates = new Set(); @@ -264,7 +268,7 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy { // File statuses this.appStateService.activeProject.files.forEach((file) => - allDistinctFileStatus.add(file.status) + allDistinctFileStatusWrapper.add(file.status) ); // Added dates @@ -273,7 +277,7 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy { ); this.statusFilters = []; - allDistinctFileStatus.forEach((status) => { + allDistinctFileStatusWrapper.forEach((status) => { this.statusFilters.push({ key: status, label: humanize(status) @@ -308,19 +312,19 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy { const statusFilterMatched = this._checkFilter( file, this.statusFilters, - (f: FileStatus, filter: FilterModel) => f.status === filter.key + (f: FileStatusWrapper, filter: FilterModel) => f.status === filter.key ); const peopleFilterMatched = this._checkFilter( file, this.peopleFilters, - (f: FileStatus, filter: FilterModel) => f.currentReviewer === filter.key + (f: FileStatusWrapper, filter: FilterModel) => f.currentReviewer === filter.key ); const addedFilterMatched = this._checkFilter( file, this.addedDateFilters, - (f: FileStatus, filter: FilterModel) => + (f: FileStatusWrapper, filter: FilterModel) => moment(f.added).format('DD/MM/YYYY') === filter.key ); @@ -333,7 +337,7 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy { this._changeDetectorRef.detectChanges(); } - private _checkFilter(file: FileStatus, filters: FilterModel[], validate: Function) { + private _checkFilter(file: FileStatusWrapper, filters: FilterModel[], validate: Function) { const hasChecked = filters.find((f) => f.checked); if (!hasChecked) { return true; @@ -348,21 +352,30 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy { return filterMatched; } - requestApprovalOrApproveFile($event: MouseEvent, fileStatus: FileStatus) { + requestApprovalOrApproveFile($event: MouseEvent, fileStatusWrapper: FileStatusWrapper) { $event.stopPropagation(); - - if (fileStatus.status === 'UNDER_REVIEW') { - this._fileActionService.setUnderApproval(fileStatus); - } else { - this._fileActionService.setApproved(fileStatus); - } + this._fileActionService.requestApprovalOrApproveFile(fileStatusWrapper).subscribe(() => { + this.reloadProjects(); + }); } - isApprovedOrUnderApproval(fileStatus: FileStatus) { - return fileStatus.status === 'APPROVED' || fileStatus.status === 'UNDER_APPROVAL'; + undoApproveOrUnderApproval($event: MouseEvent, fileStatusWrapper: FileStatusWrapper) { + $event.stopPropagation(); + this._fileActionService.undoApproveOrUnderApproval(fileStatusWrapper).subscribe(() => { + this.reloadProjects(); + }); } - canApprove(fileStatus: FileStatus) { - return fileStatus.status === 'UNDER_REVIEW' || fileStatus.status === 'UNDER_APPROVAL'; + isApprovedOrUnderApproval(fileStatusWrapper: FileStatusWrapper) { + return ( + fileStatusWrapper.status === 'APPROVED' || fileStatusWrapper.status === 'UNDER_APPROVAL' + ); + } + + canApprove(fileStatusWrapper: FileStatusWrapper) { + return ( + fileStatusWrapper.status === 'UNDER_REVIEW' || + fileStatusWrapper.status === 'UNDER_APPROVAL' + ); } } 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 e9bef2438..410dda863 100644 --- a/apps/red-ui/src/app/state/app-state.service.ts +++ b/apps/red-ui/src/app/state/app-state.service.ts @@ -20,11 +20,12 @@ import { download } from '../utils/file-download-utils'; import { humanize } from '../utils/functions'; import { AnnotationWrapper } from '../screens/file/model/annotation.wrapper'; import * as moment from 'moment'; +import { FileStatusWrapper } from '../screens/file/model/file-status.wrapper'; export interface AppState { projects: ProjectWrapper[]; activeProject: ProjectWrapper; - activeFile: FileStatus; + activeFile: FileStatusWrapper; totalAnalysedPages?: number; totalDocuments?: number; totalPeople?: number; @@ -39,7 +40,7 @@ export class ProjectWrapper { return this.files.find((f) => f.status === status); } - constructor(public project: Project, public files: FileStatus[]) {} + constructor(public project: Project, public files: FileStatusWrapper[]) {} get projectDate() { return this.project.date; @@ -68,7 +69,7 @@ export class ProjectWrapper { export class AppStateService { private _appState: AppState; private _dictionaryData: { [key: string]: TypeValue } = null; - public fileStatusChanged = new EventEmitter(); + public fileStatusChanged = new EventEmitter(); constructor( private readonly _router: Router, @@ -149,8 +150,8 @@ export class AppStateService { return this._appState.activeFile?.currentReviewer === this._userService.userId; } - get aggregatedFiles(): FileStatus[] { - const result: FileStatus[] = []; + get aggregatedFiles(): FileStatusWrapper[] { + const result: FileStatusWrapper[] = []; this._appState.projects.forEach((p) => { result.push(...p.files); }); @@ -169,7 +170,7 @@ export class AppStateService { return this._appState.projects; } - get activeFile(): FileStatus { + get activeFile(): FileStatusWrapper { return this._appState.activeFile; } @@ -235,7 +236,12 @@ export class AppStateService { if (oldFile.fileId === file.fileId) { // emit when analysis count changed if (oldFile.lastUpdated !== file.lastUpdated) { - this.fileStatusChanged.emit(file); + this.fileStatusChanged.emit( + new FileStatusWrapper( + file, + this._userService.getNameForId(file.currentReviewer) + ) + ); } found = true; break; @@ -243,11 +249,18 @@ export class AppStateService { } // emit for new file if (!found) { - this.fileStatusChanged.emit(file); + this.fileStatusChanged.emit( + new FileStatusWrapper( + file, + this._userService.getNameForId(file.currentReviewer) + ) + ); } } - project.files = files; + project.files = files.map( + (f) => new FileStatusWrapper(f, this._userService.getNameForId(f.currentReviewer)) + ); this._computeStats(); return files; @@ -386,7 +399,7 @@ export class AppStateService { await this.reloadActiveProjectFiles(); } - downloadFileRedactionReport(file: FileStatus) { + downloadFileRedactionReport(file: FileStatusWrapper) { this._fileUploadControllerService .downloadRedactionReport({ fileIds: [file.fileId] }, true, 'response') .subscribe((data) => { @@ -478,14 +491,14 @@ export class AppStateService { this._appState.ruleVersion = result.rulesVersion; } - isReviewerOrOwner(fileStatus: FileStatus) { + isReviewerOrOwner(fileStatus: FileStatusWrapper) { return ( fileStatus.currentReviewer === this._userService.userId || this.isActiveProjectOwnerAndManager ); } - fileNotUpToDateWithDictionary(fileStatus?: FileStatus) { + fileNotUpToDateWithDictionary(fileStatus?: FileStatusWrapper) { if (!fileStatus) { fileStatus = this.activeFile; } diff --git a/apps/red-ui/src/assets/i18n/en.json b/apps/red-ui/src/assets/i18n/en.json index 9ceb48c7b..8f5e5094d 100644 --- a/apps/red-ui/src/assets/i18n/en.json +++ b/apps/red-ui/src/assets/i18n/en.json @@ -165,6 +165,7 @@ "project-overview": { "under-approval": "Under Approval", "approve": "Approve", + "under-review": "Under Review", "no-files": "This Project contains no files yet. You can start your work by uploading some files!", "new-rule": { "label": "Outdated", @@ -193,6 +194,7 @@ "added-on": "Added on", "needs-work": "Needs work", "assigned-to": "Assigned to", + "pages": "Pages", "status": "Status" }, "upload-error": "Failed to upload file: {{name}}", diff --git a/apps/red-ui/src/assets/icons/general/plus.svg b/apps/red-ui/src/assets/icons/general/plus.svg index 546d1a2e1..0c64c1cac 100644 --- a/apps/red-ui/src/assets/icons/general/plus.svg +++ b/apps/red-ui/src/assets/icons/general/plus.svg @@ -1,14 +1,7 @@ - - - - - - - - + + + plus_white + + - diff --git a/apps/red-ui/src/assets/icons/general/undo.svg b/apps/red-ui/src/assets/icons/general/undo.svg new file mode 100644 index 000000000..82bf73bef --- /dev/null +++ b/apps/red-ui/src/assets/icons/general/undo.svg @@ -0,0 +1,20 @@ + + + + + diff --git a/apps/red-ui/src/assets/icons/general/upload.svg b/apps/red-ui/src/assets/icons/general/upload.svg new file mode 100644 index 000000000..bde05f03a --- /dev/null +++ b/apps/red-ui/src/assets/icons/general/upload.svg @@ -0,0 +1,7 @@ + + + upload + + + + diff --git a/apps/red-ui/src/assets/styles/red-button.scss b/apps/red-ui/src/assets/styles/red-button.scss index 629010773..3e6f49608 100644 --- a/apps/red-ui/src/assets/styles/red-button.scss +++ b/apps/red-ui/src/assets/styles/red-button.scss @@ -46,7 +46,23 @@ .mat-icon-button { transition: background-color 0.25s ease-in-out; + &:hover { background-color: $grey-2; } } + +.custom-mini-fab { + line-height: 16px !important; + width: 34px !important; + height: 34px !important; + + .mat-button-wrapper { + line-height: 16px !important; + } + + .mat-icon { + height: 16px !important; + width: 16px !important; + } +} diff --git a/libs/red-ui-http/src/lib/api/statusController.service.ts b/libs/red-ui-http/src/lib/api/statusController.service.ts index 633074567..8136b5625 100644 --- a/libs/red-ui-http/src/lib/api/statusController.service.ts +++ b/libs/red-ui-http/src/lib/api/statusController.service.ts @@ -63,28 +63,28 @@ export class StatusControllerService { * @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body. * @param reportProgress flag to report request and response progress. */ - public assignProjectOwner1( + public assignProjectOwner( projectId: string, fileId: string, reviewerId: string, observe?: 'body', reportProgress?: boolean ): Observable; - public assignProjectOwner1( + public assignProjectOwner( projectId: string, fileId: string, reviewerId: string, observe?: 'response', reportProgress?: boolean ): Observable>; - public assignProjectOwner1( + public assignProjectOwner( projectId: string, fileId: string, reviewerId: string, observe?: 'events', reportProgress?: boolean ): Observable>; - public assignProjectOwner1( + public assignProjectOwner( projectId: string, fileId: string, reviewerId: string, @@ -93,19 +93,19 @@ export class StatusControllerService { ): Observable { if (projectId === null || projectId === undefined) { throw new Error( - 'Required parameter projectId was null or undefined when calling assignProjectOwner1.' + 'Required parameter projectId was null or undefined when calling assignProjectOwner.' ); } if (fileId === null || fileId === undefined) { throw new Error( - 'Required parameter fileId was null or undefined when calling assignProjectOwner1.' + 'Required parameter fileId was null or undefined when calling assignProjectOwner.' ); } if (reviewerId === null || reviewerId === undefined) { throw new Error( - 'Required parameter reviewerId was null or undefined when calling assignProjectOwner1.' + 'Required parameter reviewerId was null or undefined when calling assignProjectOwner.' ); } @@ -146,6 +146,87 @@ export class StatusControllerService { ); } + /** + * Gets the status for a file. + * None + * @param projectId projectId + * @param fileId fileId + * @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body. + * @param reportProgress flag to report request and response progress. + */ + public getFileStatus( + projectId: string, + fileId: string, + observe?: 'body', + reportProgress?: boolean + ): Observable; + public getFileStatus( + projectId: string, + fileId: string, + observe?: 'response', + reportProgress?: boolean + ): Observable>; + public getFileStatus( + projectId: string, + fileId: string, + observe?: 'events', + reportProgress?: boolean + ): Observable>; + public getFileStatus( + projectId: string, + fileId: string, + observe: any = 'body', + reportProgress: boolean = false + ): Observable { + if (projectId === null || projectId === undefined) { + throw new Error( + 'Required parameter projectId was null or undefined when calling getFileStatus.' + ); + } + + if (fileId === null || fileId === undefined) { + throw new Error( + 'Required parameter fileId was null or undefined when calling getFileStatus.' + ); + } + + let headers = this.defaultHeaders; + + // authentication (RED-OAUTH) required + if (this.configuration.accessToken) { + const accessToken = + typeof this.configuration.accessToken === 'function' + ? this.configuration.accessToken() + : this.configuration.accessToken; + headers = headers.set('Authorization', 'Bearer ' + accessToken); + } + + // to determine the Accept header + const httpHeaderAccepts: string[] = ['application/json']; + const httpHeaderAcceptSelected: string | undefined = this.configuration.selectHeaderAccept( + httpHeaderAccepts + ); + if (httpHeaderAcceptSelected !== undefined) { + headers = headers.set('Accept', httpHeaderAcceptSelected); + } + + // to determine the Content-Type header + const consumes: string[] = []; + + return this.httpClient.request( + 'get', + `${this.basePath}/status/${encodeURIComponent(String(projectId))}/${encodeURIComponent( + String(fileId) + )}`, + { + withCredentials: this.configuration.withCredentials, + headers: headers, + observe: observe, + reportProgress: reportProgress + } + ); + } + /** * Gets the status for all files in a project. * None @@ -375,4 +456,85 @@ export class StatusControllerService { } ); } + + /** + * Sets the status UNDER_REVIEW for a file. + * None + * @param projectId projectId + * @param fileId fileId + * @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body. + * @param reportProgress flag to report request and response progress. + */ + public setStatusUnderReview( + projectId: string, + fileId: string, + observe?: 'body', + reportProgress?: boolean + ): Observable; + public setStatusUnderReview( + projectId: string, + fileId: string, + observe?: 'response', + reportProgress?: boolean + ): Observable>; + public setStatusUnderReview( + projectId: string, + fileId: string, + observe?: 'events', + reportProgress?: boolean + ): Observable>; + public setStatusUnderReview( + projectId: string, + fileId: string, + observe: any = 'body', + reportProgress: boolean = false + ): Observable { + if (projectId === null || projectId === undefined) { + throw new Error( + 'Required parameter projectId was null or undefined when calling setStatusUnderReview.' + ); + } + + if (fileId === null || fileId === undefined) { + throw new Error( + 'Required parameter fileId was null or undefined when calling setStatusUnderReview.' + ); + } + + let headers = this.defaultHeaders; + + // authentication (RED-OAUTH) required + if (this.configuration.accessToken) { + const accessToken = + typeof this.configuration.accessToken === 'function' + ? this.configuration.accessToken() + : this.configuration.accessToken; + headers = headers.set('Authorization', 'Bearer ' + accessToken); + } + + // to determine the Accept header + const httpHeaderAccepts: string[] = []; + const httpHeaderAcceptSelected: string | undefined = this.configuration.selectHeaderAccept( + httpHeaderAccepts + ); + if (httpHeaderAcceptSelected !== undefined) { + headers = headers.set('Accept', httpHeaderAcceptSelected); + } + + // to determine the Content-Type header + const consumes: string[] = []; + + return this.httpClient.request( + 'post', + `${this.basePath}/status/underreview/${encodeURIComponent( + String(projectId) + )}/${encodeURIComponent(String(fileId))}`, + { + withCredentials: this.configuration.withCredentials, + headers: headers, + observe: observe, + reportProgress: reportProgress + } + ); + } } diff --git a/libs/red-ui-http/src/lib/model/fileStatus.ts b/libs/red-ui-http/src/lib/model/fileStatus.ts index c3a95d190..f1408a4cb 100644 --- a/libs/red-ui-http/src/lib/model/fileStatus.ts +++ b/libs/red-ui-http/src/lib/model/fileStatus.ts @@ -50,6 +50,10 @@ export interface FileStatus { * Shows if any requests were found during the analysis. */ hasRequests?: boolean; + /** + * Shows the last date of a successful analysis. + */ + lastProcessed?: string; /** * Date and time when the file was last updated. */