diff --git a/projects/netgrif-components-core/src/lib/actions/front-action.module.ts b/projects/netgrif-components-core/src/lib/actions/front-action.module.ts index 926acea17..c45918912 100644 --- a/projects/netgrif-components-core/src/lib/actions/front-action.module.ts +++ b/projects/netgrif-components-core/src/lib/actions/front-action.module.ts @@ -1,7 +1,7 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import {FrontActionRegistryService} from "../registry/front-action-registry.service"; -import {redirectAction} from "./model/router-action-definitions"; +import {redirectAction, snackBarAction} from "./model/router-action-definitions"; import {reloadTaskAction, validateTaskAction} from "./model/task-action-definitions"; @NgModule({ @@ -16,5 +16,6 @@ export class FrontActionModule { frontActionsRegistry.register('redirect', redirectAction); frontActionsRegistry.register('validate', validateTaskAction); frontActionsRegistry.register('reloadTask', reloadTaskAction); + frontActionsRegistry.register('snackBar', snackBarAction); } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/file-field/file-default-field/abstract-file-default-field.component.spec.ts b/projects/netgrif-components-core/src/lib/data-fields/file-field/file-default-field/abstract-file-default-field.component.spec.ts index e66f177b5..ee15de46e 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/file-field/file-default-field/abstract-file-default-field.component.spec.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/file-field/file-default-field/abstract-file-default-field.component.spec.ts @@ -16,9 +16,6 @@ import {MockUserResourceService} from "../../../utility/tests/mocks/mock-user-re import {ConfigurationService} from "../../../configuration/configuration.service"; import {TestConfigurationService} from "../../../utility/tests/test-config"; import {Component, CUSTOM_ELEMENTS_SCHEMA, Inject, Optional} from "@angular/core"; -import {BrowserDynamicTestingModule} from "@angular/platform-browser-dynamic/testing"; -import {ErrorSnackBarComponent} from "../../../snack-bar/components/error-snack-bar/error-snack-bar.component"; -import {SuccessSnackBarComponent} from "../../../snack-bar/components/success-snack-bar/success-snack-bar.component"; import {TaskResourceService} from "../../../resources/engine-endpoint/task-resource.service"; import {LoggerService} from "../../../logger/services/logger.service"; import {SnackBarService} from "../../../snack-bar/services/snack-bar.service"; @@ -29,6 +26,7 @@ import {AbstractFileDefaultFieldComponent} from "./abstract-file-default-field.c import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../../models/data-field-portal-data-injection-token"; import {FormControl} from "@angular/forms"; import {WrappedBoolean} from "../../data-field-template/models/wrapped-boolean"; +import {FrontActionService} from "../../../actions/services/front-action.service"; describe('AbstractFileDefaultFieldComponent', () => { let component: TestFileComponent; @@ -48,6 +46,7 @@ describe('AbstractFileDefaultFieldComponent', () => { providers: [ SideMenuService, EventService, + FrontActionService, {provide: AuthenticationMethodService, useClass: MockAuthenticationMethodService}, {provide: AuthenticationService, useClass: MockAuthenticationService}, {provide: UserResourceService, useClass: MockUserResourceService}, @@ -97,8 +96,9 @@ class TestFileComponent extends AbstractFileDefaultFieldComponent { translate: TranslateService, sanitizer: DomSanitizer, eventService: EventService, + frontActionService: FrontActionService, @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(taskResourceService, log, snackbar, translate, eventService, sanitizer, dataFieldPortalData); + super(taskResourceService, log, snackbar, translate, eventService, sanitizer, frontActionService, dataFieldPortalData); } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/file-field/file-default-field/abstract-file-default-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/file-field/file-default-field/abstract-file-default-field.component.ts index 690a84ab7..75342fcba 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/file-field/file-default-field/abstract-file-default-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/file-field/file-default-field/abstract-file-default-field.component.ts @@ -26,6 +26,8 @@ import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../../models/data-fie import {FILE_FIELD_HEIGHT, FILE_FIELD_PADDING, PREVIEW, PREVIEW_BUTTON} from '../models/file-field-constants'; import {FileFieldRequest} from "../../../resources/interface/file-field-request-body"; import {AbstractFileFieldDefaultComponent} from '../../models/abstract-file-field-default-component'; +import {FrontAction} from "../../models/changed-fields"; +import {FrontActionService} from "../../../actions/services/front-action.service"; export interface FileState { progress: number; @@ -114,6 +116,7 @@ export abstract class AbstractFileDefaultFieldComponent extends AbstractFileFiel protected _translate: TranslateService, protected _eventService: EventService, protected _sanitizer: DomSanitizer, + protected _frontActionService: FrontActionService, @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { super(_log, _snackbar, _translate, dataFieldPortalData); this.state = this.defaultState; @@ -217,60 +220,68 @@ export abstract class AbstractFileDefaultFieldComponent extends AbstractFileFiel fileFormData.append('file', fileToUpload); fileFormData.append('data', new Blob([JSON.stringify(this.createRequestBody())], {type: 'application/json'})); this._taskResourceService.uploadFile(this.taskId, fileFormData, false) - .subscribe((response: EventOutcomeMessageResource) => { - if ((response as ProviderProgress).type && (response as ProviderProgress).type === ProgressType.UPLOAD) { - this.state.progress = (response as ProviderProgress).progress; - } else { - this.state.completed = true; - this.state.uploading = false; - this.state.progress = 0; + .subscribe({ + next: (response: EventOutcomeMessageResource) => { + if ((response as ProviderProgress).type && (response as ProviderProgress).type === ProgressType.UPLOAD) { + this.state.progress = (response as ProviderProgress).progress; + } else { + this.state.completed = true; + this.state.uploading = false; + this.state.progress = 0; - if (response.error) { - this.state.error = true; - this._log.error( - `File [${this.dataField.stringId}] ${this.fileUploadEl.nativeElement.files.item(0)} uploading has failed!`, response.error - ); if (response.error) { - this._snackbar.openErrorSnackBar(this._translate.instant(response.error)); + this.state.error = true; + this._log.error( + `File [${this.dataField.stringId}] ${this.fileUploadEl.nativeElement.files.item(0)} uploading has failed!`, response.error + ); + if (response.error) { + this._snackbar.openErrorSnackBar(this._translate.instant(response.error)); + } else { + this._snackbar.openErrorSnackBar(this._translate.instant('dataField.snackBar.fileUploadFailed')); + } } else { - this._snackbar.openErrorSnackBar(this._translate.instant('dataField.snackBar.fileUploadFailed')); + const changedFieldsMap: ChangedFieldsMap = this._eventService.parseChangedFieldsFromOutcomeTree(response.outcome); + this.dataField.emitChangedFields(changedFieldsMap); + this._log.debug( + `File [${this.dataField.stringId}] ${this.fileUploadEl.nativeElement.files.item(0).name} was successfully uploaded` + ); + this.state.error = false; + this.dataField.downloaded = false; + this.dataField.value.name = fileToUpload.name; + if (this.isFilePreview) { + this.initializePreviewIfDisplayable(); + } + this.fullSource.next(undefined); + this.fileForDownload = undefined; + this.formControlRef.setValue(this.dataField.value.name); + this._snackbar.openSuccessSnackBar(!!response.outcome.message ? response.outcome.message : this._translate.instant('tasks.snackbar.dataSaved')); + const frontActions: Array = this._eventService.parseFrontActionsFromOutcomeTree(response.outcome); + if (frontActions?.length > 0) { + this._frontActionService.runAll(frontActions); + } } + this.dataField.touch = true; + this.dataField.update(); + this.fileUploadEl.nativeElement.value = ''; + } + }, + error: (error) => { + this.state.completed = true; + this.state.error = true; + this.state.uploading = false; + this.state.progress = 0; + this._log.error( + `File [${this.dataField.stringId}] ${this.fileUploadEl.nativeElement.files.item(0)} uploading has failed!`, error + ); + if (error?.error?.message) { + this._snackbar.openErrorSnackBar(this._translate.instant(error.error.message)); } else { - const changedFieldsMap: ChangedFieldsMap = this._eventService.parseChangedFieldsFromOutcomeTree(response.outcome); - this.dataField.emitChangedFields(changedFieldsMap); - this._log.debug( - `File [${this.dataField.stringId}] ${this.fileUploadEl.nativeElement.files.item(0).name} was successfully uploaded` - ); - this.state.error = false; - this.dataField.downloaded = false; - this.dataField.value.name = fileToUpload.name; - if (this.isFilePreview) { - this.initializePreviewIfDisplayable(); - } - this.fullSource.next(undefined); - this.fileForDownload = undefined; - this.formControlRef.setValue(this.dataField.value.name); + this._snackbar.openErrorSnackBar(this._translate.instant('dataField.snackBar.fileUploadFailed')); } this.dataField.touch = true; this.dataField.update(); this.fileUploadEl.nativeElement.value = ''; } - }, error => { - this.state.completed = true; - this.state.error = true; - this.state.uploading = false; - this.state.progress = 0; - this._log.error( - `File [${this.dataField.stringId}] ${this.fileUploadEl.nativeElement.files.item(0)} uploading has failed!`, error - ); - if (error?.error?.message) { - this._snackbar.openErrorSnackBar(this._translate.instant(error.error.message)); - } else { - this._snackbar.openErrorSnackBar(this._translate.instant('dataField.snackBar.fileUploadFailed')); - } - this.dataField.touch = true; - this.dataField.update(); - this.fileUploadEl.nativeElement.value = ''; }); } @@ -410,7 +421,8 @@ export abstract class AbstractFileDefaultFieldComponent extends AbstractFileFiel this.state.downloading = true; let params = new HttpParams() params = params.set("fieldId", this.dataField.stringId); - this._taskResourceService.downloadFilePreview(this.resolveParentTaskId(), params).subscribe(response => { if (response instanceof Blob) { + this._taskResourceService.downloadFilePreview(this.resolveParentTaskId(), params).subscribe(response => { + if (response instanceof Blob) { this._log.debug(`Preview of file [${this.dataField.stringId}] ${this.dataField.value.name} was successfully downloaded`); this.fileForPreview = new Blob([response], {type: 'application/octet-stream'}); this.previewSource = this._sanitizer.bypassSecurityTrustUrl(URL.createObjectURL(this.fileForPreview)); @@ -445,7 +457,8 @@ export abstract class AbstractFileDefaultFieldComponent extends AbstractFileFiel } let params = new HttpParams(); params = params.set("fieldId", this.dataField.stringId); - this._taskResourceService.downloadFile(this.resolveParentTaskId(), params).subscribe(response => { if (!(response as ProviderProgress).type || (response as ProviderProgress).type !== ProgressType.DOWNLOAD) { + this._taskResourceService.downloadFile(this.resolveParentTaskId(), params).subscribe(response => { + if (!(response as ProviderProgress).type || (response as ProviderProgress).type !== ProgressType.DOWNLOAD) { this._log.debug(`File [${this.dataField.stringId}] ${this.dataField.value.name} was successfully downloaded`); this.initDownloadFile(response); } diff --git a/projects/netgrif-components-core/src/lib/data-fields/file-list-field/file-list-default-field/abstract-file-list-default-field.component.spec.ts b/projects/netgrif-components-core/src/lib/data-fields/file-list-field/file-list-default-field/abstract-file-list-default-field.component.spec.ts index e03a36ea6..2d9bb5574 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/file-list-field/file-list-default-field/abstract-file-list-default-field.component.spec.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/file-list-field/file-list-default-field/abstract-file-list-default-field.component.spec.ts @@ -16,9 +16,6 @@ import {MockUserResourceService} from "../../../utility/tests/mocks/mock-user-re import {ConfigurationService} from "../../../configuration/configuration.service"; import {TestConfigurationService} from "../../../utility/tests/test-config"; import {Component, CUSTOM_ELEMENTS_SCHEMA, Inject, Optional} from "@angular/core"; -import {BrowserDynamicTestingModule} from "@angular/platform-browser-dynamic/testing"; -import {ErrorSnackBarComponent} from "../../../snack-bar/components/error-snack-bar/error-snack-bar.component"; -import {SuccessSnackBarComponent} from "../../../snack-bar/components/success-snack-bar/success-snack-bar.component"; import {TaskResourceService} from "../../../resources/engine-endpoint/task-resource.service"; import {LoggerService} from "../../../logger/services/logger.service"; import {SnackBarService} from "../../../snack-bar/services/snack-bar.service"; @@ -28,6 +25,7 @@ import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../../models/data-fie import {AbstractFileListDefaultFieldComponent} from "./abstract-file-list-default-field.component"; import {FormControl} from "@angular/forms"; import {WrappedBoolean} from "../../data-field-template/models/wrapped-boolean"; +import {FrontActionService} from "../../../actions/services/front-action.service"; describe('AbstractFileListDefaultFieldComponent', () => { let component: TestFileListComponent; @@ -46,6 +44,7 @@ describe('AbstractFileListDefaultFieldComponent', () => { providers: [ SideMenuService, EventService, + FrontActionService, {provide: AuthenticationMethodService, useClass: MockAuthenticationMethodService}, {provide: AuthenticationService, useClass: MockAuthenticationService}, {provide: UserResourceService, useClass: MockUserResourceService}, @@ -94,8 +93,9 @@ class TestFileListComponent extends AbstractFileListDefaultFieldComponent { snackbar: SnackBarService, translate: TranslateService, eventService: EventService, + frontActionService: FrontActionService, @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(taskResourceService, log, snackbar, translate, eventService, dataFieldPortalData); + super(taskResourceService, log, snackbar, translate, eventService, frontActionService, dataFieldPortalData); } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/file-list-field/file-list-default-field/abstract-file-list-default-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/file-list-field/file-list-default-field/abstract-file-list-default-field.component.ts index 9fb99c8ee..7513b72e7 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/file-list-field/file-list-default-field/abstract-file-list-default-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/file-list-field/file-list-default-field/abstract-file-list-default-field.component.ts @@ -1,13 +1,10 @@ import { AfterViewInit, Component, - ElementRef, Inject, - Input, OnDestroy, OnInit, Optional, - ViewChild } from "@angular/core"; import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../../models/data-field-portal-data-injection-token"; import {FileListField, FileListFieldValidation} from "../models/file-list-field"; @@ -17,16 +14,16 @@ import {LoggerService} from "../../../logger/services/logger.service"; import {SnackBarService} from "../../../snack-bar/services/snack-bar.service"; import {TranslateService} from "@ngx-translate/core"; import {EventService} from "../../../event/services/event.service"; -import {FileFieldIdBody} from "../../models/file-field-id-body"; import {EventOutcomeMessageResource} from "../../../resources/interface/message-resource"; import {ProgressType, ProviderProgress} from "../../../resources/resource-provider.service"; import {ChangedFieldsMap} from "../../../event/services/interfaces/changed-fields-map"; import {HttpParams} from "@angular/common/http"; import {take} from "rxjs/operators"; import {FileFieldValue} from "../../file-field/models/file-field-value"; -import {AbstractBaseDataFieldComponent} from "../../base-component/abstract-base-data-field.component"; import {FileFieldRequest} from "../../../resources/interface/file-field-request-body"; import {AbstractFileFieldDefaultComponent} from '../../models/abstract-file-field-default-component'; +import {FrontAction} from "../../models/changed-fields"; +import {FrontActionService} from "../../../actions/services/front-action.service"; export interface FilesState { progress: number; @@ -60,6 +57,7 @@ export abstract class AbstractFileListDefaultFieldComponent extends AbstractFile protected _snackbar: SnackBarService, protected _translate: TranslateService, protected _eventService: EventService, + protected _frontActionService: FrontActionService, @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { super(_log, _snackbar, _translate, dataFieldPortalData); this.state = this.defaultState; @@ -171,58 +169,66 @@ export abstract class AbstractFileListDefaultFieldComponent extends AbstractFile fieldId: this.dataField.stringId, } fileFormData.append('data', new Blob([JSON.stringify(requestBody)], {type: 'application/json'})); - this._taskResourceService.uploadFile(this.taskId, fileFormData, true).subscribe((response: EventOutcomeMessageResource) => { - if ((response as ProviderProgress).type && (response as ProviderProgress).type === ProgressType.UPLOAD) { - this.state.progress = (response as ProviderProgress).progress; - } else { - this.state.completed = true; - this.state.uploading = false; - this.state.progress = 0; - this._log.debug( - `Files [${this.dataField.stringId}] were successfully uploaded` - ); - if (response.error) { - this.state.error = true; - this._log.error( - `File [${this.dataField.stringId}] ${this.fileUploadEl.nativeElement.files.item(0)} uploading has failed!`, response.error + this._taskResourceService.uploadFile(this.taskId, fileFormData, true) + .subscribe({ + next: (response: EventOutcomeMessageResource) => { + if ((response as ProviderProgress).type && (response as ProviderProgress).type === ProgressType.UPLOAD) { + this.state.progress = (response as ProviderProgress).progress; + } else { + this.state.completed = true; + this.state.uploading = false; + this.state.progress = 0; + this._log.debug( + `Files [${this.dataField.stringId}] were successfully uploaded` ); if (response.error) { - this._snackbar.openErrorSnackBar(this._translate.instant(response.error)); + this.state.error = true; + this._log.error( + `File [${this.dataField.stringId}] ${this.fileUploadEl.nativeElement.files.item(0)} uploading has failed!`, response.error + ); + if (response.error) { + this._snackbar.openErrorSnackBar(this._translate.instant(response.error)); + } else { + this._snackbar.openErrorSnackBar(this._translate.instant('dataField.snackBar.fileUploadFailed')); + } } else { - this._snackbar.openErrorSnackBar(this._translate.instant('dataField.snackBar.fileUploadFailed')); + const changedFieldsMap: ChangedFieldsMap = this._eventService.parseChangedFieldsFromOutcomeTree(response.outcome); + this.dataField.emitChangedFields(changedFieldsMap); + this.state.error = false; + filesToUpload.forEach(fileToUpload => { + this.uploadedFiles.push(fileToUpload.name); + this.dataField.value.namesPaths.push({name: fileToUpload.name}); + this.formControlRef.setValue(this.dataField.value.namesPaths.map(namePath => { + return namePath['name']; + }).join('/')); + }); + this._snackbar.openSuccessSnackBar(!!response.outcome.message ? response.outcome.message : this._translate.instant('tasks.snackbar.dataSaved')); + const frontActions: Array = this._eventService.parseFrontActionsFromOutcomeTree(response.outcome); + if (frontActions?.length > 0) { + this._frontActionService.runAll(frontActions); + } } + this.dataField.touch = true; + this.dataField.update(); + this.fileUploadEl.nativeElement.value = ''; + } + }, error: (error) => { + this.state.completed = true; + this.state.error = true; + this.state.uploading = false; + this.state.progress = 0; + if (error?.error?.message) { + this._snackbar.openErrorSnackBar(this._translate.instant(error.error.message)); } else { - const changedFieldsMap: ChangedFieldsMap = this._eventService.parseChangedFieldsFromOutcomeTree(response.outcome); - this.dataField.emitChangedFields(changedFieldsMap); - this.state.error = false; - filesToUpload.forEach(fileToUpload => { - this.uploadedFiles.push(fileToUpload.name); - this.dataField.value.namesPaths.push({name: fileToUpload.name}); - this.formControlRef.setValue(this.dataField.value.namesPaths.map(namePath => { - return namePath['name']; - }).join('/')); - }); + this._snackbar.openErrorSnackBar(this._translate.instant('dataField.snackBar.fileUploadFailed')); } + this._log.error( + `File [${this.dataField.stringId}] ${this.fileUploadEl.nativeElement.files.item(0)} uploading has failed!`, error + ); this.dataField.touch = true; this.dataField.update(); this.fileUploadEl.nativeElement.value = ''; } - }, error => { - this.state.completed = true; - this.state.error = true; - this.state.uploading = false; - this.state.progress = 0; - if (error?.error?.message) { - this._snackbar.openErrorSnackBar(this._translate.instant(error.error.message)); - } else { - this._snackbar.openErrorSnackBar(this._translate.instant('dataField.snackBar.fileUploadFailed')); - } - this._log.error( - `File [${this.dataField.stringId}] ${this.fileUploadEl.nativeElement.files.item(0)} uploading has failed!`, error - ); - this.dataField.touch = true; - this.dataField.update(); - this.fileUploadEl.nativeElement.value = ''; }); } diff --git a/projects/netgrif-components/src/lib/data-fields/file-field/file-default-field/file-default-field.component.ts b/projects/netgrif-components/src/lib/data-fields/file-field/file-default-field/file-default-field.component.ts index 378008fd9..f770cc156 100644 --- a/projects/netgrif-components/src/lib/data-fields/file-field/file-default-field/file-default-field.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/file-field/file-default-field/file-default-field.component.ts @@ -5,7 +5,7 @@ import { LoggerService, SnackBarService, TaskResourceService, - AbstractFileDefaultFieldComponent + AbstractFileDefaultFieldComponent, FrontActionService } from "@netgrif/components-core"; import {TranslateService} from "@ngx-translate/core"; import {DomSanitizer} from "@angular/platform-browser"; @@ -26,8 +26,9 @@ export class FileDefaultFieldComponent extends AbstractFileDefaultFieldComponent eventService: EventService, protected _sanitizer: DomSanitizer, protected dialog: MatDialog, + frontActionService: FrontActionService, @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(taskResourceService, log, snackbar, translate, eventService, _sanitizer, dataFieldPortalData); + super(taskResourceService, log, snackbar, translate, eventService, _sanitizer, frontActionService, dataFieldPortalData); } public showPreviewDialog() { diff --git a/projects/netgrif-components/src/lib/data-fields/file-list-field/file-list-default-field/file-list-default-field.component.ts b/projects/netgrif-components/src/lib/data-fields/file-list-field/file-list-default-field/file-list-default-field.component.ts index 9a4d00a7f..e581ce13b 100644 --- a/projects/netgrif-components/src/lib/data-fields/file-list-field/file-list-default-field/file-list-default-field.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/file-list-field/file-list-default-field/file-list-default-field.component.ts @@ -7,7 +7,7 @@ import { EventService, DATA_FIELD_PORTAL_DATA, DataFieldPortalData, - FileListField, AbstractFileListDefaultFieldComponent + FileListField, AbstractFileListDefaultFieldComponent, FrontActionService } from '@netgrif/components-core' @Component({ @@ -22,7 +22,8 @@ export class FileListDefaultFieldComponent extends AbstractFileListDefaultFieldC snackbar: SnackBarService, translate: TranslateService, eventService: EventService, + frontActionService: FrontActionService, @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(taskResourceService, log, snackbar, translate, eventService, dataFieldPortalData); + super(taskResourceService, log, snackbar, translate, eventService, frontActionService, dataFieldPortalData); } }