Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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({
Expand All @@ -16,5 +16,6 @@ export class FrontActionModule {
frontActionsRegistry.register('redirect', redirectAction);
frontActionsRegistry.register('validate', validateTaskAction);
frontActionsRegistry.register('reloadTask', reloadTaskAction);
frontActionsRegistry.register('snackBar', snackBarAction);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export class FrontActionService {
const fn = this._frontActionRegistry.get(frontAction.id)
if (!fn) {
this._log.error("Frontend action is not defined for ID [" + frontAction.id +"]")
return;
}
fn.call(this._injector, frontAction)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -29,6 +26,8 @@ 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";
import {MockTaskResourceService} from "../../../utility/tests/mocks/mock-task-resource.service";

describe('AbstractFileDefaultFieldComponent', () => {
let component: TestFileComponent;
Expand All @@ -48,10 +47,12 @@ describe('AbstractFileDefaultFieldComponent', () => {
providers: [
SideMenuService,
EventService,
FrontActionService,
{provide: AuthenticationMethodService, useClass: MockAuthenticationMethodService},
{provide: AuthenticationService, useClass: MockAuthenticationService},
{provide: UserResourceService, useClass: MockUserResourceService},
{provide: ConfigurationService, useClass: TestConfigurationService},
{provide: TaskResourceService, useClass: MockTaskResourceService},
{provide: DATA_FIELD_PORTAL_DATA, useValue: {
dataField: new FileField('', '', {
required: true,
Expand Down Expand Up @@ -81,14 +82,57 @@ describe('AbstractFileDefaultFieldComponent', () => {
expect(component).toBeTruthy();
});


it('should simulate file download', () => {
// Spy on the 'download' method
spyOn(component, 'download').and.callFake(() => {
// Simulate the download process
const anchor = document.createElement('a');
anchor.href = 'data:text/plain;charset=utf-8,' + encodeURIComponent('mockContent');
anchor.download = 'mockFile.txt';
document.body.appendChild(anchor);
anchor.click();
document.body.removeChild(anchor);
});

// Call the 'download' method
component.download();

// Assert that the 'download' method was called
expect(component.download).toHaveBeenCalled();
});

it('should simulate file upload', () => {
// Create a mock file
const mockFile = new File(['mockContent'], 'mockFile.txt', {type: 'text/plain'});

// Get the file input element's reference
const fileInput = component.fileUploadEl.nativeElement;

// Create a DataTransfer object to simulate file selection
const dataTransfer = new DataTransfer();
dataTransfer.items.add(mockFile);
fileInput.files = dataTransfer.files;
component.dataField.value = {file: mockFile, name: "mockFile.txt"}
// Trigger the file upload method
spyOn(component, 'upload').and.callThrough();
const uploadButtonEvent = new Event('change');
fileInput.dispatchEvent(uploadButtonEvent);
component.upload();

// Assertions
expect(component.upload).toHaveBeenCalled();
expect(component.dataField.value).toBeTruthy(); // Ensure value is processed
});

afterEach(() => {
TestBed.resetTestingModule();
});
});

@Component({
selector: 'ncc-test-file',
template: ''
template: '<input type="file" #fileUploadInput name="fileUpload" [multiple]="true" accept="{{dataField.allowTypes}}" class="invisible-input"/>'
})
class TestFileComponent extends AbstractFileDefaultFieldComponent {
constructor(taskResourceService: TaskResourceService,
Expand All @@ -97,8 +141,9 @@ class TestFileComponent extends AbstractFileDefaultFieldComponent {
translate: TranslateService,
sanitizer: DomSanitizer,
eventService: EventService,
frontActionService: FrontActionService,
@Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData<FileField>) {
super(taskResourceService, log, snackbar, translate, eventService, sanitizer, dataFieldPortalData);
super(taskResourceService, log, snackbar, translate, eventService, sanitizer, frontActionService, dataFieldPortalData);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
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;
Expand Down Expand Up @@ -114,6 +116,7 @@
protected _translate: TranslateService,
protected _eventService: EventService,
protected _sanitizer: DomSanitizer,
protected _frontActionService: FrontActionService,
@Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData<FileField>) {
super(_log, _snackbar, _translate, dataFieldPortalData);
this.state = this.defaultState;
Expand Down Expand Up @@ -217,60 +220,65 @@
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.state.error = true;
this._log.error(
`File [${this.dataField.stringId}] ${this.fileUploadEl.nativeElement.files.item(0)?.name} uploading has failed!`, response.error
);
Comment thread
coderabbitai[bot] marked this conversation as resolved.
this._snackbar.openErrorSnackBar(this._translate.instant(response.error));

} else {
this._snackbar.openErrorSnackBar(this._translate.instant('dataField.snackBar.fileUploadFailed'));
this._log.debug(
Comment thread
machacjozef marked this conversation as resolved.
`File [${this.dataField.stringId}] ${this.fileUploadEl.nativeElement.files.item(0)?.name} was successfully uploaded`
);
const changedFieldsMap: ChangedFieldsMap = this._eventService.parseChangedFieldsFromOutcomeTree(response.outcome);
this.dataField.emitChangedFields(changedFieldsMap);
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'));

Check warning on line 254 in projects/netgrif-components-core/src/lib/data-fields/file-field/file-default-field/abstract-file-default-field.component.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Unexpected negated condition.

See more on https://sonarcloud.io/project/issues?id=netgrif_components&issues=AZ3O0hl5cCPq9sm4VVs5&open=AZ3O0hl5cCPq9sm4VVs5&pullRequest=326

Check warning on line 254 in projects/netgrif-components-core/src/lib/data-fields/file-field/file-default-field/abstract-file-default-field.component.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Redundant double negation.

See more on https://sonarcloud.io/project/issues?id=netgrif_components&issues=AZ3O0hl5cCPq9sm4VVs6&open=AZ3O0hl5cCPq9sm4VVs6&pullRequest=326
const frontActions: Array<FrontAction> = this._eventService.parseFrontActionsFromOutcomeTree(response.outcome);
if (frontActions?.length > 0) {
this._frontActionService.runAll(frontActions);
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}
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)?.name} 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 = '';
});
}

Expand Down Expand Up @@ -410,7 +418,8 @@
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 => {

Check warning on line 421 in projects/netgrif-components-core/src/lib/data-fields/file-field/file-default-field/abstract-file-default-field.component.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

'(next?: (value: Blob | ProviderProgress) => void, error?: (error: any) => void, complete?: () => void): Subscription' is deprecated.

See more on https://sonarcloud.io/project/issues?id=netgrif_components&issues=AZ3O0hl5cCPq9sm4VVs7&open=AZ3O0hl5cCPq9sm4VVs7&pullRequest=326
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));
Expand Down Expand Up @@ -445,7 +454,8 @@
}
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 => {

Check warning on line 457 in projects/netgrif-components-core/src/lib/data-fields/file-field/file-default-field/abstract-file-default-field.component.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

'(next?: (value: Blob | ProviderProgress) => void, error?: (error: any) => void, complete?: () => void): Subscription' is deprecated.

See more on https://sonarcloud.io/project/issues?id=netgrif_components&issues=AZ3O0hl5cCPq9sm4VVs8&open=AZ3O0hl5cCPq9sm4VVs8&pullRequest=326
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);
}
Expand Down
Loading
Loading