mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2026-09-09 18:03:21 +00:00
ACS-11224 Migrate upload components to Angular control flow (#11691)
This commit is contained in:
@@ -1,74 +1,79 @@
|
||||
<nav
|
||||
*ngIf="folderNode"
|
||||
data-automation-id="breadcrumb"
|
||||
class="adf-breadcrumb-container"
|
||||
role="navigation"
|
||||
[attr.aria-label]="'BREADCRUMB.ARIA-LABEL.BREADCRUMB' | translate"
|
||||
>
|
||||
<button
|
||||
*ngIf="hasPreviousNodes()"
|
||||
tabindex="0"
|
||||
class="adf-breadcrumb-dropdown-trigger"
|
||||
(click)="open()"
|
||||
[attr.aria-label]="'BREADCRUMB.ARIA-LABEL.DROPDOWN' | translate"
|
||||
@if (folderNode) {
|
||||
<nav
|
||||
data-automation-id="breadcrumb"
|
||||
class="adf-breadcrumb-container"
|
||||
role="navigation"
|
||||
[attr.aria-label]="'BREADCRUMB.ARIA-LABEL.BREADCRUMB' | translate"
|
||||
>
|
||||
<div class="adf-breadcrumb-dropdown-trigger-icon">
|
||||
<mat-icon [class.adf-isRoot]="!hasPreviousNodes()" adf-icon="folder" />
|
||||
<mat-icon [class.adf-isRoot]="!hasPreviousNodes()" class="adf-breadcrumb-dropdown-trigger-arrow" adf-icon="arrow_drop_down" />
|
||||
</div>
|
||||
</button>
|
||||
@if (hasPreviousNodes()) {
|
||||
<button
|
||||
tabindex="0"
|
||||
class="adf-breadcrumb-dropdown-trigger"
|
||||
(click)="open()"
|
||||
[attr.aria-label]="'BREADCRUMB.ARIA-LABEL.DROPDOWN' | translate"
|
||||
>
|
||||
<div class="adf-breadcrumb-dropdown-trigger-icon">
|
||||
<mat-icon [class.adf-isRoot]="!hasPreviousNodes()" adf-icon="folder" />
|
||||
<mat-icon [class.adf-isRoot]="!hasPreviousNodes()" class="adf-breadcrumb-dropdown-trigger-arrow" adf-icon="arrow_drop_down" />
|
||||
</div>
|
||||
</button>
|
||||
<mat-select
|
||||
#dropdown
|
||||
class="adf-breadcrumb-dropdown-path"
|
||||
tabindex="-1"
|
||||
role="button"
|
||||
>
|
||||
@for (node of previousNodes; track node.id) {
|
||||
<mat-option
|
||||
(click)="onRoutePathClick(node, $event)"
|
||||
(onSelectionChange)="onRouteClick(node)"
|
||||
class="adf-breadcrumb-path-option"
|
||||
[disabled]="readOnly"
|
||||
>
|
||||
{{ node.name ?? '' | translate }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
}
|
||||
|
||||
<mat-select
|
||||
#dropdown
|
||||
*ngIf="hasPreviousNodes()"
|
||||
class="adf-breadcrumb-dropdown-path"
|
||||
tabindex="-1"
|
||||
role="button"
|
||||
>
|
||||
<mat-option
|
||||
*ngFor="let node of previousNodes"
|
||||
(click)="onRoutePathClick(node, $event)"
|
||||
(onSelectionChange)="onRouteClick(node)"
|
||||
class="adf-breadcrumb-path-option"
|
||||
[disabled]="readOnly"
|
||||
@for (item of lastNodes; track item.id; let last = $last) {
|
||||
<div
|
||||
[class.adf-active]="last"
|
||||
title="{{ item.name ?? '' | translate }}"
|
||||
class="adf-breadcrumb-item">
|
||||
@if (breadcrumbItemIsAnchor(last)) {
|
||||
<a
|
||||
href="#"
|
||||
[attr.data-automation-id]="'breadcrumb_' + item.name"
|
||||
class="adf-breadcrumb-item-anchor"
|
||||
(click)="onRoutePathClick(item, $event)"
|
||||
>
|
||||
{{ item.name ?? '' | translate }}
|
||||
</a>
|
||||
} @else {
|
||||
<div class="adf-breadcrumb-item-current" aria-current="location">
|
||||
{{ (selectedRowItemsCount < 1 ? item.name ?? '' : 'BREADCRUMB.HEADER.SELECTED') | translate: { count: selectedRowItemsCount } }}
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (!last) {
|
||||
<mat-icon class="adf-breadcrumb-item-chevron" adf-icon="chevron_right" />
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</nav>
|
||||
|
||||
@if (!folderNode && hasRoot) {
|
||||
<nav
|
||||
data-automation-id="breadcrumb"
|
||||
role="navigation"
|
||||
[attr.aria-label]="'BREADCRUMB.ARIA-LABEL.BREADCRUMB' | translate"
|
||||
>
|
||||
{{ node.name | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
|
||||
<div
|
||||
*ngFor="let item of lastNodes; let last = last"
|
||||
[class.adf-active]="last"
|
||||
[ngSwitch]="breadcrumbItemIsAnchor(last)"
|
||||
title="{{ item.name | translate }}"
|
||||
class="adf-breadcrumb-item">
|
||||
<a
|
||||
*ngSwitchCase="true"
|
||||
href="#"
|
||||
[attr.data-automation-id]="'breadcrumb_' + item.name"
|
||||
class="adf-breadcrumb-item-anchor"
|
||||
(click)="onRoutePathClick(item, $event)"
|
||||
>
|
||||
{{ item.name | translate }}
|
||||
</a>
|
||||
|
||||
<div *ngSwitchDefault class="adf-breadcrumb-item-current" aria-current="location">
|
||||
{{ (selectedRowItemsCount < 1 ? item.name : 'BREADCRUMB.HEADER.SELECTED') | translate: { count: selectedRowItemsCount } }}
|
||||
</div>
|
||||
|
||||
<mat-icon class="adf-breadcrumb-item-chevron" *ngIf="!last" adf-icon="chevron_right" />
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<nav
|
||||
*ngIf="!folderNode && hasRoot"
|
||||
data-automation-id="breadcrumb"
|
||||
role="navigation"
|
||||
[attr.aria-label]="'BREADCRUMB.ARIA-LABEL.BREADCRUMB' | translate"
|
||||
>
|
||||
<div class="adf-breadcrumb-item adf-active" role="group">
|
||||
<div class="adf-breadcrumb-item-current">
|
||||
{{ root | translate }}
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="adf-breadcrumb-item adf-active" role="group">
|
||||
<div class="adf-breadcrumb-item-current">
|
||||
{{ root ?? '' | translate }}
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,6 @@ import {
|
||||
import { MatSelect, MatSelectModule } from '@angular/material/select';
|
||||
import { Node, PathElement } from '@alfresco/js-api';
|
||||
import { DocumentListComponent } from '../document-list/components/document-list.component';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { TranslatePipe, TranslateService } from '@ngx-translate/core';
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
import { IconModule } from '@alfresco/adf-core';
|
||||
@@ -39,7 +38,7 @@ import { LiveAnnouncer } from '@angular/cdk/a11y';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-breadcrumb',
|
||||
imports: [CommonModule, IconModule, TranslatePipe, MatSelectModule],
|
||||
imports: [IconModule, TranslatePipe, MatSelectModule],
|
||||
templateUrl: './breadcrumb.component.html',
|
||||
styleUrls: ['./breadcrumb.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
|
||||
@@ -1,29 +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 { NgModule } from '@angular/core';
|
||||
import { BreadcrumbComponent } from './breadcrumb.component';
|
||||
import { DropdownBreadcrumbComponent } from './dropdown-breadcrumb.component';
|
||||
|
||||
export const BREADCRUMB_DIRECTIVES = [BreadcrumbComponent, DropdownBreadcrumbComponent] as const;
|
||||
|
||||
/** @deprecated use `...BREADCRUMB_DIRECTIVES` instead */
|
||||
@NgModule({
|
||||
imports: [...BREADCRUMB_DIRECTIVES],
|
||||
exports: [...BREADCRUMB_DIRECTIVES]
|
||||
})
|
||||
export class BreadcrumbModule {}
|
||||
@@ -1,48 +1,47 @@
|
||||
<nav *ngIf="route.length > 0" class="adf-dropdown-breadcrumb-container"
|
||||
role="navigation"
|
||||
[attr.aria-label]="'BREADCRUMB.ARIA-LABEL.BREADCRUMB' | translate">
|
||||
|
||||
@if (route.length > 0) {
|
||||
<nav class="adf-dropdown-breadcrumb-container"
|
||||
role="navigation"
|
||||
[attr.aria-label]="'BREADCRUMB.ARIA-LABEL.BREADCRUMB' | translate">
|
||||
<button
|
||||
id="dropdown-breadcrumb-button"
|
||||
[tabindex]="hasPreviousNodes() ? 0 : -1"
|
||||
class="adf-dropdown-breadcrumb-trigger"
|
||||
(click)="open()"
|
||||
[attr.aria-label]="'BREADCRUMB.ARIA-LABEL.DROPDOWN' | translate:{ folderName: currentNode?.name }"
|
||||
[attr.aria-haspopup]="hasPreviousNodes() ? 'true' : null"
|
||||
[attr.aria-expanded]="dropdown?.panelOpen || false"
|
||||
data-automation-id="dropdown-breadcrumb-trigger">
|
||||
<mat-icon class="adf-dropdown-breadcrumb-icon" [class.adf-isRoot]="!hasPreviousNodes()" adf-icon="folder" />
|
||||
id="dropdown-breadcrumb-button"
|
||||
[tabindex]="hasPreviousNodes() ? 0 : -1"
|
||||
class="adf-dropdown-breadcrumb-trigger"
|
||||
(click)="open()"
|
||||
[attr.aria-label]="'BREADCRUMB.ARIA-LABEL.DROPDOWN' | translate:{ folderName: currentNode?.name }"
|
||||
[attr.aria-haspopup]="hasPreviousNodes() ? 'true' : null"
|
||||
[attr.aria-expanded]="dropdown?.panelOpen || false"
|
||||
data-automation-id="dropdown-breadcrumb-trigger">
|
||||
<mat-icon class="adf-dropdown-breadcrumb-icon" [class.adf-isRoot]="!hasPreviousNodes()" adf-icon="folder" />
|
||||
</button>
|
||||
|
||||
<mat-icon class="adf-dropdown-breadcrumb-icon adf-dropdown-breadcrumb-item-chevron" adf-icon="chevron_right" />
|
||||
|
||||
<div class="adf-dropdown-breadcrumb-path">
|
||||
@if (hasPreviousNodes()) {
|
||||
<mat-select
|
||||
#dropdown
|
||||
*ngIf="hasPreviousNodes()"
|
||||
panelClass="adf-breadcrumb-dropdown-panel"
|
||||
class="adf-dropdown-breadcrumb-path-select"
|
||||
tabindex="-1"
|
||||
role="button"
|
||||
data-automation-id="dropdown-breadcrumb-path"
|
||||
aria-labelledby="dropdown-breadcrumb-button">
|
||||
|
||||
#dropdown
|
||||
panelClass="adf-breadcrumb-dropdown-panel"
|
||||
class="adf-dropdown-breadcrumb-path-select"
|
||||
tabindex="-1"
|
||||
role="button"
|
||||
data-automation-id="dropdown-breadcrumb-path"
|
||||
aria-labelledby="dropdown-breadcrumb-button">
|
||||
@for (node of previousNodes; track node.id) {
|
||||
<mat-option
|
||||
*ngFor="let node of previousNodes;"
|
||||
(click)="onRoutePathClick(node, $event)"
|
||||
(onSelectionChange)="onRouteClick(node)"
|
||||
class="adf-dropdown-breadcrumb-path-option adf-dropdown-breadcrumb-path-option-node"
|
||||
data-automation-class="dropdown-breadcrumb-path-option"
|
||||
[disabled]="readOnly">
|
||||
{{ node.name | translate }}
|
||||
(click)="onRoutePathClick(node, $event)"
|
||||
(onSelectionChange)="onRouteClick(node)"
|
||||
class="adf-dropdown-breadcrumb-path-option adf-dropdown-breadcrumb-path-option-node"
|
||||
data-automation-class="dropdown-breadcrumb-path-option"
|
||||
[disabled]="readOnly">
|
||||
{{ node.name ?? '' | translate }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
}
|
||||
</div>
|
||||
|
||||
<span
|
||||
class="adf-current-folder"
|
||||
[class.adf-isRoot]="!hasPreviousNodes()"
|
||||
data-automation-id="current-folder"
|
||||
aria-current="location">{{ currentNode.name }}
|
||||
class="adf-current-folder"
|
||||
[class.adf-isRoot]="!hasPreviousNodes()"
|
||||
data-automation-id="current-folder"
|
||||
aria-current="location">{{ currentNode.name }}
|
||||
</span>
|
||||
</nav>
|
||||
</nav>
|
||||
}
|
||||
|
||||
@@ -19,13 +19,13 @@ import { Component, OnChanges, ViewChild, ViewEncapsulation } from '@angular/cor
|
||||
import { MatSelect, MatSelectModule } from '@angular/material/select';
|
||||
import { PathElement, Node } from '@alfresco/js-api';
|
||||
import { BreadcrumbComponent } from './breadcrumb.component';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { TranslatePipe } from '@ngx-translate/core';
|
||||
import { IconModule } from '@alfresco/adf-core';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-dropdown-breadcrumb',
|
||||
imports: [CommonModule, IconModule, MatSelectModule, TranslatePipe],
|
||||
imports: [IconModule, MatSelectModule, TranslatePipe],
|
||||
templateUrl: './dropdown-breadcrumb.component.html',
|
||||
styleUrls: ['./dropdown-breadcrumb.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
|
||||
@@ -17,5 +17,3 @@
|
||||
|
||||
export * from './breadcrumb.component';
|
||||
export * from './dropdown-breadcrumb.component';
|
||||
|
||||
export * from './breadcrumb.module';
|
||||
|
||||
@@ -1,39 +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 { Person } from '@alfresco/js-api';
|
||||
|
||||
export const fakeEcmUser: Person = {
|
||||
id: 'fake-id',
|
||||
firstName: 'fake-ecm-first-name',
|
||||
lastName: 'fake-ecm-last-name',
|
||||
description: 'i am a fake user for test',
|
||||
avatarId: 'fake-avatar-id',
|
||||
email: 'fakeEcm@ecmUser.com',
|
||||
skypeId: 'fake-skype-id',
|
||||
googleId: 'fake-googleId-id',
|
||||
instantMessageId: 'fake-instantMessageId-id',
|
||||
company: null,
|
||||
jobTitle: 'job-ecm-test',
|
||||
location: 'fake location',
|
||||
mobile: '000000000',
|
||||
telephone: '11111111',
|
||||
statusUpdatedAt: new Date(),
|
||||
userStatus: 'active',
|
||||
enabled: true,
|
||||
emailNotificationsEnabled: true
|
||||
};
|
||||
@@ -41,4 +41,3 @@ export * from './models/allowable-operations.enum';
|
||||
export * from './interfaces/search-configuration.interface';
|
||||
export * from './interfaces/saved-search.interface';
|
||||
export * from './interfaces/saved-searches-strategy.interface';
|
||||
export * from './mocks/ecm-user.service.mock';
|
||||
|
||||
@@ -15,17 +15,37 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { fakeEcmUser } from '../mocks/ecm-user.service.mock';
|
||||
import { RedirectAuthService } from '@alfresco/adf-core';
|
||||
import { PeopleContentQueryRequestModel, PeopleContentService } from './people-content.service';
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { PersonPaging } from '@alfresco/js-api';
|
||||
import { Person, PersonPaging } from '@alfresco/js-api';
|
||||
import { provideHttpClient } from '@angular/common/http';
|
||||
import { provideHttpClientTesting } from '@angular/common/http/testing';
|
||||
import { EMPTY, firstValueFrom, of } from 'rxjs';
|
||||
import { AlfrescoApiService } from '../../services';
|
||||
import { AlfrescoApiServiceMock } from '../../mock';
|
||||
|
||||
const fakeEcmUser: Person = {
|
||||
id: 'fake-id',
|
||||
firstName: 'fake-ecm-first-name',
|
||||
lastName: 'fake-ecm-last-name',
|
||||
description: 'i am a fake user for test',
|
||||
avatarId: 'fake-avatar-id',
|
||||
email: 'fakeEcm@ecmUser.com',
|
||||
skypeId: 'fake-skype-id',
|
||||
googleId: 'fake-googleId-id',
|
||||
instantMessageId: 'fake-instantMessageId-id',
|
||||
company: null,
|
||||
jobTitle: 'job-ecm-test',
|
||||
location: 'fake location',
|
||||
mobile: '000000000',
|
||||
telephone: '11111111',
|
||||
statusUpdatedAt: new Date(),
|
||||
userStatus: 'active',
|
||||
enabled: true,
|
||||
emailNotificationsEnabled: true
|
||||
};
|
||||
|
||||
export const fakeEcmUser2 = {
|
||||
id: 'another-fake-id',
|
||||
firstName: 'another-fake-first-name',
|
||||
|
||||
+1
-1
@@ -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()"
|
||||
|
||||
@@ -21,7 +21,6 @@ import { MatDatetimepickerModule, MatNativeDatetimeModule } from '@mat-datetimep
|
||||
import { CONTENT_TAG_DIRECTIVES } from './tag/tag.module';
|
||||
import { DOCUMENT_LIST_DIRECTIVES } from './document-list/document-list.module';
|
||||
import { CONTENT_SEARCH_DIRECTIVES } from './search/search.module';
|
||||
import { BREADCRUMB_DIRECTIVES } from './breadcrumb/breadcrumb.module';
|
||||
import { CONTENT_VERSION_DIRECTIVES } from './version-manager/version-manager.module';
|
||||
import { CONTENT_NODE_SELECTOR_DIRECTIVES } from './content-node-selector/content-node-selector.module';
|
||||
import { CONTENT_NODE_SHARE_DIRECTIVES } from './content-node-share/content-node-share.module';
|
||||
@@ -34,17 +33,8 @@ import { versionCompatibilityFactory } from './version-compatibility/version-com
|
||||
import { VersionCompatibilityService } from './version-compatibility/version-compatibility.service';
|
||||
import { contentAuthLoaderFactory } from './auth-loader/content-auth-loader-factory';
|
||||
import { ContentAuthLoaderService } from './auth-loader/content-auth-loader.service';
|
||||
import { CategoriesManagementComponent } from './category';
|
||||
import { TreeComponent } from './tree';
|
||||
import { NewVersionUploaderDialogComponent } from './new-version-uploader';
|
||||
import { VersionCompatibilityDirective } from './version-compatibility';
|
||||
import { CONTENT_UPLOAD_DIRECTIVES } from './upload';
|
||||
import { TreeViewComponent } from './tree-view';
|
||||
import { NodeCommentsComponent } from './node-comments';
|
||||
import { AlfrescoViewerComponent } from './viewer';
|
||||
import { ContentTypeDialogComponent } from './content-type';
|
||||
import { MaterialModule } from './material.module';
|
||||
import { AlfrescoIconComponent } from './alfresco-icon/alfresco-icon.component';
|
||||
import { AlfrescoApiService } from './services/alfresco-api.service';
|
||||
import { AlfrescoApiNoAuthService } from './api-factories/alfresco-api-no-auth.service';
|
||||
import { AlfrescoApiLoaderService, createAlfrescoApiInstance } from './api-factories/alfresco-api-v2-loader.service';
|
||||
@@ -59,23 +49,13 @@ import { AlfrescoApiLoaderService, createAlfrescoApiInstance } from './api-facto
|
||||
...CONTENT_SEARCH_DIRECTIVES,
|
||||
...DOCUMENT_LIST_DIRECTIVES,
|
||||
...CONTENT_UPLOAD_DIRECTIVES,
|
||||
...BREADCRUMB_DIRECTIVES,
|
||||
...CONTENT_NODE_SELECTOR_DIRECTIVES,
|
||||
...CONTENT_NODE_SHARE_DIRECTIVES,
|
||||
...CONTENT_METADATA_DIRECTIVES,
|
||||
...CONTENT_DIRECTIVES,
|
||||
...CONTENT_PERMISSION_MANAGER_DIRECTIVES,
|
||||
...CONTENT_VERSION_DIRECTIVES,
|
||||
TreeViewComponent,
|
||||
ContentTypeDialogComponent,
|
||||
...ASPECT_LIST_DIRECTIVES,
|
||||
VersionCompatibilityDirective,
|
||||
NodeCommentsComponent,
|
||||
TreeComponent,
|
||||
AlfrescoViewerComponent,
|
||||
CategoriesManagementComponent,
|
||||
NewVersionUploaderDialogComponent,
|
||||
AlfrescoIconComponent
|
||||
...ASPECT_LIST_DIRECTIVES
|
||||
],
|
||||
providers: [provideTranslations('adf-content-services', 'assets/adf-content-services')],
|
||||
exports: [
|
||||
@@ -84,7 +64,6 @@ import { AlfrescoApiLoaderService, createAlfrescoApiInstance } from './api-facto
|
||||
...DOCUMENT_LIST_DIRECTIVES,
|
||||
...CONTENT_UPLOAD_DIRECTIVES,
|
||||
...CONTENT_SEARCH_DIRECTIVES,
|
||||
...BREADCRUMB_DIRECTIVES,
|
||||
...CONTENT_NODE_SELECTOR_DIRECTIVES,
|
||||
...CONTENT_NODE_SHARE_DIRECTIVES,
|
||||
...CONTENT_METADATA_DIRECTIVES,
|
||||
@@ -92,16 +71,7 @@ import { AlfrescoApiLoaderService, createAlfrescoApiInstance } from './api-facto
|
||||
...CONTENT_DIRECTIVES,
|
||||
...CONTENT_PERMISSION_MANAGER_DIRECTIVES,
|
||||
...CONTENT_VERSION_DIRECTIVES,
|
||||
TreeViewComponent,
|
||||
...ASPECT_LIST_DIRECTIVES,
|
||||
ContentTypeDialogComponent,
|
||||
VersionCompatibilityDirective,
|
||||
NodeCommentsComponent,
|
||||
TreeComponent,
|
||||
AlfrescoViewerComponent,
|
||||
CategoriesManagementComponent,
|
||||
NewVersionUploaderDialogComponent,
|
||||
AlfrescoIconComponent
|
||||
...ASPECT_LIST_DIRECTIVES
|
||||
]
|
||||
})
|
||||
export class ContentModule {
|
||||
|
||||
+104
-103
@@ -1,116 +1,117 @@
|
||||
<div *ngIf="canShowDialog()"
|
||||
role="dialog"
|
||||
[attr.aria-label]="'ADF_FILE_UPLOAD.ARIA-LABEL.DIALOG'| translate"
|
||||
tabindex="0"
|
||||
class="adf-upload-dialog"
|
||||
id="upload-dialog"
|
||||
[class.adf-upload-dialog--minimized]="isDialogMinimized">
|
||||
@if (canShowDialog()) {
|
||||
<div
|
||||
#uploadDialog
|
||||
role="dialog"
|
||||
[attr.aria-label]="'ADF_FILE_UPLOAD.ARIA-LABEL.DIALOG'| translate"
|
||||
tabindex="0"
|
||||
class="adf-upload-dialog"
|
||||
id="upload-dialog"
|
||||
[class.adf-upload-dialog--minimized]="isDialogMinimized">
|
||||
<header class="adf-upload-dialog__header">
|
||||
<button
|
||||
mat-icon-button
|
||||
class="adf-upload-dialog__header-button"
|
||||
[attr.data-automation-id]="'adf-upload-dialog__toggle-minimize'"
|
||||
[attr.aria-label]="(isDialogMinimized ?
|
||||
'ADF_FILE_UPLOAD.ARIA-LABEL.DIALOG_MAXIMIZE':
|
||||
'ADF_FILE_UPLOAD.ARIA-LABEL.DIALOG_MINIMIZE') | translate"
|
||||
[disabled]="isConfirmation"
|
||||
[attr.aria-expanded]="!isDialogMinimized"
|
||||
(click)="toggleMinimized()">
|
||||
<mat-icon class="adf-upload-dialog__header-button-icon" [adf-icon]="isDialogMinimized ? 'keyboard_arrow_up' : 'keyboard_arrow_down'" />
|
||||
</button>
|
||||
<button
|
||||
mat-icon-button
|
||||
class="adf-upload-dialog__header-button"
|
||||
[attr.data-automation-id]="'adf-upload-dialog__toggle-minimize'"
|
||||
[attr.aria-label]="(isDialogMinimized ?
|
||||
'ADF_FILE_UPLOAD.ARIA-LABEL.DIALOG_MAXIMIZE':
|
||||
'ADF_FILE_UPLOAD.ARIA-LABEL.DIALOG_MINIMIZE') | translate"
|
||||
[disabled]="isConfirmation"
|
||||
[attr.aria-expanded]="!isDialogMinimized"
|
||||
(click)="toggleMinimized()">
|
||||
<mat-icon class="adf-upload-dialog__header-button-icon" [adf-icon]="isDialogMinimized ? 'keyboard_arrow_up' : 'keyboard_arrow_down'" />
|
||||
</button>
|
||||
|
||||
<span
|
||||
class="adf-upload-dialog__title"
|
||||
*ngIf="!uploadList.isUploadCancelled()">
|
||||
@if (uploadList.isUploadCancelled()) {
|
||||
<span class="adf-upload-dialog__title">
|
||||
{{ 'FILE_UPLOAD.MESSAGES.UPLOAD_CANCELED' | translate }}
|
||||
</span>
|
||||
} @else {
|
||||
<span class="adf-upload-dialog__title">
|
||||
{{ 'FILE_UPLOAD.MESSAGES.UPLOAD_PROGRESS'
|
||||
| translate: {
|
||||
completed: totalCompleted,
|
||||
total: filesUploadingList.length
|
||||
}
|
||||
}}
|
||||
| translate: {
|
||||
completed: totalCompleted,
|
||||
total: filesUploadingList.length
|
||||
}
|
||||
}}
|
||||
</span>
|
||||
|
||||
<span
|
||||
class="adf-upload-dialog__title"
|
||||
*ngIf="uploadList.isUploadCancelled()">
|
||||
{{ 'FILE_UPLOAD.MESSAGES.UPLOAD_CANCELED' | translate }}
|
||||
</span>
|
||||
</header>
|
||||
|
||||
<section class="adf-upload-dialog__info"
|
||||
*ngIf="totalErrors">
|
||||
{{
|
||||
(totalErrors > 1
|
||||
? 'FILE_UPLOAD.MESSAGES.UPLOAD_ERRORS'
|
||||
: 'FILE_UPLOAD.MESSAGES.UPLOAD_ERROR')
|
||||
| translate: { total: totalErrors }
|
||||
}}
|
||||
}
|
||||
</header>
|
||||
@if (totalErrors) {
|
||||
<section class="adf-upload-dialog__info">
|
||||
{{
|
||||
(totalErrors > 1
|
||||
? 'FILE_UPLOAD.MESSAGES.UPLOAD_ERRORS'
|
||||
: 'FILE_UPLOAD.MESSAGES.UPLOAD_ERROR')
|
||||
| translate: { total: totalErrors }
|
||||
}}
|
||||
</section>
|
||||
|
||||
<section class="adf-upload-dialog__content"
|
||||
[class.adf-upload-dialog--padding]="isConfirmation" aria-live="polite">
|
||||
<adf-file-uploading-list
|
||||
class="adf-file-uploading-list"
|
||||
[class.adf-upload-dialog--hide]="isConfirmation"
|
||||
#uploadList
|
||||
[files]="filesUploadingList">
|
||||
<ng-template let-file="$implicit">
|
||||
<adf-file-uploading-list-row
|
||||
[file]="file"
|
||||
(cancel)="uploadList.cancelFile(file)" />
|
||||
</ng-template>
|
||||
</adf-file-uploading-list>
|
||||
|
||||
<div
|
||||
aria-live="polite"
|
||||
aria-labelledby="confirmationTitle"
|
||||
aria-describedby="confirmationDescription"
|
||||
class="adf-upload-dialog__confirmation"
|
||||
[class.adf-upload-dialog--hide]="!isConfirmation">
|
||||
<p role="heading" aria-level="2" id="confirmationTitle" class="adf-upload-dialog__confirmation--title">
|
||||
{{ 'ADF_FILE_UPLOAD.CONFIRMATION.MESSAGE.TITLE' | translate }}
|
||||
</p>
|
||||
<p id="confirmationDescription" class="adf-upload-dialog__confirmation--text">
|
||||
{{ 'ADF_FILE_UPLOAD.CONFIRMATION.MESSAGE.TEXT' | translate }}
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer class="adf-upload-dialog__actions" *ngIf="!isConfirmation">
|
||||
}
|
||||
<section class="adf-upload-dialog__content"
|
||||
[class.adf-upload-dialog--padding]="isConfirmation" aria-live="polite">
|
||||
<adf-file-uploading-list
|
||||
class="adf-file-uploading-list"
|
||||
[class.adf-upload-dialog--hide]="isConfirmation"
|
||||
#uploadList
|
||||
[files]="filesUploadingList">
|
||||
<ng-template let-file="$implicit">
|
||||
<adf-file-uploading-list-row
|
||||
[file]="file"
|
||||
(cancel)="uploadList.cancelFile(file)" />
|
||||
</ng-template>
|
||||
</adf-file-uploading-list>
|
||||
<div
|
||||
aria-live="polite"
|
||||
aria-labelledby="confirmationTitle"
|
||||
aria-describedby="confirmationDescription"
|
||||
class="adf-upload-dialog__confirmation"
|
||||
[class.adf-upload-dialog--hide]="!isConfirmation">
|
||||
<p role="heading" aria-level="2" id="confirmationTitle" class="adf-upload-dialog__confirmation--title">
|
||||
{{ 'ADF_FILE_UPLOAD.CONFIRMATION.MESSAGE.TITLE' | translate }}
|
||||
</p>
|
||||
<p id="confirmationDescription" class="adf-upload-dialog__confirmation--text">
|
||||
{{ 'ADF_FILE_UPLOAD.CONFIRMATION.MESSAGE.TEXT' | translate }}
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
@if (!isConfirmation) {
|
||||
<footer class="adf-upload-dialog__actions">
|
||||
@if (canShowCancelAll()) {
|
||||
<button
|
||||
id="adf-upload-dialog-cancel-all"
|
||||
[attr.aria-label]="'ADF_FILE_UPLOAD.ARIA-LABEL.STOP_ALL' | translate"
|
||||
color="primary"
|
||||
mat-button
|
||||
*ngIf="canShowCancelAll()"
|
||||
(click)="toggleConfirmation()"
|
||||
id="adf-upload-dialog-cancel-all"
|
||||
[attr.aria-label]="'ADF_FILE_UPLOAD.ARIA-LABEL.STOP_ALL' | translate"
|
||||
color="primary"
|
||||
mat-button
|
||||
(click)="toggleConfirmation()"
|
||||
>{{ 'ADF_FILE_UPLOAD.BUTTON.STOP_ALL' | translate }}</button>
|
||||
|
||||
}
|
||||
@if (canCloseDialog()) {
|
||||
<button
|
||||
id="adf-upload-dialog-close"
|
||||
[attr.aria-label]="'ADF_FILE_UPLOAD.ARIA-LABEL.DIALOG_CLOSE' | translate"
|
||||
*ngIf="canCloseDialog()"
|
||||
mat-button
|
||||
color="primary"
|
||||
(click)="close()"
|
||||
id="adf-upload-dialog-close"
|
||||
[attr.aria-label]="'ADF_FILE_UPLOAD.ARIA-LABEL.DIALOG_CLOSE' | translate"
|
||||
mat-button
|
||||
color="primary"
|
||||
(click)="close()"
|
||||
>{{ 'ADF_FILE_UPLOAD.BUTTON.CLOSE' | translate }}</button>
|
||||
}
|
||||
</footer>
|
||||
|
||||
}
|
||||
@if (isConfirmation) {
|
||||
<footer class="adf-upload-dialog__actions"
|
||||
*ngIf="isConfirmation" cdkTrapFocus cdkTrapFocusAutoCapture>
|
||||
<button
|
||||
id="adf-upload-dialog-cancel"
|
||||
[attr.aria-label]="'ADF_FILE_UPLOAD.ARIA-LABEL.CONFIRMATION.CANCEL' | translate"
|
||||
mat-button
|
||||
(click)="cancelAllUploads()"
|
||||
>{{ 'ADF_FILE_UPLOAD.CONFIRMATION.BUTTON.CANCEL' | translate }}</button>
|
||||
|
||||
<button
|
||||
id="adf-upload-dialog-confirm"
|
||||
[attr.aria-label]="'ADF_FILE_UPLOAD.ARIA-LABEL.CONFIRMATION.CONTINUE' | translate"
|
||||
mat-button
|
||||
color="primary"
|
||||
(click)="toggleConfirmation()"
|
||||
>{{ 'ADF_FILE_UPLOAD.CONFIRMATION.BUTTON.CONTINUE' | translate }}</button>
|
||||
cdkTrapFocus cdkTrapFocusAutoCapture>
|
||||
<button
|
||||
id="adf-upload-dialog-cancel"
|
||||
[attr.aria-label]="'ADF_FILE_UPLOAD.ARIA-LABEL.CONFIRMATION.CANCEL' | translate"
|
||||
mat-button
|
||||
(click)="cancelAllUploads()"
|
||||
>{{ 'ADF_FILE_UPLOAD.CONFIRMATION.BUTTON.CANCEL' | translate }}</button>
|
||||
<button
|
||||
id="adf-upload-dialog-confirm"
|
||||
[attr.aria-label]="'ADF_FILE_UPLOAD.ARIA-LABEL.CONFIRMATION.CONTINUE' | translate"
|
||||
mat-button
|
||||
color="primary"
|
||||
(click)="toggleConfirmation()"
|
||||
>{{ 'ADF_FILE_UPLOAD.CONFIRMATION.BUTTON.CONTINUE' | translate }}</button>
|
||||
</footer>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ import { delay } from 'rxjs/operators';
|
||||
import { UploadService } from '../../common/services/upload.service';
|
||||
import { FileModel, FileUploadStatus } from '../../common/models/file.model';
|
||||
import { FileUploadCompleteEvent, FileUploadDeleteEvent } from '../../common/events/file.event';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { TranslatePipe } from '@ngx-translate/core';
|
||||
import { FileUploadingListRowComponent } from './file-uploading-list-row.component';
|
||||
@@ -47,7 +47,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-file-uploading-dialog',
|
||||
imports: [CommonModule, MatButtonModule, TranslatePipe, IconModule, FileUploadingListComponent, FileUploadingListRowComponent, A11yModule],
|
||||
imports: [MatButtonModule, TranslatePipe, IconModule, FileUploadingListComponent, FileUploadingListRowComponent, A11yModule],
|
||||
templateUrl: './file-uploading-dialog.component.html',
|
||||
styleUrls: ['./file-uploading-dialog.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
@@ -56,7 +56,9 @@ export class FileUploadingDialogComponent implements OnInit, OnDestroy {
|
||||
private readonly uploadService = inject(UploadService);
|
||||
private readonly changeDetector = inject(ChangeDetectorRef);
|
||||
private readonly userPreferencesService = inject(UserPreferencesService);
|
||||
private readonly elementRef = inject(ElementRef);
|
||||
|
||||
@ViewChild('uploadDialog', { read: ElementRef })
|
||||
private readonly uploadDialogRef: ElementRef<HTMLElement> | undefined;
|
||||
|
||||
/** Dialog direction. Can be 'ltr' or 'rtl. */
|
||||
private direction: Direction = 'ltr';
|
||||
@@ -70,11 +72,11 @@ export class FileUploadingDialogComponent implements OnInit, OnDestroy {
|
||||
|
||||
/** Makes the dialog always visible even when there are no uploads. */
|
||||
@Input()
|
||||
alwaysVisible: boolean = false;
|
||||
alwaysVisible = false;
|
||||
|
||||
/** Emitted when a file in the list has an error. */
|
||||
@Output()
|
||||
error: EventEmitter<any> = new EventEmitter();
|
||||
error = new EventEmitter();
|
||||
|
||||
@HostBinding('attr.adfUploadDialogRight')
|
||||
public get isPositionRight(): boolean {
|
||||
@@ -98,10 +100,7 @@ export class FileUploadingDialogComponent implements OnInit, OnDestroy {
|
||||
|
||||
ngOnInit() {
|
||||
this.dialogActive.pipe(delay(100), takeUntilDestroyed(this.destroyRef)).subscribe(() => {
|
||||
const element: any = this.elementRef.nativeElement.querySelector('#upload-dialog');
|
||||
if (element) {
|
||||
element.focus();
|
||||
}
|
||||
this.uploadDialogRef?.nativeElement?.focus();
|
||||
});
|
||||
|
||||
this.uploadService.queueChanged.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((fileList) => {
|
||||
|
||||
+85
-64
@@ -1,92 +1,113 @@
|
||||
<div class="adf-file-uploading-row" [attr.aria-label]="file.name + ' ' + file.status">
|
||||
<mat-icon *ngIf="mimeType === 'default'" matListItemIcon class="adf-file-uploading-row__type" adf-icon="insert_drive_file" />
|
||||
@if (mimeType === 'default') {
|
||||
<mat-icon matListItemIcon class="adf-file-uploading-row__type" adf-icon="insert_drive_file" />
|
||||
} @else {
|
||||
<mat-icon svgIcon="adf:{{ mimeType }}" aria-hidden="true" />
|
||||
}
|
||||
|
||||
<mat-icon *ngIf="mimeType !== 'default'" svgIcon="adf:{{ mimeType }}" aria-hidden="true" />
|
||||
<span
|
||||
class="adf-file-uploading-row__name"
|
||||
title="{{ file.name }}">
|
||||
{{ file.name }}
|
||||
</span>
|
||||
|
||||
<span
|
||||
class="adf-file-uploading-row__name"
|
||||
title="{{ file.name }}">
|
||||
{{ file.name }}
|
||||
</span>
|
||||
|
||||
<span *ngIf="isUploadVersion()" class="adf-file-uploading-row__version" tabindex="0" >
|
||||
<mat-chip color="primary"
|
||||
[attr.aria-label]="'ADF_FILE_UPLOAD.ARIA-LABEL.VERSION' | translate: { version: versionNumber }"
|
||||
[title]="'version' + versionNumber"
|
||||
>{{ versionNumber }}</mat-chip>
|
||||
@if (isUploadVersion()) {
|
||||
<span class="adf-file-uploading-row__version" tabindex="0" >
|
||||
<mat-chip color="primary"
|
||||
[attr.aria-label]="'ADF_FILE_UPLOAD.ARIA-LABEL.VERSION' | translate: { version: versionNumber }"
|
||||
[title]="'version' + versionNumber"
|
||||
>{{ versionNumber }}</mat-chip>
|
||||
</span>
|
||||
}
|
||||
|
||||
@if (isUploading()) {
|
||||
<div
|
||||
tabindex="0"
|
||||
role="button"
|
||||
#toggleIcon="toggleIcon"
|
||||
adf-toggle-icon
|
||||
(keyup.enter)="onCancel(file)"
|
||||
(click)="onCancel(file)"
|
||||
data-automation-id="cancel-upload-progress"
|
||||
*ngIf="isUploading()"
|
||||
[attr.aria-label]="'ADF_FILE_UPLOAD.ARIA-LABEL.STOP_FILE_UPLOAD' | translate: { file: file.name }"
|
||||
class="adf-file-uploading-row__group adf-file-uploading-row__group--toggle"
|
||||
title="{{ 'ADF_FILE_UPLOAD.BUTTON.STOP_FILE' | translate }}">
|
||||
tabindex="0"
|
||||
role="button"
|
||||
(mouseenter)="onToggleMouseEnter(toggleIconState)"
|
||||
(mouseleave)="onToggleMouseLeave(toggleIconState)"
|
||||
(focus)="onToggleFocus(toggleIconState)"
|
||||
(blur)="onToggleBlur(toggleIconState)"
|
||||
(keyup.enter)="onCancel(file)"
|
||||
(click)="onCancel(file)"
|
||||
data-automation-id="cancel-upload-progress"
|
||||
[attr.aria-label]="'ADF_FILE_UPLOAD.ARIA-LABEL.STOP_FILE_UPLOAD' | translate: { file: file.name }"
|
||||
class="adf-file-uploading-row__group adf-file-uploading-row__group--toggle"
|
||||
title="{{ 'ADF_FILE_UPLOAD.BUTTON.STOP_FILE' | translate }}">
|
||||
|
||||
<span class="adf-file-uploading-row__status" *ngIf="!toggleIcon.isToggled">
|
||||
@if (toggleIconState.isToggled) {
|
||||
<mat-icon class="adf-file-uploading-row__action adf-file-uploading-row__action--cancel" adf-icon="clear" />
|
||||
} @else {
|
||||
<span class="adf-file-uploading-row__status">
|
||||
{{ file.progress.loaded | adfFileSize }} / {{ file.progress.total | adfFileSize }}
|
||||
</span>
|
||||
|
||||
<mat-icon *ngIf="toggleIcon.isToggled" class="adf-file-uploading-row__action adf-file-uploading-row__action--cancel" adf-icon="clear" />
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (isUploadComplete()) {
|
||||
<button mat-icon-button
|
||||
adf-toggle-icon
|
||||
#toggleIcon="toggleIcon"
|
||||
*ngIf="isUploadComplete()"
|
||||
class="adf-file-uploading-row__group"
|
||||
[attr.aria-label]="'ADF_FILE_UPLOAD.ARIA-LABEL.UPLOAD_SUCCESSFUL' | translate: { file: file.name }"
|
||||
title="{{ 'ADF_FILE_UPLOAD.BUTTON.UPLOAD_SUCCESSFUL' | translate }}">
|
||||
|
||||
<mat-icon class="adf-file-uploading-row__status adf-file-uploading-row__status--done" adf-icon="check_circle" />
|
||||
(mouseenter)="onToggleMouseEnter(toggleIconState)"
|
||||
(mouseleave)="onToggleMouseLeave(toggleIconState)"
|
||||
(focus)="onToggleFocus(toggleIconState)"
|
||||
(blur)="onToggleBlur(toggleIconState)"
|
||||
class="adf-file-uploading-row__group"
|
||||
[attr.aria-label]="'ADF_FILE_UPLOAD.ARIA-LABEL.UPLOAD_SUCCESSFUL' | translate: { file: file.name }"
|
||||
title="{{ 'ADF_FILE_UPLOAD.BUTTON.UPLOAD_SUCCESSFUL' | translate }}">
|
||||
<mat-icon class="adf-file-uploading-row__status adf-file-uploading-row__status--done" adf-icon="check_circle" />
|
||||
</button>
|
||||
}
|
||||
|
||||
@if (isUploadVersionComplete()) {
|
||||
<div
|
||||
*ngIf="isUploadVersionComplete()"
|
||||
class="adf-file-uploading-row__file-version"
|
||||
[attr.aria-label]="'ADF_FILE_UPLOAD.STATUS.FILE_DONE_STATUS' | translate"
|
||||
>
|
||||
<mat-icon class="adf-file-uploading-row__status--done" adf-icon="check_circle" matListItemIcon />
|
||||
class="adf-file-uploading-row__file-version"
|
||||
[attr.aria-label]="'ADF_FILE_UPLOAD.STATUS.FILE_DONE_STATUS' | translate"
|
||||
>
|
||||
<mat-icon class="adf-file-uploading-row__status--done" adf-icon="check_circle" matListItemIcon />
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (canCancelUpload()) {
|
||||
<button
|
||||
adf-toggle-icon
|
||||
#toggleIconCancel="toggleIcon"
|
||||
mat-icon-button
|
||||
*ngIf="canCancelUpload()"
|
||||
(click)="onCancel(file)"
|
||||
data-automation-id="cancel-upload-queue"
|
||||
class="adf-file-uploading-row__group"
|
||||
title="{{ 'ADF_FILE_UPLOAD.BUTTON.STOP_FILE' | translate }}"
|
||||
[attr.aria-label]="'ADF_FILE_UPLOAD.ARIA-LABEL.STOP_FILE' | translate: { file: file.name }">
|
||||
<mat-icon *ngIf="!toggleIconCancel.isToggled" class="adf-file-uploading-row__status adf-file-uploading-row__status--pending" adf-icon="schedule" />
|
||||
(mouseenter)="onToggleMouseEnter(toggleIconCancelState)"
|
||||
(mouseleave)="onToggleMouseLeave(toggleIconCancelState)"
|
||||
(focus)="onToggleFocus(toggleIconCancelState)"
|
||||
(blur)="onToggleBlur(toggleIconCancelState)"
|
||||
mat-icon-button
|
||||
(click)="onCancel(file)"
|
||||
data-automation-id="cancel-upload-queue"
|
||||
class="adf-file-uploading-row__group"
|
||||
title="{{ 'ADF_FILE_UPLOAD.BUTTON.STOP_FILE' | translate }}"
|
||||
[attr.aria-label]="'ADF_FILE_UPLOAD.ARIA-LABEL.STOP_FILE' | translate: { file: file.name }">
|
||||
|
||||
<mat-icon *ngIf="toggleIconCancel.isToggled" class="adf-file-uploading-row__action adf-file-uploading-row__action--remove" adf-icon="remove_circle" />
|
||||
@if (toggleIconCancelState.isToggled) {
|
||||
<mat-icon class="adf-file-uploading-row__action adf-file-uploading-row__action--remove" adf-icon="remove_circle" />
|
||||
} @else {
|
||||
<mat-icon class="adf-file-uploading-row__status adf-file-uploading-row__status--pending" adf-icon="schedule" />
|
||||
}
|
||||
</button>
|
||||
}
|
||||
|
||||
@if (isUploadError()) {
|
||||
@let uploadErrorLabel = getFileUploadErrorKey(file.errorCode) | translate;
|
||||
<div
|
||||
role="status"
|
||||
*ngIf="isUploadError()"
|
||||
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"
|
||||
adf-icon="report_problem"
|
||||
matListItemIcon
|
||||
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: uploadErrorLabel }"
|
||||
[title]="uploadErrorLabel"
|
||||
adf-icon="report_problem"
|
||||
matListItemIcon
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (showCancelledStatus()) {
|
||||
<div
|
||||
[attr.aria-label]="'ADF_FILE_UPLOAD.STATUS.FILE_CANCELED_STATUS' | translate"
|
||||
role="status"
|
||||
*ngIf="showCancelledStatus()"
|
||||
class="adf-file-uploading-row__block adf-file-uploading-row__status--cancelled">
|
||||
{{ 'ADF_FILE_UPLOAD.STATUS.FILE_CANCELED_STATUS' | translate }}
|
||||
[attr.aria-label]="'ADF_FILE_UPLOAD.STATUS.FILE_CANCELED_STATUS' | translate"
|
||||
role="status"
|
||||
class="adf-file-uploading-row__block adf-file-uploading-row__status--cancelled">
|
||||
{{ 'ADF_FILE_UPLOAD.STATUS.FILE_CANCELED_STATUS' | translate }}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
+114
@@ -106,4 +106,118 @@ describe('FileUploadingListRowComponent', () => {
|
||||
const cancelButton = getCancelButton();
|
||||
expect(cancelButton.title).toBe('ADF_FILE_UPLOAD.BUTTON.STOP_FILE');
|
||||
});
|
||||
|
||||
describe('getFileUploadErrorKey', () => {
|
||||
it('should return correct key format for error code 500', () => {
|
||||
const result = component.getFileUploadErrorKey(500);
|
||||
expect(result).toBe('FILE_UPLOAD.ERRORS.500');
|
||||
});
|
||||
|
||||
it('should return correct key format for error code 404', () => {
|
||||
const result = component.getFileUploadErrorKey(404);
|
||||
expect(result).toBe('FILE_UPLOAD.ERRORS.404');
|
||||
});
|
||||
|
||||
it('should return correct key format for error code 403', () => {
|
||||
const result = component.getFileUploadErrorKey(403);
|
||||
expect(result).toBe('FILE_UPLOAD.ERRORS.403');
|
||||
});
|
||||
|
||||
it('should return GENERIC key when errorCode is null', () => {
|
||||
const result = component.getFileUploadErrorKey(null);
|
||||
expect(result).toBe('FILE_UPLOAD.ERRORS.GENERIC');
|
||||
});
|
||||
|
||||
it('should return GENERIC key when errorCode is undefined', () => {
|
||||
const result = component.getFileUploadErrorKey(undefined);
|
||||
expect(result).toBe('FILE_UPLOAD.ERRORS.GENERIC');
|
||||
});
|
||||
|
||||
it('should return GENERIC key when errorCode is 0', () => {
|
||||
const result = component.getFileUploadErrorKey(0);
|
||||
expect(result).toBe('FILE_UPLOAD.ERRORS.GENERIC');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Toggle Icon State', () => {
|
||||
describe('onToggleMouseEnter', () => {
|
||||
it('should set isToggled to true when not focused', () => {
|
||||
component.toggleIconState = { isFocused: false, isToggled: false };
|
||||
|
||||
component.onToggleMouseEnter(component.toggleIconState);
|
||||
|
||||
expect(component.toggleIconState.isToggled).toBe(true);
|
||||
});
|
||||
|
||||
it('should not change isToggled when already focused', () => {
|
||||
component.toggleIconState = { isFocused: true, isToggled: false };
|
||||
|
||||
component.onToggleMouseEnter(component.toggleIconState);
|
||||
|
||||
expect(component.toggleIconState.isToggled).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('onToggleMouseLeave', () => {
|
||||
it('should set isToggled to false when not focused', () => {
|
||||
component.toggleIconState = { isFocused: false, isToggled: true };
|
||||
|
||||
component.onToggleMouseLeave(component.toggleIconState);
|
||||
|
||||
expect(component.toggleIconState.isToggled).toBe(false);
|
||||
});
|
||||
|
||||
it('should not change state when focused but not toggled', () => {
|
||||
component.toggleIconState = { isFocused: true, isToggled: false };
|
||||
|
||||
component.onToggleMouseLeave(component.toggleIconState);
|
||||
|
||||
expect(component.toggleIconState.isFocused).toBe(true);
|
||||
expect(component.toggleIconState.isToggled).toBe(false);
|
||||
});
|
||||
|
||||
it('should reset both isFocused and isToggled when both are true', () => {
|
||||
component.toggleIconState = { isFocused: true, isToggled: true };
|
||||
|
||||
component.onToggleMouseLeave(component.toggleIconState);
|
||||
|
||||
expect(component.toggleIconState.isFocused).toBe(false);
|
||||
expect(component.toggleIconState.isToggled).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('onToggleFocus', () => {
|
||||
it('should set both isFocused and isToggled to true', () => {
|
||||
component.toggleIconState = { isFocused: false, isToggled: false };
|
||||
|
||||
component.onToggleFocus(component.toggleIconState);
|
||||
|
||||
expect(component.toggleIconState.isFocused).toBe(true);
|
||||
expect(component.toggleIconState.isToggled).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('onToggleBlur', () => {
|
||||
it('should set both isFocused and isToggled to false', () => {
|
||||
component.toggleIconState = { isFocused: true, isToggled: true };
|
||||
|
||||
component.onToggleBlur(component.toggleIconState);
|
||||
|
||||
expect(component.toggleIconState.isFocused).toBe(false);
|
||||
expect(component.toggleIconState.isToggled).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Multiple toggle states', () => {
|
||||
it('should maintain independent state for toggleIconState and toggleIconCancelState', () => {
|
||||
component.onToggleFocus(component.toggleIconState);
|
||||
component.onToggleMouseEnter(component.toggleIconCancelState);
|
||||
|
||||
expect(component.toggleIconState.isFocused).toBe(true);
|
||||
expect(component.toggleIconState.isToggled).toBe(true);
|
||||
expect(component.toggleIconCancelState.isFocused).toBe(false);
|
||||
expect(component.toggleIconCancelState.isToggled).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+41
-14
@@ -17,28 +17,21 @@
|
||||
|
||||
import { FileModel, FileUploadStatus } from '../../common/models/file.model';
|
||||
import { Component, EventEmitter, Input, Output, ViewEncapsulation } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { MatListModule } from '@angular/material/list';
|
||||
import { FileSizePipe, IconModule } from '@alfresco/adf-core';
|
||||
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';
|
||||
|
||||
interface ToggleIconState {
|
||||
isFocused: boolean;
|
||||
isToggled: boolean;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'adf-file-uploading-list-row',
|
||||
imports: [
|
||||
CommonModule,
|
||||
IconModule,
|
||||
MatListModule,
|
||||
MatChipsModule,
|
||||
TranslatePipe,
|
||||
ToggleIconDirective,
|
||||
FileSizePipe,
|
||||
MatButtonModule,
|
||||
FileUploadErrorPipe
|
||||
],
|
||||
imports: [IconModule, MatListModule, MatChipsModule, TranslatePipe, FileSizePipe, MatButtonModule],
|
||||
templateUrl: './file-uploading-list-row.component.html',
|
||||
styleUrls: ['./file-uploading-list-row.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
@@ -50,10 +43,40 @@ export class FileUploadingListRowComponent {
|
||||
@Output()
|
||||
cancel = new EventEmitter<FileModel>();
|
||||
|
||||
toggleIconState: ToggleIconState = { isFocused: false, isToggled: false };
|
||||
toggleIconCancelState: ToggleIconState = { isFocused: false, isToggled: false };
|
||||
|
||||
onCancel(file: FileModel): void {
|
||||
this.cancel.emit(file);
|
||||
}
|
||||
|
||||
onToggleMouseEnter(state: ToggleIconState): void {
|
||||
if (!state.isFocused) {
|
||||
state.isToggled = true;
|
||||
}
|
||||
}
|
||||
|
||||
onToggleMouseLeave(state: ToggleIconState): void {
|
||||
if (!state.isFocused) {
|
||||
state.isToggled = false;
|
||||
}
|
||||
|
||||
if (state.isFocused && state.isToggled) {
|
||||
state.isFocused = false;
|
||||
state.isToggled = false;
|
||||
}
|
||||
}
|
||||
|
||||
onToggleFocus(state: ToggleIconState): void {
|
||||
state.isFocused = true;
|
||||
state.isToggled = true;
|
||||
}
|
||||
|
||||
onToggleBlur(state: ToggleIconState): void {
|
||||
state.isFocused = false;
|
||||
state.isToggled = false;
|
||||
}
|
||||
|
||||
showCancelledStatus(): boolean {
|
||||
return (
|
||||
this.file.status === FileUploadStatus.Cancelled ||
|
||||
@@ -93,4 +116,8 @@ export class FileUploadingListRowComponent {
|
||||
isUploadVersionComplete(): boolean {
|
||||
return this.file?.status === FileUploadStatus.Complete && this.isUploadVersion();
|
||||
}
|
||||
|
||||
getFileUploadErrorKey(errorCode?: number | null): string {
|
||||
return `FILE_UPLOAD.ERRORS.${errorCode || 'GENERIC'}`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<div class="upload-list">
|
||||
@for (file of files; track file.id) {
|
||||
<ng-template
|
||||
ngFor
|
||||
[ngForOf]="files"
|
||||
[ngForTemplate]="template" />
|
||||
[ngTemplateOutlet]="template"
|
||||
[ngTemplateOutletContext]="{ $implicit: file }" />
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -20,11 +20,11 @@ import { UploadService } from '../../common/services/upload.service';
|
||||
import { FileModel, FileUploadStatus } from '../../common/models/file.model';
|
||||
|
||||
import { Component, ContentChild, Input, Output, TemplateRef, EventEmitter, inject } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgTemplateOutlet } from '@angular/common';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-file-uploading-list',
|
||||
imports: [CommonModule],
|
||||
imports: [NgTemplateOutlet],
|
||||
templateUrl: './file-uploading-list.component.html',
|
||||
styleUrls: ['./file-uploading-list.component.scss']
|
||||
})
|
||||
|
||||
@@ -1,70 +1,74 @@
|
||||
<form class="adf-upload-button-file-container">
|
||||
<!--Files Upload-->
|
||||
<div *ngIf="!uploadFolders">
|
||||
|
||||
<!--Single Files Upload-->
|
||||
<ng-container *ngIf="!multipleFiles">
|
||||
<input
|
||||
class="adf-upload-button-file-container-upload-single-file"
|
||||
id="upload-single-file"
|
||||
data-automation-id="upload-single-file"
|
||||
[type]="file ? 'button' : 'file'"
|
||||
name="uploadFiles"
|
||||
accept="{{acceptedFilesType}}"
|
||||
[attr.disabled]="isButtonDisabled()"
|
||||
[title]="tooltip"
|
||||
(change)="onFilesAdded($event)"
|
||||
(click)="onClickUploadButton()"/>
|
||||
<label tabindex="0" (keydown.enter)="onClickUploadButton()" for="upload-single-file" class="adf-upload-button-label">
|
||||
<mat-icon class="adf-upload-button-icon" adf-icon="file_upload" />
|
||||
<span id="upload-single-file-label" *ngIf="!staticTitle">
|
||||
{{ 'FILE_UPLOAD.BUTTON.UPLOAD_FILE' | translate }}</span>
|
||||
<span id="upload-single-file-label-static" *ngIf="staticTitle">
|
||||
{{ staticTitle }}</span>
|
||||
</label>
|
||||
</ng-container>
|
||||
|
||||
<!--Multiple Files Upload-->
|
||||
<ng-container *ngIf="multipleFiles">
|
||||
<input
|
||||
id="upload-multiple-files"
|
||||
data-automation-id="upload-multiple-files"
|
||||
type="file"
|
||||
name="uploadFiles"
|
||||
multiple="multiple"
|
||||
accept="{{acceptedFilesType}}"
|
||||
[attr.disabled]="isButtonDisabled()"
|
||||
[title]="tooltip"
|
||||
(change)="onFilesAdded($event)"/>
|
||||
<label for="upload-multiple-files" class="adf-upload-button-label">
|
||||
<mat-icon class="adf-upload-button-icon" adf-icon="file_upload" />
|
||||
<span id="upload-multiple-file-label" *ngIf="!staticTitle">
|
||||
{{ 'FILE_UPLOAD.BUTTON.UPLOAD_FILE' | translate }}</span>
|
||||
<span id="upload-multiple-file-label-static" *ngIf="staticTitle">
|
||||
{{ staticTitle }}</span>
|
||||
</label>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
<!--Folders Upload-->
|
||||
<ng-container *ngIf="uploadFolders">
|
||||
<!--Files Upload-->
|
||||
@if (!uploadFolders) {
|
||||
<div>
|
||||
<!--Single Files Upload-->
|
||||
@if (!multipleFiles) {
|
||||
<input
|
||||
id="uploadFolder"
|
||||
data-automation-id="uploadFolder"
|
||||
type="file"
|
||||
name="uploadFiles"
|
||||
multiple="multiple"
|
||||
accept="{{acceptedFilesType}}"
|
||||
webkitdirectory directory
|
||||
[attr.disabled]="isButtonDisabled()"
|
||||
[title]="tooltip"
|
||||
(change)="onDirectoryAdded($event)"/>
|
||||
<label for="uploadFolder" data-automation-id="uploadFolder" class="adf-upload-button-label">
|
||||
<mat-icon class="adf-upload-button-icon" adf-icon="file_upload" />
|
||||
<span id="uploadFolder-label" *ngIf="!staticTitle">
|
||||
{{ 'FILE_UPLOAD.BUTTON.UPLOAD_FOLDER' | translate }}</span>
|
||||
<span id="uploadFolder-label-static" *ngIf="staticTitle">
|
||||
{{ staticTitle }}</span>
|
||||
class="adf-upload-button-file-container-upload-single-file"
|
||||
id="upload-single-file"
|
||||
data-automation-id="upload-single-file"
|
||||
[type]="file ? 'button' : 'file'"
|
||||
name="uploadFiles"
|
||||
accept="{{acceptedFilesType}}"
|
||||
[attr.disabled]="isButtonDisabled()"
|
||||
[title]="tooltip"
|
||||
(change)="onFilesAdded($event)"
|
||||
(click)="onClickUploadButton()"/>
|
||||
<label tabindex="0" (keydown.enter)="onClickUploadButton()" for="upload-single-file" class="adf-upload-button-label">
|
||||
<mat-icon class="adf-upload-button-icon" adf-icon="file_upload" />
|
||||
|
||||
@if (staticTitle) {
|
||||
<span id="upload-single-file-label-static"> {{ staticTitle }}</span>
|
||||
} @else {
|
||||
<span id="upload-single-file-label">{{ 'FILE_UPLOAD.BUTTON.UPLOAD_FILE' | translate }}</span>
|
||||
}
|
||||
</label>
|
||||
</ng-container>
|
||||
}
|
||||
<!--Multiple Files Upload-->
|
||||
@if (multipleFiles) {
|
||||
<input
|
||||
id="upload-multiple-files"
|
||||
data-automation-id="upload-multiple-files"
|
||||
type="file"
|
||||
name="uploadFiles"
|
||||
multiple="multiple"
|
||||
accept="{{acceptedFilesType}}"
|
||||
[attr.disabled]="isButtonDisabled()"
|
||||
[title]="tooltip"
|
||||
(change)="onFilesAdded($event)"/>
|
||||
<label for="upload-multiple-files" class="adf-upload-button-label">
|
||||
<mat-icon class="adf-upload-button-icon" adf-icon="file_upload" />
|
||||
@if (staticTitle) {
|
||||
<span id="upload-multiple-file-label-static"> {{ staticTitle }}</span>
|
||||
} @else {
|
||||
<span id="upload-multiple-file-label">{{ 'FILE_UPLOAD.BUTTON.UPLOAD_FILE' | translate }}</span>
|
||||
}
|
||||
</label>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
<!--Folders Upload-->
|
||||
@if (uploadFolders) {
|
||||
<input
|
||||
id="uploadFolder"
|
||||
data-automation-id="uploadFolder"
|
||||
type="file"
|
||||
name="uploadFiles"
|
||||
multiple="multiple"
|
||||
accept="{{acceptedFilesType}}"
|
||||
webkitdirectory directory
|
||||
[attr.disabled]="isButtonDisabled()"
|
||||
[title]="tooltip"
|
||||
(change)="onDirectoryAdded($event)"/>
|
||||
<label for="uploadFolder" data-automation-id="uploadFolder" class="adf-upload-button-label">
|
||||
<mat-icon class="adf-upload-button-icon" adf-icon="file_upload" />
|
||||
@if (staticTitle) {
|
||||
<span id="uploadFolder-label-static"> {{ staticTitle }}</span>
|
||||
} @else {
|
||||
<span id="uploadFolder-label">{{ 'FILE_UPLOAD.BUTTON.UPLOAD_FOLDER' | translate }}</span>
|
||||
}
|
||||
</label>
|
||||
}
|
||||
</form>
|
||||
|
||||
@@ -24,13 +24,13 @@ import { Node } from '@alfresco/js-api';
|
||||
import { Subject } from 'rxjs';
|
||||
import { PermissionModel } from '../../document-list/models/permissions.model';
|
||||
import { UploadBase } from './base-upload/upload-base';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { TranslatePipe } from '@ngx-translate/core';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-upload-button',
|
||||
imports: [CommonModule, MatButtonModule, TranslatePipe, IconModule],
|
||||
imports: [MatButtonModule, TranslatePipe, IconModule],
|
||||
templateUrl: './upload-button.component.html',
|
||||
styleUrls: ['./upload-button.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
|
||||
@@ -1,86 +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 { Component, ViewChild } from '@angular/core';
|
||||
import { ToggleIconDirective } from './toggle-icon.directive';
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-test-component',
|
||||
imports: [ToggleIconDirective],
|
||||
template: ` <button id="testButton" adf-toggle-icon>test</button> `
|
||||
})
|
||||
class TestComponent {
|
||||
@ViewChild(ToggleIconDirective)
|
||||
directive: ToggleIconDirective;
|
||||
}
|
||||
|
||||
describe('ToggleIconDirective', () => {
|
||||
let fixture: ComponentFixture<TestComponent>;
|
||||
let component: TestComponent;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [TestComponent]
|
||||
});
|
||||
fixture = TestBed.createComponent(TestComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should set toggle to true on mouseenter', () => {
|
||||
const button: HTMLElement = fixture.nativeElement.querySelector('#testButton');
|
||||
button.dispatchEvent(new MouseEvent('mouseenter'));
|
||||
|
||||
expect(component.directive.isToggled).toBe(true);
|
||||
});
|
||||
|
||||
it('should set toggle to false on mouseleave if element is not focused', () => {
|
||||
const button: HTMLElement = fixture.nativeElement.querySelector('#testButton');
|
||||
button.dispatchEvent(new MouseEvent('mouseleave'));
|
||||
|
||||
expect(component.directive.isToggled).toBe(false);
|
||||
});
|
||||
|
||||
it('should set toggle and focus to false on mouseleave when element is focused', () => {
|
||||
const button: HTMLElement = fixture.nativeElement.querySelector('#testButton');
|
||||
button.dispatchEvent(new Event('focus'));
|
||||
expect(component.directive.isToggled).toBe(true);
|
||||
|
||||
button.dispatchEvent(new MouseEvent('mouseleave'));
|
||||
|
||||
expect(component.directive.isToggled).toBe(false);
|
||||
expect(component.directive.isFocused).toBe(false);
|
||||
});
|
||||
|
||||
it('should set toggle and focus to true when element is focused', () => {
|
||||
const button: HTMLElement = fixture.nativeElement.querySelector('#testButton');
|
||||
button.dispatchEvent(new Event('focus'));
|
||||
|
||||
expect(component.directive.isToggled).toBe(true);
|
||||
expect(component.directive.isFocused).toBe(true);
|
||||
});
|
||||
|
||||
it('should set toggle and focus to true when element blur event', () => {
|
||||
const button: HTMLElement = fixture.nativeElement.querySelector('#testButton');
|
||||
button.dispatchEvent(new Event('focus'));
|
||||
button.dispatchEvent(new Event('blur'));
|
||||
|
||||
expect(component.directive.isToggled).toBe(false);
|
||||
expect(component.directive.isFocused).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -1,62 +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 { Directive, HostListener } from '@angular/core';
|
||||
|
||||
@Directive({
|
||||
selector: '[adf-toggle-icon]',
|
||||
exportAs: 'toggleIcon'
|
||||
})
|
||||
export class ToggleIconDirective {
|
||||
private isFocus: boolean = false;
|
||||
private toggle: boolean = false;
|
||||
|
||||
@HostListener('mouseenter') onMouseEnter() {
|
||||
if (!this.isFocus) {
|
||||
this.toggle = true;
|
||||
}
|
||||
}
|
||||
|
||||
@HostListener('mouseleave') onMouseLeave() {
|
||||
if (!this.isFocus) {
|
||||
this.toggle = false;
|
||||
}
|
||||
|
||||
if (this.isFocus && this.toggle) {
|
||||
this.isFocus = false;
|
||||
this.toggle = false;
|
||||
}
|
||||
}
|
||||
|
||||
@HostListener('focus') onFocus() {
|
||||
this.isFocus = true;
|
||||
this.toggle = true;
|
||||
}
|
||||
|
||||
@HostListener('blur') onBlur() {
|
||||
this.isFocus = false;
|
||||
this.toggle = false;
|
||||
}
|
||||
|
||||
get isToggled(): boolean {
|
||||
return this.toggle;
|
||||
}
|
||||
|
||||
get isFocused(): boolean {
|
||||
return this.isFocus;
|
||||
}
|
||||
}
|
||||
@@ -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'}`);
|
||||
}
|
||||
}
|
||||
@@ -24,9 +24,6 @@ export * from './components/file-uploading-list-row.component';
|
||||
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';
|
||||
|
||||
|
||||
@@ -22,14 +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,
|
||||
UploadButtonComponent,
|
||||
UploadVersionButtonComponent,
|
||||
|
||||
@@ -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(),
|
||||
{
|
||||
|
||||
@@ -1,30 +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.
|
||||
*/
|
||||
|
||||
export class DecimalNumberModel {
|
||||
minIntegerDigits: number;
|
||||
minFractionDigits: number;
|
||||
maxFractionDigits: number;
|
||||
|
||||
constructor(obj?: any) {
|
||||
if (obj) {
|
||||
this.minIntegerDigits = obj.minIntegerDigits;
|
||||
this.minFractionDigits = obj.minFractionDigits;
|
||||
this.maxFractionDigits = obj.maxFractionDigits;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,5 @@
|
||||
export * from './comment.model';
|
||||
export * from './pagination.model';
|
||||
export * from './request-pagination.model';
|
||||
export * from './decimal-number.model';
|
||||
export * from './general-user.model';
|
||||
export * from './path.model';
|
||||
|
||||
@@ -19,7 +19,12 @@ import { DecimalPipe } from '@angular/common';
|
||||
import { Pipe, PipeTransform, inject } from '@angular/core';
|
||||
import { AppConfigService } from '../app-config/app-config.service';
|
||||
import { UserPreferencesService } from '../common/services/user-preferences.service';
|
||||
import { DecimalNumberModel } from '../models/decimal-number.model';
|
||||
|
||||
export interface DecimalNumberModel {
|
||||
minIntegerDigits?: number;
|
||||
minFractionDigits?: number;
|
||||
maxFractionDigits?: number;
|
||||
}
|
||||
|
||||
@Pipe({
|
||||
name: 'adfDecimalNumber',
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user