Revert "[ACS-7381][ADF] Break DataTable dependency on Material Module (#9657)" (#9866)

This reverts commit f27d62585b.
This commit is contained in:
Maurizio Vitale
2024-06-25 13:53:14 +01:00
committed by GitHub
parent fb275d94c0
commit f9aadde4bf
82 changed files with 1260 additions and 1400 deletions

View File

@@ -1,15 +1,15 @@
<div class="app-container"> <div class="app-container">
<div <div
class="app-document-list-container" id="document-list-container"
id="document-list-container"> class="app-document-list-container">
<adf-upload-drag-area <adf-upload-drag-area
(updateFileVersion)="onUploadNewVersion($event)" [disabled]="disableDragArea"
[acceptedFilesType]="getFileFiltering()" [acceptedFilesType]="getFileFiltering()"
[rootFolderId]="currentFolderId"
[versioning]="versioning"
[adf-check-allowable-operation]="'create'" [adf-check-allowable-operation]="'create'"
[adf-nodes]="disableDragArea ? getCurrentDocumentListNode() : []" [adf-nodes]="disableDragArea ? getCurrentDocumentListNode() : []"
[disabled]="disableDragArea" (updateFileVersion)="onUploadNewVersion($event)">
[rootFolderId]="currentFolderId"
[versioning]="versioning">
<div *ngIf="errorMessage" class="app-error-message"> <div *ngIf="errorMessage" class="app-error-message">
<button (click)="resetError()" mat-icon-button> <button (click)="resetError()" mat-icon-button>
<mat-icon>highlight_off</mat-icon> <mat-icon>highlight_off</mat-icon>
@@ -18,7 +18,7 @@
</div> </div>
<adf-toolbar *ngIf="!disableDragArea" class="app-files-toolbar"> <adf-toolbar *ngIf="!disableDragArea" class="app-files-toolbar">
<adf-toolbar-title> <adf-toolbar-title>
<adf-breadcrumb [target]="documentList" root="Personal Files"> <adf-breadcrumb root="Personal Files" [target]="documentList">
</adf-breadcrumb> </adf-breadcrumb>
<adf-dropdown-breadcrumb [target]="documentList"> <adf-dropdown-breadcrumb [target]="documentList">
</adf-dropdown-breadcrumb> </adf-dropdown-breadcrumb>
@@ -26,83 +26,82 @@
<div class="app-document-action-buttons"> <div class="app-document-action-buttons">
<button <button
(error)="openSnackMessageError($event)"
(success)="documentList.reload()"
[adf-create-folder]="currentFolderId"
[disabled]="!canCreateContent(documentList.folderNode)"
data-automation-id="create-new-folder" data-automation-id="create-new-folder"
mat-icon-button mat-icon-button
title="New folder"> [disabled]="!canCreateContent(documentList.folderNode)"
title="New folder"
(error)="openSnackMessageError($event)"
(success)="documentList.reload()"
[adf-create-folder]="currentFolderId">
<mat-icon>create_new_folder</mat-icon> <mat-icon>create_new_folder</mat-icon>
</button> </button>
<button [adfNodeDownload]="documentList.selection" <button mat-icon-button
[disabled]="!hasSelection(documentList.selection)" [disabled]="!hasSelection(documentList.selection)"
mat-icon-button title="Download"
title="Download"> [adfNodeDownload]="documentList.selection">
<mat-icon>get_app</mat-icon> <mat-icon>get_app</mat-icon>
</button> </button>
<button (delete)="onDeleteActionSuccess($event)" <button mat-icon-button
[adf-delete]="documentList.selection"
[adf-nodes]="documentList.selection"
[permanent]="true"
adf-check-allowable-operation="delete"
data-automation-id="delete-toolbar-button" data-automation-id="delete-toolbar-button"
mat-icon-button adf-check-allowable-operation="delete"
title="Delete"> [permanent]="true"
[adf-nodes]="documentList.selection"
title="Delete"
(delete)="onDeleteActionSuccess($event)"
[adf-delete]="documentList.selection">
<mat-icon>delete</mat-icon> <mat-icon>delete</mat-icon>
</button> </button>
</div> </div>
<button (click)="showVersions = !showVersions" class="app-show-versions-button" mat-icon-button <button mat-icon-button (click)="showVersions = !showVersions" class="app-show-versions-button"
title="Toggle metadata"> title="Toggle metadata">
<mat-icon>{{ showVersions ? 'chevron_right' : 'chevron_left' }}</mat-icon> <mat-icon>{{ showVersions ? 'chevron_right' : 'chevron_left' }}</mat-icon>
</button> </button>
<adf-toolbar-divider class="app-toolbar-divider-before-more-menu"></adf-toolbar-divider> <adf-toolbar-divider class="app-toolbar-divider-before-more-menu"></adf-toolbar-divider>
<button [matMenuTriggerFor]="menu" class="app-toolbar-more-menu-button" mat-icon-button> <button class="app-toolbar-more-menu-button" mat-icon-button [matMenuTriggerFor]="menu">
<mat-icon>more_vert</mat-icon> <mat-icon>more_vert</mat-icon>
</button> </button>
<mat-menu #menu="matMenu"> <mat-menu #menu="matMenu">
<button (delete)="onDeleteActionSuccess($event)" <button mat-menu-item
[adf-delete]="documentList.selection"
[adf-nodes]="documentList.selection"
adf-check-allowable-operation="delete" adf-check-allowable-operation="delete"
mat-menu-item> [adf-nodes]="documentList.selection"
(delete)="onDeleteActionSuccess($event)"
[adf-delete]="documentList.selection">
<mat-icon>delete</mat-icon> <mat-icon>delete</mat-icon>
<span>Delete</span> <span>Delete</span>
</button> </button>
</mat-menu> </mat-menu>
</adf-toolbar> </adf-toolbar>
<div [ngClass]="{'adf-sticky-document-list': stickyHeader }" <div class="app-document-list-container-in-upload-drag-area app-document-list-container" [ngClass]="{'adf-sticky-document-list': stickyHeader }">
class="app-document-list-container-in-upload-drag-area app-document-list-container">
<adf-document-list <adf-document-list
#documentList #documentList
(error)="onNavigationError($event)" class="app-file-list-container"
(filterSelection)="onFilterSelected($event)" [permissionsStyle]="permissionsStyle"
(folderChange)="onFolderChange($event)"
(name-click)="documentList.onNodeDblClick($any($event).detail?.node)"
(permissionError)="handlePermissionError($event)"
(preview)="showFile($event)"
(ready)="emitReadyEvent($event)"
(success)="resetError()"
[allowDropFiles]="allowDropFiles"
[contentActions]="true"
[contextMenuActions]="true"
[currentFolderId]="currentFolderId" [currentFolderId]="currentFolderId"
[filterValue]="paramValues" [contextMenuActions]="true"
[headerFilters]="headerFilters" [contentActions]="true"
[includeFields]="includeFields" [allowDropFiles]="allowDropFiles"
[selectionMode]="selectionMode"
[multiselect]="multiselect" [multiselect]="multiselect"
[node]="nodeResult" [node]="nodeResult"
[permissionsStyle]="permissionsStyle" [includeFields]="includeFields"
[selectionMode]="selectionMode"
[showHeader]="showHeader"
[sortingMode]="sortingMode"
[sorting]="sorting" [sorting]="sorting"
[sortingMode]="sortingMode"
[showHeader]="showHeader"
[stickyHeader]="stickyHeader" [stickyHeader]="stickyHeader"
class="app-file-list-container"> [headerFilters]="headerFilters"
[filterValue]="paramValues"
(error)="onNavigationError($event)"
(success)="resetError()"
(ready)="emitReadyEvent($event)"
(preview)="showFile($event)"
(folderChange)="onFolderChange($event)"
(permissionError)="handlePermissionError($event)"
(name-click)="documentList.onNodeDblClick($any($event).detail?.node)"
(filterSelection)="onFilterSelected($event)">
<adf-custom-empty-content-template *ngIf="disableDragArea"> <adf-custom-empty-content-template *ngIf="disableDragArea">
<div class="app-empty_template"> <div class="app-empty_template">
@@ -111,138 +110,137 @@
</adf-custom-empty-content-template> </adf-custom-empty-content-template>
<data-columns> <data-columns>
<data-column <data-column
[sortable]="false"
key="$thumbnail" key="$thumbnail"
type="image"> type="image"
[sortable]="false">
</data-column> </data-column>
<data-column <data-column
class="adf-expand-cell-5"
key="name" key="name"
sortingKey="name" sortingKey="name"
title="Display name"> title="Display name"
class="adf-expand-cell-5">
</data-column> </data-column>
<data-column <data-column
class="adf-ellipsis-cell"
key="content.sizeInBytes" key="content.sizeInBytes"
sortingKey="sizeInBytes"
title="Size" title="Size"
type="fileSize"> type="fileSize"
sortingKey="sizeInBytes"
class="adf-ellipsis-cell">
</data-column> </data-column>
<data-column <data-column
*ngIf="searchTerm" *ngIf="searchTerm"
class="adf-expand-cell-3"
key="search" key="search"
title="Search"> title="Search"
class="adf-expand-cell-3">
<ng-template let-entry="$implicit"> <ng-template let-entry="$implicit">
<div <div [innerHTML]="searchResultsHighlight(entry.row.node.entry.search) | highlight:searchTerm">
[innerHTML]="searchResultsHighlight(entry.row.node.entry.search) | highlight:searchTerm">
</div> </div>
</ng-template> </ng-template>
</data-column> </data-column>
<data-column <data-column
[sortable]="false"
class="app-full-width adf-ellipsis-cell adf-desktop-only" class="app-full-width adf-ellipsis-cell adf-desktop-only"
key="id" title="Node id"
title="Node id"> [sortable]="false"
key="id">
</data-column> </data-column>
<data-column <data-column
title="Lock"
key="lock"
[focus]="false" [focus]="false"
[sortable]="false" [sortable]="false"
class="adf-ellipsis-cell" class="adf-ellipsis-cell">
key="lock"
title="Lock">
<ng-template let-entry="$implicit"> <ng-template let-entry="$implicit">
<button [adf-node-lock]="entry.row.node.entry" class="app-lock-button" mat-icon-button> <button mat-icon-button [adf-node-lock]="entry.row.node.entry" class="app-lock-button">
<mat-icon *ngIf="entry.row.getValue('isLocked')">lock</mat-icon> <mat-icon *ngIf="entry.row.getValue('isLocked')">lock</mat-icon>
<mat-icon *ngIf="!entry.row.getValue('isLocked')">lock_open</mat-icon> <mat-icon *ngIf="!entry.row.getValue('isLocked')">lock_open</mat-icon>
</button> </button>
</ng-template> </ng-template>
</data-column> </data-column>
<data-column <data-column
class="adf-ellipsis-cell" title="Created by"
key="createdByUser.displayName" key="createdByUser.displayName"
sortingKey="createdByUser" sortingKey="createdByUser"
title="Created by"> class="adf-ellipsis-cell">
</data-column> </data-column>
<data-column <data-column
[format]="'timeAgo'" title="Created"
class="adf-ellipsis-cell"
key="createdAt" key="createdAt"
sortingKey="createdAt" sortingKey="createdAt"
title="Created" type="date"
type="date"> [format]="'timeAgo'"
class="adf-ellipsis-cell">
</data-column> </data-column>
</data-columns> </data-columns>
<content-actions> <content-actions>
<content-action <content-action
handler="download"
icon="get_app" icon="get_app"
title="Download"> title="Download"
handler="download">
</content-action> </content-action>
<content-action <content-action
(permissionEvent)="handlePermissionError($event)"
(success)="onDeleteActionSuccess($event)"
[disableWithNoPermission]="true"
handler="delete"
icon="delete" icon="delete"
permission="delete" permission="delete"
title="Delete"> [disableWithNoPermission]="true"
title="Delete"
(permissionEvent)="handlePermissionError($event)"
(success)="onDeleteActionSuccess($event)"
handler="delete">
</content-action> </content-action>
<content-action <content-action
(error)="onContentActionError($event)"
(execute)="onPermissionRequested($event)"
icon="supervisor_account" icon="supervisor_account"
title="Permission"
permission="copy" permission="copy"
title="Permission"> (error)="onContentActionError($event)"
(execute)="onPermissionRequested($event)">
</content-action> </content-action>
<!-- document actions --> <!-- document actions -->
<content-action <content-action
(execute)="onManageVersions($event)"
icon="storage" icon="storage"
target="document" target="document"
title="Manage versions"> title="Manage versions"
(execute)="onManageVersions($event)">
</content-action> </content-action>
<content-action <content-action
(execute)="onAspectUpdate($event)"
icon="beach_access" icon="beach_access"
target="document" target="document"
title="Update Aspects"> title="Update Aspects"
(execute)="onAspectUpdate($event)">
</content-action> </content-action>
</content-actions> </content-actions>
</adf-document-list> </adf-document-list>
</div> </div>
<adf-pagination <adf-pagination
(changePageNumber)="onChangePageNumber($event)" [target]="documentList"
(changePageSize)="onChangePageSize($event)" (changePageSize)="onChangePageSize($event)"
(changePageNumber)="onChangePageNumber($event)"
(nextPage)="onNextPage($event)" (nextPage)="onNextPage($event)"
(prevPage)="onPrevPage($event)" (prevPage)="onPrevPage($event)">
[target]="documentList">
</adf-pagination> </adf-pagination>
</adf-upload-drag-area> </adf-upload-drag-area>
<adf-info-drawer-layout *ngIf="showVersions" class="app-manage-versions-sidebar"> <adf-info-drawer-layout *ngIf="showVersions" class="app-manage-versions-sidebar">
<div info-drawer-content> <div info-drawer-content>
<adf-info-drawer *ngIf="documentList.selection[0]" [title]="'Details'"> <adf-info-drawer [title]="'Details'" *ngIf="documentList.selection[0]">
<adf-info-drawer-tab label="Properties"> <adf-info-drawer-tab label="Properties">
<adf-content-metadata <adf-content-metadata
[displayCategories]="true" [node]="documentList.selection[0].entry"
[displayEmpty]="displayEmptyMetadata" [displayEmpty]="displayEmptyMetadata"
[displayTags]="true" [displayTags]="true"
[node]="documentList.selection[0].entry"> [displayCategories]="true">
</adf-content-metadata> </adf-content-metadata>
</adf-info-drawer-tab> </adf-info-drawer-tab>
<adf-info-drawer-tab label="Versions"> <adf-info-drawer-tab label="Versions">
<ng-container *ngIf="hasOneFileSelected();else choose_document_template"> <ng-container *ngIf="hasOneFileSelected();else choose_document_template">
<ng-container *ngIf="userHasPermissionToManageVersions(); else no_permission_to_versions"> <ng-container *ngIf="userHasPermissionToManageVersions(); else no_permission_to_versions">
<adf-version-manager <adf-version-manager
[allowDownload]="allowVersionDownload"
[node]="documentList.selection[0].entry" [node]="documentList.selection[0].entry"
[showComments]="true"> [showComments]="true"
[allowDownload]="allowVersionDownload">
</adf-version-manager> </adf-version-manager>
</ng-container> </ng-container>
</ng-container> </ng-container>
@@ -279,37 +277,37 @@
<div class="app-container"> <div class="app-container">
<section> <section>
<mat-slide-toggle [(ngModel)]="multiselect" data-automation-id="multiSelectToggle"> <mat-slide-toggle data-automation-id="multiSelectToggle" [(ngModel)]="multiselect">
Multiselect (with checkboxes) Multiselect (with checkboxes)
</mat-slide-toggle> </mat-slide-toggle>
</section> </section>
<section> <section>
<mat-slide-toggle [(ngModel)]="multipleFileUpload" id="adf-multiple-upload-switch"> <mat-slide-toggle id="adf-multiple-upload-switch" [(ngModel)]="multipleFileUpload" >
Multiple File Upload Multiple File Upload
</mat-slide-toggle> </mat-slide-toggle>
</section> </section>
<section> <section>
<mat-slide-toggle [(ngModel)]="folderUpload" id="adf-folder-upload-switch"> <mat-slide-toggle id="adf-folder-upload-switch" [(ngModel)]="folderUpload">
Folder upload Folder upload
</mat-slide-toggle> </mat-slide-toggle>
</section> </section>
<section> <section>
<mat-slide-toggle [(ngModel)]="acceptedFilesTypeShow" id="adf-extension-filter-upload-switch"> <mat-slide-toggle id="adf-extension-filter-upload-switch" [(ngModel)]="acceptedFilesTypeShow">
Custom extensions filter Custom extensions filter
</mat-slide-toggle> </mat-slide-toggle>
</section> </section>
<section> <section>
<mat-slide-toggle [(ngModel)]="maxSizeShow" id="adf-max-size-filter-upload-switch"> <mat-slide-toggle id="adf-max-size-filter-upload-switch" [(ngModel)]="maxSizeShow">
Max size filter Max size filter
</mat-slide-toggle> </mat-slide-toggle>
</section> </section>
<section> <section>
<mat-slide-toggle [(ngModel)]="versioning" id="adf-version-upload-switch"> <mat-slide-toggle id="adf-version-upload-switch" [(ngModel)]="versioning">
Enable versioning Enable versioning
</mat-slide-toggle> </mat-slide-toggle>
</section> </section>
@@ -335,48 +333,48 @@
<h5>Upload</h5> <h5>Upload</h5>
<section *ngIf="acceptedFilesTypeShow"> <section *ngIf="acceptedFilesTypeShow">
<mat-form-field floatPlaceholder="float"> <mat-form-field floatPlaceholder="float">
<input [(ngModel)]="acceptedFilesType" <input matInput
data-automation-id="accepted-files-type" placeholder="Extension accepted"
matInput [(ngModel)]="acceptedFilesType"
placeholder="Extension accepted"> data-automation-id="accepted-files-type">
</mat-form-field> </mat-form-field>
</section> </section>
<section *ngIf="maxSizeShow"> <section *ngIf="maxSizeShow">
<mat-form-field> <mat-form-field>
<input [(ngModel)]="maxFilesSize" data-automation-id="max-files-size" matInput placeholder="Max file size" <input matInput type="number" placeholder="Max file size" [(ngModel)]="maxFilesSize"
type="number"> data-automation-id="max-files-size">
</mat-form-field> </mat-form-field>
</section> </section>
<div *ngIf="!acceptedFilesTypeShow"> <div *ngIf="!acceptedFilesTypeShow">
<adf-upload-button <adf-upload-button
[disabled]="!enableUpload"
[rootFolderId]="documentList.currentFolderId"
[multipleFiles]="multipleFileUpload"
[uploadFolders]="folderUpload"
[maxFilesSize]="maxSizeShow ? maxFilesSize : null"
(error)="openSnackMessageError($event)" (error)="openSnackMessageError($event)"
(permissionEvent)="handlePermissionError($event)" [versioning]="versioning"
[adf-check-allowable-operation]="'create'" [adf-check-allowable-operation]="'create'"
[adf-nodes]="enableUpload ? getCurrentDocumentListNode() : []" [adf-nodes]="enableUpload ? getCurrentDocumentListNode() : []"
[disabled]="!enableUpload" (permissionEvent)="handlePermissionError($event)">
[maxFilesSize]="maxSizeShow ? maxFilesSize : null"
[multipleFiles]="multipleFileUpload"
[rootFolderId]="documentList.currentFolderId"
[uploadFolders]="folderUpload"
[versioning]="versioning">
</adf-upload-button> </adf-upload-button>
</div> </div>
<div *ngIf="acceptedFilesTypeShow"> <div *ngIf="acceptedFilesTypeShow">
<adf-upload-button <adf-upload-button
(error)="openSnackMessageError($event)" [disabled]="!enableUpload"
(permissionEvent)="handlePermissionError($event)" [rootFolderId]="documentList.currentFolderId"
[acceptedFilesType]="acceptedFilesType" [acceptedFilesType]="acceptedFilesType"
[multipleFiles]="multipleFileUpload"
[uploadFolders]="folderUpload"
[versioning]="versioning"
(error)="openSnackMessageError($event)"
[adf-check-allowable-operation]="'create'" [adf-check-allowable-operation]="'create'"
[adf-nodes]="enableUpload ? getCurrentDocumentListNode() : []" [adf-nodes]="enableUpload ? getCurrentDocumentListNode() : []"
[disabled]="!enableUpload" (permissionEvent)="handlePermissionError($event)">
[multipleFiles]="multipleFileUpload"
[rootFolderId]="documentList.currentFolderId"
[uploadFolders]="folderUpload"
[versioning]="versioning">
</adf-upload-button> </adf-upload-button>
</div> </div>
<section> <section>
<mat-checkbox [(ngModel)]="enableUpload" id="adf-disable-upload"> <mat-checkbox id="adf-disable-upload" [(ngModel)]="enableUpload">
Enable upload Enable upload
</mat-checkbox> </mat-checkbox>
</section> </section>
@@ -385,7 +383,7 @@
<div class="app-p-10"> <div class="app-p-10">
<p>Use Cmd (Mac) or Ctrl (Windows) to toggle selection of multiple items</p> <p>Use Cmd (Mac) or Ctrl (Windows) to toggle selection of multiple items</p>
<mat-form-field> <mat-form-field>
<mat-select [(ngModel)]="selectionMode" name="food" placeholder="Selection Mode"> <mat-select placeholder="Selection Mode" [(ngModel)]="selectionMode" name="food">
<mat-option *ngFor="let mode of selectionModes" [value]="mode.value"> <mat-option *ngFor="let mode of selectionModes" [value]="mode.value">
{{mode.viewValue}} {{mode.viewValue}}
</mat-option> </mat-option>

View File

@@ -15,11 +15,11 @@
* limitations under the License. * limitations under the License.
*/ */
import { BrowserActions, createApiService, LoginPage, UploadActions, UserModel, UsersActions, ViewerPage } from '@alfresco/adf-testing';
import { browser, by, element, protractor } from 'protractor'; import { browser, by, element, protractor } from 'protractor';
import { createApiService, BrowserActions, LoginPage, UploadActions, UserModel, UsersActions, ViewerPage } from '@alfresco/adf-testing';
import { ContentServicesPage } from '../../core/pages/content-services.page'; import { ContentServicesPage } from '../../core/pages/content-services.page';
import { NavigationBarPage } from '../../core/pages/navigation-bar.page';
import { FileModel } from '../../models/ACS/file.model'; import { FileModel } from '../../models/ACS/file.model';
import { NavigationBarPage } from '../../core/pages/navigation-bar.page';
describe('Content Services Viewer', () => { describe('Content Services Viewer', () => {
const acsUser = new UserModel(); const acsUser = new UserModel();
@@ -362,7 +362,7 @@ describe('Content Services Viewer', () => {
}); });
it('[C269109] Should not be able to open thumbnail panel before the pdf is loaded', async () => { it('[C269109] Should not be able to open thumbnail panel before the pdf is loaded', async () => {
const fileView = element.all(by.css(`#document-list-container td[data-automation-id="${pdfFile.name}"]`)).first(); const fileView = element.all(by.css(`#document-list-container div[data-automation-id="${pdfFile.name}"]`)).first();
await BrowserActions.click(fileView); await BrowserActions.click(fileView);
await browser.actions().sendKeys(protractor.Key.ENTER).perform(); await browser.actions().sendKeys(protractor.Key.ENTER).perform();

View File

@@ -271,7 +271,7 @@ export class ContentServicesPage {
} }
async checkLockIsDisplayedForElement(name: string): Promise<void> { async checkLockIsDisplayedForElement(name: string): Promise<void> {
const lockButton = $(`td.adf-datatable-cell[data-automation-id="${name}"] button`); const lockButton = $(`div.adf-datatable-cell[data-automation-id="${name}"] button`);
await BrowserVisibility.waitUntilElementIsVisible(lockButton); await BrowserVisibility.waitUntilElementIsVisible(lockButton);
} }
@@ -290,7 +290,7 @@ export class ContentServicesPage {
async getAttributeValueForElement(elementName: string, propertyName: string): Promise<string> { async getAttributeValueForElement(elementName: string, propertyName: string): Promise<string> {
const elementSize = $( const elementSize = $(
`.app-document-list-container td.adf-datatable-cell[data-automation-id="${elementName}"][title="${propertyName}"] span` `.app-document-list-container div.adf-datatable-cell[data-automation-id="${elementName}"][title="${propertyName}"] span`
); );
return BrowserActions.getText(elementSize); return BrowserActions.getText(elementSize);
} }
@@ -306,7 +306,7 @@ export class ContentServicesPage {
} }
async selectFolder(folderName: string): Promise<void> { async selectFolder(folderName: string): Promise<void> {
const folderSelected = $(`td[data-automation-id="${folderName}"] .adf-datatable-center-img-ie`); const folderSelected = $(`div[data-automation-id="${folderName}"] .adf-datatable-center-img-ie`);
await BrowserVisibility.waitUntilElementIsVisible(folderSelected); await BrowserVisibility.waitUntilElementIsVisible(folderSelected);
await BrowserActions.click(folderSelected); await BrowserActions.click(folderSelected);
} }

View File

@@ -32,7 +32,7 @@ export class NavigationBarPage {
async clickNavigationBarItem(title: string, untilElementIsVisible?: ElementFinder): Promise<void> { async clickNavigationBarItem(title: string, untilElementIsVisible?: ElementFinder): Promise<void> {
Logger.log(`clickNavigationBarItem ${title}`); Logger.log(`clickNavigationBarItem ${title}`);
const menu = this.getMenuItemLocator(title); const menu = $(`.app-sidenav-link[data-automation-id="${title}"]`);
await BrowserActions.closeMenuAndDialogs(); await BrowserActions.closeMenuAndDialogs();
if (untilElementIsVisible) { if (untilElementIsVisible) {

View File

@@ -20,12 +20,13 @@ import * as path from 'path';
import { BrowserVisibility, BrowserActions } from '@alfresco/adf-testing'; import { BrowserVisibility, BrowserActions } from '@alfresco/adf-testing';
export class AttachmentListPage { export class AttachmentListPage {
attachFileButton = $('input[type="file"]');
buttonMenu = $('button[data-automation-id="action_menu_0"]'); attachFileButton = $('input[type=\'file\']');
viewButton = $('button[data-automation-id*="MENU_ACTIONS.VIEW_CONTENT"]'); buttonMenu = $('button[data-automation-id=\'action_menu_0\']');
removeButton = $('button[data-automation-id*="MENU_ACTIONS.REMOVE_CONTENT"]'); viewButton = $('button[data-automation-id*=\'MENU_ACTIONS.VIEW_CONTENT\']');
downloadButton = $('button[data-automation-id*="MENU_ACTIONS.DOWNLOAD_CONTENT"]'); removeButton = $('button[data-automation-id*=\'MENU_ACTIONS.REMOVE_CONTENT\']');
noContentContainer = $('td[class*="adf-no-content-container"]'); downloadButton = $('button[data-automation-id*=\'MENU_ACTIONS.DOWNLOAD_CONTENT\']');
noContentContainer = $('div[class*=\'adf-no-content-container\']');
async checkEmptyAttachmentList(): Promise<void> { async checkEmptyAttachmentList(): Promise<void> {
await BrowserVisibility.waitUntilElementIsVisible(this.noContentContainer); await BrowserVisibility.waitUntilElementIsVisible(this.noContentContainer);
@@ -38,7 +39,7 @@ export class AttachmentListPage {
} }
async checkFileIsAttached(name: string): Promise<void> { async checkFileIsAttached(name: string): Promise<void> {
const fileAttached = $$('td[data-automation-id="' + name + '"]').first(); const fileAttached = $$('div[data-automation-id="' + name + '"]').first();
await BrowserVisibility.waitUntilElementIsVisible(fileAttached); await BrowserVisibility.waitUntilElementIsVisible(fileAttached);
} }
@@ -48,7 +49,7 @@ export class AttachmentListPage {
async viewFile(name: string): Promise<void> { async viewFile(name: string): Promise<void> {
await BrowserActions.closeMenuAndDialogs(); await BrowserActions.closeMenuAndDialogs();
await BrowserActions.click($$('td[data-automation-id="' + name + '"]').first()); await BrowserActions.click($$('div[data-automation-id="' + name + '"]').first());
await BrowserActions.click(this.buttonMenu); await BrowserActions.click(this.buttonMenu);
await browser.sleep(500); await browser.sleep(500);
await BrowserActions.click(this.viewButton); await BrowserActions.click(this.viewButton);
@@ -57,7 +58,7 @@ export class AttachmentListPage {
async removeFile(name: string): Promise<void> { async removeFile(name: string): Promise<void> {
await BrowserActions.closeMenuAndDialogs(); await BrowserActions.closeMenuAndDialogs();
await BrowserActions.click($$('td[data-automation-id="' + name + '"]').first()); await BrowserActions.click($$('div[data-automation-id="' + name + '"]').first());
await BrowserActions.click(this.buttonMenu); await BrowserActions.click(this.buttonMenu);
await browser.sleep(500); await browser.sleep(500);
await BrowserActions.click(this.removeButton); await BrowserActions.click(this.removeButton);
@@ -66,7 +67,7 @@ export class AttachmentListPage {
async downloadFile(name: string): Promise<void> { async downloadFile(name: string): Promise<void> {
await BrowserActions.closeMenuAndDialogs(); await BrowserActions.closeMenuAndDialogs();
await BrowserActions.click($$('td[data-automation-id="' + name + '"]').first()); await BrowserActions.click($$('div[data-automation-id="' + name + '"]').first());
await BrowserActions.click(this.buttonMenu); await BrowserActions.click(this.buttonMenu);
await browser.sleep(500); await browser.sleep(500);
await BrowserActions.click(this.downloadButton); await BrowserActions.click(this.downloadButton);
@@ -74,14 +75,15 @@ export class AttachmentListPage {
async doubleClickFile(name: string): Promise<void> { async doubleClickFile(name: string): Promise<void> {
await BrowserActions.closeMenuAndDialogs(); await BrowserActions.closeMenuAndDialogs();
await BrowserVisibility.waitUntilElementIsVisible($$(`td[data-automation-id="${name}"]`).first()); await BrowserVisibility.waitUntilElementIsVisible($$(`div[data-automation-id="${name}"]`).first());
const fileAttached = $$(`td[data-automation-id="${name}"]`).first(); const fileAttached = $$(`div[data-automation-id="${name}"]`).first();
await BrowserActions.click(fileAttached); await BrowserActions.click(fileAttached);
await browser.actions().sendKeys(protractor.Key.ENTER).perform(); await browser.actions().sendKeys(protractor.Key.ENTER).perform();
} }
async checkFileIsRemoved(name: string): Promise<void> { async checkFileIsRemoved(name: string): Promise<void> {
const fileAttached = $$(`td[data-automation-id="${name}"]`).first(); const fileAttached = $$(`div[data-automation-id="${name}"]`).first();
await BrowserVisibility.waitUntilElementIsNotVisible(fileAttached); await BrowserVisibility.waitUntilElementIsNotVisible(fileAttached);
} }
} }

View File

@@ -1907,11 +1907,11 @@ describe('DocumentListComponent rendering', () => {
const rows = fixture.nativeElement.querySelectorAll('.adf-datatable-body adf-datatable-row'); const rows = fixture.nativeElement.querySelectorAll('.adf-datatable-body adf-datatable-row');
expect(rows).toBeDefined(); expect(rows).toBeDefined();
expect(rows.length).toBe(3); expect(rows.length).toBe(3);
const cell1 = fixture.nativeElement.querySelector('td[title="Name"][data-automation-id="Name 1"]'); const cell1 = fixture.nativeElement.querySelector('div[title="Name"][data-automation-id="Name 1"]');
expect(cell1.innerText).toBe('Name 1'); expect(cell1.innerText).toBe('Name 1');
const cell2 = fixture.nativeElement.querySelector('td[title="Name"][data-automation-id="Name 2"]'); const cell2 = fixture.nativeElement.querySelector('div[title="Name"][data-automation-id="Name 2"]');
expect(cell2.innerText).toBe('Name 2'); expect(cell2.innerText).toBe('Name 2');
const cell3 = fixture.nativeElement.querySelector('td[title="Id"][data-automation-id="Name 3"]'); const cell3 = fixture.nativeElement.querySelector('div[title="Id"][data-automation-id="Name 3"]');
expect(cell3.innerText).toBe('3'); expect(cell3.innerText).toBe('3');
}); });
}); });

View File

@@ -1,7 +1,6 @@
<ng-container *ngIf="value$ | async as amount"> <ng-container *ngIf="value$ | async as amount">
<span [title]="amount"> <span [title]="amount">
{{ {{ amount | currency:
amount | currency:
(currencyConfig?.code || defaultCurrencyConfig.code): (currencyConfig?.code || defaultCurrencyConfig.code):
(currencyConfig?.display || defaultCurrencyConfig.display): (currencyConfig?.display || defaultCurrencyConfig.display):
(currencyConfig?.digitsInfo || defaultCurrencyConfig.digitsInfo): (currencyConfig?.digitsInfo || defaultCurrencyConfig.digitsInfo):

View File

@@ -15,13 +15,13 @@
* limitations under the License. * limitations under the License.
*/ */
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AmountCellComponent } from './amount-cell.component';
import { CurrencyConfig } from '../../data/data-column.model';
import { BehaviorSubject } from 'rxjs';
import { LOCALE_ID } from '@angular/core';
import { registerLocaleData } from '@angular/common'; import { registerLocaleData } from '@angular/common';
import localePL from '@angular/common/locales/pl'; import localePL from '@angular/common/locales/pl';
import { LOCALE_ID } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { BehaviorSubject } from 'rxjs';
import { CurrencyConfig } from '../../data/data-column.model';
import { AmountCellComponent } from './amount-cell.component';
describe('AmountCellComponent', () => { describe('AmountCellComponent', () => {
let component: AmountCellComponent; let component: AmountCellComponent;
@@ -58,14 +58,7 @@ describe('AmountCellComponent', () => {
}); });
it('should render currency value with custom currency code', () => { it('should render currency value with custom currency code', () => {
renderAndCheckCurrencyValue( renderAndCheckCurrencyValue({ code: 'MY CUSTOM CURRENCY', display: 'symbol' }, 123.45, 'MY CUSTOM CURRENCY123.45');
{
code: 'MY CUSTOM CURRENCY',
display: 'symbol'
},
123.45,
'MY CUSTOM CURRENCY123.45'
);
}); });
it('should render currency value with custom display code', () => { it('should render currency value with custom display code', () => {

View File

@@ -15,15 +15,15 @@
* limitations under the License. * limitations under the License.
*/ */
import { AsyncPipe, CurrencyPipe, NgIf } from '@angular/common'; import { ChangeDetectionStrategy, Component, ViewEncapsulation, Input, OnInit, DEFAULT_CURRENCY_CODE, inject } from '@angular/core';
import { ChangeDetectionStrategy, Component, DEFAULT_CURRENCY_CODE, inject, Input, OnInit, ViewEncapsulation } from '@angular/core';
import { CurrencyConfig } from '../../data/data-column.model';
import { DataTableCellComponent } from '../datatable-cell/datatable-cell.component'; import { DataTableCellComponent } from '../datatable-cell/datatable-cell.component';
import { CurrencyConfig } from '../../data/data-column.model';
import { CommonModule } from '@angular/common';
@Component({ @Component({
selector: 'adf-amount-cell',
standalone: true, standalone: true,
imports: [AsyncPipe, CurrencyPipe, NgIf], imports: [CommonModule],
selector: 'adf-amount-cell',
templateUrl: './amount-cell.component.html', templateUrl: './amount-cell.component.html',
host: { class: 'adf-datatable-content-cell' }, host: { class: 'adf-datatable-content-cell' },
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,

View File

@@ -16,9 +16,9 @@
*/ */
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ObjectDataColumn } from '../../data/object-datacolumn.model';
import { ObjectDataTableAdapter } from '../../data/object-datatable-adapter';
import { BooleanCellComponent } from './boolean-cell.component'; import { BooleanCellComponent } from './boolean-cell.component';
import { ObjectDataTableAdapter } from '../../data/object-datatable-adapter';
import { ObjectDataColumn } from '../../data/object-datacolumn.model';
describe('BooleanCellComponent', () => { describe('BooleanCellComponent', () => {
let component: BooleanCellComponent; let component: BooleanCellComponent;

View File

@@ -15,15 +15,15 @@
* limitations under the License. * limitations under the License.
*/ */
import { AsyncPipe, NgIf } from '@angular/common';
import { ChangeDetectionStrategy, Component, OnInit, ViewEncapsulation } from '@angular/core'; import { ChangeDetectionStrategy, Component, OnInit, ViewEncapsulation } from '@angular/core';
import { BooleanPipe } from '../../../pipes';
import { DataTableCellComponent } from '../datatable-cell/datatable-cell.component'; import { DataTableCellComponent } from '../datatable-cell/datatable-cell.component';
import { CommonModule } from '@angular/common';
import { BooleanPipe } from '../../../pipes/boolean.pipe';
@Component({ @Component({
selector: 'adf-boolean-cell',
standalone: true, standalone: true,
imports: [AsyncPipe, BooleanPipe, NgIf], imports: [CommonModule, BooleanPipe],
selector: 'adf-boolean-cell',
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
template: ` template: `
<ng-container *ngIf="value$ | async | adfBoolean as value"> <ng-container *ngIf="value$ | async | adfBoolean as value">
@@ -36,6 +36,7 @@ import { DataTableCellComponent } from '../datatable-cell/datatable-cell.compone
host: { class: 'adf-datatable-content-cell' } host: { class: 'adf-datatable-content-cell' }
}) })
export class BooleanCellComponent extends DataTableCellComponent implements OnInit { export class BooleanCellComponent extends DataTableCellComponent implements OnInit {
ngOnInit() { ngOnInit() {
super.ngOnInit(); super.ngOnInit();
} }

View File

@@ -1,17 +1,21 @@
<div class="adf-columns-selector" <div
class="adf-columns-selector"
data-automation-id="adf-columns-selector" data-automation-id="adf-columns-selector"
tabindex="0" tabindex="0"
role="button" role="button"
(keyup.enter)="$event.stopPropagation()" (keyup.enter)="$event.stopPropagation()"
(click)="$event.stopPropagation();"> (click)="$event.stopPropagation();"
>
<div class="adf-columns-selector-header"> <div class="adf-columns-selector-header">
<span class="adf-columns-selector-header-label"> <span class="adf-columns-selector-header-label">
{{ 'ADF-DATATABLE.COLUMNS_SELECTOR.COLUMNS' | translate }} {{"ADF-DATATABLE.COLUMNS_SELECTOR.COLUMNS" | translate}}
</span> </span>
<button data-automation-id="adf-columns-selector-close-button" <button
data-automation-id="adf-columns-selector-close-button"
mat-icon-button mat-icon-button
(click)="closeMenu()"> (click)="closeMenu()"
>
<mat-icon>close</mat-icon> <mat-icon>close</mat-icon>
</button> </button>
</div> </div>
@@ -19,22 +23,26 @@
<mat-divider class="adf-columns-selector-divider"></mat-divider> <mat-divider class="adf-columns-selector-divider"></mat-divider>
<div class="adf-columns-selector-search-input-container"> <div class="adf-columns-selector-search-input-container">
<mat-icon class="adf-columns-selector-search-input-icon"> <mat-icon
class="adf-columns-selector-search-input-icon">
search search
</mat-icon> </mat-icon>
<input [formControl]="searchInputControl" <input
[formControl]="searchInputControl"
class="adf-columns-selector-search-input" class="adf-columns-selector-search-input"
data-automation-id="adf-columns-selector-search-input" data-automation-id="adf-columns-selector-search-input"
type="text" type="text"
[placeholder]="'ADF-DATATABLE.COLUMNS_SELECTOR.SEARCH' | translate"> [placeholder]='"ADF-DATATABLE.COLUMNS_SELECTOR.SEARCH" | translate'>
</div> </div>
<div class="adf-columns-selector-list-container"> <div class="adf-columns-selector-list-container">
<ng-container *ngFor="let column of columnItems"> <ng-container *ngFor="let column of columnItems">
<div *ngIf="(column.title | translate | filterString:searchQuery) as translatedTitle" <div
*ngIf="(column.title | translate | filterString:searchQuery) as translatedTitle"
class="adf-columns-selector-list-item"> class="adf-columns-selector-list-item">
<mat-checkbox color="primary" <mat-checkbox
color="primary"
class="adf-columns-selector-column-checkbox" class="adf-columns-selector-column-checkbox"
[attr.data-automation-id]="'adf-columns-selector-column-checkbox-' + column.title" [attr.data-automation-id]="'adf-columns-selector-column-checkbox-' + column.title"
[checked]="!column.isHidden" [checked]="!column.isHidden"
@@ -49,11 +57,12 @@
<mat-divider class="adf-columns-selector-divider"></mat-divider> <mat-divider class="adf-columns-selector-divider"></mat-divider>
<div class="adf-columns-selector-footer"> <div class="adf-columns-selector-footer">
<button mat-flat-button <button
mat-flat-button
data-automation-id="adf-columns-selector-apply-button" data-automation-id="adf-columns-selector-apply-button"
color="primary" color="primary"
(click)="apply()"> (click)="apply()">
{{ 'ADF-DATATABLE.COLUMNS_SELECTOR.APPLY' | translate }} {{"ADF-DATATABLE.COLUMNS_SELECTOR.APPLY" | translate}}
</button> </button>
</div> </div>
</div> </div>

View File

@@ -15,16 +15,16 @@
* limitations under the License. * limitations under the License.
*/ */
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing'; import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { MatCheckboxHarness } from '@angular/material/checkbox/testing';
import { MatMenuTrigger } from '@angular/material/menu';
import { By } from '@angular/platform-browser';
import { Observable, Subject } from 'rxjs';
import { CoreTestingModule } from '../../../testing';
import { DataColumn } from '../../data/data-column.model';
import { ColumnsSelectorComponent } from './columns-selector.component'; import { ColumnsSelectorComponent } from './columns-selector.component';
import { DataColumn } from '../../data/data-column.model';
import { Observable, Subject } from 'rxjs';
import { MatMenuTrigger } from '@angular/material/menu';
import { CoreTestingModule } from '../../../testing';
import { By } from '@angular/platform-browser';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { HarnessLoader } from '@angular/cdk/testing';
import { MatCheckboxHarness } from '@angular/material/checkbox/testing';
describe('ColumnsSelectorComponent', () => { describe('ColumnsSelectorComponent', () => {
let fixture: ComponentFixture<ColumnsSelectorComponent>; let fixture: ComponentFixture<ColumnsSelectorComponent>;
@@ -40,7 +40,8 @@ describe('ColumnsSelectorComponent', () => {
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [CoreTestingModule, ColumnsSelectorComponent] imports: [CoreTestingModule],
declarations: [ColumnsSelectorComponent]
}).compileComponents(); }).compileComponents();
fixture = TestBed.createComponent(ColumnsSelectorComponent); fixture = TestBed.createComponent(ColumnsSelectorComponent);

View File

@@ -15,36 +15,16 @@
* limitations under the License. * limitations under the License.
*/ */
import { NgForOf, NgIf } from '@angular/common';
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output, ViewEncapsulation } from '@angular/core'; import { Component, EventEmitter, Input, OnDestroy, OnInit, Output, ViewEncapsulation } from '@angular/core';
import { ReactiveFormsModule, UntypedFormControl } from '@angular/forms'; import { UntypedFormControl } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatDividerModule } from '@angular/material/divider';
import { MatIconModule } from '@angular/material/icon';
import { MatMenuTrigger } from '@angular/material/menu'; import { MatMenuTrigger } from '@angular/material/menu';
import { TranslateModule } from '@ngx-translate/core';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import { debounceTime, takeUntil } from 'rxjs/operators'; import { debounceTime, takeUntil } from 'rxjs/operators';
import { FilterStringPipe } from '../../../pipes';
import { DataColumn } from '../../data/data-column.model'; import { DataColumn } from '../../data/data-column.model';
@Component({ @Component({
selector: 'adf-datatable-column-selector', selector: 'adf-datatable-column-selector',
standalone: true,
templateUrl: './columns-selector.component.html', templateUrl: './columns-selector.component.html',
styleUrls: ['./columns-selector.component.scss'], styleUrls: ['./columns-selector.component.scss'],
imports: [
MatButtonModule,
TranslateModule,
MatIconModule,
MatDividerModule,
ReactiveFormsModule,
MatCheckboxModule,
NgIf,
NgForOf,
FilterStringPipe
],
encapsulation: ViewEncapsulation.None encapsulation: ViewEncapsulation.None
}) })
export class ColumnsSelectorComponent implements OnInit, OnDestroy { export class ColumnsSelectorComponent implements OnInit, OnDestroy {
@@ -69,16 +49,23 @@ export class ColumnsSelectorComponent implements OnInit, OnDestroy {
searchQuery = ''; searchQuery = '';
ngOnInit(): void { ngOnInit(): void {
this.mainMenuTrigger.menuOpened.pipe(takeUntil(this.onDestroy$)).subscribe(() => { this.mainMenuTrigger.menuOpened.pipe(
const columns = this.columns.map((column) => ({ ...column })); takeUntil(this.onDestroy$)
).subscribe(() => {
const columns = this.columns.map(column => ({...column}));
this.columnItems = this.columnsSorting ? this.sortColumns(columns) : columns; this.columnItems = this.columnsSorting ? this.sortColumns(columns) : columns;
}); });
this.mainMenuTrigger.menuClosed.pipe(takeUntil(this.onDestroy$)).subscribe(() => { this.mainMenuTrigger.menuClosed.pipe(
takeUntil(this.onDestroy$)
).subscribe(() => {
this.searchInputControl.setValue(''); this.searchInputControl.setValue('');
}); });
this.searchInputControl.valueChanges.pipe(debounceTime(300), takeUntil(this.onDestroy$)).subscribe((searchQuery) => { this.searchInputControl.valueChanges.pipe(
debounceTime(300),
takeUntil(this.onDestroy$)
).subscribe((searchQuery) => {
this.searchQuery = searchQuery; this.searchQuery = searchQuery;
}); });
} }
@@ -102,16 +89,12 @@ export class ColumnsSelectorComponent implements OnInit, OnDestroy {
} }
isCheckboxDisabled(column: DataColumn): boolean { isCheckboxDisabled(column: DataColumn): boolean {
return ( return this.maxColumnsVisible && column.isHidden && this.maxColumnsVisible === this.columnItems.filter(dataColumn => !dataColumn.isHidden).length;
this.maxColumnsVisible &&
column.isHidden &&
this.maxColumnsVisible === this.columnItems.filter((dataColumn) => !dataColumn.isHidden).length
);
} }
private sortColumns(columns: DataColumn[]): DataColumn[] { private sortColumns(columns: DataColumn[]): DataColumn[] {
const shownColumns = columns.filter((column) => !column.isHidden); const shownColumns = columns.filter(column => !column.isHidden);
const hiddenColumns = columns.filter((column) => column.isHidden); const hiddenColumns = columns.filter(column => column.isHidden);
return [...shownColumns, ...hiddenColumns]; return [...shownColumns, ...hiddenColumns];
} }

View File

@@ -1,16 +0,0 @@
<ng-container>
<span *ngIf="copyContent; else defaultCell"
adf-clipboard="CLIPBOARD.CLICK_TO_COPY"
[clipboard-notification]="'CLIPBOARD.SUCCESS_COPY'"
[attr.aria-label]="value$ | async"
[title]="tooltip"
class="adf-datatable-cell-value">
{{ value$ | async }}
</span>
</ng-container>
<ng-template #defaultCell>
<span [title]="tooltip"
class="adf-datatable-cell-value">
{{ value$ | async }}
</span>
</ng-template>

View File

@@ -16,12 +16,12 @@
*/ */
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing';
import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject';
import { DataRow } from '../../data/data-row.model';
import { ObjectDataTableAdapter } from '../../data/object-datatable-adapter';
import { DataTableService } from '../../services/datatable.service';
import { mockCarsData, mockCarsSchemaDefinition } from '../mocks/datatable.mock';
import { DataTableCellComponent } from './datatable-cell.component'; import { DataTableCellComponent } from './datatable-cell.component';
import { DataRow } from '../../data/data-row.model';
import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject';
import { DataTableService } from '../../services/datatable.service';
import { ObjectDataTableAdapter } from '../../data/object-datatable-adapter';
import { mockCarsData, mockCarsSchemaDefinition } from '../mocks/datatable.mock';
describe('DataTableCellComponent', () => { describe('DataTableCellComponent', () => {
let component: DataTableCellComponent; let component: DataTableCellComponent;
@@ -51,7 +51,7 @@ describe('DataTableCellComponent', () => {
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [DataTableCellComponent], declarations: [DataTableCellComponent],
providers: [DataTableService] providers: [DataTableService]
}); });

View File

@@ -15,23 +15,34 @@
* limitations under the License. * limitations under the License.
*/ */
import { AsyncPipe, NgIf } from '@angular/common'; import { ChangeDetectionStrategy, Component, Input, OnInit, ViewEncapsulation, OnDestroy, inject } from '@angular/core';
import { ChangeDetectionStrategy, Component, inject, Input, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
import { BehaviorSubject, Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { ClipboardModule } from '../../../clipboard';
import { DataColumn } from '../../data/data-column.model'; import { DataColumn } from '../../data/data-column.model';
import { DataRow } from '../../data/data-row.model'; import { DataRow } from '../../data/data-row.model';
import { DataTableAdapter } from '../../data/datatable-adapter'; import { DataTableAdapter } from '../../data/datatable-adapter';
import { BehaviorSubject, Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { DataTableService } from '../../services/datatable.service'; import { DataTableService } from '../../services/datatable.service';
@Component({ @Component({
selector: 'adf-datatable-cell', selector: 'adf-datatable-cell',
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
templateUrl: './datatable-cell.component.html', template: `
<ng-container>
<span
*ngIf="copyContent; else defaultCell"
adf-clipboard="CLIPBOARD.CLICK_TO_COPY"
[clipboard-notification]="'CLIPBOARD.SUCCESS_COPY'"
[attr.aria-label]="value$ | async"
[title]="tooltip"
class="adf-datatable-cell-value"
>{{ value$ | async }}</span
>
</ng-container>
<ng-template #defaultCell>
<span [title]="tooltip" class="adf-datatable-cell-value">{{ value$ | async }}</span>
</ng-template>
`,
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
imports: [ClipboardModule, AsyncPipe, NgIf],
host: { class: 'adf-datatable-content-cell' } host: { class: 'adf-datatable-content-cell' }
}) })
export class DataTableCellComponent implements OnInit, OnDestroy { export class DataTableCellComponent implements OnInit, OnDestroy {

View File

@@ -15,9 +15,9 @@
* limitations under the License. * limitations under the License.
*/ */
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { DataRow } from '../../data/data-row.model';
import { DataTableRowComponent } from './datatable-row.component'; import { DataTableRowComponent } from './datatable-row.component';
import { DataRow } from '../../data/data-row.model';
import { TestBed, ComponentFixture } from '@angular/core/testing';
describe('DataTableRowComponent', () => { describe('DataTableRowComponent', () => {
let fixture: ComponentFixture<DataTableRowComponent>; let fixture: ComponentFixture<DataTableRowComponent>;
@@ -31,7 +31,7 @@ describe('DataTableRowComponent', () => {
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [DataTableRowComponent] declarations: [DataTableRowComponent]
}); });
fixture = TestBed.createComponent(DataTableRowComponent); fixture = TestBed.createComponent(DataTableRowComponent);
@@ -51,14 +51,16 @@ describe('DataTableRowComponent', () => {
component.row = row; component.row = row;
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement.classList.contains('adf-is-selected')).not.toBe(true); expect(fixture.debugElement.nativeElement.classList.contains('adf-is-selected'))
.not.toBe(true);
}); });
it('should not have select class when row data is null', () => { it('should not have select class when row data is null', () => {
row.isSelected = false; row.isSelected = false;
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement.classList.contains('adf-is-selected')).not.toBe(true); expect(fixture.debugElement.nativeElement.classList.contains('adf-is-selected'))
.not.toBe(true);
}); });
it('should set aria selected to true when row is selected', () => { it('should set aria selected to true when row is selected', () => {

View File

@@ -15,13 +15,21 @@
* limitations under the License. * limitations under the License.
*/ */
import {
Component,
ViewEncapsulation,
ElementRef,
Input,
HostBinding,
HostListener,
Output,
EventEmitter
} from '@angular/core';
import { FocusableOption } from '@angular/cdk/a11y'; import { FocusableOption } from '@angular/cdk/a11y';
import { Component, ElementRef, EventEmitter, HostBinding, HostListener, Input, Output, ViewEncapsulation } from '@angular/core';
import { DataRow } from '../../data/data-row.model'; import { DataRow } from '../../data/data-row.model';
@Component({ @Component({
selector: 'adf-datatable-row', selector: 'adf-datatable-row',
standalone: true,
template: `<ng-content></ng-content>`, template: `<ng-content></ng-content>`,
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
host: { host: {

View File

@@ -1,37 +1,32 @@
<div *ngIf="data" <div
role="table" role="grid"
*ngIf="data"
class="adf-full-width adf-datatable-list" class="adf-full-width adf-datatable-list"
[class.adf-sticky-header]="isStickyHeaderEnabled()" [class.adf-sticky-header]="isStickyHeaderEnabled()"
[class.adf-datatable--empty]="(isEmpty() && !isHeaderVisible()) || loading" [class.adf-datatable--empty]="(isEmpty() && !isHeaderVisible()) || loading"
[class.adf-datatable--empty--header-visible]="isEmpty() && isHeaderVisible()"> [class.adf-datatable--empty--header-visible]="isEmpty() && isHeaderVisible()">
<thead *ngIf="isHeaderVisible()" <div *ngIf="isHeaderVisible()" class="adf-datatable-header" role="rowgroup" [ngClass]="{ 'adf-sr-only': !isHeaderVisible() }">
class="adf-datatable-header" <adf-datatable-row
[ngClass]="{ 'adf-sr-only': !isHeaderVisible() }"> cdkDropList
<adf-datatable-row cdkDropList
cdkDropListOrientation="horizontal" cdkDropListOrientation="horizontal"
[cdkDropListSortPredicate]="filterDisabledColumns" [cdkDropListSortPredicate]="filterDisabledColumns"
data-automation-id="datatable-row-header" data-automation-id="datatable-row-header"
[disabled]="!isHeaderVisible()" [disabled]="!isHeaderVisible()"
class="adf-datatable-row"> class="adf-datatable-row"
role="row">
<!-- Actions (left) --> <!-- Actions (left) -->
<th *ngIf="actions && actionsPosition === 'left'" <div *ngIf="actions && actionsPosition === 'left'" class="adf-actions-column adf-datatable-cell-header">
class="adf-actions-column adf-datatable-cell-header" <span class="adf-sr-only">{{ 'ADF-DATATABLE.ACCESSIBILITY.ACTIONS' | translate }}</span>
[attr.aria-label]="'ADF-DATATABLE.ACCESSIBILITY.ACTIONS' | translate"> </div>
</th>
<!-- Columns --> <!-- Columns -->
<th *ngIf="multiselect" <div *ngIf="multiselect" class="adf-datatable-cell-header adf-datatable-checkbox">
class="adf-datatable-cell-header adf-datatable-checkbox"> <mat-checkbox [indeterminate]="isSelectAllIndeterminate" [checked]="isSelectAllChecked" (change)="onSelectAllClick($event)" class="adf-checkbox-sr-only">{{ 'ADF-DATATABLE.ACCESSIBILITY.SELECT_ALL' | translate }}</mat-checkbox>
<mat-checkbox [indeterminate]="isSelectAllIndeterminate" </div>
[checked]="isSelectAllChecked"
(change)="onSelectAllClick($event)"
[attr.aria-label]="'ADF-DATATABLE.ACCESSIBILITY.SELECT_ALL' | translate"
[matTooltip]="'ADF-DATATABLE.ACCESSIBILITY.SELECT_ALL' | translate">
</mat-checkbox>
</th>
<th class="adf-datatable-cell--{{ col.type || 'text' }} {{ col.cssClass }} adf-datatable-cell-header adf-datatable-cell-data" <div
class="adf-datatable-cell--{{col.type || 'text'}} {{col.cssClass}} adf-datatable-cell-header adf-datatable-cell-data"
*ngFor=" *ngFor="
let col of (data.getColumns() | filterOutEvery:'isHidden':true); let col of (data.getColumns() | filterOutEvery:'isHidden':true);
let columnIndex = index let columnIndex = index
@@ -46,21 +41,20 @@
[attr.aria-label]="col.title | translate" [attr.aria-label]="col.title | translate"
(click)="onColumnHeaderClick(col, $event)" (click)="onColumnHeaderClick(col, $event)"
(keyup.enter)="onColumnHeaderClick(col, $event)" (keyup.enter)="onColumnHeaderClick(col, $event)"
role="columnheader"
[attr.tabindex]="isHeaderVisible() ? 0 : null" [attr.tabindex]="isHeaderVisible() ? 0 : null"
[attr.aria-sort]="col.sortable ? (getAriaSort(col) | translate) : null" [attr.aria-sort]="col.sortable ? (getAriaSort(col) | translate) : null"
cdkDrag cdkDrag
cdkDragLockAxis="x" cdkDragLockAxis="x"
[cdkDragPreviewClass]="'adf-drag-preview'"
(cdkDragStarted)="isDraggingHeaderColumn = true" (cdkDragStarted)="isDraggingHeaderColumn = true"
(cdkDragDropped)="onDropHeaderColumn($event)" (cdkDragDropped)="onDropHeaderColumn($event)"
[cdkDragDisabled]="!col.draggable" [cdkDragDisabled]="!col.draggable"
(mouseenter)="hoveredHeaderColumnIndex = columnIndex" (mouseenter)="hoveredHeaderColumnIndex = columnIndex"
(mouseleave)="hoveredHeaderColumnIndex = -1" (mouseleave)="hoveredHeaderColumnIndex = -1"
adf-drop-zone adf-drop-zone dropTarget="header" [dropColumn]="col">
dropTarget="header"
[dropColumn]="col">
<div adf-resizable <div
adf-resizable
#resizableElement="adf-resizable" #resizableElement="adf-resizable"
[coverPadding]="10" [coverPadding]="10"
(resizing)="onResizing($event, columnIndex)" (resizing)="onResizing($event, columnIndex)"
@@ -71,47 +65,47 @@
[ngClass]="{ 'adf-datatable-cell-header-content--hovered': [ngClass]="{ 'adf-datatable-cell-header-content--hovered':
hoveredHeaderColumnIndex === columnIndex && hoveredHeaderColumnIndex === columnIndex &&
!isDraggingHeaderColumn && !isDraggingHeaderColumn &&
!isResizing && col.sortable}"> !isResizing && col.sortable}"
>
<ng-container *ngIf="!col.header"> <ng-container *ngIf="!col.header">
<span *ngIf="col.title" <span *ngIf="col.title" matTooltip="{{col.title | translate}}" class="adf-datatable-cell-value">{{col.title | translate}}</span>
[matTooltip]="col.title | translate"
class="adf-datatable-cell-value">{{ col.title | translate }}</span>
<span *ngIf="col.title && col.sortable && isDraggingHeaderColumn" <span *ngIf="col.title && col.sortable && isDraggingHeaderColumn" class="adf-sr-only" aria-live="polite">
class="adf-sr-only"
aria-live="polite">
{{ getSortLiveAnnouncement(col) | translate: { string: col.title | translate } }} {{ getSortLiveAnnouncement(col) | translate: { string: col.title | translate } }}
</span> </span>
<span *ngIf="!col.title && !col.sortable && !headerFilterTemplate" <span *ngIf="!col.title && !col.sortable && !headerFilterTemplate" [attr.title]="'ADF-DATATABLE.ACCESSIBILITY.EMPTY_HEADER' | translate"></span>
[attr.title]="'ADF-DATATABLE.ACCESSIBILITY.EMPTY_HEADER' | translate"></span>
</ng-container> </ng-container>
<div *ngIf="col.header" class="adf-datatable-cell-value"> <div *ngIf="col.header" class="adf-datatable-cell-value">
<ng-template [ngTemplateOutlet]="col.header" <ng-template [ngTemplateOutlet]="col.header" [ngTemplateOutletContext]="{$implicit: col}"></ng-template>
[ngTemplateOutletContext]="{ $implicit: col }"></ng-template>
</div> </div>
<span [class.adf-datatable__header--sorted-asc]="isColumnSorted(col, 'asc')" <span
[class.adf-datatable__header--sorted-desc]="isColumnSorted(col, 'desc')"></span> [class.adf-datatable__header--sorted-asc]="isColumnSorted(col, 'asc')"
[class.adf-datatable__header--sorted-desc]="isColumnSorted(col, 'desc')">
</span>
<ng-template *ngIf="allowFiltering" <ng-template *ngIf="allowFiltering" [ngTemplateOutlet]="headerFilterTemplate" [ngTemplateOutletContext]="{$implicit: col}"></ng-template>
[ngTemplateOutlet]="headerFilterTemplate"
[ngTemplateOutletContext]="{ $implicit: col }"></ng-template>
<span *ngIf="col.draggable" <span
*ngIf="col.draggable"
cdkDragHandle cdkDragHandle
[ngClass]="{ 'adf-datatable-cell-header-drag-icon': !isResizing }"> [ngClass]="{ 'adf-datatable-cell-header-drag-icon': !isResizing }"
<adf-icon *ngIf="hoveredHeaderColumnIndex === columnIndex && !isResizing" >
<adf-icon
*ngIf="hoveredHeaderColumnIndex === columnIndex && !isResizing"
value="adf:drag_indicator" value="adf:drag_indicator"
[attr.data-automation-id]="'adf-datatable-cell-header-drag-icon-'+col.key"> [attr.data-automation-id]="'adf-datatable-cell-header-drag-icon-'+col.key">
</adf-icon> </adf-icon>
</span> </span>
</div> </div>
<div *ngIf="isResizingEnabled && col.resizable && !lastColumn" <div
*ngIf="isResizingEnabled && col.resizable && !lastColumn"
[ngClass]="hoveredHeaderColumnIndex === columnIndex && !isResizing || resizingColumnIndex === columnIndex ? 'adf-datatable__resize-handle-visible' : 'adf-datatable__resize-handle-hidden'" [ngClass]="hoveredHeaderColumnIndex === columnIndex && !isResizing || resizingColumnIndex === columnIndex ? 'adf-datatable__resize-handle-visible' : 'adf-datatable__resize-handle-hidden'"
adf-resize-handle adf-resize-handle
role="separator" tabindex="0"
role="button"
(click)="$event.stopPropagation()" (click)="$event.stopPropagation()"
(keyup.enter)="$event.stopPropagation()" (keyup.enter)="$event.stopPropagation()"
class="adf-datatable__resize-handle" class="adf-datatable__resize-handle"
@@ -119,15 +113,18 @@
<div class="adf-datatable__resize-handle--divider"></div> <div class="adf-datatable__resize-handle--divider"></div>
</div> </div>
<div class="adf-drop-header-cell-placeholder" *cdkDragPlaceholder></div> <div class="adf-drop-header-cell-placeholder" *cdkDragPlaceholder></div>
</th> </div>
<!-- Header actions (right) --> <!-- Header actions (right) -->
<th *ngIf="(actions && actionsPosition === 'right') || (mainActionTemplate && showMainDatatableActions)" <div
class="adf-actions-column adf-datatable-actions-menu adf-datatable-cell-header adf-datatable__actions-cell"> *ngIf="(actions && actionsPosition === 'right') ||
(mainActionTemplate && showMainDatatableActions)"
class="adf-actions-column adf-datatable-actions-menu adf-datatable-cell-header adf-datatable__actions-cell"
>
<ng-container *ngIf="mainActionTemplate"> <ng-container *ngIf="mainActionTemplate">
<button data-automation-id="adf-datatable-main-menu-button" <button
[matTooltip]="'ADF-DATATABLE.CONTENT-ACTIONS.SELECT_COLUMNS' | translate" data-automation-id="adf-datatable-main-menu-button"
[attr.aria-label]="'ADF-DATATABLE.CONTENT-ACTIONS.SELECT_COLUMNS' | translate" matTooltip="{{ 'ADF-DATATABLE.CONTENT-ACTIONS.SELECT_COLUMNS' | translate }}"
mat-icon-button mat-icon-button
#mainMenuTrigger="matMenuTrigger" #mainMenuTrigger="matMenuTrigger"
(keydown.enter)="mainMenuTrigger.openMenu()" (keydown.enter)="mainMenuTrigger.openMenu()"
@@ -135,18 +132,24 @@
<mat-icon>view_week_outline</mat-icon> <mat-icon>view_week_outline</mat-icon>
</button> </button>
<mat-menu #mainMenu> <mat-menu #mainMenu>
<ng-container [ngTemplateOutlet]="mainActionTemplate" <ng-container
[ngTemplateOutletContext]="{ $implicit: mainMenuTrigger }"> [ngTemplateOutlet]="mainActionTemplate"
[ngTemplateOutletContext]="{
$implicit: mainMenuTrigger
}">
</ng-container> </ng-container>
</mat-menu> </mat-menu>
<span class="adf-sr-only">{{ 'ADF-DATATABLE.ACCESSIBILITY.ACTIONS' | translate }}</span>
</ng-container> </ng-container>
</th> </div>
</adf-datatable-row> </adf-datatable-row>
</thead> </div>
<tbody class="adf-datatable-body" <div
[ngClass]="{ 'adf-blur-datatable-body': blurOnResize && (isDraggingHeaderColumn || isResizing) }"> class="adf-datatable-body"
[ngClass]="{ 'adf-blur-datatable-body': blurOnResize && (isDraggingHeaderColumn || isResizing) }"
role="rowgroup">
<ng-container *ngIf="!loading && !noPermission"> <ng-container *ngIf="!loading && !noPermission">
<adf-datatable-row *ngFor="let row of data.getRows(); let idx = index" <adf-datatable-row *ngFor="let row of data.getRows(); let idx = index"
[row]="row" [row]="row"
@@ -160,10 +163,8 @@
[attr.data-automation-id]="'datatable-row-' + idx" [attr.data-automation-id]="'datatable-row-' + idx"
(contextmenu)="markRowAsContextMenuSource(row)"> (contextmenu)="markRowAsContextMenuSource(row)">
<!-- Actions (left) --> <!-- Actions (left) -->
<td *ngIf="actions && actionsPosition === 'left'" class="adf-datatable-cell"> <div *ngIf="actions && actionsPosition === 'left'" role="gridcell" class="adf-datatable-cell">
<button mat-icon-button <button mat-icon-button [matMenuTriggerFor]="menu" #actionsMenuTrigger="matMenuTrigger"
[matMenuTriggerFor]="menu"
#actionsMenuTrigger="matMenuTrigger"
[ngClass]="getHideActionsWithoutHoverClass(actionsMenuTrigger)" [ngClass]="getHideActionsWithoutHoverClass(actionsMenuTrigger)"
[title]="'ADF-DATATABLE.CONTENT-ACTIONS.TOOLTIP' | translate" [title]="'ADF-DATATABLE.CONTENT-ACTIONS.TOOLTIP' | translate"
[attr.id]="'action_menu_left_' + idx" [attr.id]="'action_menu_left_' + idx"
@@ -171,8 +172,7 @@
<mat-icon>more_vert</mat-icon> <mat-icon>more_vert</mat-icon>
</button> </button>
<mat-menu #menu="matMenu"> <mat-menu #menu="matMenu">
<button mat-menu-item <button mat-menu-item *ngFor="let action of getRowActions(row)"
*ngFor="let action of getRowActions(row)"
[attr.data-automation-id]="action.title" [attr.data-automation-id]="action.title"
[disabled]="action.disabled" [disabled]="action.disabled"
(click)="onExecuteRowAction(row, action)"> (click)="onExecuteRowAction(row, action)">
@@ -180,21 +180,23 @@
<span>{{ action.title | translate }}</span> <span>{{ action.title | translate }}</span>
</button> </button>
</mat-menu> </mat-menu>
</td> </div>
<td *ngIf="multiselect" <label *ngIf="multiselect" [for]="'select-file-' + idx" class="adf-datatable-cell adf-datatable-checkbox">
class="adf-datatable-cell adf-datatable-checkbox"> <mat-checkbox
<mat-checkbox [id]="'select-file-' + idx" [id]="'select-file-' + idx"
[checked]="row.isSelected" [checked]="row.isSelected"
[attr.aria-checked]="row.isSelected" [attr.aria-checked]="row.isSelected"
role="checkbox"
(change)="onCheckboxChange(row, $event)" (change)="onCheckboxChange(row, $event)"
[attr.aria-label]="'ADF-DATATABLE.ACCESSIBILITY.SELECT_FILE' | translate" class="adf-checkbox-sr-only">
[matTooltip]="'ADF-DATATABLE.ACCESSIBILITY.SELECT_FILE' | translate"> {{ 'ADF-DATATABLE.ACCESSIBILITY.SELECT_FILE' | translate }}
</mat-checkbox> </mat-checkbox>
</td> </label>
<td *ngFor=" <div *ngFor="
let col of (data.getColumns() | filterOutEvery:'isHidden':true), let col of (data.getColumns() | filterOutEvery:'isHidden':true),
let lastColumn = last;" let lastColumn = last;"
role="gridcell"
class="adf-datatable-cell adf-datatable-cell--{{col.type || 'text'}} {{col.cssClass}} adf-datatable-cell-data" class="adf-datatable-cell adf-datatable-cell--{{col.type || 'text'}} {{col.cssClass}} adf-datatable-cell-data"
[attr.title]="col.title | translate" [attr.title]="col.title | translate"
[attr.data-automation-id]="getAutomationValue(row)" [attr.data-automation-id]="getAutomationValue(row)"
@@ -205,10 +207,7 @@
(keydown.enter)="onEnterKeyPressed(row, $any($event))" (keydown.enter)="onEnterKeyPressed(row, $any($event))"
[adf-context-menu]="getContextMenuActions(row, col)" [adf-context-menu]="getContextMenuActions(row, col)"
[adf-context-menu-enabled]="contextMenu" [adf-context-menu-enabled]="contextMenu"
adf-drop-zone adf-drop-zone dropTarget="cell" [dropColumn]="col" [dropRow]="row"
dropTarget="cell"
[dropColumn]="col"
[dropRow]="row"
[ngStyle]="(col.width) && !lastColumn && {'flex': getFlexValue(col)}"> [ngStyle]="(col.width) && !lastColumn && {'flex': getFlexValue(col)}">
<div *ngIf="!col.template" class="adf-datatable-cell-container"> <div *ngIf="!col.template" class="adf-datatable-cell-container">
<ng-container [ngSwitch]="data.getColumnType(row, col)"> <ng-container [ngSwitch]="data.getColumnType(row, col)">
@@ -217,8 +216,7 @@
</mat-icon> </mat-icon>
<ng-template #no_iconvalue> <ng-template #no_iconvalue>
<mat-icon class="adf-datatable-selected" <mat-icon class="adf-datatable-selected"
*ngIf="row.isSelected && !multiselect; else no_selected_row" *ngIf="row.isSelected && !multiselect; else no_selected_row" svgIcon="selected">
svgIcon="selected">
</mat-icon> </mat-icon>
<ng-template #no_selected_row> <ng-template #no_selected_row>
<img class="adf-datatable-center-img-ie" <img class="adf-datatable-center-img-ie"
@@ -238,15 +236,15 @@
</ng-template> </ng-template>
</div> </div>
<div *ngSwitchCase="'icon'" class="adf-cell-value"> <div *ngSwitchCase="'icon'" class="adf-cell-value">
<adf-icon-cell [data]="data" <adf-icon-cell
[data]="data"
[column]="col" [column]="col"
[row]="row" [row]="row"
[resolverFn]="resolverFn" [resolverFn]="resolverFn"
[tooltip]="getCellTooltip(row, col)"> [tooltip]="getCellTooltip(row, col)">
</adf-icon-cell> </adf-icon-cell>
</div> </div>
<div *ngSwitchCase="'date'" class="adf-cell-value adf-cell-date" <div *ngSwitchCase="'date'" class="adf-cell-value adf-cell-date" [attr.tabindex]="data.getValue(row, col, resolverFn)? 0 : -1"
[attr.tabindex]="data.getValue(row, col, resolverFn)? 0 : -1"
[attr.data-automation-id]="'date_' + (data.getValue(row, col, resolverFn) | adfLocalizedDate: 'medium') "> [attr.data-automation-id]="'date_' + (data.getValue(row, col, resolverFn) | adfLocalizedDate: 'medium') ">
<adf-date-cell class="adf-datatable-center-date-column-ie" <adf-date-cell class="adf-datatable-center-date-column-ie"
[data]="data" [data]="data"
@@ -257,18 +255,17 @@
[dateConfig]="col.dateConfig"> [dateConfig]="col.dateConfig">
</adf-date-cell> </adf-date-cell>
</div> </div>
<div *ngSwitchCase="'location'" <div *ngSwitchCase="'location'" [attr.tabindex]="data.getValue(row, col, resolverFn)? 0 : -1" class="adf-cell-value"
[attr.tabindex]="data.getValue(row, col, resolverFn)? 0 : -1" class="adf-cell-value"
[attr.data-automation-id]="'location' + data.getValue(row, col, resolverFn)"> [attr.data-automation-id]="'location' + data.getValue(row, col, resolverFn)">
<adf-location-cell [data]="data" <adf-location-cell
[data]="data"
[column]="col" [column]="col"
[row]="row" [row]="row"
[resolverFn]="resolverFn" [resolverFn]="resolverFn"
[tooltip]="getCellTooltip(row, col)"> [tooltip]="getCellTooltip(row, col)">
</adf-location-cell> </adf-location-cell>
</div> </div>
<div *ngSwitchCase="'fileSize'" <div *ngSwitchCase="'fileSize'" [attr.tabindex]="data.getValue(row, col, resolverFn)? 0 : -1" class="adf-cell-value"
[attr.tabindex]="data.getValue(row, col, resolverFn)? 0 : -1" class="adf-cell-value"
[attr.data-automation-id]="'fileSize_' + data.getValue(row, col, resolverFn)"> [attr.data-automation-id]="'fileSize_' + data.getValue(row, col, resolverFn)">
<adf-filesize-cell class="adf-datatable-center-size-column-ie" <adf-filesize-cell class="adf-datatable-center-size-column-ie"
[data]="data" [data]="data"
@@ -278,11 +275,10 @@
[tooltip]="getCellTooltip(row, col)"> [tooltip]="getCellTooltip(row, col)">
</adf-filesize-cell> </adf-filesize-cell>
</div> </div>
<div *ngSwitchCase="'text'" <div *ngSwitchCase="'text'" [attr.tabindex]="data.getValue(row, col, resolverFn)? 0 : -1" class="adf-cell-value"
class="adf-cell-value"
[attr.tabindex]="data.getValue(row, col, resolverFn)? 0 : -1"
[attr.data-automation-id]="'text_' + data.getValue(row, col, resolverFn)"> [attr.data-automation-id]="'text_' + data.getValue(row, col, resolverFn)">
<adf-datatable-cell [copyContent]="col.copyContent" <adf-datatable-cell
[copyContent]="col.copyContent"
[data]="data" [data]="data"
[column]="col" [column]="col"
[row]="row" [row]="row"
@@ -290,21 +286,19 @@
[tooltip]="getCellTooltip(row, col)"> [tooltip]="getCellTooltip(row, col)">
</adf-datatable-cell> </adf-datatable-cell>
</div> </div>
<div *ngSwitchCase="'boolean'" <div *ngSwitchCase="'boolean'" [attr.tabindex]="data.getValue(row, col, resolverFn)? 0 : -1" class="adf-cell-value"
class="adf-cell-value"
[attr.tabindex]="data.getValue(row, col, resolverFn)? 0 : -1"
[attr.data-automation-id]="'boolean_' + data.getValue(row, col, resolverFn)"> [attr.data-automation-id]="'boolean_' + data.getValue(row, col, resolverFn)">
<adf-boolean-cell [data]="data" <adf-boolean-cell
[data]="data"
[column]="col" [column]="col"
[row]="row" [row]="row"
[resolverFn]="resolverFn" [resolverFn]="resolverFn"
[tooltip]="getCellTooltip(row, col)"> [tooltip]="getCellTooltip(row, col)">
</adf-boolean-cell> </adf-boolean-cell>
</div> </div>
<div *ngSwitchCase="'json'" <div *ngSwitchCase="'json'" [attr.tabindex]="data.getValue(row, col, resolverFn)? 0 : -1" class="adf-cell-value">
class="adf-cell-value" <adf-json-cell
[attr.tabindex]="data.getValue(row, col, resolverFn)? 0 : -1"> [editable]="col.editable"
<adf-json-cell [editable]="col.editable"
[data]="data" [data]="data"
[column]="col" [column]="col"
[resolverFn]="resolverFn" [resolverFn]="resolverFn"
@@ -315,7 +309,8 @@
class="adf-cell-value" class="adf-cell-value"
[attr.tabindex]="data.getValue(row, col, resolverFn)? 0 : -1" [attr.tabindex]="data.getValue(row, col, resolverFn)? 0 : -1"
[attr.data-automation-id]="'amount_' + data.getValue(row, col, resolverFn)"> [attr.data-automation-id]="'amount_' + data.getValue(row, col, resolverFn)">
<adf-amount-cell [data]="data" <adf-amount-cell
[data]="data"
[column]="col" [column]="col"
[resolverFn]="resolverFn" [resolverFn]="resolverFn"
[row]="row" [row]="row"
@@ -326,7 +321,8 @@
class="adf-cell-value" class="adf-cell-value"
[attr.tabindex]="data.getValue(row, col, resolverFn)? 0 : -1" [attr.tabindex]="data.getValue(row, col, resolverFn)? 0 : -1"
[attr.data-automation-id]="'number_' + data.getValue(row, col, resolverFn)"> [attr.data-automation-id]="'number_' + data.getValue(row, col, resolverFn)">
<adf-number-cell [data]="data" <adf-number-cell
[data]="data"
[column]="col" [column]="col"
[resolverFn]="resolverFn" [resolverFn]="resolverFn"
[row]="row" [row]="row"
@@ -339,27 +335,24 @@
</ng-container> </ng-container>
</div> </div>
<div *ngIf="col.template" class="adf-datatable-cell-container"> <div *ngIf="col.template" class="adf-datatable-cell-container">
<div class="adf-cell-value" <div class="adf-cell-value" [attr.tabindex]="col.focus ? 0 : null">
[attr.tabindex]="col.focus ? 0 : null"> <ng-container
<ng-container [ngTemplateOutlet]="col.template" [ngTemplateOutlet]="col.template"
[ngTemplateOutletContext]="{ [ngTemplateOutletContext]="{ $implicit: { data: data, row: row, col: col }, value: data.getValue(row, col, resolverFn) }">
$implicit: { data, row, col },
value: data.getValue(row, col, resolverFn)
}">
</ng-container> </ng-container>
</div> </div>
</div> </div>
</td> </div>
<!-- Row actions (right) --> <!-- Row actions (right) -->
<td *ngIf="(actions && actionsPosition === 'right') || <div *ngIf="
(actions && actionsPosition === 'right') ||
(mainActionTemplate && showMainDatatableActions)" (mainActionTemplate && showMainDatatableActions)"
role="gridcell"
class="adf-datatable-cell adf-datatable__actions-cell adf-datatable-center-actions-column-ie adf-datatable-actions-menu"> class="adf-datatable-cell adf-datatable__actions-cell adf-datatable-center-actions-column-ie adf-datatable-actions-menu">
<ng-container *ngIf="(actions && actionsPosition === 'right')"> <ng-container *ngIf="(actions && actionsPosition === 'right')">
<button mat-icon-button <button mat-icon-button [matMenuTriggerFor]="menu" #actionsMenuTrigger="matMenuTrigger"
[matMenuTriggerFor]="menu"
#actionsMenuTrigger="matMenuTrigger"
[ngClass]="getHideActionsWithoutHoverClass(actionsMenuTrigger)" [ngClass]="getHideActionsWithoutHoverClass(actionsMenuTrigger)"
[attr.aria-label]="'ADF-DATATABLE.ACCESSIBILITY.ROW_OPTION_BUTTON' | translate" [attr.aria-label]="'ADF-DATATABLE.ACCESSIBILITY.ROW_OPTION_BUTTON' | translate"
[title]="'ADF-DATATABLE.CONTENT-ACTIONS.TOOLTIP' | translate" [title]="'ADF-DATATABLE.CONTENT-ACTIONS.TOOLTIP' | translate"
@@ -379,34 +372,35 @@
</button> </button>
</mat-menu> </mat-menu>
</ng-container> </ng-container>
</td> </div>
</adf-datatable-row> </adf-datatable-row>
<tr *ngIf="isEmpty()" class="adf-datatable-row"> <div *ngIf="isEmpty()" role="row" class="adf-datatable-row">
<td class="adf-no-content-container adf-datatable-cell"> <div class="adf-no-content-container adf-datatable-cell" role="gridcell">
<ng-template *ngIf="noContentTemplate" <ng-template *ngIf="noContentTemplate"
ngFor [ngForOf]="[data]" ngFor [ngForOf]="[data]"
[ngForTemplate]="noContentTemplate"> [ngForTemplate]="noContentTemplate">
</ng-template> </ng-template>
<ng-content select="adf-empty-list"></ng-content> <ng-content select="adf-empty-list"></ng-content>
</td> </div>
</tr> </div>
</ng-container> </ng-container>
<tr *ngIf="!loading && noPermission" <div *ngIf="!loading && noPermission"
role="row"
class="adf-datatable-row adf-no-permission__row"> class="adf-datatable-row adf-no-permission__row">
<td class="adf-no-permission__cell adf-no-content-container adf-datatable-cell"> <div class="adf-no-permission__cell adf-no-content-container adf-datatable-cell">
<ng-template *ngIf="noPermissionTemplate" <ng-template *ngIf="noPermissionTemplate"
ngFor [ngForOf]="[data]" ngFor [ngForOf]="[data]"
[ngForTemplate]="noPermissionTemplate"> [ngForTemplate]="noPermissionTemplate">
</ng-template> </ng-template>
</td> </div>
</tr> </div>
<tr *ngIf="loading" class="adf-datatable-row"> <div *ngIf="loading" class="adf-datatable-row">
<td class="adf-no-content-container adf-datatable-cell"> <div class="adf-no-content-container adf-datatable-cell">
<ng-template *ngIf="loadingTemplate" <ng-template *ngIf="loadingTemplate"
ngFor [ngForOf]="[data]" ngFor [ngForOf]="[data]"
[ngForTemplate]="loadingTemplate"> [ngForTemplate]="loadingTemplate">
</ng-template> </ng-template>
</td> </div>
</tr> </div>
</tbody> </div>
</div> </div>

View File

@@ -283,11 +283,6 @@ $data-table-cell-min-width-file-size: $data-table-cell-min-width-1 !default;
padding-right: 15px; padding-right: 15px;
} }
.adf-datatable-checkbox {
display: flex;
justify-content: center;
}
.adf-cell-value { .adf-cell-value {
display: flex; display: flex;
min-height: inherit; min-height: inherit;
@@ -438,13 +433,13 @@ $data-table-cell-min-width-file-size: $data-table-cell-min-width-1 !default;
} }
/* mobile phone */ /* mobile phone */
@media all and (width <= 768px) { @media all and (max-width: 768px) {
.adf-desktop-only.adf-ellipsis-cell { .adf-desktop-only.adf-ellipsis-cell {
display: none; display: none;
} }
} }
@media (width <= 768px) { @media (max-device-width: 768px) {
.adf-desktop-only.adf-ellipsis-cell { .adf-desktop-only.adf-ellipsis-cell {
display: none; display: none;
} }
@@ -500,6 +495,11 @@ $data-table-cell-min-width-file-size: $data-table-cell-min-width-1 !default;
right: -3px; right: -3px;
} }
&.adf-datatable-checkbox {
display: flex;
align-items: center;
}
.adf-datatable-cell-header-content { .adf-datatable-cell-header-content {
display: flex; display: flex;
flex-grow: 1; flex-grow: 1;
@@ -557,13 +557,27 @@ $data-table-cell-min-width-file-size: $data-table-cell-min-width-1 !default;
} }
} }
.adf-datatable-cell-header.adf-drag-preview { .cdk-drag-preview {
&.adf-datatable-cell-header {
border-radius: 6px; border-radius: 6px;
background-color: var(--theme-background-color); background-color: var(--theme-background-color);
@include mat.elevation-transition; @include mat.elevation-transition;
@include mat.elevation(4); @include mat.elevation(4);
} }
}
/* [Accessibility] Material checkbox labels */
.adf-checkbox-sr-only .mat-checkbox-label {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;
}
.adf-sticky-header { .adf-sticky-header {
border-top: 0; border-top: 0;
@@ -606,7 +620,7 @@ $data-table-cell-min-width-file-size: $data-table-cell-min-width-1 !default;
align-items: center; align-items: center;
height: inherit; height: inherit;
.adf-datatable-body[role='rowgroup'] { .adf-datatable-body[role="rowgroup"] {
.adf-datatable-row { .adf-datatable-row {
height: 100%; height: 100%;
background-color: var(--adf-theme-background-card-color); background-color: var(--adf-theme-background-card-color);
@@ -646,7 +660,7 @@ $data-table-cell-min-width-file-size: $data-table-cell-min-width-1 !default;
} }
} }
@media screen and (width <= 380px) { @media screen and (max-width: 380px) {
.adf-datatable-header { .adf-datatable-header {
max-height: 50%; max-height: 50%;
} }

View File

@@ -15,34 +15,31 @@
* limitations under the License. * limitations under the License.
*/ */
import { CdkDrag, CdkDragDrop, CdkDropList } from '@angular/cdk/drag-drop';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { Component, NO_ERRORS_SCHEMA, QueryList, SimpleChange, TemplateRef, ViewChild } from '@angular/core'; import { Component, NO_ERRORS_SCHEMA, QueryList, SimpleChange, TemplateRef, ViewChild } from '@angular/core';
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing'; import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { MatCheckboxChange } from '@angular/material/checkbox'; import { MatCheckboxChange } from '@angular/material/checkbox';
import { MatCheckboxHarness } from '@angular/material/checkbox/testing';
import { By } from '@angular/platform-browser';
import { take } from 'rxjs/operators';
import { domSanitizerMock } from '../../../mock/dom-sanitizer-mock';
import { matIconRegistryMock } from '../../../mock/mat-icon-registry-mock';
import { CoreTestingModule } from '../../../testing';
import { DataColumnComponent, DataColumnListComponent } from '../../data-column';
import { DataColumn } from '../../data/data-column.model'; import { DataColumn } from '../../data/data-column.model';
import { DataRow } from '../../data/data-row.model'; import { DataRow } from '../../data/data-row.model';
import { DataSorting } from '../../data/data-sorting.model'; import { DataSorting } from '../../data/data-sorting.model';
import { ObjectDataColumn } from '../../data/object-datacolumn.model'; import { ObjectDataColumn } from '../../data/object-datacolumn.model';
import { ObjectDataTableAdapter } from '../../data/object-datatable-adapter'; import { ObjectDataTableAdapter } from '../../data/object-datatable-adapter';
import { mockCarsData, mockCarsSchemaDefinition } from '../mocks/datatable.mock';
import { DataTableComponent, ShowHeaderMode } from './datatable.component'; import { DataTableComponent, ShowHeaderMode } from './datatable.component';
import { CoreTestingModule } from '../../../testing/core.testing.module';
import { DataColumnListComponent } from '../../data-column/data-column-list.component';
import { DataColumnComponent } from '../../data-column/data-column.component';
import { domSanitizerMock } from '../../../mock/dom-sanitizer-mock';
import { matIconRegistryMock } from '../../../mock/mat-icon-registry-mock';
import { CdkDrag, CdkDragDrop, CdkDropList } from '@angular/cdk/drag-drop';
import { take } from 'rxjs/operators';
import { By } from '@angular/platform-browser';
import { mockCarsData, mockCarsSchemaDefinition } from '../mocks/datatable.mock';
import { MatCheckboxHarness } from '@angular/material/checkbox/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
@Component({ @Component({ selector: 'adf-custom-column-template-component', template: ` <ng-template #tmplRef></ng-template> ` })
selector: 'adf-custom-column-template-component',
template: ` <ng-template #tmplRef></ng-template>`
})
class CustomColumnTemplateComponent { class CustomColumnTemplateComponent {
@ViewChild('tmplRef', { static: true }) templateRef: TemplateRef<any>; @ViewChild('tmplRef', { static: true }) templateRef: TemplateRef<any>;
} }
@Component({ @Component({
selector: 'adf-custom-column-header-component', selector: 'adf-custom-column-header-component',
template: ` <ng-template #tmplRef> CUSTOM HEADER </ng-template> ` template: ` <ng-template #tmplRef> CUSTOM HEADER </ng-template> `
@@ -317,12 +314,7 @@ describe('DataTable', () => {
}); });
it('should emit "sorting-changed" DOM event', (done) => { it('should emit "sorting-changed" DOM event', (done) => {
const column = new ObjectDataColumn({ const column = new ObjectDataColumn({ key: 'name', sortable: true, direction: 'asc', sortingKey: 'displayName' });
key: 'name',
sortable: true,
direction: 'asc',
sortingKey: 'displayName'
});
dataTable.data = new ObjectDataTableAdapter([{ name: '1' }, { name: '2' }], [column]); dataTable.data = new ObjectDataTableAdapter([{ name: '1' }, { name: '2' }], [column]);
dataTable.data.setSorting(new DataSorting('name', 'desc')); dataTable.data.setSorting(new DataSorting('name', 'desc'));
@@ -526,15 +518,7 @@ describe('DataTable', () => {
it('should unselect the row with [multiple] selection mode and modifier key', (done) => { it('should unselect the row with [multiple] selection mode and modifier key', (done) => {
dataTable.selectionMode = 'multiple'; dataTable.selectionMode = 'multiple';
dataTable.data = new ObjectDataTableAdapter( dataTable.data = new ObjectDataTableAdapter([{ name: '1', isSelected: true }], [new ObjectDataColumn({ key: 'name' })]);
[
{
name: '1',
isSelected: true
}
],
[new ObjectDataColumn({ key: 'name' })]
);
const rows = dataTable.data.getRows(); const rows = dataTable.data.getRows();
rows[0].isSelected = true; rows[0].isSelected = true;
@@ -547,7 +531,8 @@ describe('DataTable', () => {
dataTable.onRowClick(rows[0], { dataTable.onRowClick(rows[0], {
metaKey: true, metaKey: true,
preventDefault: () => {} preventDefault: () => {},
composedPath: () => []
} as any); } as any);
}); });
@@ -588,16 +573,7 @@ describe('DataTable', () => {
it('should select multiple rows with [multiple] selection mode and modifier key', (done) => { it('should select multiple rows with [multiple] selection mode and modifier key', (done) => {
dataTable.selectionMode = 'multiple'; dataTable.selectionMode = 'multiple';
dataTable.data = new ObjectDataTableAdapter( dataTable.data = new ObjectDataTableAdapter([{ name: '1', isSelected: true }, { name: '2' }], [new ObjectDataColumn({ key: 'name' })]);
[
{
name: '1',
isSelected: true
},
{ name: '2' }
],
[new ObjectDataColumn({ key: 'name' })]
);
const rows = dataTable.data.getRows(); const rows = dataTable.data.getRows();
rows[0].isSelected = true; rows[0].isSelected = true;
@@ -762,13 +738,7 @@ describe('DataTable', () => {
it('should not sort upon clicking non-sortable column header', () => { it('should not sort upon clicking non-sortable column header', () => {
dataTable.data = new ObjectDataTableAdapter( dataTable.data = new ObjectDataTableAdapter(
[{ name: '1' }, { name: '2' }], [{ name: '1' }, { name: '2' }],
[ [new ObjectDataColumn({ key: 'name', sortable: false }), new ObjectDataColumn({ key: 'other', sortable: true })]
new ObjectDataColumn({ key: 'name', sortable: false }),
new ObjectDataColumn({
key: 'other',
sortable: true
})
]
); );
fixture.detectChanges(); fixture.detectChanges();
dataTable.ngAfterViewInit(); dataTable.ngAfterViewInit();
@@ -783,15 +753,7 @@ describe('DataTable', () => {
}); });
it('should set sorting upon column header clicked', () => { it('should set sorting upon column header clicked', () => {
dataTable.data = new ObjectDataTableAdapter( dataTable.data = new ObjectDataTableAdapter([{ name: '1' }], [new ObjectDataColumn({ key: 'column_1', sortable: true })]);
[{ name: '1' }],
[
new ObjectDataColumn({
key: 'column_1',
sortable: true
})
]
);
fixture.detectChanges(); fixture.detectChanges();
dataTable.ngAfterViewInit(); dataTable.ngAfterViewInit();
const adapter = dataTable.data; const adapter = dataTable.data;
@@ -806,15 +768,7 @@ describe('DataTable', () => {
}); });
it('should invert sorting upon column header clicked', () => { it('should invert sorting upon column header clicked', () => {
dataTable.data = new ObjectDataTableAdapter( dataTable.data = new ObjectDataTableAdapter([{ name: '1' }], [new ObjectDataColumn({ key: 'column_1', sortable: true })]);
[{ name: '1' }],
[
new ObjectDataColumn({
key: 'column_1',
sortable: true
})
]
);
fixture.detectChanges(); fixture.detectChanges();
dataTable.ngAfterViewInit(); dataTable.ngAfterViewInit();
@@ -841,13 +795,7 @@ describe('DataTable', () => {
it('should indicate column that has sorting applied', () => { it('should indicate column that has sorting applied', () => {
dataTable.data = new ObjectDataTableAdapter( dataTable.data = new ObjectDataTableAdapter(
[{ name: '1' }, { name: '2' }], [{ name: '1' }, { name: '2' }],
[ [new ObjectDataColumn({ key: 'name', sortable: true }), new ObjectDataColumn({ key: 'other', sortable: true })]
new ObjectDataColumn({ key: 'name', sortable: true }),
new ObjectDataColumn({
key: 'other',
sortable: true
})
]
); );
fixture.detectChanges(); fixture.detectChanges();
dataTable.ngAfterViewInit(); dataTable.ngAfterViewInit();
@@ -865,13 +813,7 @@ describe('DataTable', () => {
it('should return false for columns that have no sorting', () => { it('should return false for columns that have no sorting', () => {
dataTable.data = new ObjectDataTableAdapter( dataTable.data = new ObjectDataTableAdapter(
[{ name: '1' }, { name: '2' }], [{ name: '1' }, { name: '2' }],
[ [new ObjectDataColumn({ key: 'name', sortable: false }), new ObjectDataColumn({ key: 'other', sortable: false })]
new ObjectDataColumn({ key: 'name', sortable: false }),
new ObjectDataColumn({
key: 'other',
sortable: false
})
]
); );
const [col1, col2] = dataTable.getSortableColumns(); const [col1, col2] = dataTable.getSortableColumns();
@@ -920,13 +862,7 @@ describe('DataTable', () => {
it('should have indeterminate state for "select all" when at least 1 row is selected or not all rows', () => { it('should have indeterminate state for "select all" when at least 1 row is selected or not all rows', () => {
dataTable.data = new ObjectDataTableAdapter( dataTable.data = new ObjectDataTableAdapter(
[{ name: '1' }, { name: '2' }], [{ name: '1' }, { name: '2' }],
[ [new ObjectDataColumn({ key: 'name', sortable: false }), new ObjectDataColumn({ key: 'other', sortable: false })]
new ObjectDataColumn({ key: 'name', sortable: false }),
new ObjectDataColumn({
key: 'other',
sortable: false
})
]
); );
const rows = dataTable.data.getRows(); const rows = dataTable.data.getRows();
@@ -999,7 +935,7 @@ describe('DataTable', () => {
const column = {} as DataColumn; const column = {} as DataColumn;
const row: any = { const row: any = {
getValue: () => 'https://www.google.com' getValue: () => 'http://www.google.com'
}; };
expect(dataTable.isIconValue(row, column)).toBeFalsy(); expect(dataTable.isIconValue(row, column)).toBeFalsy();
@@ -1019,7 +955,7 @@ describe('DataTable', () => {
const column = {} as DataColumn; const column = {} as DataColumn;
const row: any = { const row: any = {
getValue: () => 'https://www.google.com' getValue: () => 'http://www.google.com'
}; };
expect(dataTable.asIconValue(row, column)).toBe(null); expect(dataTable.asIconValue(row, column)).toBe(null);
@@ -1216,14 +1152,7 @@ describe('DataTable', () => {
{ id: 1, name: 'foo' }, { id: 1, name: 'foo' },
{ id: 2, name: 'bar' } { id: 2, name: 'bar' }
], ],
[ [new ObjectDataColumn({ key: 'id', title: 'ID' }), new ObjectDataColumn({ key: 'name', title: 'Name', header: customHeader })]
new ObjectDataColumn({ key: 'id', title: 'ID' }),
new ObjectDataColumn({
key: 'name',
title: 'Name',
header: customHeader
})
]
); );
fixture.detectChanges(); fixture.detectChanges();
@@ -1280,7 +1209,7 @@ describe('DataTable', () => {
dataTable.resetSelection(); dataTable.resetSelection();
const rowClickPromise = dataTable.rowClick.pipe(take(1)).toPromise(); const rowClickPromise = dataTable.rowClick.pipe(take(1)).toPromise();
const rowElement = fixture.debugElement.query(By.css(`[data-automation-id="datatable-row-0"] > td`)).nativeElement as HTMLElement; const rowElement = fixture.debugElement.query(By.css(`[data-automation-id="datatable-row-0"] > div`)).nativeElement as HTMLElement;
rowElement.dispatchEvent(new MouseEvent('click')); rowElement.dispatchEvent(new MouseEvent('click'));
fixture.detectChanges(); fixture.detectChanges();
await rowClickPromise; await rowClickPromise;
@@ -1291,7 +1220,7 @@ describe('DataTable', () => {
dataTable.resetSelection(); dataTable.resetSelection();
const cellClickPromise = dataTable.rowClick.pipe(take(1)).toPromise(); const cellClickPromise = dataTable.rowClick.pipe(take(1)).toPromise();
const cellElement = fixture.debugElement.query(By.css(`[data-automation-id="datatable-row-1"] > td`)).nativeElement as HTMLElement; const cellElement = fixture.debugElement.query(By.css(`[data-automation-id="datatable-row-1"] > div`)).nativeElement as HTMLElement;
cellElement.dispatchEvent(new MouseEvent('click', { bubbles: true })); cellElement.dispatchEvent(new MouseEvent('click', { bubbles: true }));
fixture.detectChanges(); fixture.detectChanges();
await cellClickPromise; await cellClickPromise;
@@ -1410,19 +1339,19 @@ describe('Accesibility', () => {
}); });
fixture.detectChanges(); fixture.detectChanges();
const datatable = element.querySelector('.adf-datatable-list').attributes; const datatableAttributes = element.querySelector('.adf-datatable-list').attributes;
const header = element.querySelector('.adf-datatable-list .adf-datatable-header'); const datatableHeaderAttributes = element.querySelector('.adf-datatable-list .adf-datatable-header').attributes;
const headerCell = element.querySelector('.adf-datatable-cell-header'); const datatableHeaderCellAttributes = element.querySelector('.adf-datatable-cell-header').attributes;
const body = element.querySelector('.adf-datatable-body'); const datatableBodyAttributes = element.querySelector('.adf-datatable-body').attributes;
const row = element.querySelector('.adf-datatable-body .adf-datatable-row'); const datatableBodyRowAttributes = element.querySelector('.adf-datatable-body .adf-datatable-row').attributes;
const cell = element.querySelector('.adf-datatable-body .adf-datatable-cell'); const datatableBodyCellAttributes = element.querySelector('.adf-datatable-body .adf-datatable-cell').attributes;
expect(datatable.getNamedItem('role').value).toEqual('table'); expect(datatableAttributes.getNamedItem('role').value).toEqual('grid');
expect(header.tagName).toEqual('THEAD'); expect(datatableHeaderAttributes.getNamedItem('role').value).toEqual('rowgroup');
expect(headerCell.tagName).toEqual('TH'); expect(datatableHeaderCellAttributes.getNamedItem('role').value).toEqual('columnheader');
expect(body.tagName).toEqual('TBODY'); expect(datatableBodyAttributes.getNamedItem('role').value).toEqual('rowgroup');
expect(row.tagName).toEqual('ADF-DATATABLE-ROW'); expect(datatableBodyRowAttributes.getNamedItem('role').value).toEqual('row');
expect(cell.tagName).toEqual('TD'); expect(datatableBodyCellAttributes.getNamedItem('role').value).toEqual('gridcell');
}); });
describe('aria-sort', () => { describe('aria-sort', () => {
@@ -1551,16 +1480,7 @@ describe('Accesibility', () => {
dataTable.showHeader = ShowHeaderMode.Never; dataTable.showHeader = ShowHeaderMode.Never;
const dataRows = [{ name: 'name1' }]; const dataRows = [{ name: 'name1' }];
dataTable.data = new ObjectDataTableAdapter( dataTable.data = new ObjectDataTableAdapter([], [new ObjectDataColumn({ key: 'name', template: columnCustomTemplate, focus: false })]);
[],
[
new ObjectDataColumn({
key: 'name',
template: columnCustomTemplate,
focus: false
})
]
);
dataTable.ngOnChanges({ dataTable.ngOnChanges({
rows: new SimpleChange(null, dataRows, false) rows: new SimpleChange(null, dataRows, false)
@@ -1577,16 +1497,7 @@ describe('Accesibility', () => {
dataTable.showHeader = ShowHeaderMode.Never; dataTable.showHeader = ShowHeaderMode.Never;
const dataRows = [{ name: 'name1' }]; const dataRows = [{ name: 'name1' }];
dataTable.data = new ObjectDataTableAdapter( dataTable.data = new ObjectDataTableAdapter([], [new ObjectDataColumn({ key: 'name', template: columnCustomTemplate, focus: true })]);
[],
[
new ObjectDataColumn({
key: 'name',
template: columnCustomTemplate,
focus: true
})
]
);
dataTable.ngOnChanges({ dataTable.ngOnChanges({
rows: new SimpleChange(null, dataRows, false) rows: new SimpleChange(null, dataRows, false)

View File

@@ -15,14 +15,14 @@
* limitations under the License. * limitations under the License.
*/ */
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { RouterTestingModule } from '@angular/router/testing';
import { Meta, moduleMetadata, Story } from '@storybook/angular'; import { Meta, moduleMetadata, Story } from '@storybook/angular';
import { CoreStoryModule } from '../../../testing/core.story.module'; import { CoreStoryModule } from '../../../testing/core.story.module';
import { DataTableModule } from '../../datatable.module';
import { mockPathInfos } from '../mocks/datatable.mock';
import { DataTableComponent } from './datatable.component'; import { DataTableComponent } from './datatable.component';
import { DataTableModule } from '../../datatable.module';
import { RouterTestingModule } from '@angular/router/testing';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { mockPathInfos } from '../mocks/datatable.mock';
export default { export default {
component: DataTableComponent, component: DataTableComponent,
@@ -150,22 +150,9 @@ export default {
cssClass: 'adf-ellipsis-cell', cssClass: 'adf-ellipsis-cell',
copyContent: true copyContent: true
}, },
{ { type: 'image', key: 'imageCol', title: 'Image Column', draggable: true, cssClass: 'adf-ellipsis-cell' },
type: 'image',
key: 'imageCol',
title: 'Image Column',
draggable: true,
cssClass: 'adf-ellipsis-cell'
},
{ type: 'icon', key: 'iconCol', title: 'Icon Column', draggable: true, cssClass: 'adf-ellipsis-cell' }, { type: 'icon', key: 'iconCol', title: 'Icon Column', draggable: true, cssClass: 'adf-ellipsis-cell' },
{ { type: 'date', key: 'dateCol', title: 'Date Column', sortable: true, draggable: true, cssClass: 'adf-ellipsis-cell' },
type: 'date',
key: 'dateCol',
title: 'Date Column',
sortable: true,
draggable: true,
cssClass: 'adf-ellipsis-cell'
},
{ {
type: 'date', type: 'date',
key: 'dateCol', key: 'dateCol',
@@ -175,43 +162,11 @@ export default {
cssClass: 'adf-ellipsis-cell', cssClass: 'adf-ellipsis-cell',
dateConfig: { format: 'timeAgo' } dateConfig: { format: 'timeAgo' }
}, },
{ { type: 'fileSize', key: 'fileSizeCol', title: 'File Size Column', sortable: true, draggable: true, cssClass: 'adf-ellipsis-cell' },
type: 'fileSize', { type: 'location', format: '/files', key: 'locationCol', title: 'Location Column', draggable: true, cssClass: 'adf-ellipsis-cell' },
key: 'fileSizeCol', { type: 'boolean', key: 'booleanCol', title: 'Boolean Column', draggable: true, cssClass: 'adf-ellipsis-cell' },
title: 'File Size Column', { type: 'amount', key: 'amountCol', title: 'Amount Column', draggable: true, cssClass: 'adf-ellipsis-cell' },
sortable: true, { type: 'number', key: 'numberCol', title: 'Number Column', draggable: true, cssClass: 'adf-ellipsis-cell' },
draggable: true,
cssClass: 'adf-ellipsis-cell'
},
{
type: 'location',
format: '/files',
key: 'locationCol',
title: 'Location Column',
draggable: true,
cssClass: 'adf-ellipsis-cell'
},
{
type: 'boolean',
key: 'booleanCol',
title: 'Boolean Column',
draggable: true,
cssClass: 'adf-ellipsis-cell'
},
{
type: 'amount',
key: 'amountCol',
title: 'Amount Column',
draggable: true,
cssClass: 'adf-ellipsis-cell'
},
{
type: 'number',
key: 'numberCol',
title: 'Number Column',
draggable: true,
cssClass: 'adf-ellipsis-cell'
},
{ type: 'json', key: 'jsonCol', title: 'JSON Column', draggable: true, cssClass: 'adf-ellipsis-cell' } { type: 'json', key: 'jsonCol', title: 'JSON Column', draggable: true, cssClass: 'adf-ellipsis-cell' }
], ],
table: { table: {

View File

@@ -17,9 +17,6 @@
/* eslint-disable @angular-eslint/no-conflicting-lifecycle */ /* eslint-disable @angular-eslint/no-conflicting-lifecycle */
import { FocusKeyManager } from '@angular/cdk/a11y';
import { CdkDrag, CdkDragDrop, CdkDropList, DragDropModule, moveItemInArray } from '@angular/cdk/drag-drop';
import { CommonModule } from '@angular/common';
import { import {
AfterContentInit, AfterContentInit,
AfterViewInit, AfterViewInit,
@@ -42,45 +39,28 @@ import {
ViewChildren, ViewChildren,
ViewEncapsulation ViewEncapsulation
} from '@angular/core'; } from '@angular/core';
import { MatButtonModule } from '@angular/material/button'; import { FocusKeyManager } from '@angular/cdk/a11y';
import { MatCheckboxChange, MatCheckboxModule } from '@angular/material/checkbox'; import { MatCheckboxChange } from '@angular/material/checkbox';
import { MatFormFieldModule } from '@angular/material/form-field'; import { MatMenuTrigger } from '@angular/material/menu';
import { MatIconModule, MatIconRegistry } from '@angular/material/icon';
import { MatMenuModule, MatMenuTrigger } from '@angular/material/menu';
import { MatSelectModule } from '@angular/material/select';
import { MatTooltipModule } from '@angular/material/tooltip';
import { DomSanitizer } from '@angular/platform-browser';
import { TranslateModule } from '@ngx-translate/core';
import { Observable, Observer, Subscription } from 'rxjs'; import { Observable, Observer, Subscription } from 'rxjs';
import { buffer, debounceTime, filter, map, share } from 'rxjs/operators'; import { DataColumnListComponent } from '../../data-column/data-column-list.component';
import { ContextMenuModule } from '../../../context-menu';
import { DirectiveModule } from '../../../directives';
import { IconComponent } from '../../../icon';
import { FileTypePipe, FilterOutArrayObjectsByPropPipe, LocalizedDatePipe } from '../../../pipes';
import { DataColumnListComponent } from '../../data-column';
import { DataColumn } from '../../data/data-column.model'; import { DataColumn } from '../../data/data-column.model';
import { DataRowEvent } from '../../data/data-row-event.model'; import { DataRowEvent } from '../../data/data-row-event.model';
import { DataRow } from '../../data/data-row.model'; import { DataRow } from '../../data/data-row.model';
import { DataSorting } from '../../data/data-sorting.model'; import { DataSorting } from '../../data/data-sorting.model';
import { DataTableAdapter } from '../../data/datatable-adapter'; import { DataTableAdapter } from '../../data/datatable-adapter';
import { ObjectDataColumn } from '../../data/object-datacolumn.model'; import { DataTableRowComponent } from '../datatable-row/datatable-row.component';
import { ObjectDataRow } from '../../data/object-datarow.model'; import { ObjectDataRow } from '../../data/object-datarow.model';
import { ObjectDataColumn } from '../../data/object-datacolumn.model';
import { ObjectDataTableAdapter } from '../../data/object-datatable-adapter'; import { ObjectDataTableAdapter } from '../../data/object-datatable-adapter';
import { DropZoneDirective } from '../../directives/drop-zone.directive';
import { ResizableModule } from '../../directives/resizable/resizable.module';
import { ResizeEvent } from '../../directives/resizable/types';
import { AmountCellComponent } from '../amount-cell/amount-cell.component';
import { BooleanCellComponent } from '../boolean-cell/boolean-cell.component';
import { DataCellEvent } from '../data-cell.event'; import { DataCellEvent } from '../data-cell.event';
import { DataRowActionEvent } from '../data-row-action.event'; import { DataRowActionEvent } from '../data-row-action.event';
import { DataTableCellComponent } from '../datatable-cell/datatable-cell.component'; import { buffer, debounceTime, filter, map, share } from 'rxjs/operators';
import { DataTableRowComponent } from '../datatable-row/datatable-row.component'; import { CdkDrag, CdkDragDrop, CdkDropList, moveItemInArray } from '@angular/cdk/drag-drop';
import { DateCellComponent } from '../date-cell/date-cell.component'; import { MatIconRegistry } from '@angular/material/icon';
import { FileSizeCellComponent } from '../filesize-cell/filesize-cell.component'; import { DomSanitizer } from '@angular/platform-browser';
import { IconCellComponent } from '../icon-cell/icon-cell.component'; import { ResizeEvent } from '../../directives/resizable/types';
import { JsonCellComponent } from '../json-cell/json-cell.component';
import { LocationCellComponent } from '../location-cell/location-cell.component';
import { NumberCellComponent } from '../number-cell/number-cell.component';
// eslint-disable-next-line no-shadow // eslint-disable-next-line no-shadow
export enum ShowHeaderMode { export enum ShowHeaderMode {
@@ -91,40 +71,9 @@ export enum ShowHeaderMode {
@Component({ @Component({
selector: 'adf-datatable', selector: 'adf-datatable',
standalone: true,
templateUrl: './datatable.component.html', templateUrl: './datatable.component.html',
styleUrls: ['./datatable.component.scss'], styleUrls: ['./datatable.component.scss'],
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
imports: [
CommonModule,
DragDropModule,
DataTableRowComponent,
TranslateModule,
MatCheckboxModule,
ResizableModule,
DropZoneDirective,
MatTooltipModule,
MatMenuModule,
MatIconModule,
MatButtonModule,
MatFormFieldModule,
MatSelectModule,
DirectiveModule,
ContextMenuModule,
IconCellComponent,
DateCellComponent,
LocationCellComponent,
FileSizeCellComponent,
DataTableCellComponent,
BooleanCellComponent,
JsonCellComponent,
AmountCellComponent,
NumberCellComponent,
LocalizedDatePipe,
FilterOutArrayObjectsByPropPipe,
FileTypePipe,
IconComponent
],
host: { class: 'adf-datatable' } host: { class: 'adf-datatable' }
}) })
export class DataTableComponent implements OnInit, AfterContentInit, OnChanges, DoCheck, OnDestroy, AfterViewInit { export class DataTableComponent implements OnInit, AfterContentInit, OnChanges, DoCheck, OnDestroy, AfterViewInit {

View File

@@ -1,11 +1,13 @@
<ng-container *ngIf="value$ | async as date"> <ng-container *ngIf="value$ | async as date">
<span [title]="tooltip | adfLocalizedDate: config.tooltipFormat: config.locale" <span
[title]="tooltip | adfLocalizedDate: config.tooltipFormat: config.locale"
class="adf-datatable-cell-value" class="adf-datatable-cell-value"
*ngIf="config.format === 'timeAgo'; else standard_date"> *ngIf="config.format === 'timeAgo'; else standard_date">
{{ date | adfTimeAgo: config.locale }} {{ date | adfTimeAgo: config.locale }}
</span> </span>
<ng-template #standard_date> <ng-template #standard_date>
<span class="adf-datatable-cell-value" <span
class="adf-datatable-cell-value"
[title]="tooltip | adfLocalizedDate: config.tooltipFormat: config.locale"> [title]="tooltip | adfLocalizedDate: config.tooltipFormat: config.locale">
{{ date | adfLocalizedDate: config.format: config.locale }} {{ date | adfLocalizedDate: config.format: config.locale }}
</span> </span>

View File

@@ -15,16 +15,16 @@
* limitations under the License. * limitations under the License.
*/ */
import { registerLocaleData } from '@angular/common';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import localePL from '@angular/common/locales/pl';
import { LOCALE_ID } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing';
import { DateCellComponent } from './date-cell.component';
import { DataColumn, DateConfig } from '../../data/data-column.model';
import { BehaviorSubject } from 'rxjs'; import { BehaviorSubject } from 'rxjs';
import { AppConfigService } from '../../../app-config'; import { AppConfigService } from '../../../app-config';
import { CoreTestingModule } from '../../../testing'; import { HttpClientTestingModule } from '@angular/common/http/testing';
import { DataColumn, DateConfig } from '../../data/data-column.model'; import { TranslateModule } from '@ngx-translate/core';
import { DateCellComponent } from './date-cell.component'; import { LOCALE_ID } from '@angular/core';
import { registerLocaleData } from '@angular/common';
import localePL from '@angular/common/locales/pl';
let component: DateCellComponent; let component: DateCellComponent;
let appConfigService: AppConfigService; let appConfigService: AppConfigService;
@@ -62,7 +62,11 @@ const checkDisplayedTooltip = (expectedTooltip: string) => {
const configureTestingModule = (providers: any[]) => { const configureTestingModule = (providers: any[]) => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [CoreTestingModule, DateCellComponent, HttpClientTestingModule], imports: [
DateCellComponent,
HttpClientTestingModule,
TranslateModule.forRoot()
],
providers providers
}); });
fixture = TestBed.createComponent(DateCellComponent); fixture = TestBed.createComponent(DateCellComponent);

View File

@@ -15,12 +15,12 @@
* limitations under the License. * limitations under the License.
*/ */
import { CommonModule } from '@angular/common'; import { ChangeDetectionStrategy, Component, Input, OnInit, ViewEncapsulation, inject } from '@angular/core';
import { ChangeDetectionStrategy, Component, inject, Input, OnInit, ViewEncapsulation } from '@angular/core';
import { AppConfigService } from '../../../app-config';
import { LocalizedDatePipe, TimeAgoPipe } from '../../../pipes';
import { DateConfig } from '../../data/data-column.model';
import { DataTableCellComponent } from '../datatable-cell/datatable-cell.component'; import { DataTableCellComponent } from '../datatable-cell/datatable-cell.component';
import { AppConfigService } from '../../../app-config/app-config.service';
import { DateConfig } from '../../data/data-column.model';
import { CommonModule } from '@angular/common';
import { LocalizedDatePipe, TimeAgoPipe } from '../../../pipes';
@Component({ @Component({
standalone: true, standalone: true,
@@ -32,6 +32,7 @@ import { DataTableCellComponent } from '../datatable-cell/datatable-cell.compone
changeDetection: ChangeDetectionStrategy.OnPush changeDetection: ChangeDetectionStrategy.OnPush
}) })
export class DateCellComponent extends DataTableCellComponent implements OnInit { export class DateCellComponent extends DataTableCellComponent implements OnInit {
@Input() @Input()
dateConfig: DateConfig; dateConfig: DateConfig;

View File

@@ -16,8 +16,8 @@
*/ */
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing';
import { CoreTestingModule } from '../../../testing';
import { EmptyListComponent } from './empty-list.component'; import { EmptyListComponent } from './empty-list.component';
import { CoreTestingModule } from '../../../testing/core.testing.module';
describe('EmptyListComponentComponent', () => { describe('EmptyListComponentComponent', () => {
let fixture: ComponentFixture<EmptyListComponent>; let fixture: ComponentFixture<EmptyListComponent>;

View File

@@ -19,27 +19,12 @@ import { Component, Directive, ViewEncapsulation } from '@angular/core';
@Component({ @Component({
selector: 'adf-empty-list', selector: 'adf-empty-list',
standalone: true,
styleUrls: ['./empty-list.component.scss'], styleUrls: ['./empty-list.component.scss'],
templateUrl: './empty-list.component.html', templateUrl: './empty-list.component.html',
encapsulation: ViewEncapsulation.None encapsulation: ViewEncapsulation.None
}) })
export class EmptyListComponent {} export class EmptyListComponent {}
@Directive({ @Directive({ selector: '[adf-empty-list-header]' }) export class EmptyListHeaderDirective {}
selector: '[adf-empty-list-header]', @Directive({ selector: '[adf-empty-list-body]' }) export class EmptyListBodyDirective {}
standalone: true @Directive({ selector: '[adf-empty-list-footer]' }) export class EmptyListFooterDirective {}
})
export class EmptyListHeaderDirective {}
@Directive({
selector: '[adf-empty-list-body]',
standalone: true
})
export class EmptyListBodyDirective {}
@Directive({
selector: '[adf-empty-list-footer]',
standalone: true
})
export class EmptyListFooterDirective {}

View File

@@ -15,24 +15,21 @@
* limitations under the License. * limitations under the License.
*/ */
import { AsyncPipe, NgIf } from '@angular/common';
import { Component, OnInit, ViewEncapsulation } from '@angular/core'; import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { FileSizePipe } from '../../../pipes';
import { DataTableCellComponent } from '../datatable-cell/datatable-cell.component'; import { DataTableCellComponent } from '../datatable-cell/datatable-cell.component';
@Component({ @Component({
selector: 'adf-filesize-cell', selector: 'adf-filesize-cell',
standalone: true,
template: ` template: `
<ng-container *ngIf="value$ | async | adfFileSize as fileSize"> <ng-container *ngIf="value$ | async | adfFileSize as fileSize">
<span [title]="tooltip">{{ fileSize }}</span> <span [title]="tooltip">{{ fileSize }}</span>
</ng-container> </ng-container>
`, `,
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
imports: [NgIf, AsyncPipe, FileSizePipe],
host: { class: 'adf-filesize-cell' } host: { class: 'adf-filesize-cell' }
}) })
export class FileSizeCellComponent extends DataTableCellComponent implements OnInit { export class FileSizeCellComponent extends DataTableCellComponent implements OnInit {
ngOnInit(): void { ngOnInit(): void {
super.ngOnInit(); super.ngOnInit();
} }

View File

@@ -15,14 +15,14 @@
* limitations under the License. * limitations under the License.
*/ */
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MatIconHarness } from '@angular/material/icon/testing';
import { ObjectDataColumn } from '../../data/object-datacolumn.model';
import { ObjectDataTableAdapter } from '../../data/object-datatable-adapter';
import { IconCellComponent } from './icon-cell.component'; import { IconCellComponent } from './icon-cell.component';
import { ObjectDataTableAdapter } from '../../data/object-datatable-adapter';
import { ObjectDataColumn } from '../../data/object-datacolumn.model';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatIconHarness } from '@angular/material/icon/testing';
describe('IconCellComponent', () => { describe('IconCellComponent', () => {
let component: IconCellComponent; let component: IconCellComponent;

View File

@@ -18,8 +18,8 @@
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit, ViewEncapsulation } from '@angular/core'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit, ViewEncapsulation } from '@angular/core';
import { MatIconModule } from '@angular/material/icon'; import { MatIconModule } from '@angular/material/icon';
import { takeUntil } from 'rxjs/operators';
import { DataTableCellComponent } from '../datatable-cell/datatable-cell.component'; import { DataTableCellComponent } from '../datatable-cell/datatable-cell.component';
import { takeUntil } from 'rxjs/operators';
@Component({ @Component({
standalone: true, standalone: true,

View File

@@ -1,7 +0,0 @@
<ng-container *ngIf="value$ | async as value; else editEmpty">
<button mat-button color="primary" (click)="view()">json</button>
</ng-container>
<ng-template #editEmpty>
<button *ngIf="editable" mat-button color="primary" (click)="view()">json</button>
</ng-template>

View File

@@ -15,14 +15,14 @@
* limitations under the License. * limitations under the License.
*/ */
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MatButtonHarness } from '@angular/material/button/testing';
import { CoreTestingModule } from '../../../testing';
import { ObjectDataColumn } from '../../data/object-datacolumn.model';
import { ObjectDataTableAdapter } from '../../data/object-datatable-adapter'; import { ObjectDataTableAdapter } from '../../data/object-datatable-adapter';
import { ObjectDataColumn } from '../../data/object-datacolumn.model';
import { CoreTestingModule } from '../../../testing/core.testing.module';
import { JsonCellComponent } from './json-cell.component'; import { JsonCellComponent } from './json-cell.component';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { HarnessLoader } from '@angular/cdk/testing';
import { MatButtonHarness } from '@angular/material/button/testing';
describe('JsonCellComponent', () => { describe('JsonCellComponent', () => {
let loader: HarnessLoader; let loader: HarnessLoader;

View File

@@ -15,21 +15,25 @@
* limitations under the License. * limitations under the License.
*/ */
import { AsyncPipe, NgIf } from '@angular/common'; import { ChangeDetectionStrategy, Component, OnInit, ViewEncapsulation, Input } from '@angular/core';
import { ChangeDetectionStrategy, Component, Input, OnInit, ViewEncapsulation } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatDialog } from '@angular/material/dialog';
import { EditJsonDialogComponent, EditJsonDialogSettings } from '../../../dialogs';
import { DataTableCellComponent } from '../datatable-cell/datatable-cell.component'; import { DataTableCellComponent } from '../datatable-cell/datatable-cell.component';
import { MatDialog } from '@angular/material/dialog';
import { EditJsonDialogComponent, EditJsonDialogSettings } from '../../../dialogs/edit-json/edit-json.dialog';
@Component({ @Component({
selector: 'adf-json-cell', selector: 'adf-json-cell',
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
templateUrl: './json-cell.component.html', template: `
<ng-container *ngIf="value$ | async as value; else editEmpty">
<button mat-button color="primary" (click)="view()">json</button>
</ng-container>
<ng-template #editEmpty>
<button *ngIf="editable" mat-button color="primary" (click)="view()">json</button>
</ng-template>
`,
styleUrls: ['./json-cell.component.scss'], styleUrls: ['./json-cell.component.scss'],
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
imports: [AsyncPipe, MatButtonModule, NgIf],
host: { class: 'adf-datatable-content-cell' } host: { class: 'adf-datatable-content-cell' }
}) })
export class JsonCellComponent extends DataTableCellComponent implements OnInit { export class JsonCellComponent extends DataTableCellComponent implements OnInit {

View File

@@ -16,10 +16,10 @@
*/ */
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing';
import { CoreTestingModule } from '../../../testing';
import { ObjectDataColumn } from '../../data/object-datacolumn.model';
import { ObjectDataTableAdapter } from '../../data/object-datatable-adapter'; import { ObjectDataTableAdapter } from '../../data/object-datatable-adapter';
import { ObjectDataColumn } from '../../data/object-datacolumn.model';
import { LocationCellComponent } from './location-cell.component'; import { LocationCellComponent } from './location-cell.component';
import { CoreTestingModule } from '../../../testing/core.testing.module';
describe('LocationCellComponent', () => { describe('LocationCellComponent', () => {
let component: LocationCellComponent; let component: LocationCellComponent;
@@ -30,7 +30,10 @@ describe('LocationCellComponent', () => {
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [LocationCellComponent, CoreTestingModule] imports: [
LocationCellComponent,
CoreTestingModule
]
}); });
fixture = TestBed.createComponent(LocationCellComponent); fixture = TestBed.createComponent(LocationCellComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
@@ -51,7 +54,10 @@ describe('LocationCellComponent', () => {
columnData = { format: '/files', type: 'location', key: 'path'}; columnData = { format: '/files', type: 'location', key: 'path'};
dataTableAdapter = new ObjectDataTableAdapter([rowData], [new ObjectDataColumn(columnData)]); dataTableAdapter = new ObjectDataTableAdapter(
[rowData],
[ new ObjectDataColumn(columnData) ]
);
component.link = []; component.link = [];
component.column = dataTableAdapter.getColumns()[0]; component.column = dataTableAdapter.getColumns()[0];

View File

@@ -15,15 +15,15 @@
* limitations under the License. * limitations under the License.
*/ */
import { PathInfo } from '@alfresco/js-api';
import { AsyncPipe } from '@angular/common';
import { ChangeDetectionStrategy, Component, Input, OnInit, ViewEncapsulation } from '@angular/core'; import { ChangeDetectionStrategy, Component, Input, OnInit, ViewEncapsulation } from '@angular/core';
import { RouterModule } from '@angular/router';
import { DataTableCellComponent } from '../datatable-cell/datatable-cell.component'; import { DataTableCellComponent } from '../datatable-cell/datatable-cell.component';
import { AsyncPipe } from '@angular/common';
import { RouterModule } from '@angular/router';
import { PathInfo } from '@alfresco/js-api';
@Component({ @Component({
imports: [AsyncPipe, RouterModule],
standalone: true, standalone: true,
imports: [AsyncPipe, RouterModule],
selector: 'adf-location-cell', selector: 'adf-location-cell',
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
template: ` template: `

View File

@@ -22,12 +22,11 @@ export const mockCarsData: any = [
{ {
car_id: 1, car_id: 1,
car_name: 'Fiat 126p (Process)', car_name: 'Fiat 126p (Process)',
car_price: 599.0, car_price: 599.00,
fuel_consumption: 5.25789, fuel_consumption: 5.25789,
is_available: 'false', is_available: 'false',
production_start: '1972-04-23', production_start: '1972-04-23',
description: description: 'The Fiat 126 (Type 126) is a four-passenger, rear-engine, city car manufactured and marketed by Fiat over a twenty-eight year production run from 1972 until 2000, over a single generation.',
'The Fiat 126 (Type 126) is a four-passenger, rear-engine, city car manufactured and marketed by Fiat over a twenty-eight year production run from 1972 until 2000, over a single generation.',
icon: 'airport_shuttle', icon: 'airport_shuttle',
wikipedia_link: 'https://en.wikipedia.org/wiki/Fiat_126' wikipedia_link: 'https://en.wikipedia.org/wiki/Fiat_126'
}, },
@@ -49,8 +48,7 @@ export const mockCarsData: any = [
fuel_consumption: 6, fuel_consumption: 6,
is_available: 'true', is_available: 'true',
production_start: '1998-06-25T12:25:20', production_start: '1998-06-25T12:25:20',
description: description: 'The Audi A3 is a subcompact executive/small family car (C-segment) manufactured and marketed by the German automaker Audi AG since September 1996, currently in its fourth generation.',
'The Audi A3 is a subcompact executive/small family car (C-segment) manufactured and marketed by the German automaker Audi AG since September 1996, currently in its fourth generation.',
icon: 'directions_car', icon: 'directions_car',
wikipedia_link: 'https://en.wikipedia.org/wiki/Audi_A3' wikipedia_link: 'https://en.wikipedia.org/wiki/Audi_A3'
} }

View File

@@ -1,7 +1,6 @@
<ng-container *ngIf="value$ | async as number"> <ng-container *ngIf="value$ | async as number">
<span [title]="number"> <span [title]="number">
{{ {{ number | number:
number | number:
(decimalConfig?.digitsInfo || defaultDecimalConfig.digitsInfo): (decimalConfig?.digitsInfo || defaultDecimalConfig.digitsInfo):
(decimalConfig?.locale || defaultDecimalConfig.locale) (decimalConfig?.locale || defaultDecimalConfig.locale)
}} }}

View File

@@ -15,13 +15,13 @@
* limitations under the License. * limitations under the License.
*/ */
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { NumberCellComponent } from './number-cell.component';
import { DecimalConfig } from '../../data/data-column.model';
import { BehaviorSubject } from 'rxjs';
import { LOCALE_ID } from '@angular/core';
import { registerLocaleData } from '@angular/common'; import { registerLocaleData } from '@angular/common';
import localePL from '@angular/common/locales/pl'; import localePL from '@angular/common/locales/pl';
import { LOCALE_ID } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { BehaviorSubject } from 'rxjs';
import { DecimalConfig } from '../../data/data-column.model';
import { NumberCellComponent } from './number-cell.component';
describe('NumberCellComponent', () => { describe('NumberCellComponent', () => {
let component: NumberCellComponent; let component: NumberCellComponent;

View File

@@ -15,14 +15,20 @@
* limitations under the License. * limitations under the License.
*/ */
import { AsyncPipe, DecimalPipe, NgIf } from '@angular/common'; import {
import { ChangeDetectionStrategy, Component, Input, OnInit, ViewEncapsulation } from '@angular/core'; ChangeDetectionStrategy,
import { DecimalConfig } from '../../data/data-column.model'; Component,
ViewEncapsulation,
Input,
OnInit
} from '@angular/core';
import { DataTableCellComponent } from '../datatable-cell/datatable-cell.component'; import { DataTableCellComponent } from '../datatable-cell/datatable-cell.component';
import { DecimalConfig } from '../../data/data-column.model';
import { CommonModule } from '@angular/common';
@Component({ @Component({
imports: [AsyncPipe, DecimalPipe, NgIf],
standalone: true, standalone: true,
imports: [CommonModule],
selector: 'adf-number-cell', selector: 'adf-number-cell',
templateUrl: './number-cell.component.html', templateUrl: './number-cell.component.html',
host: { class: 'adf-datatable-content-cell' }, host: { class: 'adf-datatable-content-cell' },
@@ -30,6 +36,7 @@ import { DataTableCellComponent } from '../datatable-cell/datatable-cell.compone
changeDetection: ChangeDetectionStrategy.OnPush changeDetection: ChangeDetectionStrategy.OnPush
}) })
export class NumberCellComponent extends DataTableCellComponent implements OnInit { export class NumberCellComponent extends DataTableCellComponent implements OnInit {
@Input() @Input()
decimalConfig: DecimalConfig; decimalConfig: DecimalConfig;

View File

@@ -22,10 +22,10 @@ import { DataColumnComponent } from './data-column.component';
@Component({ @Component({
selector: 'adf-data-column-header', selector: 'adf-data-column-header',
standalone: true,
template: '' template: ''
}) })
export class DateColumnHeaderComponent implements AfterContentInit { export class DateColumnHeaderComponent implements AfterContentInit {
@ContentChild(TemplateRef) @ContentChild(TemplateRef)
public header: TemplateRef<any>; public header: TemplateRef<any>;

View File

@@ -22,9 +22,10 @@ import { DataColumnComponent } from './data-column.component';
@Component({ @Component({
selector: 'data-columns', selector: 'data-columns',
standalone: true,
template: '' template: ''
}) })
export class DataColumnListComponent { export class DataColumnListComponent {
@ContentChildren(DataColumnComponent) columns: QueryList<DataColumnComponent>; @ContentChildren(DataColumnComponent) columns: QueryList<DataColumnComponent>;
} }

View File

@@ -15,9 +15,9 @@
* limitations under the License. * limitations under the License.
*/ */
import { TestBed } from '@angular/core/testing';
import { CoreTestingModule } from '../../testing';
import { DataColumnComponent } from './data-column.component'; import { DataColumnComponent } from './data-column.component';
import { CoreTestingModule } from '../../testing/core.testing.module';
import { TestBed } from '@angular/core/testing';
describe('DataColumnListComponent', () => { describe('DataColumnListComponent', () => {
beforeEach(() => { beforeEach(() => {

View File

@@ -15,25 +15,30 @@
* limitations under the License. * limitations under the License.
*/ */
import { RouterTestingModule } from '@angular/router/testing';
import { Meta, moduleMetadata, Story } from '@storybook/angular'; import { Meta, moduleMetadata, Story } from '@storybook/angular';
import * as mockData from '../../mock/data-column.mock';
import { CoreStoryModule } from '../../testing/core.story.module';
import { DataTableModule } from '../datatable.module';
import { DataRow } from '../index';
import { DataColumnComponent } from './data-column.component'; import { DataColumnComponent } from './data-column.component';
import { DataTableModule } from '../datatable.module';
import { CoreStoryModule } from '../../testing/core.story.module';
import * as mockData from '../../mock/data-column.mock';
import { RouterTestingModule } from '@angular/router/testing';
import { DataRow } from '../index';
export default { export default {
component: DataColumnComponent, component: DataColumnComponent,
title: 'Core/Data Column/Data Column', title: 'Core/Data Column/Data Column',
decorators: [ decorators: [
moduleMetadata({ moduleMetadata({
imports: [CoreStoryModule, DataTableModule, RouterTestingModule] imports: [
CoreStoryModule,
DataTableModule,
RouterTestingModule
]
}) })
], ],
argTypes: { argTypes: {
copyContent: { copyContent: {
description: 'Enables/disables a Clipboard directive to allow copying of cell contents.', description:
'Enables/disables a Clipboard directive to allow copying of cell contents.',
control: { type: 'boolean' }, control: { type: 'boolean' },
defaultValue: false, defaultValue: false,
table: { table: {
@@ -44,7 +49,8 @@ export default {
} }
}, },
cssClass: { cssClass: {
description: 'Additional CSS class to be applied to column (header and cells).', description:
'Additional CSS class to be applied to column (header and cells).',
control: { type: 'text' }, control: { type: 'text' },
defaultValue: '', defaultValue: '',
table: { table: {
@@ -55,7 +61,8 @@ export default {
} }
}, },
customData: { customData: {
description: 'You can specify any custom data which can be used by any specific feature', description:
'You can specify any custom data which can be used by any specific feature',
control: { disable: true }, control: { disable: true },
table: { table: {
category: 'Component Inputs', category: 'Component Inputs',
@@ -120,7 +127,8 @@ export default {
} }
}, },
format: { format: {
description: 'Used for location type. Setups root path for router navigation.', description:
'Used for location type. Setups root path for router navigation.',
control: { type: 'text', disable: true }, control: { type: 'text', disable: true },
table: { table: {
category: 'Component Inputs', category: 'Component Inputs',
@@ -167,7 +175,8 @@ export default {
} }
}, },
key: { key: {
description: 'Data source key. Can be either a column/property key like title or a property path like `createdBy.name`.', description:
'Data source key. Can be either a column/property key like title or a property path like `createdBy.name`.',
control: { type: 'text', disable: false }, control: { type: 'text', disable: false },
table: { table: {
category: 'Component Inputs', category: 'Component Inputs',
@@ -177,7 +186,8 @@ export default {
} }
}, },
sortable: { sortable: {
description: 'Toggles ability to sort by this column, for example by clicking the column header.', description:
'Toggles ability to sort by this column, for example by clicking the column header.',
control: { type: 'boolean' }, control: { type: 'boolean' },
defaultValue: true, defaultValue: true,
table: { table: {
@@ -191,7 +201,8 @@ export default {
} }
}, },
sortingKey: { sortingKey: {
description: 'When using server side sorting the column used by the api call where the sorting will be performed', description:
'When using server side sorting the column used by the api call where the sorting will be performed',
control: { disable: true }, control: { disable: true },
table: { table: {
category: 'Component Inputs', category: 'Component Inputs',
@@ -230,7 +241,18 @@ export default {
description: description:
'Value type for the column. Possible settings are: `text`, `icon`, `image`, `date`, `fileSize`, `location`, `boolean`, `amount`, `number` and `json`.', 'Value type for the column. Possible settings are: `text`, `icon`, `image`, `date`, `fileSize`, `location`, `boolean`, `amount`, `number` and `json`.',
control: { type: 'select', disable: false }, control: { type: 'select', disable: false },
options: ['text', 'icon', 'image', 'date', 'fileSize', 'location', 'boolean', 'amount', 'number', 'json'], options: [
'text',
'icon',
'image',
'date',
'fileSize',
'location',
'boolean',
'amount',
'number',
'json'
],
table: { table: {
category: 'Component Inputs', category: 'Component Inputs',
type: { type: {
@@ -243,7 +265,8 @@ export default {
defaultValue: 'text' defaultValue: 'text'
}, },
currencyConfig: { currencyConfig: {
description: `The currencyConfig input allows you to customize the formatting and display of currency values within the component.`, description:
`The currencyConfig input allows you to customize the formatting and display of currency values within the component.`,
control: { type: 'object', disable: true }, control: { type: 'object', disable: true },
table: { table: {
category: 'Component Inputs', category: 'Component Inputs',
@@ -262,7 +285,8 @@ export default {
} }
}, },
decimalConfig: { decimalConfig: {
description: `The decimalConfig input allows you to customize the formatting and display of decimal values within the component.`, description:
`The decimalConfig input allows you to customize the formatting and display of decimal values within the component.`,
control: { type: 'object', disable: true }, control: { type: 'object', disable: true },
table: { table: {
category: 'Component Inputs', category: 'Component Inputs',
@@ -279,7 +303,8 @@ export default {
} }
}, },
dateConfig: { dateConfig: {
description: `The dateConfig input allows you to configure date formatting and localization for a component.`, description:
`The dateConfig input allows you to configure date formatting and localization for a component.`,
control: { type: 'object', disable: true }, control: { type: 'object', disable: true },
table: { table: {
category: 'Component Inputs', category: 'Component Inputs',
@@ -309,7 +334,8 @@ export default {
} }
} as Meta; } as Meta;
const formatCustomTooltip = (row: DataRow): string => (row ? 'This is ' + row.getValue('firstname') : null); const formatCustomTooltip = (row: DataRow): string =>
row ? 'This is ' + row.getValue('firstname') : null;
const template: Story<DataColumnComponent> = (args: DataColumnComponent & { rows: DataRow[] }) => ({ const template: Story<DataColumnComponent> = (args: DataColumnComponent & { rows: DataRow[] }) => ({
props: args, props: args,
@@ -488,3 +514,4 @@ numberColumn.args = {
type: 'number', type: 'number',
title: 'Number Column' title: 'Number Column'
}; };

View File

@@ -17,16 +17,16 @@
/* eslint-disable @angular-eslint/component-selector, @angular-eslint/no-input-rename */ /* eslint-disable @angular-eslint/component-selector, @angular-eslint/no-input-rename */
import { DataColumnType } from '@alfresco/adf-extensions';
import { Component, ContentChild, Input, OnInit, TemplateRef } from '@angular/core'; import { Component, ContentChild, Input, OnInit, TemplateRef } from '@angular/core';
import { DataColumnType } from '@alfresco/adf-extensions';
import { CurrencyConfig, DateConfig, DecimalConfig } from '../data/data-column.model'; import { CurrencyConfig, DateConfig, DecimalConfig } from '../data/data-column.model';
@Component({ @Component({
selector: 'data-column', selector: 'data-column',
standalone: true,
template: '' template: ''
}) })
export class DataColumnComponent implements OnInit { export class DataColumnComponent implements OnInit {
/** Id of the Column */ /** Id of the Column */
@Input() @Input()
id: string = ''; id: string = '';

View File

@@ -15,13 +15,26 @@
* limitations under the License. * limitations under the License.
*/ */
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { DateColumnHeaderComponent } from './data-column-header.component';
import { DataColumnListComponent } from './data-column-list.component'; import { DataColumnListComponent } from './data-column-list.component';
import { DataColumnComponent } from './data-column.component'; import { DataColumnComponent } from './data-column.component';
import { DateColumnHeaderComponent } from './data-column-header.component';
@NgModule({ @NgModule({
imports: [DataColumnComponent, DataColumnListComponent, DateColumnHeaderComponent], imports: [
exports: [DataColumnComponent, DataColumnListComponent, DateColumnHeaderComponent] CommonModule
],
declarations: [
DataColumnComponent,
DataColumnListComponent,
DateColumnHeaderComponent
],
exports: [
DataColumnComponent,
DataColumnListComponent,
DateColumnHeaderComponent
]
}) })
export class DataColumnModule {} export class DataColumnModule {}

View File

@@ -17,8 +17,8 @@
/* eslint-disable id-blacklist */ /* eslint-disable id-blacklist */
import { DataColumnType } from '@alfresco/adf-extensions';
import { TemplateRef } from '@angular/core'; import { TemplateRef } from '@angular/core';
import { DataColumnType } from '@alfresco/adf-extensions';
export interface DataColumn<T = unknown> { export interface DataColumn<T = unknown> {
id?: string; id?: string;

View File

@@ -16,5 +16,10 @@
*/ */
export class DataSorting { export class DataSorting {
constructor(public key?: string, public direction?: string, public options?: Intl.CollatorOptions) {} constructor(
public key?: string,
public direction?: string,
public options?: Intl.CollatorOptions
) {
}
} }

View File

@@ -15,10 +15,10 @@
* limitations under the License. * limitations under the License.
*/ */
import { ContentChild, Directive, Input } from '@angular/core'; import { ContentChild, Input, Directive } from '@angular/core';
import { ReplaySubject } from 'rxjs'; import { ReplaySubject } from 'rxjs';
import { AppConfigService } from '../../app-config'; import { AppConfigService } from '../../app-config/app-config.service';
import { DataColumnListComponent } from '../data-column'; import { DataColumnListComponent } from '../data-column/data-column-list.component';
import { DataColumn } from './data-column.model'; import { DataColumn } from './data-column.model';
import { ObjectDataColumn } from './object-datacolumn.model'; import { ObjectDataColumn } from './object-datacolumn.model';

View File

@@ -15,31 +15,22 @@
* limitations under the License. * limitations under the License.
*/ */
import { Subject } from 'rxjs';
import { DataColumn } from './data-column.model'; import { DataColumn } from './data-column.model';
import { DataRow } from './data-row.model'; import { DataRow } from './data-row.model';
import { DataSorting } from './data-sorting.model'; import { DataSorting } from './data-sorting.model';
import { Subject } from 'rxjs';
export interface DataTableAdapter { export interface DataTableAdapter {
rowsChanged?: Subject<Array<DataRow>>; rowsChanged?: Subject<Array<DataRow>>;
selectedRow: DataRow; selectedRow: DataRow;
getRows(): Array<DataRow>; getRows(): Array<DataRow>;
setRows(rows: Array<DataRow>): void; setRows(rows: Array<DataRow>): void;
getColumns(): Array<DataColumn>; getColumns(): Array<DataColumn>;
setColumns(columns: Array<DataColumn>): void; setColumns(columns: Array<DataColumn>): void;
getValue(row: DataRow, col: DataColumn, resolverFn?: (_row: DataRow, _col: DataColumn) => any): any; getValue(row: DataRow, col: DataColumn, resolverFn?: (_row: DataRow, _col: DataColumn) => any): any;
getColumnType(row: DataRow, col: DataColumn): string; getColumnType(row: DataRow, col: DataColumn): string;
getSorting(): DataSorting; getSorting(): DataSorting;
setSorting(sorting: DataSorting): void; setSorting(sorting: DataSorting): void;
sort(key?: string, direction?: string): void; sort(key?: string, direction?: string): void;
} }

View File

@@ -15,9 +15,9 @@
* limitations under the License. * limitations under the License.
*/ */
import { DataColumnType } from '@alfresco/adf-extensions';
import { TemplateRef } from '@angular/core'; import { TemplateRef } from '@angular/core';
import { CurrencyConfig, DataColumn, DateConfig, DecimalConfig } from './data-column.model'; import { DataColumnType } from '@alfresco/adf-extensions';
import { CurrencyConfig, DataColumn, DecimalConfig, DateConfig } from './data-column.model';
// Simple implementation of the DataColumn interface. // Simple implementation of the DataColumn interface.
export class ObjectDataColumn<T = unknown> implements DataColumn<T> { export class ObjectDataColumn<T = unknown> implements DataColumn<T> {

View File

@@ -15,15 +15,17 @@
* limitations under the License. * limitations under the License.
*/ */
import { ObjectUtils } from '../../common'; import { ObjectUtils } from '../../common/utils';
import { DataRow } from './data-row.model'; import { DataRow } from './data-row.model';
// Simple implementation of the DataRow interface. // Simple implementation of the DataRow interface.
export class ObjectDataRow implements DataRow { export class ObjectDataRow implements DataRow {
constructor(private obj: any, public isSelected: boolean = false) { constructor(private obj: any, public isSelected: boolean = false) {
if (!obj) { if (!obj) {
throw new Error('Object source not found'); throw new Error('Object source not found');
} }
} }
getValue(key: string): any { getValue(key: string): any {

View File

@@ -18,11 +18,12 @@
import { DataColumn } from './data-column.model'; import { DataColumn } from './data-column.model';
import { DataRow } from './data-row.model'; import { DataRow } from './data-row.model';
import { DataSorting } from './data-sorting.model'; import { DataSorting } from './data-sorting.model';
import { ObjectDataColumn } from './object-datacolumn.model';
import { ObjectDataRow } from './object-datarow.model';
import { ObjectDataTableAdapter } from './object-datatable-adapter'; import { ObjectDataTableAdapter } from './object-datatable-adapter';
import { ObjectDataRow } from './object-datarow.model';
import { ObjectDataColumn } from './object-datacolumn.model';
describe('ObjectDataTableAdapter', () => { describe('ObjectDataTableAdapter', () => {
it('should init with empty row collection', () => { it('should init with empty row collection', () => {
const adapter = new ObjectDataTableAdapter(null, []); const adapter = new ObjectDataTableAdapter(null, []);
expect(adapter.getRows()).toBeDefined(); expect(adapter.getRows()).toBeDefined();
@@ -45,7 +46,10 @@ describe('ObjectDataTableAdapter', () => {
}); });
it('should map columns without rows', () => { it('should map columns without rows', () => {
const adapter = new ObjectDataTableAdapter(null, [{} as DataColumn, {} as DataColumn]); const adapter = new ObjectDataTableAdapter(null, [
{} as DataColumn,
{} as DataColumn
]);
const columns = adapter.getColumns(); const columns = adapter.getColumns();
expect(columns.length).toBe(2); expect(columns.length).toBe(2);
@@ -112,7 +116,10 @@ describe('ObjectDataTableAdapter', () => {
}); });
it('should reset columns by null value', () => { it('should reset columns by null value', () => {
const adapter = new ObjectDataTableAdapter([], [{} as DataColumn, {} as DataColumn]); const adapter = new ObjectDataTableAdapter([], [
{} as DataColumn,
{} as DataColumn
]);
expect(adapter.getColumns()).toBeDefined(); expect(adapter.getColumns()).toBeDefined();
expect(adapter.getColumns().length).toBe(2); expect(adapter.getColumns().length).toBe(2);
@@ -181,7 +188,9 @@ describe('ObjectDataTableAdapter', () => {
{ id: 2, name: 'abs' }, { id: 2, name: 'abs' },
{ id: 1, name: 'xyz' } { id: 1, name: 'xyz' }
], ],
[new ObjectDataColumn({ key: 'id', sortable: true })] [
new ObjectDataColumn({ key: 'id', sortable: true })
]
); );
const rows = adapter.getRows(); const rows = adapter.getRows();
@@ -190,16 +199,10 @@ describe('ObjectDataTableAdapter', () => {
}); });
it('should take first sortable column by default', () => { it('should take first sortable column by default', () => {
const adapter = new ObjectDataTableAdapter( const adapter = new ObjectDataTableAdapter([], [
[],
[
{ key: 'icon' } as DataColumn, { key: 'icon' } as DataColumn,
new ObjectDataColumn({ new ObjectDataColumn({ key: 'id', sortable: true })
key: 'id', ]);
sortable: true
})
]
);
expect(adapter.getSorting()).toEqual( expect(adapter.getSorting()).toEqual(
jasmine.objectContaining({ jasmine.objectContaining({
@@ -218,7 +221,10 @@ describe('ObjectDataTableAdapter', () => {
{ id: 1, created: new Date(2016, 7, 6, 15, 7, 2) }, { id: 1, created: new Date(2016, 7, 6, 15, 7, 2) },
{ id: 2, created: new Date(2016, 7, 6, 15, 7, 1) } { id: 2, created: new Date(2016, 7, 6, 15, 7, 1) }
], ],
[{ key: 'id' } as DataColumn, { key: 'created' } as DataColumn] [
{ key: 'id' } as DataColumn,
{ key: 'created' } as DataColumn
]
); );
adapter.setSorting(new DataSorting('created', 'asc', { numeric: true })); adapter.setSorting(new DataSorting('created', 'asc', { numeric: true }));
@@ -229,7 +235,11 @@ describe('ObjectDataTableAdapter', () => {
}); });
it('should sort by numbers', () => { it('should sort by numbers', () => {
const adapter = new ObjectDataTableAdapter([{ id: 123 }, { id: 38 }, { id: 50 }], [{ key: 'id' } as DataColumn]); const adapter = new ObjectDataTableAdapter([
{ id: 123 },
{ id: 38 },
{ id: 50 }
],[{key: 'id'} as DataColumn]);
adapter.setSorting(new DataSorting('id', 'asc', { numeric: true })); adapter.setSorting(new DataSorting('id', 'asc', { numeric: true }));
@@ -245,7 +255,10 @@ describe('ObjectDataTableAdapter', () => {
{ id: 2, name: 'abs' }, { id: 2, name: 'abs' },
{ id: 1, name: 'xyz' } { id: 1, name: 'xyz' }
], ],
[new ObjectDataColumn({ key: 'id' }), new ObjectDataColumn({ key: 'name' })] [
new ObjectDataColumn({ key: 'id' }),
new ObjectDataColumn({ key: 'name' })
]
); );
expect(adapter.getSorting()).toBeUndefined(); expect(adapter.getSorting()).toBeUndefined();
@@ -257,7 +270,9 @@ describe('ObjectDataTableAdapter', () => {
{ id: 2, name: 'abs' }, { id: 2, name: 'abs' },
{ id: 1, name: 'xyz' } { id: 1, name: 'xyz' }
], ],
[new ObjectDataColumn({ key: 'id', sortable: true })] [
new ObjectDataColumn({ key: 'id', sortable: true })
]
); );
adapter.setSorting(new DataSorting('id', 'asc', { numeric: true })); adapter.setSorting(new DataSorting('id', 'asc', { numeric: true }));
@@ -301,6 +316,7 @@ describe('ObjectDataTableAdapter', () => {
}); });
describe('ObjectDataRow', () => { describe('ObjectDataRow', () => {
it('should require object source', () => { it('should require object source', () => {
expect(() => new ObjectDataRow(null)).toThrowError('Object source not found'); expect(() => new ObjectDataRow(null)).toThrowError('Object source not found');
}); });

View File

@@ -15,13 +15,13 @@
* limitations under the License. * limitations under the License.
*/ */
import { Subject } from 'rxjs';
import { DataColumn } from './data-column.model'; import { DataColumn } from './data-column.model';
import { DataRow } from './data-row.model'; import { DataRow } from './data-row.model';
import { ObjectDataRow } from './object-datarow.model';
import { ObjectDataColumn } from './object-datacolumn.model';
import { DataSorting } from './data-sorting.model'; import { DataSorting } from './data-sorting.model';
import { DataTableAdapter } from './datatable-adapter'; import { DataTableAdapter } from './datatable-adapter';
import { ObjectDataColumn } from './object-datacolumn.model'; import { Subject } from 'rxjs';
import { ObjectDataRow } from './object-datarow.model';
// Simple implementation of the DataTableAdapter interface. // Simple implementation of the DataTableAdapter interface.
export class ObjectDataTableAdapter implements DataTableAdapter { export class ObjectDataTableAdapter implements DataTableAdapter {

View File

@@ -15,50 +15,85 @@
* limitations under the License. * limitations under the License.
*/ */
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { LocalizedDatePipe } from '../pipes'; import { RouterModule } from '@angular/router';
import { AmountCellComponent } from './components/amount-cell/amount-cell.component'; import { TranslateModule } from '@ngx-translate/core';
import { BooleanCellComponent } from './components/boolean-cell/boolean-cell.component';
import { ColumnsSelectorComponent } from './components/columns-selector/columns-selector.component'; import { MaterialModule } from '../material.module';
import { ContextMenuModule } from '../context-menu/context-menu.module';
import { PipeModule } from '../pipes/pipe.module';
import { DirectiveModule } from '../directives/directive.module';
import { DataTableCellComponent } from './components/datatable-cell/datatable-cell.component'; import { DataTableCellComponent } from './components/datatable-cell/datatable-cell.component';
import { DataTableRowComponent } from './components/datatable-row/datatable-row.component'; import { DataTableRowComponent } from './components/datatable-row/datatable-row.component';
import { DataTableComponent } from './components/datatable/datatable.component'; import { DataTableComponent } from './components/datatable/datatable.component';
import { DateCellComponent } from './components/date-cell/date-cell.component'; import { DateCellComponent } from './components/date-cell/date-cell.component';
import { import { ColumnsSelectorComponent } from './components/columns-selector/columns-selector.component';
EmptyListBodyDirective, import { EmptyListBodyDirective,
EmptyListComponent, EmptyListComponent,
EmptyListFooterDirective, EmptyListFooterDirective,
EmptyListHeaderDirective EmptyListHeaderDirective } from './components/empty-list/empty-list.component';
} from './components/empty-list/empty-list.component';
import { FileSizeCellComponent } from './components/filesize-cell/filesize-cell.component'; import { FileSizeCellComponent } from './components/filesize-cell/filesize-cell.component';
import { IconCellComponent } from './components/icon-cell/icon-cell.component';
import { JsonCellComponent } from './components/json-cell/json-cell.component';
import { LocationCellComponent } from './components/location-cell/location-cell.component'; import { LocationCellComponent } from './components/location-cell/location-cell.component';
import { NumberCellComponent } from './components/number-cell/number-cell.component'; import { LoadingContentTemplateDirective } from './directives/loading-template.directive';
import { DataColumnComponent, DataColumnListComponent, DateColumnHeaderComponent } from './data-column'; import { NoContentTemplateDirective } from './directives/no-content-template.directive';
import { NoPermissionTemplateDirective } from './directives/no-permission-template.directive';
import { HeaderFilterTemplateDirective } from './directives/header-filter-template.directive';
import { CustomEmptyContentTemplateDirective } from './directives/custom-empty-content-template.directive'; import { CustomEmptyContentTemplateDirective } from './directives/custom-empty-content-template.directive';
import { CustomLoadingContentTemplateDirective } from './directives/custom-loading-template.directive'; import { CustomLoadingContentTemplateDirective } from './directives/custom-loading-template.directive';
import { CustomNoPermissionTemplateDirective } from './directives/custom-no-permission-template.directive'; import { CustomNoPermissionTemplateDirective } from './directives/custom-no-permission-template.directive';
import { DropZoneDirective } from './directives/drop-zone.directive';
import { HeaderFilterTemplateDirective } from './directives/header-filter-template.directive';
import { LoadingContentTemplateDirective } from './directives/loading-template.directive';
import { MainMenuDataTableTemplateDirective } from './directives/main-data-table-action-template.directive'; import { MainMenuDataTableTemplateDirective } from './directives/main-data-table-action-template.directive';
import { NoContentTemplateDirective } from './directives/no-content-template.directive'; import { JsonCellComponent } from './components/json-cell/json-cell.component';
import { NoPermissionTemplateDirective } from './directives/no-permission-template.directive'; import { ClipboardModule } from '../clipboard/clipboard.module';
import { DropZoneDirective } from './directives/drop-zone.directive';
import { DragDropModule } from '@angular/cdk/drag-drop';
import { IconModule } from '../icon/icon.module';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { DataColumnComponent, DataColumnListComponent, DateColumnHeaderComponent } from './data-column';
import { ResizableModule } from './directives/resizable/resizable.module';
import { DataColumnModule } from './data-column/data-column.module';
import { BooleanCellComponent } from './components/boolean-cell/boolean-cell.component';
import { AmountCellComponent } from './components/amount-cell/amount-cell.component';
import { NumberCellComponent } from './components/number-cell/number-cell.component';
import { LocalizedDatePipe } from '../pipes';
import { IconCellComponent } from './components/icon-cell/icon-cell.component';
@NgModule({ @NgModule({
imports: [ imports: [
RouterModule,
MaterialModule,
CommonModule,
TranslateModule,
ContextMenuModule,
PipeModule,
DirectiveModule,
ClipboardModule,
DragDropModule,
IconModule,
FormsModule,
ReactiveFormsModule,
ResizableModule,
DataColumnModule,
BooleanCellComponent,
AmountCellComponent,
NumberCellComponent,
LocationCellComponent,
DateCellComponent,
LocalizedDatePipe,
IconCellComponent
],
declarations: [
DataTableComponent, DataTableComponent,
EmptyListComponent,
EmptyListHeaderDirective,
EmptyListBodyDirective,
EmptyListFooterDirective,
DataTableCellComponent, DataTableCellComponent,
DataTableRowComponent, DataTableRowComponent,
DataColumnComponent,
DataColumnListComponent,
DateColumnHeaderComponent,
ColumnsSelectorComponent,
EmptyListComponent,
FileSizeCellComponent, FileSizeCellComponent,
JsonCellComponent, JsonCellComponent,
DropZoneDirective, ColumnsSelectorComponent,
NoContentTemplateDirective, NoContentTemplateDirective,
NoPermissionTemplateDirective, NoPermissionTemplateDirective,
LoadingContentTemplateDirective, LoadingContentTemplateDirective,
@@ -67,16 +102,7 @@ import { NoPermissionTemplateDirective } from './directives/no-permission-templa
CustomLoadingContentTemplateDirective, CustomLoadingContentTemplateDirective,
CustomNoPermissionTemplateDirective, CustomNoPermissionTemplateDirective,
MainMenuDataTableTemplateDirective, MainMenuDataTableTemplateDirective,
BooleanCellComponent, DropZoneDirective
AmountCellComponent,
NumberCellComponent,
LocationCellComponent,
DateCellComponent,
LocalizedDatePipe,
IconCellComponent,
EmptyListHeaderDirective,
EmptyListBodyDirective,
EmptyListFooterDirective
], ],
exports: [ exports: [
DataTableComponent, DataTableComponent,

View File

@@ -17,8 +17,13 @@
import { Directive } from '@angular/core'; import { Directive } from '@angular/core';
/**
* Directive selectors without adf- prefix will be deprecated on 3.0.0.
* The empty-folder-content selector will be deprecated as it has been replace by
* adf-custom-empty-content-template.
*/
@Directive({ @Directive({
selector: 'adf-custom-empty-content-template', selector: 'adf-custom-empty-content-template, empty-folder-content'
standalone: true
}) })
export class CustomEmptyContentTemplateDirective {} export class CustomEmptyContentTemplateDirective {}

View File

@@ -18,7 +18,6 @@
import { Directive } from '@angular/core'; import { Directive } from '@angular/core';
@Directive({ @Directive({
selector: 'adf-custom-loading-content-template', selector: 'adf-custom-loading-content-template'
standalone: true
}) })
export class CustomLoadingContentTemplateDirective {} export class CustomLoadingContentTemplateDirective {}

View File

@@ -17,8 +17,12 @@
import { Directive } from '@angular/core'; import { Directive } from '@angular/core';
/**
* Directive selectors without adf- prefix will be deprecated on 3.0.0.
* The no-permission-content selector will be deprecated as it has been replace by
* adf-custom-no-permission-template.
*/
@Directive({ @Directive({
selector: 'adf-custom-no-permission-template', selector: 'adf-custom-no-permission-template, no-permission-content'
standalone: true
}) })
export class CustomNoPermissionTemplateDirective {} export class CustomNoPermissionTemplateDirective {}

View File

@@ -15,13 +15,12 @@
* limitations under the License. * limitations under the License.
*/ */
import { Directive, ElementRef, Input, NgZone, OnDestroy, OnInit } from '@angular/core'; import { Directive, Input, ElementRef, NgZone, OnInit, OnDestroy } from '@angular/core';
import { DataColumn } from '../data/data-column.model';
import { DataRow } from '../data/data-row.model'; import { DataRow } from '../data/data-row.model';
import { DataColumn } from '../data/data-column.model';
@Directive({ @Directive({
selector: '[adf-drop-zone]', selector: '[adf-drop-zone]'
standalone: true
}) })
export class DropZoneDirective implements OnInit, OnDestroy { export class DropZoneDirective implements OnInit, OnDestroy {
private element: HTMLElement; private element: HTMLElement;

View File

@@ -15,10 +15,10 @@
* limitations under the License. * limitations under the License.
*/ */
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { TestBed, ComponentFixture } from '@angular/core/testing';
import { CoreTestingModule } from '../../testing';
import { DataTableComponent } from '../components/datatable/datatable.component'; import { DataTableComponent } from '../components/datatable/datatable.component';
import { HeaderFilterTemplateDirective } from './header-filter-template.directive'; import { HeaderFilterTemplateDirective } from './header-filter-template.directive';
import { CoreTestingModule } from '../../testing/core.testing.module';
describe('HeaderFilterTemplateDirective', () => { describe('HeaderFilterTemplateDirective', () => {
let fixture: ComponentFixture<DataTableComponent>; let fixture: ComponentFixture<DataTableComponent>;

View File

@@ -19,14 +19,15 @@ import { AfterContentInit, ContentChild, Directive, TemplateRef } from '@angular
import { DataTableComponent } from '../components/datatable/datatable.component'; import { DataTableComponent } from '../components/datatable/datatable.component';
@Directive({ @Directive({
selector: 'adf-header-filter-template', selector: 'adf-header-filter-template'
standalone: true
}) })
export class HeaderFilterTemplateDirective implements AfterContentInit { export class HeaderFilterTemplateDirective implements AfterContentInit {
@ContentChild(TemplateRef) @ContentChild(TemplateRef)
template: any; template: any;
constructor(private dataTable: DataTableComponent) {} constructor(private dataTable: DataTableComponent) {
}
ngAfterContentInit() { ngAfterContentInit() {
if (this.dataTable) { if (this.dataTable) {

View File

@@ -15,10 +15,10 @@
* limitations under the License. * limitations under the License.
*/ */
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { TestBed, ComponentFixture } from '@angular/core/testing';
import { CoreTestingModule } from '../../testing';
import { DataTableComponent } from '../components/datatable/datatable.component'; import { DataTableComponent } from '../components/datatable/datatable.component';
import { LoadingContentTemplateDirective } from './loading-template.directive'; import { LoadingContentTemplateDirective } from './loading-template.directive';
import { CoreTestingModule } from '../../testing/core.testing.module';
describe('LoadingContentTemplateDirective', () => { describe('LoadingContentTemplateDirective', () => {
let fixture: ComponentFixture<DataTableComponent>; let fixture: ComponentFixture<DataTableComponent>;

View File

@@ -18,19 +18,24 @@
import { AfterContentInit, ContentChild, Directive, TemplateRef } from '@angular/core'; import { AfterContentInit, ContentChild, Directive, TemplateRef } from '@angular/core';
import { DataTableComponent } from '../components/datatable/datatable.component'; import { DataTableComponent } from '../components/datatable/datatable.component';
/**
* Directive selectors without adf- prefix will be deprecated on 3.0.0
*/
@Directive({ @Directive({
selector: 'adf-loading-content-template', selector: 'adf-loading-content-template, loading-content-template'
standalone: true
}) })
export class LoadingContentTemplateDirective implements AfterContentInit { export class LoadingContentTemplateDirective implements AfterContentInit {
@ContentChild(TemplateRef) @ContentChild(TemplateRef)
template: any; template: any;
constructor(private dataTable: DataTableComponent) {} constructor(private dataTable: DataTableComponent) {
}
ngAfterContentInit() { ngAfterContentInit() {
if (this.dataTable) { if (this.dataTable) {
this.dataTable.loadingTemplate = this.template; this.dataTable.loadingTemplate = this.template;
} }
} }
} }

View File

@@ -15,10 +15,12 @@
* limitations under the License. * limitations under the License.
*/ */
import { DataTableComponent, MainMenuDataTableTemplateDirective } from '@alfresco/adf-core'; import { TestBed, ComponentFixture } from '@angular/core/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { DataTableComponent } from '../components/datatable/datatable.component';
import { MainMenuDataTableTemplateDirective } from './main-data-table-action-template.directive';
describe('MainMenuDataTableTemplateDirective', () => { describe('MainMenuDataTableTemplateDirective', () => {
let fixture: ComponentFixture<DataTableComponent>; let fixture: ComponentFixture<DataTableComponent>;
let dataTable: DataTableComponent; let dataTable: DataTableComponent;
let directive: MainMenuDataTableTemplateDirective; let directive: MainMenuDataTableTemplateDirective;

View File

@@ -19,10 +19,10 @@ import { AfterContentInit, ContentChild, Directive, TemplateRef } from '@angular
import { DataTableComponent } from '../components/datatable/datatable.component'; import { DataTableComponent } from '../components/datatable/datatable.component';
@Directive({ @Directive({
selector: 'adf-main-menu-datatable-template', selector: 'adf-main-menu-datatable-template'
standalone: true
}) })
export class MainMenuDataTableTemplateDirective implements AfterContentInit { export class MainMenuDataTableTemplateDirective implements AfterContentInit {
@ContentChild(TemplateRef) @ContentChild(TemplateRef)
template: any; template: any;

View File

@@ -15,10 +15,10 @@
* limitations under the License. * limitations under the License.
*/ */
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { TestBed, ComponentFixture } from '@angular/core/testing';
import { CoreTestingModule } from '../../testing';
import { DataTableComponent } from '../components/datatable/datatable.component'; import { DataTableComponent } from '../components/datatable/datatable.component';
import { NoContentTemplateDirective } from './no-content-template.directive'; import { NoContentTemplateDirective } from './no-content-template.directive';
import { CoreTestingModule } from '../../testing/core.testing.module';
describe('NoContentTemplateDirective', () => { describe('NoContentTemplateDirective', () => {
let fixture: ComponentFixture<DataTableComponent>; let fixture: ComponentFixture<DataTableComponent>;

View File

@@ -22,14 +22,15 @@ import { DataTableComponent } from '../components/datatable/datatable.component'
* Directive selectors without adf- prefix will be deprecated on 3.0.0 * Directive selectors without adf- prefix will be deprecated on 3.0.0
*/ */
@Directive({ @Directive({
selector: 'adf-no-content-template', selector: 'adf-no-content-template, no-content-template'
standalone: true
}) })
export class NoContentTemplateDirective implements AfterContentInit { export class NoContentTemplateDirective implements AfterContentInit {
@ContentChild(TemplateRef) @ContentChild(TemplateRef)
template: any; template: any;
constructor(private dataTable: DataTableComponent) {} constructor(private dataTable: DataTableComponent) {
}
ngAfterContentInit() { ngAfterContentInit() {
if (this.dataTable) { if (this.dataTable) {

View File

@@ -15,10 +15,10 @@
* limitations under the License. * limitations under the License.
*/ */
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { TestBed, ComponentFixture } from '@angular/core/testing';
import { CoreTestingModule } from '../../testing';
import { DataTableComponent } from '../components/datatable/datatable.component'; import { DataTableComponent } from '../components/datatable/datatable.component';
import { NoPermissionTemplateDirective } from './no-permission-template.directive'; import { NoPermissionTemplateDirective } from './no-permission-template.directive';
import { CoreTestingModule } from '../../testing/core.testing.module';
describe('NoPermissionTemplateDirective', () => { describe('NoPermissionTemplateDirective', () => {
let fixture: ComponentFixture<DataTableComponent>; let fixture: ComponentFixture<DataTableComponent>;

View File

@@ -22,14 +22,15 @@ import { DataTableComponent } from '../components/datatable/datatable.component'
* Directive selectors without adf- prefix will be deprecated on 3.0.0 * Directive selectors without adf- prefix will be deprecated on 3.0.0
*/ */
@Directive({ @Directive({
selector: 'adf-no-permission-template', selector: 'adf-no-permission-template, no-permission-template'
standalone: true
}) })
export class NoPermissionTemplateDirective implements AfterContentInit { export class NoPermissionTemplateDirective implements AfterContentInit {
@ContentChild(TemplateRef) @ContentChild(TemplateRef)
template: any; template: any;
constructor(private dataTable: DataTableComponent) {} constructor(private dataTable: DataTableComponent) {
}
ngAfterContentInit() { ngAfterContentInit() {
if (this.dataTable) { if (this.dataTable) {

View File

@@ -15,8 +15,8 @@
* limitations under the License. * limitations under the License.
*/ */
import { ElementRef, NgZone, Renderer2 } from '@angular/core';
import { TestBed } from '@angular/core/testing'; import { TestBed } from '@angular/core/testing';
import { ElementRef, NgZone, Renderer2 } from '@angular/core';
import { ResizableDirective } from './resizable.directive'; import { ResizableDirective } from './resizable.directive';
describe('ResizableDirective', () => { describe('ResizableDirective', () => {
@@ -54,7 +54,7 @@ describe('ResizableDirective', () => {
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [ResizableDirective], declarations: [ResizableDirective],
providers: [ providers: [
{ provide: Renderer2, useValue: rendererMock }, { provide: Renderer2, useValue: rendererMock },
{ provide: ElementRef, useValue: elementRefMock } { provide: ElementRef, useValue: elementRefMock }
@@ -103,15 +103,7 @@ describe('ResizableDirective', () => {
directive.mousedown.next({ ...mouseDownEvent, resize: true }); directive.mousedown.next({ ...mouseDownEvent, resize: true });
expect(directive.resizeStart.emit).toHaveBeenCalledWith({ expect(directive.resizeStart.emit).toHaveBeenCalledWith({ rectangle: { top: 0, left: 0, bottom: 0, right: 0, width: 0 } });
rectangle: {
top: 0,
left: 0,
bottom: 0,
right: 0,
width: 0
}
});
}); });
it('should unset cursor on mouseup', () => { it('should unset cursor on mouseup', () => {
@@ -133,9 +125,7 @@ describe('ResizableDirective', () => {
directive.mousedown.next({ ...mouseDownEvent, resize: true }); directive.mousedown.next({ ...mouseDownEvent, resize: true });
directive.mouseup.next(mouseUpEvent); directive.mouseup.next(mouseUpEvent);
expect(directive.resizeEnd.emit).toHaveBeenCalledWith({ expect(directive.resizeEnd.emit).toHaveBeenCalledWith({ rectangle: { top: 0, left: 0, right: 0, width: 150, height: 0, bottom: 0, scrollTop: 0, scrollLeft: 0 } });
rectangle: { top: 0, left: 0, right: 0, width: 150, height: 0, bottom: 0, scrollTop: 0, scrollLeft: 0 }
});
}); });
it('should emit resizing on mousemove', () => { it('should emit resizing on mousemove', () => {
@@ -147,15 +137,7 @@ describe('ResizableDirective', () => {
directive.mousedown.next({ ...mouseDownEvent, resize: true }); directive.mousedown.next({ ...mouseDownEvent, resize: true });
directive.mousemove.next(mouseMoveEvent); directive.mousemove.next(mouseMoveEvent);
expect(directive.resizing.emit).toHaveBeenCalledWith({ expect(directive.resizing.emit).toHaveBeenCalledWith({ rectangle: { top: 0, left: 0, bottom: 0, right: 120, width: 120 } });
rectangle: {
top: 0,
left: 0,
bottom: 0,
right: 120,
width: 120
}
});
}); });
it('should emit resizing on mousemove considering cover padding', () => { it('should emit resizing on mousemove considering cover padding', () => {
@@ -169,14 +151,6 @@ describe('ResizableDirective', () => {
directive.mousedown.next({ ...mouseDownEvent, resize: true }); directive.mousedown.next({ ...mouseDownEvent, resize: true });
directive.mousemove.next(mouseMoveEvent); directive.mousemove.next(mouseMoveEvent);
expect(directive.resizing.emit).toHaveBeenCalledWith({ expect(directive.resizing.emit).toHaveBeenCalledWith({ rectangle: { top: 0, left: 0, bottom: 0, right: 130, width: 130 } });
rectangle: {
top: 0,
left: 0,
bottom: 0,
right: 130,
width: 130
}
});
}); });
}); });

View File

@@ -15,14 +15,13 @@
* limitations under the License. * limitations under the License.
*/ */
import { Directive, ElementRef, EventEmitter, Input, NgZone, OnDestroy, OnInit, Output, Renderer2 } from '@angular/core'; import { Subject, Observable, Observer, merge } from 'rxjs';
import { merge, Observable, Observer, Subject } from 'rxjs'; import { BoundingRectangle, ResizeEvent, IResizeMouseEvent, ICoordinateX } from './types';
import { filter, map, mergeMap, pairwise, share, take, takeUntil } from 'rxjs/operators'; import { map, take, share, filter, pairwise, mergeMap, takeUntil } from 'rxjs/operators';
import { BoundingRectangle, ICoordinateX, IResizeMouseEvent, ResizeEvent } from './types'; import { OnInit, Output, NgZone, OnDestroy, Directive, Renderer2, ElementRef, EventEmitter, Input } from '@angular/core';
@Directive({ @Directive({
selector: '[adf-resizable]', selector: '[adf-resizable]',
standalone: true,
exportAs: 'adf-resizable' exportAs: 'adf-resizable'
}) })
export class ResizableDirective implements OnInit, OnDestroy { export class ResizableDirective implements OnInit, OnDestroy {

View File

@@ -20,7 +20,7 @@ import { ResizableDirective } from './resizable.directive';
import { ResizeHandleDirective } from './resize-handle.directive'; import { ResizeHandleDirective } from './resize-handle.directive';
@NgModule({ @NgModule({
imports: [ResizableDirective, ResizeHandleDirective], declarations: [ResizableDirective, ResizeHandleDirective],
exports: [ResizableDirective, ResizeHandleDirective] exports: [ResizableDirective, ResizeHandleDirective]
}) })
export class ResizableModule {} export class ResizableModule {}

View File

@@ -15,8 +15,8 @@
* limitations under the License. * limitations under the License.
*/ */
import { ElementRef, NgZone, Renderer2 } from '@angular/core';
import { TestBed } from '@angular/core/testing'; import { TestBed } from '@angular/core/testing';
import { ElementRef, NgZone, Renderer2 } from '@angular/core';
import { ResizeHandleDirective } from './resize-handle.directive'; import { ResizeHandleDirective } from './resize-handle.directive';
describe('ResizeHandleDirective', () => { describe('ResizeHandleDirective', () => {
@@ -30,14 +30,12 @@ describe('ResizeHandleDirective', () => {
}; };
const elementRefMock = { const elementRefMock = {
nativeElement: { nativeElement: { dispatchEvent: () => { } }
dispatchEvent: () => {}
}
}; };
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [ResizeHandleDirective], declarations: [ResizeHandleDirective],
providers: [ providers: [
{ provide: Renderer2, useValue: rendererMock }, { provide: Renderer2, useValue: rendererMock },
{ provide: ElementRef, useValue: elementRefMock } { provide: ElementRef, useValue: elementRefMock }

View File

@@ -15,13 +15,12 @@
* limitations under the License. * limitations under the License.
*/ */
import { Directive, ElementRef, Input, NgZone, OnDestroy, OnInit, Renderer2 } from '@angular/core';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import { ResizableDirective } from './resizable.directive'; import { ResizableDirective } from './resizable.directive';
import { Input, OnInit, Directive, Renderer2, ElementRef, OnDestroy, NgZone } from '@angular/core';
@Directive({ @Directive({
selector: '[adf-resize-handle]', selector: '[adf-resize-handle]'
standalone: true
}) })
export class ResizeHandleDirective implements OnInit, OnDestroy { export class ResizeHandleDirective implements OnInit, OnDestroy {
/** /**

View File

@@ -52,5 +52,6 @@ export * from './directives/main-data-table-action-template.directive';
export * from './services/datatable.service'; export * from './services/datatable.service';
export * from './datatable.module'; export * from './datatable.module';
export * from './data-column'; export * from './data-column';

View File

@@ -15,25 +15,35 @@
* limitations under the License. * limitations under the License.
*/ */
import { AppConfigService, ColumnsSelectorComponent, DataColumn, DataRowEvent, getDataColumnMock, ObjectDataRow, User } from '@alfresco/adf-core'; import { Component, SimpleChange, ViewChild } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import {
AppConfigService,
ColumnsSelectorComponent,
CustomEmptyContentTemplateDirective,
DataColumn,
DataRowEvent,
DataTableModule,
getDataColumnMock,
ObjectDataRow,
User
} from '@alfresco/adf-core';
import { ProcessListCloudService } from '../services/process-list-cloud.service';
import { ProcessListCloudComponent } from './process-list-cloud.component';
import { fakeCustomSchema, fakeProcessCloudList, processListSchemaMock } from '../mock/process-list-service.mock';
import { of } from 'rxjs';
import { shareReplay, skip } from 'rxjs/operators';
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
import { ProcessListCloudSortingModel } from '../models/process-list-sorting.model';
import { PROCESS_LISTS_PREFERENCES_SERVICE_TOKEN } from '../../../services/cloud-token.service';
import { ProcessListCloudPreferences } from '../models/process-cloud-preferences';
import { PROCESS_LIST_CUSTOM_VARIABLE_COLUMN } from '../../../models/data-column-custom-data';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { PreferenceCloudServiceInterface } from '@alfresco/adf-process-services-cloud'; import { PreferenceCloudServiceInterface } from '@alfresco/adf-process-services-cloud';
import { HarnessLoader } from '@angular/cdk/testing'; import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { Component, SimpleChange, ViewChild } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatProgressSpinnerHarness } from '@angular/material/progress-spinner/testing'; import { MatProgressSpinnerHarness } from '@angular/material/progress-spinner/testing';
import { By } from '@angular/platform-browser';
import { of } from 'rxjs';
import { shareReplay, skip } from 'rxjs/operators';
import { PROCESS_LIST_CUSTOM_VARIABLE_COLUMN } from '../../../models/data-column-custom-data';
import { PROCESS_LISTS_PREFERENCES_SERVICE_TOKEN } from '../../../services/cloud-token.service';
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
import { fakeCustomSchema, fakeProcessCloudList, processListSchemaMock } from '../mock/process-list-service.mock';
import { ProcessListCloudPreferences } from '../models/process-cloud-preferences';
import { ProcessListCloudSortingModel } from '../models/process-list-sorting.model';
import { ProcessListCloudService } from '../services/process-list-cloud.service';
import { ProcessListCloudComponent } from './process-list-cloud.component';
@Component({ @Component({
template: ` <adf-cloud-process-list #processListCloud> template: ` <adf-cloud-process-list #processListCloud>
@@ -626,9 +636,9 @@ describe('ProcessListCloudComponent: Creating an empty custom template - EmptyTe
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [ProcessServiceCloudTestingModule, MatProgressSpinnerModule], imports: [ProcessServiceCloudTestingModule, DataTableModule, MatProgressSpinnerModule],
providers: [{ provide: PROCESS_LISTS_PREFERENCES_SERVICE_TOKEN, useValue: preferencesService }], providers: [{ provide: PROCESS_LISTS_PREFERENCES_SERVICE_TOKEN, useValue: preferencesService }],
declarations: [EmptyTemplateComponent, ProcessListCloudComponent] declarations: [EmptyTemplateComponent, ProcessListCloudComponent, CustomEmptyContentTemplateDirective]
}); });
fixtureEmpty = TestBed.createComponent(EmptyTemplateComponent); fixtureEmpty = TestBed.createComponent(EmptyTemplateComponent);
fixtureEmpty.detectChanges(); fixtureEmpty.detectChanges();

View File

@@ -650,7 +650,7 @@ describe('TaskListCloudComponent: Copy cell content directive from app.config sp
fixture.detectChanges(); fixture.detectChanges();
const cell = fixture.debugElement.query(By.css('[data-automation-id="text_ADF_CLOUD_TASK_LIST.PROPERTIES.PRIORITY_VALUES.NONE"]')); const cell = fixture.debugElement.query(By.css('[data-automation-id="text_ADF_CLOUD_TASK_LIST.PROPERTIES.PRIORITY_VALUES.NONE"]'));
expect(cell.nativeElement.textContent.trim()).toEqual('ADF_CLOUD_TASK_LIST.PROPERTIES.PRIORITY_VALUES.NONE'); expect(cell.nativeElement.textContent).toEqual('ADF_CLOUD_TASK_LIST.PROPERTIES.PRIORITY_VALUES.NONE');
}); });
it('replacePriorityValues should return undefined when no rows defined', () => { it('replacePriorityValues should return undefined when no rows defined', () => {

View File

@@ -24,6 +24,7 @@ import { materialLocators } from './public-api';
const MAX_LOADING_TIME = 120000; const MAX_LOADING_TIME = 120000;
export class DataTableComponentPage { export class DataTableComponentPage {
rootElement: ElementFinder; rootElement: ElementFinder;
list: ElementArrayFinder; list: ElementArrayFinder;
contents: ElementArrayFinder; contents: ElementArrayFinder;
@@ -38,22 +39,22 @@ export class DataTableComponentPage {
noContentContainer: ElementFinder; noContentContainer: ElementFinder;
mainMenuButton: ElementFinder; mainMenuButton: ElementFinder;
rows = `adf-datatable tbody[class*='adf-datatable-body'] adf-datatable-row[class*='adf-datatable-row']`; rows = `adf-datatable div[class*='adf-datatable-body'] adf-datatable-row[class*='adf-datatable-row']`;
constructor(rootElement = $$('adf-datatable').first()) { constructor(rootElement = $$('adf-datatable').first()) {
this.rootElement = rootElement; this.rootElement = rootElement;
this.list = this.rootElement.$$(`tbody[class*='adf-datatable-body'] adf-datatable-row[class*='adf-datatable-row']`); this.list = this.rootElement.$$(`div[class*='adf-datatable-body'] adf-datatable-row[class*='adf-datatable-row']`);
this.contents = this.rootElement.$$('.adf-datatable-body span'); this.contents = this.rootElement.$$('.adf-datatable-body span');
this.tableBody = this.rootElement.$$(`.adf-datatable-body`).first(); this.tableBody = this.rootElement.$$(`.adf-datatable-body`).first();
this.allColumns = this.rootElement.$$('div[data-automation-id*="auto_header_content_id"]'); this.allColumns = this.rootElement.$$('div[data-automation-id*="auto_header_content_id"]');
this.mainMenuButton = this.rootElement.$('[data-automation-id="adf-datatable-main-menu-button"]'); this.mainMenuButton = this.rootElement.$('[data-automation-id="adf-datatable-main-menu-button"]');
this.selectedRowNumber = this.rootElement.$(`adf-datatable-row[class*='is-selected'] div[data-automation-id*='text_']`); this.selectedRowNumber = this.rootElement.$(`adf-datatable-row[class*='is-selected'] div[data-automation-id*='text_']`);
this.allSelectedRows = this.rootElement.$$(`adf-datatable-row[class*='is-selected']`); this.allSelectedRows = this.rootElement.$$(`adf-datatable-row[class*='is-selected']`);
this.selectAll = this.rootElement.$(`thead[class*='adf-datatable-header'] ${materialLocators.Checkbox.root}`); this.selectAll = this.rootElement.$(`div[class*='adf-datatable-header'] ${materialLocators.Checkbox.root}`);
this.emptyList = this.rootElement.$(`adf-empty-content`); this.emptyList = this.rootElement.$(`adf-empty-content`);
this.emptyListTitle = this.rootElement.$(`.adf-empty-content__title`); this.emptyListTitle = this.rootElement.$(`.adf-empty-content__title`);
this.emptyListSubtitle = this.rootElement.$(`.adf-empty-content__subtitle`); this.emptyListSubtitle = this.rootElement.$(`.adf-empty-content__subtitle`);
this.noContentContainer = $(`td[class*='adf-no-content-container']`); this.noContentContainer = $(`div[class*='adf-no-content-container']`);
} }
geCellElementDetail(detail: string): ElementArrayFinder { geCellElementDetail(detail: string): ElementArrayFinder {
@@ -113,23 +114,19 @@ export class DataTableComponentPage {
} }
async checkRowIsSelected(columnName: string, columnValue: string): Promise<void> { async checkRowIsSelected(columnName: string, columnValue: string): Promise<void> {
const selectedRow = this.getCellElementByValue(columnName, columnValue).element( const selectedRow = this.getCellElementByValue(columnName, columnValue).element(by.xpath(`ancestor::adf-datatable-row[contains(@class, 'is-selected')]`));
by.xpath(`ancestor::adf-datatable-row[contains(@class, 'is-selected')]`)
);
await BrowserVisibility.waitUntilElementIsVisible(selectedRow); await BrowserVisibility.waitUntilElementIsVisible(selectedRow);
} }
async checkRowIsNotSelected(columnName: string, columnValue: string): Promise<void> { async checkRowIsNotSelected(columnName: string, columnValue: string): Promise<void> {
const selectedRow = this.getCellElementByValue(columnName, columnValue).element( const selectedRow = this.getCellElementByValue(columnName, columnValue).element(by.xpath(`ancestor::adf-datatable-row[contains(@class, 'is-selected')]`));
by.xpath(`ancestor::adf-datatable-row[contains(@class, 'is-selected')]`)
);
await BrowserVisibility.waitUntilElementIsNotVisible(selectedRow); await BrowserVisibility.waitUntilElementIsNotVisible(selectedRow);
} }
async getColumnValueForRow(identifyingColumn: string, identifyingValue: string, columnName: string): Promise<string> { async getColumnValueForRow(identifyingColumn: string, identifyingValue: string, columnName: string): Promise<string> {
const row = this.getRow(identifyingColumn, identifyingValue); const row = this.getRow(identifyingColumn, identifyingValue);
await BrowserVisibility.waitUntilElementIsVisible(row); await BrowserVisibility.waitUntilElementIsVisible(row);
const rowColumn = row.$(`td[title="${columnName}"] span`); const rowColumn = row.$(`div[title="${columnName}"] span`);
return BrowserActions.getText(rowColumn); return BrowserActions.getText(rowColumn);
} }
@@ -142,7 +139,7 @@ export class DataTableComponentPage {
* @returns 'true' if the list is sorted as await expected and 'false' if it isn't * @returns 'true' if the list is sorted as await expected and 'false' if it isn't
*/ */
async checkListIsSorted(sortOrder: string, columnTitle: string, listType: string = 'STRING'): Promise<any> { async checkListIsSorted(sortOrder: string, columnTitle: string, listType: string = 'STRING'): Promise<any> {
const column = $$(`td.adf-datatable-cell[title='${columnTitle}'] span`); const column = $$(`div.adf-datatable-cell[title='${columnTitle}'] span`);
await BrowserVisibility.waitUntilElementIsVisible(column.first()); await BrowserVisibility.waitUntilElementIsVisible(column.first());
const initialList: string[] = []; const initialList: string[] = [];
@@ -232,14 +229,14 @@ export class DataTableComponentPage {
async getAllRowsColumnValues(column: string): Promise<string[]> { async getAllRowsColumnValues(column: string): Promise<string[]> {
let columnValues: string[] = []; let columnValues: string[] = [];
const columnLocator = $$( const columnLocator = $$(`adf-datatable div[class*='adf-datatable-body'] adf-datatable-row[class*='adf-datatable-row'] div[title="${column}"] span`);
`adf-datatable tbody[class*='adf-datatable-body'] adf-datatable-row[class*='adf-datatable-row'] *[title="${column}"] span`
);
await BrowserVisibility.waitUntilElementIsPresent(columnLocator.first(), 1000); await BrowserVisibility.waitUntilElementIsPresent(columnLocator.first(), 1000);
try { try {
await BrowserVisibility.waitUntilElementIsPresent(columnLocator.first(), 1000); await BrowserVisibility.waitUntilElementIsPresent(columnLocator.first(), 1000);
columnValues = await columnLocator.filter(async (el) => el.isPresent()).map(async (el) => el.getText()); columnValues = await columnLocator
.filter(async (el) => el.isPresent())
.map(async (el) => el.getText());
} catch (error) { } catch (error) {
Logger.log(error); Logger.log(error);
} }
@@ -248,7 +245,7 @@ export class DataTableComponentPage {
} }
async getRowsWithSameColumnValues(columnName: string, columnValue: string) { async getRowsWithSameColumnValues(columnName: string, columnValue: string) {
const columnLocator = `td[title='${columnName}'] div[data-automation-id="text_${columnValue}"] span`; const columnLocator = `div[title='${columnName}'] div[data-automation-id="text_${columnValue}"] span`;
await BrowserVisibility.waitUntilElementIsVisible(this.rootElement.$$(columnLocator).first()); await BrowserVisibility.waitUntilElementIsVisible(this.rootElement.$$(columnLocator).first());
return this.rootElement.$$(columnLocator).getText(); return this.rootElement.$$(columnLocator).getText();
} }
@@ -276,7 +273,7 @@ export class DataTableComponentPage {
* @param titleColumn column title * @param titleColumn column title
*/ */
async sortByColumn(sortOrder: string, titleColumn: string): Promise<void> { async sortByColumn(sortOrder: string, titleColumn: string): Promise<void> {
const locator = $(`th[data-automation-id="auto_id_${titleColumn}"]`); const locator = $(`div[data-automation-id="auto_id_${titleColumn}"]`);
await BrowserVisibility.waitUntilElementIsVisible(locator); await BrowserVisibility.waitUntilElementIsVisible(locator);
const result = await BrowserActions.getAttribute(locator, 'class'); const result = await BrowserActions.getAttribute(locator, 'class');
@@ -329,20 +326,12 @@ export class DataTableComponentPage {
} }
getRow(columnName: string, columnValue: string): ElementFinder { getRow(columnName: string, columnValue: string): ElementFinder {
return this.rootElement return this.rootElement.all(by.xpath(`//div[starts-with(@title, '${columnName}')]//div[contains(@data-automation-id, '${columnValue}')]//ancestor::adf-datatable-row[contains(@class, 'adf-datatable-row')]`)).first();
.all(
by.xpath(
`//td[starts-with(@title, '${columnName}')]//div[contains(@data-automation-id, '${columnValue}')]//ancestor::adf-datatable-row[contains(@class, 'adf-datatable-row')]`
)
)
.first();
} }
// @deprecated use Playwright instead // @deprecated use Playwright instead
getRowByIndex(index: number): ElementFinder { getRowByIndex(index: number): ElementFinder {
return this.rootElement.element( return this.rootElement.element(by.xpath(`//div[contains(@class,'adf-datatable-body')]//adf-datatable-row[contains(@class,'adf-datatable-row')][${index}]`));
by.xpath(`//div[contains(@class,'adf-datatable-body')]//adf-datatable-row[contains(@class,'adf-datatable-row')][${index}]`)
);
} }
async contentInPosition(position: number): Promise<string> { async contentInPosition(position: number): Promise<string> {
@@ -351,7 +340,7 @@ export class DataTableComponentPage {
} }
getCellElementByValue(columnName: string, columnValue: string, columnPrefix = 'text_'): ElementFinder { getCellElementByValue(columnName: string, columnValue: string, columnPrefix = 'text_'): ElementFinder {
return this.rootElement.$$(`td[title="${columnName}"] div[data-automation-id="${columnPrefix}${columnValue}"] span`).first(); return this.rootElement.$$(`div[title="${columnName}"] div[data-automation-id="${columnPrefix}${columnValue}"] span`).first();
} }
async tableIsLoaded(): Promise<void> { async tableIsLoaded(): Promise<void> {
@@ -361,27 +350,23 @@ export class DataTableComponentPage {
async waitTillContentLoaded(): Promise<void> { async waitTillContentLoaded(): Promise<void> {
if (await this.isSpinnerPresent()) { if (await this.isSpinnerPresent()) {
Logger.log('wait datatable loading spinner disappear'); Logger.log('wait datatable loading spinner disappear');
await BrowserVisibility.waitUntilElementIsNotVisible( await BrowserVisibility.waitUntilElementIsNotVisible(this.rootElement.element(by.tagName(materialLocators.Progress.spinner.root)), MAX_LOADING_TIME);
this.rootElement.element(by.tagName(materialLocators.Progress.spinner.root)),
MAX_LOADING_TIME
);
if (await this.isEmpty()) { if (await this.isEmpty()) {
Logger.log('empty page'); Logger.log('empty page');
} else { } else {
await this.waitFirstElementPresent(); await this.waitFirstElementPresent();
} }
} else if (await this.isEmpty()) { } else if (await this.isEmpty()) {
Logger.log('empty page'); Logger.log('empty page');
} else { } else {
try { try {
Logger.log('wait datatable loading spinner is present'); Logger.log('wait datatable loading spinner is present');
await BrowserVisibility.waitUntilElementIsVisible(this.rootElement.element(by.tagName(materialLocators.Progress.spinner.root)), 2000); await BrowserVisibility.waitUntilElementIsVisible(this.rootElement.element(by.tagName(materialLocators.Progress.spinner.root)), 2000);
await BrowserVisibility.waitUntilElementIsNotVisible( await BrowserVisibility.waitUntilElementIsNotVisible(this.rootElement.element(by.tagName(materialLocators.Progress.spinner.root)), MAX_LOADING_TIME);
this.rootElement.element(by.tagName(materialLocators.Progress.spinner.root)), } catch (error) {
MAX_LOADING_TIME }
);
} catch (error) {}
if (await this.isEmpty()) { if (await this.isEmpty()) {
Logger.log('empty page'); Logger.log('empty page');
@@ -407,7 +392,8 @@ export class DataTableComponentPage {
try { try {
Logger.log('wait datatable loading spinner is present'); Logger.log('wait datatable loading spinner is present');
await BrowserVisibility.waitUntilElementIsVisible(element(by.tagName(materialLocators.Progress.bar.root))); await BrowserVisibility.waitUntilElementIsVisible(element(by.tagName(materialLocators.Progress.bar.root)));
} catch (error) {} } catch (error) {
}
if (await this.isEmpty()) { if (await this.isEmpty()) {
Logger.log('empty page'); Logger.log('empty page');
} else { } else {
@@ -418,10 +404,14 @@ export class DataTableComponentPage {
// @deprecated use Playwright instead // @deprecated use Playwright instead
async isColumnDisplayed(columnTitle: string): Promise<boolean> { async isColumnDisplayed(columnTitle: string): Promise<boolean> {
return (await this.allColumns).some(async (column) => { const isColumnDisplayed = (await this.allColumns).some(
async column => {
const columnText = await column.getText(); const columnText = await column.getText();
return columnText === columnTitle; return columnText === columnTitle;
}); }
);
return isColumnDisplayed;
} }
// @deprecated use Playwright instead // @deprecated use Playwright instead
@@ -434,11 +424,11 @@ export class DataTableComponentPage {
} }
getCellByRowNumberAndColumnName(rowNumber: number, columnName: string): ElementFinder { getCellByRowNumberAndColumnName(rowNumber: number, columnName: string): ElementFinder {
return this.list.get(rowNumber).$$(`td[title="${columnName}"] span`).first(); return this.list.get(rowNumber).$$(`div[title="${columnName}"] span`).first();
} }
getCellByRowContentAndColumn(rowColumn: string, rowContent: string, columnName: string): ElementFinder { getCellByRowContentAndColumn(rowColumn: string, rowContent: string, columnName: string): ElementFinder {
return this.getRow(rowColumn, rowContent).$(`td[title='${columnName}']`); return this.getRow(rowColumn, rowContent).$(`div[title='${columnName}']`);
} }
async selectRowByContent(content: string): Promise<void> { async selectRowByContent(content: string): Promise<void> {
@@ -457,52 +447,42 @@ export class DataTableComponentPage {
} }
getCellByContent(content: string): ElementFinder { getCellByContent(content: string): ElementFinder {
return this.rootElement return this.rootElement.all(by.cssContainingText(`adf-datatable-row[class*='adf-datatable-row'] div[class*='adf-datatable-cell']`, content)).first();
.all(by.cssContainingText(`adf-datatable-row[class*='adf-datatable-row'] td[class*='adf-datatable-cell']`, content))
.first();
} }
async checkCellByHighlightContent(content: string): Promise<void> { async checkCellByHighlightContent(content: string): Promise<void> {
const cell = this.rootElement.element( const cell = this.rootElement.element(by.cssContainingText(`adf-datatable-row[class*='adf-datatable-row'] div[class*='adf-name-location-cell-name'] span.adf-highlight`, content));
by.cssContainingText(
`adf-datatable-row[class*='adf-datatable-row'] div[class*='adf-name-location-cell-name'] span.adf-highlight`,
content
)
);
await BrowserVisibility.waitUntilElementIsVisible(cell); await BrowserVisibility.waitUntilElementIsVisible(cell);
} }
async clickRowByContent(name: string): Promise<void> { async clickRowByContent(name: string): Promise<void> {
const resultElement = this.rootElement.$$(`td[data-automation-id='${name}']`).first(); const resultElement = this.rootElement.$$(`div[data-automation-id='${name}']`).first();
await BrowserActions.click(resultElement); await BrowserActions.click(resultElement);
} }
async clickRowByContentCheckbox(name: string): Promise<void> { async clickRowByContentCheckbox(name: string): Promise<void> {
const resultElement = this.rootElement const resultElement = this.rootElement.$$(`div[data-automation-id='${name}']`).first().element(by.xpath(`ancestor::adf-datatable-row/label/${materialLocators.Checkbox.root}`));
.$$(`div[data-automation-id='${name}']`)
.first()
.element(by.xpath(`ancestor::adf-datatable-row/label/${materialLocators.Checkbox.root}`));
browser.actions().mouseMove(resultElement); browser.actions().mouseMove(resultElement);
await BrowserActions.click(resultElement); await BrowserActions.click(resultElement);
} }
async checkRowContentIsDisplayed(content: string): Promise<void> { async checkRowContentIsDisplayed(content: string): Promise<void> {
const resultElement = this.rootElement.$$(`td[data-automation-id='${content}']`).first(); const resultElement = this.rootElement.$$(`div[data-automation-id='${content}']`).first();
await BrowserVisibility.waitUntilElementIsVisible(resultElement); await BrowserVisibility.waitUntilElementIsVisible(resultElement);
} }
async checkRowContentIsNotDisplayed(content: string): Promise<void> { async checkRowContentIsNotDisplayed(content: string): Promise<void> {
const resultElement = this.rootElement.$$(`tr[data-automation-id='${content}']`).first(); const resultElement = this.rootElement.$$(`div[data-automation-id='${content}']`).first();
await BrowserVisibility.waitUntilElementIsNotVisible(resultElement); await BrowserVisibility.waitUntilElementIsNotVisible(resultElement);
} }
async checkRowContentIsDisabled(content: string): Promise<void> { async checkRowContentIsDisabled(content: string): Promise<void> {
const resultElement = this.rootElement.$$(`tr[data-automation-id='${content}'] div.adf-cell-value img[aria-label='Disabled']`).first(); const resultElement = this.rootElement.$$(`div[data-automation-id='${content}'] div.adf-cell-value img[aria-label='Disabled']`).first();
await BrowserVisibility.waitUntilElementIsVisible(resultElement); await BrowserVisibility.waitUntilElementIsVisible(resultElement);
} }
async doubleClickRowByContent(name: string): Promise<void> { async doubleClickRowByContent(name: string): Promise<void> {
const resultElement = this.rootElement.$$(`td[data-automation-id='${name}']`).first(); const resultElement = this.rootElement.$$(`div[data-automation-id='${name}']`).first();
await BrowserActions.click(resultElement); await BrowserActions.click(resultElement);
await browser.actions().sendKeys(protractor.Key.ENTER).perform(); await browser.actions().sendKeys(protractor.Key.ENTER).perform();
} }

View File

@@ -23,7 +23,7 @@ import { BrowserVisibility } from '../../utils/browser-visibility';
export class DataTableItem { export class DataTableItem {
columns = new Array<Column>(); columns = new Array<Column>();
rootElement: ElementFinder; rootElement: ElementFinder;
rows = `tbody[class*='adf-datatable-body'] adf-datatable-row[class*='adf-datatable-row']`; rows = `div[class*='adf-datatable-body'] adf-datatable-row[class*='adf-datatable-row']`;
constructor(rootElement = $$('adf-datatable').first()) { constructor(rootElement = $$('adf-datatable').first()) {
this.rootElement = rootElement; this.rootElement = rootElement;
@@ -34,16 +34,14 @@ export class DataTableItem {
} }
async getColumn(columnName: string): Promise<Column> { async getColumn(columnName: string): Promise<Column> {
return this.columns.find((column) => column.getColumnName() === columnName); return this.columns.find(
(column) => column.getColumnName() === columnName
);
} }
async getRow(columnName: string, columnValue: string): Promise<ElementFinder> { async getRow(columnName: string, columnValue: string): Promise<ElementFinder> {
console.log('getRow', '-------------------------------------------------------');
const column = await this.getColumn(columnName); const column = await this.getColumn(columnName);
const locator = const locator = `//div[@title="${column.columnName}"]` + column.createLocator(columnValue) + `//ancestor::adf-datatable-row[contains(@class, 'adf-datatable-row')]`;
`//td[@title="${column.columnName}"]` +
column.createLocator(columnValue) +
`//ancestor::adf-datatable-row[contains(@class, 'adf-datatable-row')]`;
return this.rootElement.element(by.xpath(locator)); return this.rootElement.element(by.xpath(locator));
} }
@@ -73,26 +71,19 @@ export class DataTableItem {
async getColumnValueForRow(identifyingColumnName: string, identifyingColumnValue: string, columnName: string): Promise<string> { async getColumnValueForRow(identifyingColumnName: string, identifyingColumnValue: string, columnName: string): Promise<string> {
const row = await this.getRow(identifyingColumnName, identifyingColumnValue); const row = await this.getRow(identifyingColumnName, identifyingColumnValue);
await BrowserVisibility.waitUntilElementIsVisible(row); await BrowserVisibility.waitUntilElementIsVisible(row);
const rowColumn = row.$(`td[title="${columnName}"] span`); const rowColumn = row.$(`div[title="${columnName}"] span`);
return BrowserActions.getText(rowColumn); return BrowserActions.getText(rowColumn);
} }
async checkRowIsSelected(columnName: string, columnValue: string): Promise<void> { async checkRowIsSelected(columnName: string, columnValue: string): Promise<void> {
console.log('checkRowIsSelected', '-------------------------------------------------------');
const column = await this.getColumn(columnName); const column = await this.getColumn(columnName);
const locator = const locator = `//div[@title="${column.columnName}"]` + column.createLocator(columnValue) + `//ancestor::adf-datatable-row[contains(@class, 'is-selected')]`;
`//td[@title="${column.columnName}"]` +
column.createLocator(columnValue) +
`//ancestor::adf-datatable-row[contains(@class, 'is-selected')]`;
await BrowserVisibility.waitUntilElementIsVisible(element(by.xpath(locator))); await BrowserVisibility.waitUntilElementIsVisible(element(by.xpath(locator)));
} }
async checkRowIsNotSelected(columnName: string, columnValue: string): Promise<void> { async checkRowIsNotSelected(columnName: string, columnValue: string): Promise<void> {
const column = await this.getColumn(columnName); const column = await this.getColumn(columnName);
const locator = const locator = `//div[@title="${column.columnName}"]` + column.createLocator(columnValue) + `//ancestor::adf-datatable-row[contains(@class, 'is-selected')]`;
`//div[@title="${column.columnName}"]` +
column.createLocator(columnValue) +
`//ancestor::adf-datatable-row[contains(@class, 'is-selected')]`;
await BrowserVisibility.waitUntilElementIsNotVisible(element(by.xpath(locator))); await BrowserVisibility.waitUntilElementIsNotVisible(element(by.xpath(locator)));
} }

View File

@@ -58,7 +58,7 @@ export class ViewerPage {
unknownFormat = $(`adf-viewer-unknown-format .adf-viewer__unknown-format-view`); unknownFormat = $(`adf-viewer-unknown-format .adf-viewer__unknown-format-view`);
async viewFile(fileName: string): Promise<void> { async viewFile(fileName: string): Promise<void> {
const fileView = $$(`#document-list-container td[data-automation-id="${fileName}"]`).first(); const fileView = $$(`#document-list-container div[data-automation-id="${fileName}"]`).first();
await BrowserActions.click(fileView); await BrowserActions.click(fileView);
await browser.actions().sendKeys(protractor.Key.ENTER).perform(); await browser.actions().sendKeys(protractor.Key.ENTER).perform();
await this.waitTillContentLoaded(); await this.waitTillContentLoaded();
@@ -245,7 +245,7 @@ export class ViewerPage {
} }
async clickInfoButton(): Promise<void> { async clickInfoButton(): Promise<void> {
await BrowserActions.click(this.infoButton); await BrowserActions.click($('button[data-automation-id="adf-toolbar-sidebar"]'));
} }
async clickOnTab(tabName: string): Promise<void> { async clickOnTab(tabName: string): Promise<void> {