From d637da45bcb49d44673434d6d24237ac44abb295 Mon Sep 17 00:00:00 2001 From: Timo Date: Tue, 24 Nov 2020 18:31:32 +0200 Subject: [PATCH] various issues implemented --- .../add-edit-project-dialog.component.ts | 2 +- apps/red-ui/src/app/dialogs/dialog.service.ts | 6 +- .../manual-annotation-dialog.component.ts | 7 +- .../file-preview-screen.component.html | 4 +- .../file-preview-screen.component.ts | 10 ++ .../file/pdf-viewer/pdf-viewer.component.ts | 12 +- .../file/service/file-download.service.ts | 10 +- .../project-listing-screen.component.ts | 5 +- .../bulk-actions/bulk-actions.component.html | 8 + .../bulk-actions/bulk-actions.component.ts | 18 +- .../red-ui/src/app/state/app-state.service.ts | 8 +- .../src/app/state/model/project.wrapper.ts | 4 + .../src/app/upload/file-upload.service.ts | 6 +- apps/red-ui/src/app/utils/functions.ts | 8 + apps/red-ui/src/assets/i18n/en.json | 1 + libs/red-ui-http/src/lib/api.module.ts | 17 +- libs/red-ui-http/src/lib/api/api.ts | 12 +- ...ts => fileManagementController.service.ts} | 138 +++++++++++---- .../legalBasisMappingController.service.ts | 134 +++++++++++++++ .../lib/api/redactionLogController.service.ts | 162 +++++++++--------- .../lib/model/bulkDownloadRedactedRequest.ts | 15 ++ .../src/lib/model/cellRectangle.ts | 18 ++ .../src/lib/model/legalBasisMapping.ts | 15 ++ libs/red-ui-http/src/lib/model/models.ts | 5 + libs/red-ui-http/src/lib/model/sectionGrid.ts | 16 ++ .../src/lib/model/sectionRectangle.ts | 22 +++ 26 files changed, 512 insertions(+), 151 deletions(-) rename libs/red-ui-http/src/lib/api/{fileUploadController.service.ts => fileManagementController.service.ts} (84%) create mode 100644 libs/red-ui-http/src/lib/api/legalBasisMappingController.service.ts create mode 100644 libs/red-ui-http/src/lib/model/bulkDownloadRedactedRequest.ts create mode 100644 libs/red-ui-http/src/lib/model/cellRectangle.ts create mode 100644 libs/red-ui-http/src/lib/model/legalBasisMapping.ts create mode 100644 libs/red-ui-http/src/lib/model/sectionGrid.ts create mode 100644 libs/red-ui-http/src/lib/model/sectionRectangle.ts diff --git a/apps/red-ui/src/app/dialogs/add-edit-project-dialog/add-edit-project-dialog.component.ts b/apps/red-ui/src/app/dialogs/add-edit-project-dialog/add-edit-project-dialog.component.ts index 8b48fba55..2a6ffd323 100644 --- a/apps/red-ui/src/app/dialogs/add-edit-project-dialog/add-edit-project-dialog.component.ts +++ b/apps/red-ui/src/app/dialogs/add-edit-project-dialog/add-edit-project-dialog.component.ts @@ -38,7 +38,7 @@ export class AddEditProjectDialogComponent implements OnInit { const savedProject = await this._appStateService.addOrUpdateProject(project); if (savedProject) { - this.dialogRef.close(true); + this.dialogRef.close({ project: savedProject }); } } diff --git a/apps/red-ui/src/app/dialogs/dialog.service.ts b/apps/red-ui/src/app/dialogs/dialog.service.ts index 2e7a2f9e4..0272202a8 100644 --- a/apps/red-ui/src/app/dialogs/dialog.service.ts +++ b/apps/red-ui/src/app/dialogs/dialog.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@angular/core'; import { FileDetailsDialogComponent } from './file-details-dialog/file-details-dialog.component'; import { MatDialog, MatDialogRef } from '@angular/material/dialog'; -import { FileStatus, FileUploadControllerService, ManualRedactionControllerService, Project } from '@redaction/red-ui-http'; +import { FileStatus, FileManagementControllerService, ManualRedactionControllerService, Project } from '@redaction/red-ui-http'; import { ConfirmationDialogComponent, ConfirmationDialogInput } from '../common/confirmation-dialog/confirmation-dialog.component'; import { NotificationService, NotificationType } from '../notification/notification.service'; import { TranslateService } from '@ngx-translate/core'; @@ -27,7 +27,7 @@ export class DialogService { private readonly _dialog: MatDialog, private readonly _translateService: TranslateService, private readonly _appStateService: AppStateService, - private readonly _fileUploadControllerService: FileUploadControllerService, + private readonly _fileManagementControllerService: FileManagementControllerService, private readonly _notificationService: NotificationService, private readonly _manualAnnotationService: ManualAnnotationService, private readonly _manualRedactionControllerService: ManualRedactionControllerService @@ -56,7 +56,7 @@ export class DialogService { if (result) { const promises = fileIds .map((fileId) => this._appStateService.getFileById(projectId, fileId)) - .map((file) => this._fileUploadControllerService.deleteFile(file.projectId, file.fileId).toPromise()); + .map((file) => this._fileManagementControllerService.deleteFile(file.projectId, file.fileId).toPromise()); Promise.all(promises) .then(async () => { diff --git a/apps/red-ui/src/app/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.ts b/apps/red-ui/src/app/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.ts index 789552723..8868c2921 100644 --- a/apps/red-ui/src/app/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.ts +++ b/apps/red-ui/src/app/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.ts @@ -2,7 +2,7 @@ import { Component, Inject, OnInit } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { AppStateService } from '../../state/app-state.service'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; -import { AddRedactionRequest, TypeValue } from '@redaction/red-ui-http'; +import { AddRedactionRequest, LegalBasisMappingControllerService, TypeValue } from '@redaction/red-ui-http'; import { NotificationService } from '../../notification/notification.service'; import { TranslateService } from '@ngx-translate/core'; import { UserService } from '../../user/user.service'; @@ -65,6 +65,7 @@ export class ManualAnnotationDialogComponent implements OnInit { private readonly _formBuilder: FormBuilder, private readonly _notificationService: NotificationService, private readonly _translateService: TranslateService, + private readonly _legalBasisMappingControllerService: LegalBasisMappingControllerService, private readonly _manualAnnotationService: ManualAnnotationService, private readonly _permissionsService: PermissionsService, public dialogRef: MatDialogRef, @@ -72,6 +73,10 @@ export class ManualAnnotationDialogComponent implements OnInit { ) {} async ngOnInit() { + this._legalBasisMappingControllerService.getLegalBasisMapping().subscribe((data) => { + console.log(data); + }); + this.isDocumentAdmin = this._permissionsService.isManagerAndOwner(); this.isDictionaryRequest = this.manualRedactionEntryWrapper.type === 'DICTIONARY'; 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 dbb76b0ed..fa0022e55 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 @@ -111,7 +111,7 @@ >
{ - header.getItems().push({ + const originalHeaderItems = header.getItems(); + originalHeaderItems.splice(8, 0, { + type: 'divider', + dataElement: 'rectangleToolDivider' + }); + originalHeaderItems.splice(9, 0, { type: 'toolGroupButton', toolGroup: 'rectangleTools', dataElement: 'shapeToolGroupButton', title: 'annotation.rectangle' }); - header.getHeader('toolbarGroup-Shapes').delete(6); }); this.instance.docViewer.getTool('AnnotationCreateRectangle').setStyles((currentStyle) => ({ @@ -224,9 +228,9 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges { private _handleCustomActions() { if (this.canPerformActions) { - this.instance.enableElements(['add-redaction', 'add-dictionary', 'add-rectangle']); + this.instance.enableElements(['add-redaction', 'add-dictionary', 'add-rectangle', 'shapeToolGroupButton']); } else { - this.instance.disableElements(['add-redaction', 'add-dictionary', 'add-rectangle']); + this.instance.disableElements(['add-redaction', 'add-dictionary', 'add-rectangle', 'shapeToolGroupButton']); } } diff --git a/apps/red-ui/src/app/screens/file/service/file-download.service.ts b/apps/red-ui/src/app/screens/file/service/file-download.service.ts index 2a4fde98b..1e8d75818 100644 --- a/apps/red-ui/src/app/screens/file/service/file-download.service.ts +++ b/apps/red-ui/src/app/screens/file/service/file-download.service.ts @@ -2,8 +2,8 @@ import { Injectable } from '@angular/core'; import { forkJoin, Observable, of } from 'rxjs'; import { map, tap } from 'rxjs/operators'; import { + FileManagementControllerService, FileStatus, - FileUploadControllerService, ManualRedactionControllerService, RedactionLogControllerService, ViewedPagesControllerService @@ -20,7 +20,7 @@ export class FileDownloadService { constructor( private readonly _appStateService: AppStateService, private readonly _permissionsService: PermissionsService, - private readonly _fileUploadControllerService: FileUploadControllerService, + private readonly _fileManagementControllerService: FileManagementControllerService, private readonly _manualRedactionControllerService: ManualRedactionControllerService, private readonly _redactionLogControllerService: RedactionLogControllerService, private readonly _viewedPagesControllerService: ViewedPagesControllerService @@ -63,7 +63,7 @@ export class FileDownloadService { case FileType.ANNOTATED: fileObs$ = fetch() ? of(fetch()) - : this._fileUploadControllerService.downloadAnnotatedFile(fileStatus.fileId, true, fileStatus.lastProcessed, 'body').pipe( + : this._fileManagementControllerService.downloadAnnotatedFile(fileStatus.fileId, true, fileStatus.lastProcessed, 'body').pipe( tap((data) => { saveTo(data); }) @@ -72,7 +72,7 @@ export class FileDownloadService { case FileType.REDACTED: fileObs$ = fetch() ? of(fetch()) - : this._fileUploadControllerService.downloadRedactedFile(fileStatus.fileId, true, fileStatus.lastProcessed, 'body').pipe( + : this._fileManagementControllerService.downloadRedactedFile(fileStatus.fileId, true, fileStatus.lastProcessed, 'body').pipe( tap((data) => { saveTo(data); }) @@ -82,7 +82,7 @@ export class FileDownloadService { default: fileObs$ = fetch() ? of(fetch()) - : this._fileUploadControllerService.downloadOriginalFile(fileStatus.fileId, true, fileStatus.lastUploaded, 'body').pipe( + : this._fileManagementControllerService.downloadOriginalFile(fileStatus.fileId, true, fileStatus.lastUploaded, 'body').pipe( tap((data) => { saveTo(data); }) 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 408bf3358..9d02cdb9e 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 @@ -6,7 +6,6 @@ import { DoughnutChartConfig } from '../../components/simple-doughnut-chart/simp import { groupBy, humanize } from '../../utils/functions'; import { DialogService } from '../../dialogs/dialog.service'; import { FilterModel } from '../../common/filter/model/filter.model'; -import * as moment from 'moment'; import { annotationFilterChecker, getFilteredEntities, @@ -23,6 +22,7 @@ import { tap } from 'rxjs/operators'; import { TranslateChartService } from '../../utils/translate-chart.service'; import { RedactionFilterSorter } from '../../common/sorters/redaction-filter-sorter'; import { StatusSorter } from '../../common/sorters/status-sorter'; +import { Router } from '@angular/router'; @Component({ selector: 'redaction-project-listing-screen', @@ -53,6 +53,7 @@ export class ProjectListingScreenComponent implements OnInit, OnDestroy { private readonly _changeDetectorRef: ChangeDetectorRef, private readonly _dialogService: DialogService, private readonly _translateService: TranslateService, + private readonly _router: Router, public readonly sortingService: SortingService, public readonly translateChartService: TranslateChartService ) {} @@ -121,13 +122,13 @@ export class ProjectListingScreenComponent implements OnInit, OnDestroy { } public canOpenProject(pw: ProjectWrapper): boolean { - // return this.userService.isManager(this.user) || pw.project.memberIds.includes(this.user.id); return true; } public openAddProjectDialog(): void { this._dialogService.openAddProjectDialog((addResponse) => { this._calculateData(); + this._router.navigate([`/ui/projects/${addResponse.project.projectId}`]); if (addResponse.addMembers) { this.openAssignProjectOwnerDialog(null, addResponse.project); } diff --git a/apps/red-ui/src/app/screens/project-overview-screen/bulk-actions/bulk-actions.component.html b/apps/red-ui/src/app/screens/project-overview-screen/bulk-actions/bulk-actions.component.html index 3b13dd77a..b00f8dcd2 100644 --- a/apps/red-ui/src/app/screens/project-overview-screen/bulk-actions/bulk-actions.component.html +++ b/apps/red-ui/src/app/screens/project-overview-screen/bulk-actions/bulk-actions.component.html @@ -29,6 +29,14 @@ icon="red:check-alt" > + + file.fileId) }, this._appStateService.activeProjectId, false, 'response') + .subscribe((data) => { + download(data, 'redacted_files_' + computerize(this._appStateService.activeProject.name) + '.zip'); + }); + } + + get canDownloadRedactedFiles() { + return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canDownloadRedactedFile(file), true); + } } 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 a911ad7be..e1981cc25 100644 --- a/apps/red-ui/src/app/state/app-state.service.ts +++ b/apps/red-ui/src/app/state/app-state.service.ts @@ -1,7 +1,7 @@ import { EventEmitter, Injectable } from '@angular/core'; import { DictionaryControllerService, - FileUploadControllerService, + FileManagementControllerService, Project, ProjectControllerService, ReanalysisControllerService, @@ -43,7 +43,7 @@ export class AppStateService { constructor( private readonly _router: Router, private readonly _userService: UserService, - private readonly _fileUploadControllerService: FileUploadControllerService, + private readonly _fileManagementControllerService: FileManagementControllerService, private readonly _projectControllerService: ProjectControllerService, private readonly _notificationService: NotificationService, private readonly _reanalysisControllerService: ReanalysisControllerService, @@ -237,7 +237,7 @@ export class AppStateService { if (!project) { project = this.activeProject.project; } - this._fileUploadControllerService.downloadRedactionReportForProject(project.projectId, true, 'response').subscribe((data) => { + this._fileManagementControllerService.downloadRedactionReportForProject(project.projectId, true, 'response').subscribe((data) => { download(data, 'redaction-report-' + project.projectName + '.docx'); }); } @@ -354,7 +354,7 @@ export class AppStateService { if (!file) { file = this.activeFile; } - this._fileUploadControllerService.downloadRedactionReport({ fileIds: [file.fileId] }, true, 'response').subscribe((data) => { + this._fileManagementControllerService.downloadRedactionReport({ fileIds: [file.fileId] }, true, 'response').subscribe((data) => { download(data, 'redaction-report-' + file.filename + '.docx'); }); } diff --git a/apps/red-ui/src/app/state/model/project.wrapper.ts b/apps/red-ui/src/app/state/model/project.wrapper.ts index 433b9ddc3..95c737215 100644 --- a/apps/red-ui/src/app/state/model/project.wrapper.ts +++ b/apps/red-ui/src/app/state/model/project.wrapper.ts @@ -53,6 +53,10 @@ export class ProjectWrapper { return this._files.length > 0; } + get name() { + return this.project.projectName; + } + hasStatus(status: string) { return this._files.find((f) => f.status === status); } diff --git a/apps/red-ui/src/app/upload/file-upload.service.ts b/apps/red-ui/src/app/upload/file-upload.service.ts index 214e5b835..037d86c04 100644 --- a/apps/red-ui/src/app/upload/file-upload.service.ts +++ b/apps/red-ui/src/app/upload/file-upload.service.ts @@ -1,8 +1,8 @@ import { Injectable } from '@angular/core'; import { FileUploadModel } from './model/file-upload.model'; -import { FileUploadControllerService } from '@redaction/red-ui-http'; import { AppStateService } from '../state/app-state.service'; import { HttpEventType } from '@angular/common/http'; +import { FileManagementControllerService } from '@redaction/red-ui-http'; @Injectable({ providedIn: 'root' @@ -10,12 +10,12 @@ import { HttpEventType } from '@angular/common/http'; export class FileUploadService { files: FileUploadModel[] = []; - constructor(private readonly _appStateService: AppStateService, private readonly _fileUploadControllerService: FileUploadControllerService) {} + constructor(private readonly _appStateService: AppStateService, private readonly _fileManagementControllerService: FileManagementControllerService) {} uploadFiles(files: FileUploadModel[]) { this.files.push(...files); files.forEach((newFile) => { - this._fileUploadControllerService.uploadFileForm(newFile.file, this._appStateService.activeProject.project.projectId, 'events', true).subscribe( + this._fileManagementControllerService.uploadFileForm(newFile.file, this._appStateService.activeProject.project.projectId, 'events', true).subscribe( async (event) => { if (event.type === HttpEventType.UploadProgress) { newFile.progress = Math.round((event.loaded / (event.total || event.loaded)) * 100); diff --git a/apps/red-ui/src/app/utils/functions.ts b/apps/red-ui/src/app/utils/functions.ts index 8ada1c82a..e616a656c 100644 --- a/apps/red-ui/src/app/utils/functions.ts +++ b/apps/red-ui/src/app/utils/functions.ts @@ -5,6 +5,14 @@ export function groupBy(xs: any[], key: string) { }, {}); } +export function computerize(str: string) { + if (!str) { + return undefined; + } + const frags = str.toLowerCase().split(/[ \-_]+/); + return frags.join('_'); +} + export function humanize(str: string) { if (!str) { return undefined; diff --git a/apps/red-ui/src/assets/i18n/en.json b/apps/red-ui/src/assets/i18n/en.json index b7a6156d8..01791dfcd 100644 --- a/apps/red-ui/src/assets/i18n/en.json +++ b/apps/red-ui/src/assets/i18n/en.json @@ -147,6 +147,7 @@ "upload-document": "Upload Document" }, "download-redacted-file": "Download Redacted File", + "download-redacted-files": "Download Redacted Files", "under-approval": "For Approval", "approve": "Approve", "under-review": "Under Review", diff --git a/libs/red-ui-http/src/lib/api.module.ts b/libs/red-ui-http/src/lib/api.module.ts index 1255fb726..235a6f927 100644 --- a/libs/red-ui-http/src/lib/api.module.ts +++ b/libs/red-ui-http/src/lib/api.module.ts @@ -4,7 +4,7 @@ import { HttpClient } from '@angular/common/http'; import { DebugControllerService } from './api/debugController.service'; import { DictionaryControllerService } from './api/dictionaryController.service'; -import { FileUploadControllerService } from './api/fileUploadController.service'; +import { FileManagementControllerService } from './api/fileManagementController.service'; import { LicenseReportControllerService } from './api/licenseReportController.service'; import { ManualRedactionControllerService } from './api/manualRedactionController.service'; import { PdfMetaDataConfigurationControllerService } from './api/pdfMetaDataConfigurationController.service'; @@ -16,6 +16,7 @@ import { StatusControllerService } from './api/statusController.service'; import { UserControllerService } from './api/userController.service'; import { VersionsControllerService } from './api/versionsController.service'; import { ViewedPagesControllerService } from './api/viewedPagesController.service'; +import { LegalBasisMappingControllerService } from './api/legalBasisMappingController.service'; @NgModule({ imports: [], @@ -24,7 +25,7 @@ import { ViewedPagesControllerService } from './api/viewedPagesController.servic providers: [ DebugControllerService, DictionaryControllerService, - FileUploadControllerService, + FileManagementControllerService, LicenseReportControllerService, ManualRedactionControllerService, PdfMetaDataConfigurationControllerService, @@ -35,7 +36,8 @@ import { ViewedPagesControllerService } from './api/viewedPagesController.servic UserControllerService, StatusControllerService, VersionsControllerService, - ViewedPagesControllerService + ViewedPagesControllerService, + LegalBasisMappingControllerService ] }) export class ApiModule { @@ -44,16 +46,11 @@ export class ApiModule { throw new Error('ApiModule is already loaded. Import in your base AppModule only.'); } if (!http) { - throw new Error( - 'You need to import the HttpClientModule in your AppModule! \n' + - 'See also https://github.com/angular/angular/issues/20575' - ); + throw new Error('You need to import the HttpClientModule in your AppModule! \n' + 'See also https://github.com/angular/angular/issues/20575'); } } - public static forRoot( - configurationFactory: () => Configuration - ): ModuleWithProviders { + public static forRoot(configurationFactory: () => Configuration): ModuleWithProviders { return { ngModule: ApiModule, providers: [{ provide: Configuration, useFactory: configurationFactory }] diff --git a/libs/red-ui-http/src/lib/api/api.ts b/libs/red-ui-http/src/lib/api/api.ts index 61ddce0c3..bf0d17fe4 100644 --- a/libs/red-ui-http/src/lib/api/api.ts +++ b/libs/red-ui-http/src/lib/api/api.ts @@ -3,7 +3,7 @@ import { VersionsControllerService } from './versionsController.service'; export * from './debugController.service'; import { DebugControllerService } from './debugController.service'; import { DictionaryControllerService } from './dictionaryController.service'; -import { FileUploadControllerService } from './fileUploadController.service'; +import { FileManagementControllerService } from './fileManagementController.service'; import { LicenseReportControllerService } from './licenseReportController.service'; import { ManualRedactionControllerService } from './manualRedactionController.service'; import { PdfMetaDataConfigurationControllerService } from './pdfMetaDataConfigurationController.service'; @@ -14,10 +14,11 @@ import { RulesControllerService } from './rulesController.service'; import { StatusControllerService } from './statusController.service'; import { UserControllerService } from './userController.service'; import { ViewedPagesControllerService } from './viewedPagesController.service'; +import { LegalBasisMappingControllerService } from './legalBasisMappingController.service'; export * from './dictionaryController.service'; -export * from './fileUploadController.service'; +export * from './fileManagementController.service'; export * from './licenseReportController.service'; @@ -41,10 +42,12 @@ export * from './versionsController.service'; export * from './viewedPagesController.service'; +export * from './legalBasisMappingController.service'; + export const APIS = [ DebugControllerService, DictionaryControllerService, - FileUploadControllerService, + FileManagementControllerService, LicenseReportControllerService, ManualRedactionControllerService, PdfMetaDataConfigurationControllerService, @@ -55,5 +58,6 @@ export const APIS = [ StatusControllerService, UserControllerService, VersionsControllerService, - ViewedPagesControllerService + ViewedPagesControllerService, + LegalBasisMappingControllerService ]; diff --git a/libs/red-ui-http/src/lib/api/fileUploadController.service.ts b/libs/red-ui-http/src/lib/api/fileManagementController.service.ts similarity index 84% rename from libs/red-ui-http/src/lib/api/fileUploadController.service.ts rename to libs/red-ui-http/src/lib/api/fileManagementController.service.ts index b3e992d12..47b59cc9b 100644 --- a/libs/red-ui-http/src/lib/api/fileUploadController.service.ts +++ b/libs/red-ui-http/src/lib/api/fileManagementController.service.ts @@ -16,6 +16,7 @@ import { CustomHttpUrlEncodingCodec } from '../encoder'; import { Observable } from 'rxjs'; +import { BulkDownloadRedactedRequest } from '../model/bulkDownloadRedactedRequest'; import { FileIds } from '../model/fileIds'; import { FileUploadResult } from '../model/fileUploadResult'; @@ -23,10 +24,10 @@ import { BASE_PATH } from '../variables'; import { Configuration } from '../configuration'; @Injectable() -export class FileUploadControllerService { +export class FileManagementControllerService { + protected basePath = ''; public defaultHeaders = new HttpHeaders(); public configuration = new Configuration(); - protected basePath = ''; constructor(protected httpClient: HttpClient, @Optional() @Inject(BASE_PATH) basePath: string, @Optional() configuration: Configuration) { if (basePath) { @@ -38,6 +39,20 @@ export class FileUploadControllerService { } } + /** + * @param consumes string[] mime-types + * @return true: consumes contains 'multipart/form-data', false: otherwise + */ + private canConsumeForm(consumes: string[]): boolean { + const form = 'multipart/form-data'; + for (const consume of consumes) { + if (form === consume) { + return true; + } + } + return false; + } + /** * Deletes a file for a given projectId and FileId * None @@ -47,11 +62,8 @@ export class FileUploadControllerService { * @param reportProgress flag to report request and response progress. */ public deleteFile(projectId: string, fileId: string, observe?: 'body', reportProgress?: boolean): Observable; - public deleteFile(projectId: string, fileId: string, observe?: 'response', reportProgress?: boolean): Observable>; - public deleteFile(projectId: string, fileId: string, observe?: 'events', reportProgress?: boolean): Observable>; - public deleteFile(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 deleteFile.'); @@ -282,6 +294,89 @@ export class FileUploadControllerService { }); } + /** + * Returns a downloadable byte stream of the requested files in a zip format + * Use the optional \"inline\" request parameter to select, if this report will be opened in the browser. + * @param body bulkDownloadRedactedRequest + * @param projectId The projectId + * @param inline inline + * @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 downloadRedactedFiles( + body: BulkDownloadRedactedRequest, + projectId: string, + inline?: boolean, + observe?: 'body', + reportProgress?: boolean + ): Observable; + public downloadRedactedFiles( + body: BulkDownloadRedactedRequest, + projectId: string, + inline?: boolean, + observe?: 'response', + reportProgress?: boolean + ): Observable>; + public downloadRedactedFiles( + body: BulkDownloadRedactedRequest, + projectId: string, + inline?: boolean, + observe?: 'events', + reportProgress?: boolean + ): Observable>; + public downloadRedactedFiles( + body: BulkDownloadRedactedRequest, + projectId: string, + inline?: boolean, + observe: any = 'body', + reportProgress: boolean = false + ): Observable { + if (body === null || body === undefined) { + throw new Error('Required parameter body was null or undefined when calling downloadRedactedFiles.'); + } + + if (projectId === null || projectId === undefined) { + throw new Error('Required parameter projectId was null or undefined when calling downloadRedactedFiles.'); + } + + let queryParameters = new HttpParams({ encoder: new CustomHttpUrlEncodingCodec() }); + if (inline !== undefined && inline !== null) { + queryParameters = queryParameters.set('inline', inline); + } + + 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[] = ['application/json']; + const httpContentTypeSelected: string | undefined = this.configuration.selectHeaderContentType(consumes); + if (httpContentTypeSelected !== undefined) { + headers = headers.set('Content-Type', httpContentTypeSelected); + } + + return this.httpClient.request('post', `${this.basePath}/download/bulk/redacted/${encodeURIComponent(String(projectId))}`, { + responseType: 'blob', + body: body, + params: queryParameters, + withCredentials: this.configuration.withCredentials, + headers: headers, + observe: observe, + reportProgress: reportProgress + }); + } + /** * Returns a downloadable byte stream of the redaction report file for the specified fileIds * Use the optional \"inline\" request parameter to select, if this report will be opened in the browser. @@ -291,11 +386,8 @@ export class FileUploadControllerService { * @param reportProgress flag to report request and response progress. */ public downloadRedactionReport(body: FileIds, inline?: boolean, observe?: 'body', reportProgress?: boolean): Observable; - public downloadRedactionReport(body: FileIds, inline?: boolean, observe?: 'response', reportProgress?: boolean): Observable>; - public downloadRedactionReport(body: FileIds, inline?: boolean, observe?: 'events', reportProgress?: boolean): Observable>; - public downloadRedactionReport(body: FileIds, inline?: boolean, observe: any = 'body', reportProgress: boolean = false): Observable { if (body === null || body === undefined) { throw new Error('Required parameter body was null or undefined when calling downloadRedactionReport.'); @@ -315,7 +407,7 @@ export class FileUploadControllerService { } // to determine the Accept header - const httpHeaderAccepts: string[] = ['application/octet-stream']; + const httpHeaderAccepts: string[] = ['*/*']; const httpHeaderAcceptSelected: string | undefined = this.configuration.selectHeaderAccept(httpHeaderAccepts); if (httpHeaderAcceptSelected !== undefined) { headers = headers.set('Accept', httpHeaderAcceptSelected); @@ -328,8 +420,7 @@ export class FileUploadControllerService { headers = headers.set('Content-Type', httpContentTypeSelected); } - return this.httpClient.request('post', `${this.basePath}/download/report`, { - responseType: 'blob', + return this.httpClient.request('post', `${this.basePath}/download/report`, { body: body, params: queryParameters, withCredentials: this.configuration.withCredentials, @@ -348,16 +439,13 @@ export class FileUploadControllerService { * @param reportProgress flag to report request and response progress. */ public downloadRedactionReportForProject(projectId: string, inline?: boolean, observe?: 'body', reportProgress?: boolean): Observable; - public downloadRedactionReportForProject( projectId: string, inline?: boolean, observe?: 'response', reportProgress?: boolean ): Observable>; - public downloadRedactionReportForProject(projectId: string, inline?: boolean, observe?: 'events', reportProgress?: boolean): Observable>; - public downloadRedactionReportForProject(projectId: string, inline?: boolean, observe: any = 'body', reportProgress: boolean = false): Observable { if (projectId === null || projectId === undefined) { throw new Error('Required parameter projectId was null or undefined when calling downloadRedactionReportForProject.'); @@ -377,7 +465,7 @@ export class FileUploadControllerService { } // to determine the Accept header - const httpHeaderAccepts: string[] = ['application/octet-stream']; + const httpHeaderAccepts: string[] = ['*/*']; const httpHeaderAcceptSelected: string | undefined = this.configuration.selectHeaderAccept(httpHeaderAccepts); if (httpHeaderAcceptSelected !== undefined) { headers = headers.set('Accept', httpHeaderAcceptSelected); @@ -386,8 +474,7 @@ export class FileUploadControllerService { // to determine the Content-Type header const consumes: string[] = []; - return this.httpClient.request('get', `${this.basePath}/download/report/${encodeURIComponent(String(projectId))}`, { - responseType: 'blob', + return this.httpClient.request('get', `${this.basePath}/download/report/${encodeURIComponent(String(projectId))}`, { params: queryParameters, withCredentials: this.configuration.withCredentials, headers: headers, @@ -405,11 +492,8 @@ export class FileUploadControllerService { * @param reportProgress flag to report request and response progress. */ public uploadFileForm(file: Blob, projectId: string, observe?: 'body', reportProgress?: boolean): Observable; - public uploadFileForm(file: Blob, projectId: string, observe?: 'response', reportProgress?: boolean): Observable>; - public uploadFileForm(file: Blob, projectId: string, observe?: 'events', reportProgress?: boolean): Observable>; - public uploadFileForm(file: Blob, projectId: string, observe: any = 'body', reportProgress: boolean = false): Observable { if (file === null || file === undefined) { throw new Error('Required parameter file was null or undefined when calling uploadFile.'); @@ -463,18 +547,4 @@ export class FileUploadControllerService { reportProgress: reportProgress }); } - - /** - * @param consumes string[] mime-types - * @return true: consumes contains 'multipart/form-data', false: otherwise - */ - private canConsumeForm(consumes: string[]): boolean { - const form = 'multipart/form-data'; - for (const consume of consumes) { - if (form === consume) { - return true; - } - } - return false; - } } diff --git a/libs/red-ui-http/src/lib/api/legalBasisMappingController.service.ts b/libs/red-ui-http/src/lib/api/legalBasisMappingController.service.ts new file mode 100644 index 000000000..b0ee87cdf --- /dev/null +++ b/libs/red-ui-http/src/lib/api/legalBasisMappingController.service.ts @@ -0,0 +1,134 @@ +/** + * API Documentation for Redaction Gateway + * Description for redaction + * + * OpenAPI spec version: 1.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ /* tslint:disable:no-unused-variable member-ordering */ + +import { Inject, Injectable, Optional } from '@angular/core'; +import { HttpClient, HttpEvent, HttpHeaders, HttpResponse } from '@angular/common/http'; + +import { Observable } from 'rxjs'; + +import { LegalBasisMapping } from '../model/legalBasisMapping'; + +import { BASE_PATH } from '../variables'; +import { Configuration } from '../configuration'; + +@Injectable() +export class LegalBasisMappingControllerService { + protected basePath = ''; + public defaultHeaders = new HttpHeaders(); + public configuration = new Configuration(); + + constructor(protected httpClient: HttpClient, @Optional() @Inject(BASE_PATH) basePath: string, @Optional() configuration: Configuration) { + if (basePath) { + this.basePath = basePath; + } + if (configuration) { + this.configuration = configuration; + this.basePath = basePath || configuration.basePath || this.basePath; + } + } + + /** + * @param consumes string[] mime-types + * @return true: consumes contains 'multipart/form-data', false: otherwise + */ + private canConsumeForm(consumes: string[]): boolean { + const form = 'multipart/form-data'; + for (const consume of consumes) { + if (form === consume) { + return true; + } + } + return false; + } + + /** + * Set the mapping between legal basis and redaction reason. + * None + * @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 getLegalBasisMapping(observe?: 'body', reportProgress?: boolean): Observable; + public getLegalBasisMapping(observe?: 'response', reportProgress?: boolean): Observable>; + public getLegalBasisMapping(observe?: 'events', reportProgress?: boolean): Observable>; + public getLegalBasisMapping(observe: any = 'body', reportProgress: boolean = false): Observable { + 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}/legalBasis`, { + withCredentials: this.configuration.withCredentials, + headers: headers, + observe: observe, + reportProgress: reportProgress + }); + } + + /** + * Set the mapping between legal basis and redaction reason. + * None + * @param body legalBasisMapping + * @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 setLegalBasisMapping(body: LegalBasisMapping, observe?: 'body', reportProgress?: boolean): Observable; + public setLegalBasisMapping(body: LegalBasisMapping, observe?: 'response', reportProgress?: boolean): Observable>; + public setLegalBasisMapping(body: LegalBasisMapping, observe?: 'events', reportProgress?: boolean): Observable>; + public setLegalBasisMapping(body: LegalBasisMapping, observe: any = 'body', reportProgress: boolean = false): Observable { + if (body === null || body === undefined) { + throw new Error('Required parameter body was null or undefined when calling setLegalBasisMapping.'); + } + + 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[] = ['application/json']; + const httpContentTypeSelected: string | undefined = this.configuration.selectHeaderContentType(consumes); + if (httpContentTypeSelected !== undefined) { + headers = headers.set('Content-Type', httpContentTypeSelected); + } + + return this.httpClient.request('post', `${this.basePath}/legalBasis`, { + body: body, + withCredentials: this.configuration.withCredentials, + headers: headers, + observe: observe, + reportProgress: reportProgress + }); + } +} diff --git a/libs/red-ui-http/src/lib/api/redactionLogController.service.ts b/libs/red-ui-http/src/lib/api/redactionLogController.service.ts index 018520a15..b927ab456 100644 --- a/libs/red-ui-http/src/lib/api/redactionLogController.service.ts +++ b/libs/red-ui-http/src/lib/api/redactionLogController.service.ts @@ -16,21 +16,18 @@ import { HttpClient, HttpEvent, HttpHeaders, HttpResponse } from '@angular/commo import { Observable } from 'rxjs'; import { RedactionLog } from '../model/redactionLog'; +import { SectionGrid } from '../model/sectionGrid'; import { BASE_PATH } from '../variables'; import { Configuration } from '../configuration'; @Injectable() export class RedactionLogControllerService { + protected basePath = ''; public defaultHeaders = new HttpHeaders(); public configuration = new Configuration(); - protected basePath = ''; - constructor( - protected httpClient: HttpClient, - @Optional() @Inject(BASE_PATH) basePath: string, - @Optional() configuration: Configuration - ) { + constructor(protected httpClient: HttpClient, @Optional() @Inject(BASE_PATH) basePath: string, @Optional() configuration: Configuration) { if (basePath) { this.basePath = basePath; } @@ -40,77 +37,6 @@ export class RedactionLogControllerService { } } - /** - * Gets the redaction log for a fileId - * None - * @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 getRedactionLog( - fileId: string, - observe?: 'body', - reportProgress?: boolean - ): Observable; - - public getRedactionLog( - fileId: string, - observe?: 'response', - reportProgress?: boolean - ): Observable>; - - public getRedactionLog( - fileId: string, - observe?: 'events', - reportProgress?: boolean - ): Observable>; - - public getRedactionLog( - fileId: string, - observe: any = 'body', - reportProgress: boolean = false - ): Observable { - if (fileId === null || fileId === undefined) { - throw new Error( - 'Required parameter fileId was null or undefined when calling getRedactionLog.' - ); - } - - 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}/redactionLog/${encodeURIComponent(String(fileId))}`, - { - withCredentials: this.configuration.withCredentials, - headers: headers, - observe: observe, - reportProgress: reportProgress - } - ); - } - /** * @param consumes string[] mime-types * @return true: consumes contains 'multipart/form-data', false: otherwise @@ -124,4 +50,86 @@ export class RedactionLogControllerService { } return false; } + + /** + * Gets the redaction log for a fileId + * None + * @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 getRedactionLog(fileId: string, observe?: 'body', reportProgress?: boolean): Observable; + public getRedactionLog(fileId: string, observe?: 'response', reportProgress?: boolean): Observable>; + public getRedactionLog(fileId: string, observe?: 'events', reportProgress?: boolean): Observable>; + public getRedactionLog(fileId: string, observe: any = 'body', reportProgress: boolean = false): Observable { + if (fileId === null || fileId === undefined) { + throw new Error('Required parameter fileId was null or undefined when calling getRedactionLog.'); + } + + 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}/redactionLog/${encodeURIComponent(String(fileId))}`, { + withCredentials: this.configuration.withCredentials, + headers: headers, + observe: observe, + reportProgress: reportProgress + }); + } + + /** + * Gets the section grid for a fileId + * None + * @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 getSectionGrid(fileId: string, observe?: 'body', reportProgress?: boolean): Observable; + public getSectionGrid(fileId: string, observe?: 'response', reportProgress?: boolean): Observable>; + public getSectionGrid(fileId: string, observe?: 'events', reportProgress?: boolean): Observable>; + public getSectionGrid(fileId: string, observe: any = 'body', reportProgress: boolean = false): Observable { + if (fileId === null || fileId === undefined) { + throw new Error('Required parameter fileId was null or undefined when calling getSectionGrid.'); + } + + 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}/sectionGrid/${encodeURIComponent(String(fileId))}`, { + withCredentials: this.configuration.withCredentials, + headers: headers, + observe: observe, + reportProgress: reportProgress + }); + } } diff --git a/libs/red-ui-http/src/lib/model/bulkDownloadRedactedRequest.ts b/libs/red-ui-http/src/lib/model/bulkDownloadRedactedRequest.ts new file mode 100644 index 000000000..5b7c64b63 --- /dev/null +++ b/libs/red-ui-http/src/lib/model/bulkDownloadRedactedRequest.ts @@ -0,0 +1,15 @@ +/** + * API Documentation for Redaction Gateway + * Description for redaction + * + * OpenAPI spec version: 1.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +export interface BulkDownloadRedactedRequest { + fileIds?: Array; +} diff --git a/libs/red-ui-http/src/lib/model/cellRectangle.ts b/libs/red-ui-http/src/lib/model/cellRectangle.ts new file mode 100644 index 000000000..791a61ce3 --- /dev/null +++ b/libs/red-ui-http/src/lib/model/cellRectangle.ts @@ -0,0 +1,18 @@ +/** + * API Documentation for Redaction Gateway + * Description for redaction + * + * OpenAPI spec version: 1.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ +import { Point } from './point'; + +export interface CellRectangle { + height?: number; + topLeft?: Point; + width?: number; +} diff --git a/libs/red-ui-http/src/lib/model/legalBasisMapping.ts b/libs/red-ui-http/src/lib/model/legalBasisMapping.ts new file mode 100644 index 000000000..36ea765d0 --- /dev/null +++ b/libs/red-ui-http/src/lib/model/legalBasisMapping.ts @@ -0,0 +1,15 @@ +/** + * API Documentation for Redaction Gateway + * Description for redaction + * + * OpenAPI spec version: 1.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +export interface LegalBasisMapping { + reasonByLegalBasis?: any; +} diff --git a/libs/red-ui-http/src/lib/model/models.ts b/libs/red-ui-http/src/lib/model/models.ts index 4347ac83f..8dddf2752 100644 --- a/libs/red-ui-http/src/lib/model/models.ts +++ b/libs/red-ui-http/src/lib/model/models.ts @@ -35,3 +35,8 @@ export * from './versionsResponse'; export * from './viewedPages'; export * from './viewedPagesRequest'; export * from './approveRequest'; +export * from './bulkDownloadRedactedRequest'; +export * from './sectionGrid'; +export * from './sectionRectangle'; +export * from './legalBasisMapping'; +export * from './cellRectangle'; diff --git a/libs/red-ui-http/src/lib/model/sectionGrid.ts b/libs/red-ui-http/src/lib/model/sectionGrid.ts new file mode 100644 index 000000000..dc9f397d6 --- /dev/null +++ b/libs/red-ui-http/src/lib/model/sectionGrid.ts @@ -0,0 +1,16 @@ +/** + * API Documentation for Redaction Gateway + * Description for redaction + * + * OpenAPI spec version: 1.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ +import { SectionRectangle } from './sectionRectangle'; + +export interface SectionGrid { + rectanglesPerPage?: { [key: string]: Array }; +} diff --git a/libs/red-ui-http/src/lib/model/sectionRectangle.ts b/libs/red-ui-http/src/lib/model/sectionRectangle.ts new file mode 100644 index 000000000..a41abfe76 --- /dev/null +++ b/libs/red-ui-http/src/lib/model/sectionRectangle.ts @@ -0,0 +1,22 @@ +/** + * API Documentation for Redaction Gateway + * Description for redaction + * + * OpenAPI spec version: 1.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ +import { CellRectangle } from './cellRectangle'; +import { Point } from './point'; + +export interface SectionRectangle { + height?: number; + numberOfParts?: number; + part?: number; + tableCells?: Array; + topLeft?: Point; + width?: number; +}