refactor: clean up upload error handling and improve UI translations

- Removed the FileUploadErrorPipe and its associated tests to streamline error handling.
- Updated the upload button and file uploading list row components to enhance translation handling for error messages.
- Adjusted HTML templates to ensure consistent spacing in static titles.
- Minor refactoring in the file uploading list row component to introduce a new method for error key retrieval.
This commit is contained in:
Denys Vuika
2026-02-25 15:42:14 +00:00
parent 5194777451
commit 7f19c6661c
10 changed files with 25 additions and 106 deletions
@@ -76,7 +76,7 @@
<div>
<ng-container *ngIf="isUploadEnabled()">
<adf-upload-button
[staticTitle]="'FORM.FIELD.UPLOAD' | translate "
[staticTitle]="'FORM.FIELD.UPLOAD' | translate"
[multipleFiles]="isMultipleSelection()"
[rootFolderId]="currentDirectoryId"
[disabled]="isNotAllowedToUpload()"
@@ -89,8 +89,8 @@
role="status"
class="adf-file-uploading-row__block adf-file-uploading-row__status--error">
<mat-icon
[attr.aria-label]="'ADF_FILE_UPLOAD.ARIA-LABEL.UPLOAD_FILE_ERROR' | translate: { error: file.errorCode | adfFileUploadError }"
[title]="file.errorCode | adfFileUploadError"
[attr.aria-label]="'ADF_FILE_UPLOAD.ARIA-LABEL.UPLOAD_FILE_ERROR' | translate: { error: getFileUploadErrorKey(file.errorCode) | translate }"
[title]="getFileUploadErrorKey(file.errorCode) | translate"
adf-icon="report_problem"
matListItemIcon
/>
@@ -24,11 +24,10 @@ import { MatChipsModule } from '@angular/material/chips';
import { TranslatePipe } from '@ngx-translate/core';
import { ToggleIconDirective } from '../directives/toggle-icon.directive';
import { MatButtonModule } from '@angular/material/button';
import { FileUploadErrorPipe } from '../pipes/file-upload-error.pipe';
@Component({
selector: 'adf-file-uploading-list-row',
imports: [IconModule, MatListModule, MatChipsModule, TranslatePipe, ToggleIconDirective, FileSizePipe, MatButtonModule, FileUploadErrorPipe],
imports: [IconModule, MatListModule, MatChipsModule, TranslatePipe, ToggleIconDirective, FileSizePipe, MatButtonModule],
templateUrl: './file-uploading-list-row.component.html',
styleUrls: ['./file-uploading-list-row.component.scss'],
encapsulation: ViewEncapsulation.None
@@ -83,4 +82,8 @@ export class FileUploadingListRowComponent {
isUploadVersionComplete(): boolean {
return this.file?.status === FileUploadStatus.Complete && this.isUploadVersion();
}
getFileUploadErrorKey(errorCode: number): string {
return `FILE_UPLOAD.ERRORS.${errorCode || 'GENERIC'}`;
}
}
@@ -21,7 +21,7 @@
<span id="upload-single-file-label">{{ 'FILE_UPLOAD.BUTTON.UPLOAD_FILE' | translate }}</span>
}
@if (staticTitle) {
<span id="upload-single-file-label-static">{{ staticTitle }}</span>
<span id="upload-single-file-label-static"> {{ staticTitle }}</span>
}
</label>
}
@@ -43,7 +43,7 @@
<span id="upload-multiple-file-label">{{ 'FILE_UPLOAD.BUTTON.UPLOAD_FILE' | translate }}</span>
}
@if (staticTitle) {
<span id="upload-multiple-file-label-static">{{ staticTitle }}</span>
<span id="upload-multiple-file-label-static"> {{ staticTitle }}</span>
}
</label>
}
@@ -69,7 +69,7 @@
<span id="uploadFolder-label">{{ 'FILE_UPLOAD.BUTTON.UPLOAD_FOLDER' | translate }}</span>
}
@if (staticTitle) {
<span id="uploadFolder-label-static">{{ staticTitle }}</span>
<span id="uploadFolder-label-static"> {{ staticTitle }}</span>
}
</label>
}
@@ -1,52 +0,0 @@
/*!
* @license
* Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { NoopTranslateModule } from '@alfresco/adf-core';
import { FileUploadErrorPipe } from './file-upload-error.pipe';
import { TestBed } from '@angular/core/testing';
describe('FileUploadErrorPipe', () => {
let pipe: FileUploadErrorPipe;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [NoopTranslateModule],
providers: [FileUploadErrorPipe]
});
pipe = TestBed.inject(FileUploadErrorPipe);
});
it('should return generic message when error code is null', () => {
expect(pipe.transform(null)).toBe('FILE_UPLOAD.ERRORS.GENERIC');
});
it('should return 500 message', () => {
expect(pipe.transform(500)).toBe('FILE_UPLOAD.ERRORS.500');
});
it('should return 504 message', () => {
expect(pipe.transform(504)).toBe('FILE_UPLOAD.ERRORS.504');
});
it('should return 403 message', () => {
expect(pipe.transform(403)).toBe('FILE_UPLOAD.ERRORS.403');
});
it('should return 404 message', () => {
expect(pipe.transform(404)).toBe('FILE_UPLOAD.ERRORS.404');
});
});
@@ -1,31 +0,0 @@
/*!
* @license
* Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Pipe, PipeTransform, inject } from '@angular/core';
import { TranslationService } from '@alfresco/adf-core';
@Pipe({
name: 'adfFileUploadError',
pure: true
})
export class FileUploadErrorPipe implements PipeTransform {
private readonly translation = inject(TranslationService);
transform(errorCode: number): string {
return this.translation.instant(`FILE_UPLOAD.ERRORS.${errorCode || 'GENERIC'}`);
}
}
@@ -26,8 +26,6 @@ export * from './components/upload-files.event';
export * from './directives/file-draggable.directive';
export * from './directives/toggle-icon.directive';
export * from './pipes/file-upload-error.pipe';
export * from './components/base-upload/upload-base';
export * from './upload.module';
@@ -22,12 +22,10 @@ import { FileUploadingListComponent } from './components/file-uploading-list.com
import { UploadButtonComponent } from './components/upload-button.component';
import { UploadVersionButtonComponent } from './components/upload-version-button.component';
import { UploadDragAreaComponent } from './components/upload-drag-area.component';
import { FileUploadErrorPipe } from './pipes/file-upload-error.pipe';
import { FileDraggableDirective } from './directives/file-draggable.directive';
import { ToggleIconDirective } from './directives/toggle-icon.directive';
export const CONTENT_UPLOAD_DIRECTIVES = [
FileUploadErrorPipe,
FileDraggableDirective,
ToggleIconDirective,
UploadDragAreaComponent,
@@ -48,6 +48,7 @@ import { AlfrescoViewerComponent } from './alfresco-viewer.component';
import { RenditionService } from '../../common/services/rendition.service';
import { NodeActionsService } from '../../document-list/services/node-actions.service';
import { provideApiTesting } from '../../testing/providers';
import { MatIconTestingModule } from '@angular/material/icon/testing';
@Component({
selector: 'adf-viewer-container-toolbar',
@@ -179,7 +180,7 @@ describe('AlfrescoViewerComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [NoopAuthModule, NoopTranslateModule, MatDialogModule, AlfrescoViewerComponent],
imports: [NoopAuthModule, MatIconTestingModule, NoopTranslateModule, MatDialogModule, AlfrescoViewerComponent],
providers: [
provideApiTesting(),
{
@@ -33,6 +33,7 @@ import { ViewerWithCustomToolbarActionsComponent } from './mock/adf-viewer-conta
import { ViewerWithCustomToolbarComponent } from './mock/adf-viewer-container-toolbar.component.mock';
import { ViewerComponent } from './viewer.component';
import { ThumbnailService } from '../../common/services/thumbnail.service';
import { MatIconTestingModule } from '@angular/material/icon/testing';
@Component({
selector: 'adf-dialog-dummy',
@@ -71,6 +72,7 @@ describe('ViewerComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
MatIconTestingModule,
ViewerWithCustomToolbarComponent,
ViewerWithCustomSidebarComponent,
ViewerWithCustomOpenWithComponent,
@@ -106,8 +108,8 @@ describe('ViewerComponent', () => {
describe('Mime Type Test', () => {
it('should mimeType change when blobFile changes', () => {
const mockSimpleChanges: SimpleChanges = {
blobFile: new SimpleChange(null, { type: 'image/png' }, true)
const mockSimpleChanges: SimpleChanges = {
blobFile: new SimpleChange(null, { type: 'image/png' }, true)
};
component.ngOnChanges(mockSimpleChanges);
@@ -117,9 +119,9 @@ describe('ViewerComponent', () => {
it('should set mimeTypeIconUrl when mimeType changes and no nodeMimeType is provided', () => {
spyOn(thumbnailService, 'getMimeTypeIcon').and.returnValue('image/png');
const mockSimpleChanges: SimpleChanges = {
mimeType: new SimpleChange(null, 'image/png', true),
nodeMimeType: undefined
const mockSimpleChanges: SimpleChanges = {
mimeType: new SimpleChange(null, 'image/png', true),
nodeMimeType: undefined
};
component.ngOnChanges(mockSimpleChanges);
@@ -130,9 +132,9 @@ describe('ViewerComponent', () => {
it('should set mimeTypeIconUrl when nodeMimeType changes', () => {
spyOn(thumbnailService, 'getMimeTypeIcon').and.returnValue('application/pdf');
const mockSimpleChanges: SimpleChanges = {
mimeType: new SimpleChange(null, 'image/png', true),
nodeMimeType: new SimpleChange(null, 'application/pdf', true)
const mockSimpleChanges: SimpleChanges = {
mimeType: new SimpleChange(null, 'image/png', true),
nodeMimeType: new SimpleChange(null, 'application/pdf', true)
};
component.ngOnChanges(mockSimpleChanges);
@@ -531,8 +533,8 @@ describe('ViewerComponent', () => {
});
it('should file name be present if is overlay mode ', async () => {
const mockSimpleChanges: SimpleChanges = {
blobFile: new SimpleChange(null, { type: 'image/png' }, true)
const mockSimpleChanges: SimpleChanges = {
blobFile: new SimpleChange(null, { type: 'image/png' }, true)
};
component.ngOnChanges(mockSimpleChanges);
fixture.detectChanges();