mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-12 17:04:57 +00:00
[AAE-7819] Change column order - enable drag and drop for datatable - [1/3] (#7567)
* [AAE-7819] Enable drag and drop for datatable [1/3] * [AAE-7819] Change column order - load and save columns order preferences for PROCESSES - [2/3] (#7568) * [AAE-7819] Load and save column order preferences for processes * [AAE-7819] Load and save column order preferences for tasks [3/3] (#7569) * fix css * fix icon module import * Fix unit tests * Fix test * Fix e2e * Fix C279927
This commit is contained in:
parent
e89cea79be
commit
48c3fac018
@ -227,13 +227,13 @@ export class DataTableComponent {
|
|||||||
],
|
],
|
||||||
[
|
[
|
||||||
{ type: 'image', key: 'icon', title: '', srTitle: 'Thumbnail' },
|
{ type: 'image', key: 'icon', title: '', srTitle: 'Thumbnail' },
|
||||||
{ type: 'text', key: 'id', title: 'Id', sortable: true , cssClass: '' },
|
{ type: 'text', key: 'id', title: 'Id', sortable: true , cssClass: '', draggable: true},
|
||||||
{ type: 'date', key: 'createdOn', title: 'Created On', sortable: true, cssClass: 'adf-ellipsis-cell adf-expand-cell-2' },
|
{ type: 'date', key: 'createdOn', title: 'Created On', sortable: true, cssClass: 'adf-ellipsis-cell adf-expand-cell-2', draggable: true },
|
||||||
{ type: 'text', key: 'name', title: 'Name', cssClass: 'adf-ellipsis-cell', sortable: true },
|
{ type: 'text', key: 'name', title: 'Name', cssClass: 'adf-ellipsis-cell', sortable: true, draggable: true },
|
||||||
{ type: 'text', key: 'createdBy.name', title: 'Created By', sortable: true, cssClass: ''},
|
{ type: 'text', key: 'createdBy.name', title: 'Created By', sortable: true, cssClass: '', draggable: true},
|
||||||
{ type: 'json', key: 'json', title: 'Json', cssClass: 'adf-expand-cell-2'},
|
{ type: 'json', key: 'json', title: 'Json', cssClass: 'adf-expand-cell-2', draggable: true},
|
||||||
{ type: 'text', key: 'users', title: 'Users', cssClass: 'adf-expand-cell-2'},
|
{ type: 'text', key: 'users', title: 'Users', cssClass: 'adf-expand-cell-2', draggable: true},
|
||||||
{ type: 'json', key: 'status', title: 'Status', cssClass: 'adf-expand-cell-2'}
|
{ type: 'json', key: 'status', title: 'Status', cssClass: 'adf-expand-cell-2', draggable: true}
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -43,6 +43,7 @@ Defines column properties for DataTable, Tasklist, Document List and other compo
|
|||||||
|
|
||||||
| Name | Type | Default value | Description |
|
| Name | Type | Default value | Description |
|
||||||
| ---- | ---- | ------------- | ----------- |
|
| ---- | ---- | ------------- | ----------- |
|
||||||
|
| id | `string` | '' | Column identifier. |
|
||||||
| copyContent | `boolean` | | Enables/disables a [Clipboard directive](../../core/directives/clipboard.directive.md) to allow copying of cell contents. |
|
| copyContent | `boolean` | | Enables/disables a [Clipboard directive](../../core/directives/clipboard.directive.md) to allow copying of cell contents. |
|
||||||
| cssClass | `string` | | Additional CSS class to be applied to column (header and cells). |
|
| cssClass | `string` | | Additional CSS class to be applied to column (header and cells). |
|
||||||
| editable | `boolean` | false | Toggles the editing support of the column data. |
|
| editable | `boolean` | false | Toggles the editing support of the column data. |
|
||||||
@ -51,6 +52,7 @@ Defines column properties for DataTable, Tasklist, Document List and other compo
|
|||||||
| formatTooltip | `Function` | | Custom tooltip formatter function. |
|
| formatTooltip | `Function` | | Custom tooltip formatter function. |
|
||||||
| key | `string` | | Data source key. Can be either a column/property key like `title` or a property path like `createdBy.name`. |
|
| key | `string` | | Data source key. Can be either a column/property key like `title` or a property path like `createdBy.name`. |
|
||||||
| sortable | `boolean` | true | Toggles ability to sort by this column, for example by clicking the column header. |
|
| sortable | `boolean` | true | Toggles ability to sort by this column, for example by clicking the column header. |
|
||||||
|
| draggable | `boolean` | false | Toggles drag and drop for header column. |
|
||||||
| sortingKey | `string` | | When using server side sorting the column used by the api call where the sorting will be performed |
|
| sortingKey | `string` | | When using server side sorting the column used by the api call where the sorting will be performed |
|
||||||
| srTitle | `string` | | Title to be used for screen readers. |
|
| srTitle | `string` | | Title to be used for screen readers. |
|
||||||
| title | `string` | "" | Display title of the column, typically used for column headers. You can use the i18n resource key to get it translated automatically. |
|
| title | `string` | "" | Display title of the column, typically used for column headers. You can use the i18n resource key to get it translated automatically. |
|
||||||
|
@ -63,10 +63,10 @@ export class ContentServicesPage {
|
|||||||
errorSnackBar = $('simple-snack-bar[class*="mat-simple-snackbar"]');
|
errorSnackBar = $('simple-snack-bar[class*="mat-simple-snackbar"]');
|
||||||
emptyPagination = $('adf-pagination[class*="adf-pagination__empty"]');
|
emptyPagination = $('adf-pagination[class*="adf-pagination__empty"]');
|
||||||
dragAndDrop = $$('adf-upload-drag-area div').first();
|
dragAndDrop = $$('adf-upload-drag-area div').first();
|
||||||
nameHeader = $$('div[data-automation-id="auto_id_name"] > span').first();
|
nameHeader = $$('div[data-automation-id="auto_header_content_id_name"] > span').first();
|
||||||
sizeHeader = $$('div[data-automation-id="auto_id_content.sizeInBytes"] > span').first();
|
sizeHeader = $$('div[data-automation-id="auto_header_content_id_content.sizeInBytes"] > span').first();
|
||||||
createdByHeader = $$('div[data-automation-id="auto_id_createdByUser.displayName"] > span').first();
|
createdByHeader = $$('div[data-automation-id="auto_header_content_id_createdByUser.displayName"] > span').first();
|
||||||
createdHeader = $$('div[data-automation-id="auto_id_createdAt"] > span').first();
|
createdHeader = $$('div[data-automation-id="auto_header_content_id_createdAt"] > span').first();
|
||||||
recentFiles = $('.app-container-recent');
|
recentFiles = $('.app-container-recent');
|
||||||
recentFilesExpanded = $('.app-container-recent mat-expansion-panel-header.mat-expanded');
|
recentFilesExpanded = $('.app-container-recent mat-expansion-panel-header.mat-expanded');
|
||||||
recentFilesClosed = $('.app-container-recent mat-expansion-panel-header');
|
recentFilesClosed = $('.app-container-recent mat-expansion-panel-header');
|
||||||
|
@ -59,6 +59,8 @@ import { DocumentListModule } from '../document-list.module';
|
|||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
import { ShareDataRow } from '../data/share-data-row.model';
|
import { ShareDataRow } from '../data/share-data-row.model';
|
||||||
import { DocumentLoaderNode } from '../models/document-folder.model';
|
import { DocumentLoaderNode } from '../models/document-folder.model';
|
||||||
|
import { matIconRegistryMock } from '../../testing/mat-icon-registry-mock';
|
||||||
|
import { domSanitizerMock } from '../../testing/dom-sanitizer-mock';
|
||||||
|
|
||||||
describe('DocumentList', () => {
|
describe('DocumentList', () => {
|
||||||
|
|
||||||
@ -1139,7 +1141,7 @@ describe('DocumentList', () => {
|
|||||||
|
|
||||||
it('should display [empty folder] template ', () => {
|
it('should display [empty folder] template ', () => {
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
documentList.dataTable = new DataTableComponent(null, null);
|
documentList.dataTable = new DataTableComponent(null, null, matIconRegistryMock, domSanitizerMock);
|
||||||
expect(documentList.dataTable).toBeDefined();
|
expect(documentList.dataTable).toBeDefined();
|
||||||
expect(fixture.debugElement.query(By.css('adf-empty-list'))).not.toBeNull();
|
expect(fixture.debugElement.query(By.css('adf-empty-list'))).not.toBeNull();
|
||||||
});
|
});
|
||||||
@ -1157,7 +1159,7 @@ describe('DocumentList', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should empty folder NOT show the pagination', () => {
|
it('should empty folder NOT show the pagination', () => {
|
||||||
documentList.dataTable = new DataTableComponent(null, null);
|
documentList.dataTable = new DataTableComponent(null, null, matIconRegistryMock, domSanitizerMock);
|
||||||
|
|
||||||
expect(documentList.isEmpty()).toBeTruthy();
|
expect(documentList.isEmpty()).toBeTruthy();
|
||||||
expect(element.querySelector('alfresco-pagination')).toBe(null);
|
expect(element.querySelector('alfresco-pagination')).toBe(null);
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
import { DomSanitizer } from '@angular/platform-browser';
|
||||||
|
|
||||||
|
export const domSanitizerMock = {
|
||||||
|
bypassSecurityTrustResourceUrl: () => {}
|
||||||
|
} as any as DomSanitizer;
|
@ -0,0 +1,5 @@
|
|||||||
|
import { MatIconRegistry } from '@angular/material/icon';
|
||||||
|
|
||||||
|
export const matIconRegistryMock = {
|
||||||
|
addSvgIconInNamespace: () => {}
|
||||||
|
} as any as MatIconRegistry;
|
1
lib/core/assets/images/drag_indicator_24px.svg
Normal file
1
lib/core/assets/images/drag_indicator_24px.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="currentColor"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M11 18c0 1.1-.9 2-2 2s-2-.9-2-2 .9-2 2-2 2 .9 2 2zm-2-8c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0-6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm6 4c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/></svg>
|
After Width: | Height: | Size: 456 B |
@ -25,6 +25,9 @@ import { Component, ContentChild, Input, OnInit, TemplateRef } from '@angular/co
|
|||||||
})
|
})
|
||||||
export class DataColumnComponent implements OnInit {
|
export class DataColumnComponent implements OnInit {
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
id: string = '';
|
||||||
|
|
||||||
/** Data source key. Can be either a column/property key like `title`
|
/** Data source key. Can be either a column/property key like `title`
|
||||||
* or a property path like `createdBy.name`.
|
* or a property path like `createdBy.name`.
|
||||||
*/
|
*/
|
||||||
@ -45,6 +48,10 @@ export class DataColumnComponent implements OnInit {
|
|||||||
@Input()
|
@Input()
|
||||||
sortable: boolean = true;
|
sortable: boolean = true;
|
||||||
|
|
||||||
|
/* Enable drag and drop for header column */
|
||||||
|
@Input()
|
||||||
|
draggable: boolean = false;
|
||||||
|
|
||||||
/** Display title of the column, typically used for column headers. You can use the
|
/** Display title of the column, typically used for column headers. You can use the
|
||||||
* i18n resource key to get it translated automatically.
|
* i18n resource key to get it translated automatically.
|
||||||
*/
|
*/
|
||||||
|
@ -8,21 +8,26 @@
|
|||||||
[class.adf-datatable--empty--header-visible]="isEmpty() && isHeaderVisible()">
|
[class.adf-datatable--empty--header-visible]="isEmpty() && isHeaderVisible()">
|
||||||
<div *ngIf="isHeaderVisible()" class="adf-datatable-header" role="rowgroup" [ngClass]="{ 'adf-sr-only': !isHeaderVisible() }">
|
<div *ngIf="isHeaderVisible()" class="adf-datatable-header" role="rowgroup" [ngClass]="{ 'adf-sr-only': !isHeaderVisible() }">
|
||||||
<adf-datatable-row
|
<adf-datatable-row
|
||||||
|
cdkDropList
|
||||||
|
cdkDropListOrientation="horizontal"
|
||||||
data-automation-id="datatable-row-header"
|
data-automation-id="datatable-row-header"
|
||||||
[disabled]="!isHeaderVisible()"
|
[disabled]="!isHeaderVisible()"
|
||||||
class="adf-datatable-row"
|
class="adf-datatable-row"
|
||||||
*ngIf="display === 'list'"
|
*ngIf="display === 'list'"
|
||||||
role="row">
|
role="row">
|
||||||
|
|
||||||
<!-- Actions (left) -->
|
<!-- Actions (left) -->
|
||||||
<div *ngIf="actions && actionsPosition === 'left'" class="adf-actions-column adf-datatable-cell-header">
|
<div *ngIf="actions && actionsPosition === 'left'" class="adf-actions-column adf-datatable-cell-header">
|
||||||
<span class="adf-sr-only">{{ 'ADF-DATATABLE.ACCESSIBILITY.ACTIONS' | translate }}</span>
|
<span class="adf-sr-only">{{ 'ADF-DATATABLE.ACCESSIBILITY.ACTIONS' | translate }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Columns -->
|
<!-- Columns -->
|
||||||
<div *ngIf="multiselect" class="adf-datatable-cell-header adf-datatable-checkbox">
|
<div *ngIf="multiselect" 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" [checked]="isSelectAllChecked" (change)="onSelectAllClick($event)" class="adf-checkbox-sr-only">{{ 'ADF-DATATABLE.ACCESSIBILITY.SELECT_ALL' | translate }}</mat-checkbox>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="adf-datatable-cell--{{col.type || 'text'}} {{col.cssClass}} adf-datatable-cell-header"
|
<div class="adf-datatable-cell--{{col.type || 'text'}} {{col.cssClass}} adf-datatable-cell-header"
|
||||||
*ngFor="let col of data.getColumns()"
|
*ngFor="let col of data.getColumns(); let columnIndex = index"
|
||||||
[class.adf-sortable]="col.sortable"
|
[class.adf-sortable]="col.sortable"
|
||||||
[attr.data-automation-id]="'auto_id_' + col.key"
|
[attr.data-automation-id]="'auto_id_' + col.key"
|
||||||
[class.adf-datatable__header--sorted-asc]="isColumnSorted(col, 'asc')"
|
[class.adf-datatable__header--sorted-asc]="isColumnSorted(col, 'asc')"
|
||||||
@ -32,14 +37,59 @@
|
|||||||
role="columnheader"
|
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
|
||||||
|
cdkDragBoundary="adf-datatable-row"
|
||||||
|
cdkDragLockAxis="x"
|
||||||
|
(cdkDragStarted)="isDraggingHeaderColumn = true"
|
||||||
|
(cdkDragDropped)="onDropHeaderColumn($event)"
|
||||||
|
[cdkDragDisabled]="!col.draggable"
|
||||||
|
(mouseenter)="hoveredHeaderColumnIndex = columnIndex"
|
||||||
|
(mouseleave)="hoveredHeaderColumnIndex = -1"
|
||||||
adf-drop-zone dropTarget="header" [dropColumn]="col">
|
adf-drop-zone dropTarget="header" [dropColumn]="col">
|
||||||
<ng-container *ngIf="!col.header">
|
|
||||||
<span *ngIf="col.title" class="adf-datatable-cell-value">{{ col.title | translate}}</span>
|
<div
|
||||||
<span *ngIf="col.title && col.sortable" class="adf-sr-only" aria-live="polite">{{ getSortLiveAnnouncement(col) | translate: { string: col.title | translate } }}</span>
|
*ngIf="!col.header"
|
||||||
|
[attr.data-automation-id]="'auto_header_content_id_' + col.key"
|
||||||
|
class="adf-datatable-cell-header-content"
|
||||||
|
[class.adf-datatable-cell-header-content--hovered]="hoveredHeaderColumnIndex === columnIndex && !isDraggingHeaderColumn"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
*ngIf="hoveredHeaderColumnIndex === columnIndex && col.draggable"
|
||||||
|
class="adf-datatable-cell-header-drag-icon-placeholder"
|
||||||
|
[attr.data-automation-id]="'adf-datatable-cell-header-drag-icon-placeholder-'+col.key"
|
||||||
|
></span>
|
||||||
|
|
||||||
|
<span *ngIf="col.title" class="adf-datatable-cell-value"> {{col.title | translate}}</span>
|
||||||
|
|
||||||
|
<span *ngIf="col.title && col.sortable && isDraggingHeaderColumn" class="adf-sr-only" aria-live="polite">
|
||||||
|
{{ getSortLiveAnnouncement(col) | translate: { string: col.title | translate } }}
|
||||||
|
</span>
|
||||||
|
|
||||||
<ng-template *ngIf="allowFiltering" [ngTemplateOutlet]="headerFilterTemplate" [ngTemplateOutletContext]="{$implicit: col}"></ng-template>
|
<ng-template *ngIf="allowFiltering" [ngTemplateOutlet]="headerFilterTemplate" [ngTemplateOutletContext]="{$implicit: col}"></ng-template>
|
||||||
</ng-container>
|
|
||||||
|
<span
|
||||||
|
[class.adf-datatable__header--sorted-asc]="isColumnSorted(col, 'asc')"
|
||||||
|
[class.adf-datatable__header--sorted-desc]="isColumnSorted(col, 'desc')">
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<ng-template *ngIf="col.header" [ngTemplateOutlet]="col.header" [ngTemplateOutletContext]="{$implicit: col}"></ng-template>
|
<ng-template *ngIf="col.header" [ngTemplateOutlet]="col.header" [ngTemplateOutletContext]="{$implicit: col}"></ng-template>
|
||||||
|
|
||||||
|
<div
|
||||||
|
*ngIf="col.draggable"
|
||||||
|
cdkDragHandle
|
||||||
|
class="adf-datatable-cell-header-drag-icon"
|
||||||
|
>
|
||||||
|
<adf-icon
|
||||||
|
*ngIf="hoveredHeaderColumnIndex === columnIndex"
|
||||||
|
value="adf:drag_indicator"
|
||||||
|
[attr.data-automation-id]="'adf-datatable-cell-header-drag-icon-'+col.key">
|
||||||
|
</adf-icon>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="adf-drop-header-cell-placeholder" *cdkDragPlaceholder></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Actions (right) -->
|
<!-- Actions (right) -->
|
||||||
<div *ngIf="actions && actionsPosition === 'right'" class="adf-actions-column adf-datatable-cell-header adf-datatable__actions-cell">
|
<div *ngIf="actions && actionsPosition === 'right'" class="adf-actions-column adf-datatable-cell-header adf-datatable__actions-cell">
|
||||||
<span class="adf-sr-only">{{ 'ADF-DATATABLE.ACCESSIBILITY.ACTIONS' | translate }}</span>
|
<span class="adf-sr-only">{{ 'ADF-DATATABLE.ACCESSIBILITY.ACTIONS' | translate }}</span>
|
||||||
@ -58,7 +108,10 @@
|
|||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="adf-datatable-body" role="rowgroup">
|
<div
|
||||||
|
class="adf-datatable-body"
|
||||||
|
[class.adf-blur-datatable-body]="isDraggingHeaderColumn"
|
||||||
|
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"
|
||||||
@ -171,7 +224,7 @@
|
|||||||
[tooltip]="getCellTooltip(row, col)">
|
[tooltip]="getCellTooltip(row, col)">
|
||||||
</adf-filesize-cell>
|
</adf-filesize-cell>
|
||||||
</div>
|
</div>
|
||||||
<div *ngSwitchCase="'text'" [attr.tabindex]="data.getValue(row, col, resolverFn)? 0 : -1" class="adf-cell-value"
|
<div *ngSwitchCase="'text'" [attr.tabindex]="data.getValue(row, col, resolverFn)? 0 : -1" class="adf-cell-value"
|
||||||
[attr.data-automation-id]="'text_' + data.getValue(row, col, resolverFn)">
|
[attr.data-automation-id]="'text_' + data.getValue(row, col, resolverFn)">
|
||||||
<adf-datatable-cell
|
<adf-datatable-cell
|
||||||
[copyContent]="col.copyContent"
|
[copyContent]="col.copyContent"
|
||||||
|
@ -9,8 +9,8 @@ $data-table-column-spacing: 36px !default;
|
|||||||
$data-table-column-padding: 18px !default;
|
$data-table-column-padding: 18px !default;
|
||||||
$data-table-card-padding: var(--theme-headline-line-height) !default;
|
$data-table-card-padding: var(--theme-headline-line-height) !default;
|
||||||
$data-table-cell-top: calc($data-table-card-padding / 2);
|
$data-table-cell-top: calc($data-table-card-padding / 2);
|
||||||
$data-table-thumbnail-width: 50px !default;
|
$data-table-thumbnail-width: 65px !default;
|
||||||
$data-table-cell-min-width: 50px !default;
|
$data-table-cell-min-width: 65px !default;
|
||||||
$data-table-cell-min-width-no-grow: 100px !default;
|
$data-table-cell-min-width-no-grow: 100px !default;
|
||||||
$data-table-cell-min-width-file-size: $data-table-cell-min-width !default;
|
$data-table-cell-min-width-file-size: $data-table-cell-min-width !default;
|
||||||
|
|
||||||
@ -208,6 +208,13 @@ $data-table-cell-min-width-file-size: $data-table-cell-min-width !default;
|
|||||||
width: fit-content;
|
width: fit-content;
|
||||||
min-width: 100%;
|
min-width: 100%;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
.adf-datatable-row {
|
||||||
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
background-color: inherit;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.adf-datatable-cell {
|
.adf-datatable-cell {
|
||||||
@ -234,6 +241,10 @@ $data-table-cell-min-width-file-size: $data-table-cell-min-width !default;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.adf-blur-datatable-body {
|
||||||
|
filter: blur(3px);
|
||||||
|
}
|
||||||
|
|
||||||
.adf-datatable-body {
|
.adf-datatable-body {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@ -315,66 +326,6 @@ $data-table-cell-min-width-file-size: $data-table-cell-min-width !default;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.adf-datatable-cell-header {
|
|
||||||
@include adf-no-select;
|
|
||||||
|
|
||||||
cursor: pointer;
|
|
||||||
position: relative;
|
|
||||||
vertical-align: bottom;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
font-weight: bold;
|
|
||||||
line-height: 24px;
|
|
||||||
letter-spacing: 0;
|
|
||||||
min-height: $data-table-row-height !important;
|
|
||||||
font-size: $data-table-header-font-size;
|
|
||||||
color: var(--theme-text-fg-color);
|
|
||||||
padding-bottom: 8px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
padding-top: 12px !important;
|
|
||||||
|
|
||||||
&.adf-sortable {
|
|
||||||
@include adf-no-select;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.adf-datatable__header--sorted-asc,
|
|
||||||
&.adf-datatable__header--sorted-desc {
|
|
||||||
color: var(--theme-text-fg-color);
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
@include typo-icon;
|
|
||||||
|
|
||||||
font-size: $data-table-header-sort-icon-size;
|
|
||||||
content: '\e5d8';
|
|
||||||
left: 5px;
|
|
||||||
right: 5px;
|
|
||||||
position: relative;
|
|
||||||
vertical-align: sub;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.adf-datatable__header--sorted-desc::before {
|
|
||||||
content: '\e5db';
|
|
||||||
}
|
|
||||||
|
|
||||||
&.adf-datatable-cell--fileSize.adf-datatable__header--sorted-asc::before,
|
|
||||||
&.adf-datatable-cell--fileSize.adf-datatable__header--sorted-desc::before {
|
|
||||||
left: -3px;
|
|
||||||
right: -3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.adf-datatable-checkbox {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.adf-datatable-cell-header.adf-expand-cell-1,
|
.adf-datatable-cell-header.adf-expand-cell-1,
|
||||||
.adf-datatable-cell.adf-expand-cell-1 {
|
.adf-datatable-cell.adf-expand-cell-1 {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
@ -421,11 +372,12 @@ $data-table-cell-min-width-file-size: $data-table-cell-min-width !default;
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
padding: 0 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.adf-datatable-cell-value {
|
.adf-datatable-cell-value {
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
padding: 10px;
|
padding-right: 10px;
|
||||||
display: block;
|
display: block;
|
||||||
|
|
||||||
@media screen and (-ms-high-contrast: active), screen and (-ms-high-contrast: none) {
|
@media screen and (-ms-high-contrast: active), screen and (-ms-high-contrast: none) {
|
||||||
@ -519,7 +471,6 @@ $data-table-cell-min-width-file-size: $data-table-cell-min-width !default;
|
|||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
padding: 0 4px;
|
|
||||||
|
|
||||||
&.adf-datatable-cell-header,
|
&.adf-datatable-cell-header,
|
||||||
.adf-datatable-content-cell {
|
.adf-datatable-content-cell {
|
||||||
@ -606,6 +557,136 @@ $data-table-cell-min-width-file-size: $data-table-cell-min-width !default;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.adf-datatable-cell-header {
|
||||||
|
@include adf-no-select;
|
||||||
|
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
font-weight: bold;
|
||||||
|
line-height: 24px;
|
||||||
|
letter-spacing: 0;
|
||||||
|
min-height: $data-table-row-height !important;
|
||||||
|
font-size: $data-table-header-font-size;
|
||||||
|
color: var(--theme-text-fg-color);
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
&.adf-sortable {
|
||||||
|
@include adf-no-select;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.adf-datatable__header--sorted-asc,
|
||||||
|
.adf-datatable__header--sorted-desc {
|
||||||
|
color: var(--theme-text-fg-color);
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
@include typo-icon;
|
||||||
|
|
||||||
|
font-size: $data-table-header-sort-icon-size;
|
||||||
|
content: '\e5d8';
|
||||||
|
left: 5px;
|
||||||
|
right: 5px;
|
||||||
|
position: relative;
|
||||||
|
vertical-align: sub;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.adf-datatable__header--sorted-desc::after {
|
||||||
|
content: '\e5db';
|
||||||
|
}
|
||||||
|
|
||||||
|
.adf-datatable-cell--fileSize.adf-datatable__header--sorted-asc::before,
|
||||||
|
.adf-datatable-cell--fileSize.adf-datatable__header--sorted-desc::before {
|
||||||
|
left: -3px;
|
||||||
|
right: -3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.adf-datatable-checkbox {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.adf-datatable-cell-header-content {
|
||||||
|
display: flex;
|
||||||
|
flex-grow: 1;
|
||||||
|
align-items: center;
|
||||||
|
margin: 0 2px;
|
||||||
|
padding: 0 8px;
|
||||||
|
column-gap: 5px;
|
||||||
|
|
||||||
|
.adf-datatable-cell-header-drag-icon-placeholder {
|
||||||
|
min-width: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--hovered {
|
||||||
|
background-color: var(--theme-bg-hover-color);
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.adf-datatable-cell-header-drag-icon {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 3px;
|
||||||
|
margin: auto;
|
||||||
|
color: #ccc;
|
||||||
|
cursor: move;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.adf-datatable-cell-value {
|
||||||
|
padding: 10px 0 !important;
|
||||||
|
line-height: 24px;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.adf-drop-header-cell-placeholder {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
flex-grow: 1;
|
||||||
|
background: var(--theme-bg-hover-color);
|
||||||
|
border: dotted 1px rgba(0, 0, 0, 0.25);
|
||||||
|
min-height: 55px;
|
||||||
|
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.adf-datatable-cell-header.adf-ellipsis-cell {
|
||||||
|
.adf-datatable-cell-header-content {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.adf-datatable-cell-header-content--hovered {
|
||||||
|
.adf-datatable-cell-value {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cdk-drag-preview {
|
||||||
|
&.adf-datatable-cell-header {
|
||||||
|
border-radius: 6px;
|
||||||
|
background-color: var(--theme-background-color);
|
||||||
|
|
||||||
|
@include mat-elevation-transition;
|
||||||
|
@include mat-overridable-elevation(4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* [Accessibility] Material checkbox labels */
|
/* [Accessibility] Material checkbox labels */
|
||||||
.adf-checkbox-sr-only .mat-checkbox-label {
|
.adf-checkbox-sr-only .mat-checkbox-label {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -29,6 +29,9 @@ import { CoreTestingModule } from '../../../testing/core.testing.module';
|
|||||||
import { DataColumnListComponent } from '../../../data-column/data-column-list.component';
|
import { DataColumnListComponent } from '../../../data-column/data-column-list.component';
|
||||||
import { DataColumnComponent } from '../../../data-column/data-column.component';
|
import { DataColumnComponent } from '../../../data-column/data-column.component';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { domSanitizerMock } from 'content-services/src/lib/testing/dom-sanitizer-mock';
|
||||||
|
import { matIconRegistryMock } from 'content-services/src/lib/testing/mat-icon-registry-mock';
|
||||||
|
import { CdkDragDrop } from '@angular/cdk/drag-drop';
|
||||||
|
|
||||||
@Component({selector: 'adf-custom-column-template-component', template: `
|
@Component({selector: 'adf-custom-column-template-component', template: `
|
||||||
<ng-template #tmplRef></ng-template>
|
<ng-template #tmplRef></ng-template>
|
||||||
@ -722,7 +725,7 @@ describe('DataTable', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should initialize default adapter', () => {
|
it('should initialize default adapter', () => {
|
||||||
const table = new DataTableComponent(null, null);
|
const table = new DataTableComponent(null, null, matIconRegistryMock, domSanitizerMock);
|
||||||
expect(table.data).toBeUndefined();
|
expect(table.data).toBeUndefined();
|
||||||
table.ngOnChanges({ data: new SimpleChange('123', {}, true) });
|
table.ngOnChanges({ data: new SimpleChange('123', {}, true) });
|
||||||
expect(table.data).toEqual(jasmine.any(ObjectDataTableAdapter));
|
expect(table.data).toEqual(jasmine.any(ObjectDataTableAdapter));
|
||||||
@ -1605,3 +1608,115 @@ describe('Accesibility', () => {
|
|||||||
expect(cell.getAttribute('tabindex')).toBe('0');
|
expect(cell.getAttribute('tabindex')).toBe('0');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Drag&Drop column header', () => {
|
||||||
|
let fixture: ComponentFixture<DataTableComponent>;
|
||||||
|
let dataTable: DataTableComponent;
|
||||||
|
let data: { id: number; name: string }[] = [];
|
||||||
|
let dataTableSchema: DataColumn[] = [];
|
||||||
|
|
||||||
|
setupTestBed({
|
||||||
|
imports: [
|
||||||
|
TranslateModule.forRoot(),
|
||||||
|
CoreTestingModule
|
||||||
|
],
|
||||||
|
declarations: [CustomColumnTemplateComponent],
|
||||||
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(DataTableComponent);
|
||||||
|
dataTable = fixture.componentInstance;
|
||||||
|
data = [
|
||||||
|
{ id: 1, name: 'name1' },
|
||||||
|
{ id: 2, name: 'name2' }
|
||||||
|
];
|
||||||
|
|
||||||
|
dataTableSchema = [
|
||||||
|
new ObjectDataColumn({ key: 'id', title: 'ID', draggable: false }),
|
||||||
|
new ObjectDataColumn({ key: 'name', title: 'Name', draggable: true })
|
||||||
|
];
|
||||||
|
|
||||||
|
dataTable.data = new ObjectDataTableAdapter(
|
||||||
|
[...data],
|
||||||
|
[...dataTableSchema]
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show/hide drag indicator icon', () => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const hedaderColumn = fixture.debugElement.nativeElement.querySelector('[data-automation-id="auto_id_name"]');
|
||||||
|
hedaderColumn.dispatchEvent(new MouseEvent('mouseenter'));
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
let dragIcon = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-datatable-cell-header-drag-icon-name"]');
|
||||||
|
let dragIconPlaceholder = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-datatable-cell-header-drag-icon-placeholder-name"]');
|
||||||
|
expect(dragIcon).toBeTruthy();
|
||||||
|
expect(dragIconPlaceholder).toBeTruthy();
|
||||||
|
|
||||||
|
hedaderColumn.dispatchEvent(new MouseEvent('mouseleave'));
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
dragIcon = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-datatable-cell-header-drag-icon-name"]');
|
||||||
|
dragIconPlaceholder = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-datatable-cell-header-drag-icon-placeholder-name"]');
|
||||||
|
expect(dragIcon).toBeFalsy();
|
||||||
|
expect(dragIconPlaceholder).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not show drag indicator icon, when drag and drop is disabled', () => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const hedaderColumn = fixture.debugElement.nativeElement.querySelector('[data-automation-id="auto_id_id"]');
|
||||||
|
hedaderColumn.dispatchEvent(new MouseEvent('mouseenter'));
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const dragIcon = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-datatable-cell-header-drag-icon-id"]');
|
||||||
|
const dragIconPlaceholder = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-datatable-cell-header-drag-icon-placeholder-id"]');
|
||||||
|
|
||||||
|
expect(dragIcon).toBeFalsy();
|
||||||
|
expect(dragIconPlaceholder).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should emit on change column order', () => {
|
||||||
|
const columnOrderChangedSpy = spyOn(dataTable.columnOrderChanged, 'emit');
|
||||||
|
const dropEvent: CdkDragDrop<unknown> = {
|
||||||
|
previousIndex: 0,
|
||||||
|
currentIndex: 1,
|
||||||
|
item: undefined,
|
||||||
|
container: undefined,
|
||||||
|
previousContainer: undefined,
|
||||||
|
isPointerOverContainer: true,
|
||||||
|
distance: { x: 0, y: 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
dataTable.onDropHeaderColumn(dropEvent);
|
||||||
|
|
||||||
|
expect(columnOrderChangedSpy).toHaveBeenCalledWith(dataTableSchema.reverse());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should change columns order', () => {
|
||||||
|
const dropEvent: CdkDragDrop<unknown> = {
|
||||||
|
previousIndex: 0,
|
||||||
|
currentIndex: 1,
|
||||||
|
item: undefined,
|
||||||
|
container: undefined,
|
||||||
|
previousContainer: undefined,
|
||||||
|
isPointerOverContainer: true,
|
||||||
|
distance: { x: 0, y: 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
dataTable.onDropHeaderColumn(dropEvent);
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const columns = dataTable.data.getColumns();
|
||||||
|
const headerCells = fixture.debugElement.nativeElement.querySelectorAll('.adf-datatable-cell--text.adf-datatable-cell-header');
|
||||||
|
|
||||||
|
expect(columns[0].key).toEqual(dataTableSchema[1].key);
|
||||||
|
expect(columns[1].key).toEqual(dataTableSchema[0].key);
|
||||||
|
|
||||||
|
expect(headerCells[0].innerText).toBe(dataTableSchema[1].title);
|
||||||
|
expect(headerCells[1].innerText).toBe(dataTableSchema[0].title);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
import {
|
import {
|
||||||
ViewChildren, QueryList, HostListener,
|
ViewChildren, QueryList, HostListener,
|
||||||
AfterContentInit, Component, ContentChild, DoCheck, ElementRef, EventEmitter, Input,
|
AfterContentInit, Component, ContentChild, DoCheck, ElementRef, EventEmitter, Input,
|
||||||
IterableDiffers, OnChanges, Output, SimpleChange, SimpleChanges, TemplateRef, ViewEncapsulation, OnDestroy, AfterViewInit
|
IterableDiffers, OnChanges, Output, SimpleChange, SimpleChanges, TemplateRef, ViewEncapsulation, OnDestroy, AfterViewInit, OnInit
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { FocusKeyManager } from '@angular/cdk/a11y';
|
import { FocusKeyManager } from '@angular/cdk/a11y';
|
||||||
import { MatCheckboxChange } from '@angular/material/checkbox';
|
import { MatCheckboxChange } from '@angular/material/checkbox';
|
||||||
@ -40,6 +40,9 @@ import { ObjectDataTableAdapter } from '../../data/object-datatable-adapter';
|
|||||||
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 { share, buffer, map, filter, debounceTime } from 'rxjs/operators';
|
import { share, buffer, map, filter, debounceTime } from 'rxjs/operators';
|
||||||
|
import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
|
||||||
|
import { MatIconRegistry } from '@angular/material/icon';
|
||||||
|
import { DomSanitizer } from '@angular/platform-browser';
|
||||||
|
|
||||||
// eslint-disable-next-line no-shadow
|
// eslint-disable-next-line no-shadow
|
||||||
export enum DisplayMode {
|
export enum DisplayMode {
|
||||||
@ -61,7 +64,7 @@ export enum ShowHeaderMode {
|
|||||||
encapsulation: ViewEncapsulation.None,
|
encapsulation: ViewEncapsulation.None,
|
||||||
host: { class: 'adf-datatable' }
|
host: { class: 'adf-datatable' }
|
||||||
})
|
})
|
||||||
export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck, OnDestroy, AfterViewInit {
|
export class DataTableComponent implements OnInit, AfterContentInit, OnChanges, DoCheck, OnDestroy, AfterViewInit {
|
||||||
|
|
||||||
@ViewChildren(DataTableRowComponent)
|
@ViewChildren(DataTableRowComponent)
|
||||||
rowsList: QueryList<DataTableRowComponent>;
|
rowsList: QueryList<DataTableRowComponent>;
|
||||||
@ -160,6 +163,9 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck,
|
|||||||
@Output()
|
@Output()
|
||||||
executeRowAction = new EventEmitter<DataRowActionEvent>();
|
executeRowAction = new EventEmitter<DataRowActionEvent>();
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
columnOrderChanged = new EventEmitter<DataColumn[]>();
|
||||||
|
|
||||||
/** Flag that indicates if the datatable is in loading state and needs to show the
|
/** Flag that indicates if the datatable is in loading state and needs to show the
|
||||||
* loading template (see the docs to learn how to configure a loading template).
|
* loading template (see the docs to learn how to configure a loading template).
|
||||||
*/
|
*/
|
||||||
@ -199,6 +205,9 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck,
|
|||||||
isSelectAllChecked: boolean = false;
|
isSelectAllChecked: boolean = false;
|
||||||
selection = new Array<DataRow>();
|
selection = new Array<DataRow>();
|
||||||
|
|
||||||
|
isDraggingHeaderColumn = false;
|
||||||
|
hoveredHeaderColumnIndex = -1;
|
||||||
|
|
||||||
/** This array of fake rows fix the flex layout for the gallery view */
|
/** This array of fake rows fix the flex layout for the gallery view */
|
||||||
fakeRows = [];
|
fakeRows = [];
|
||||||
|
|
||||||
@ -220,14 +229,21 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck,
|
|||||||
}
|
}
|
||||||
|
|
||||||
constructor(private elementRef: ElementRef,
|
constructor(private elementRef: ElementRef,
|
||||||
differs: IterableDiffers) {
|
differs: IterableDiffers,
|
||||||
|
private matIconRegistry: MatIconRegistry,
|
||||||
|
private sanitizer: DomSanitizer) {
|
||||||
if (differs) {
|
if (differs) {
|
||||||
this.differ = differs.find([]).create(null);
|
this.differ = differs.find([]).create(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.click$ = new Observable<DataRowEvent>((observer) => this.clickObserver = observer)
|
this.click$ = new Observable<DataRowEvent>((observer) => this.clickObserver = observer)
|
||||||
.pipe(share());
|
.pipe(share());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.registerDragHandleIcon();
|
||||||
|
}
|
||||||
|
|
||||||
ngAfterContentInit() {
|
ngAfterContentInit() {
|
||||||
if (this.columnList) {
|
if (this.columnList) {
|
||||||
this.subscriptions.push(
|
this.subscriptions.push(
|
||||||
@ -260,13 +276,18 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck,
|
|||||||
if (dataChanges) {
|
if (dataChanges) {
|
||||||
this.data = changes['data'].currentValue;
|
this.data = changes['data'].currentValue;
|
||||||
this.resetSelection();
|
this.resetSelection();
|
||||||
} else if (rowChanges) {
|
}
|
||||||
|
|
||||||
|
if (rowChanges) {
|
||||||
this.setTableRows(changes['rows'].currentValue);
|
this.setTableRows(changes['rows'].currentValue);
|
||||||
this.setTableSorting(this.sorting);
|
this.setTableSorting(this.sorting);
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
if (columnChanges) {
|
||||||
this.setTableColumns(changes['columns'].currentValue);
|
this.setTableColumns(changes['columns'].currentValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,6 +312,14 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck,
|
|||||||
return column.key === this.data.getSorting().key;
|
return column.key === this.data.getSorting().key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onDropHeaderColumn(event: CdkDragDrop<unknown>): void {
|
||||||
|
const columns = this.data.getColumns();
|
||||||
|
moveItemInArray(columns, event.previousIndex, event.currentIndex);
|
||||||
|
|
||||||
|
this.columnOrderChanged.emit(columns);
|
||||||
|
this.isDraggingHeaderColumn = false;
|
||||||
|
}
|
||||||
|
|
||||||
ngDoCheck() {
|
ngDoCheck() {
|
||||||
const changes = this.differ.diff(this.rows);
|
const changes = this.differ.diff(this.rows);
|
||||||
if (changes) {
|
if (changes) {
|
||||||
@ -849,6 +878,18 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck,
|
|||||||
'ADF-DATATABLE.ACCESSIBILITY.SORT_ASCENDING_BY' :
|
'ADF-DATATABLE.ACCESSIBILITY.SORT_ASCENDING_BY' :
|
||||||
'ADF-DATATABLE.ACCESSIBILITY.SORT_DESCENDING_BY';
|
'ADF-DATATABLE.ACCESSIBILITY.SORT_DESCENDING_BY';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private registerDragHandleIcon(): void {
|
||||||
|
const iconUrl = this.sanitizer.bypassSecurityTrustResourceUrl(
|
||||||
|
'./assets/images/drag_indicator_24px.svg'
|
||||||
|
);
|
||||||
|
|
||||||
|
this.matIconRegistry.addSvgIconInNamespace(
|
||||||
|
'adf',
|
||||||
|
'drag_indicator',
|
||||||
|
iconUrl
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DataTableDropEvent {
|
export interface DataTableDropEvent {
|
||||||
|
@ -30,6 +30,7 @@ export interface DataColumnTypes {
|
|||||||
export type DataColumnType = keyof DataColumnTypes;
|
export type DataColumnType = keyof DataColumnTypes;
|
||||||
|
|
||||||
export interface DataColumn {
|
export interface DataColumn {
|
||||||
|
id?: string;
|
||||||
key: string;
|
key: string;
|
||||||
type: DataColumnType;
|
type: DataColumnType;
|
||||||
format?: string;
|
format?: string;
|
||||||
@ -44,4 +45,5 @@ export interface DataColumn {
|
|||||||
focus?: boolean;
|
focus?: boolean;
|
||||||
sortingKey?: string;
|
sortingKey?: string;
|
||||||
header?: TemplateRef<any>;
|
header?: TemplateRef<any>;
|
||||||
|
draggable?: boolean;
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { ContentChild, Input, Directive } from '@angular/core';
|
import { ContentChild, Input, Directive } from '@angular/core';
|
||||||
|
import { ReplaySubject } from 'rxjs';
|
||||||
import { AppConfigService } from '../../app-config/app-config.service';
|
import { AppConfigService } from '../../app-config/app-config.service';
|
||||||
import { DataColumnListComponent } from '../../data-column/data-column-list.component';
|
import { DataColumnListComponent } from '../../data-column/data-column-list.component';
|
||||||
import { DataColumn } from './data-column.model';
|
import { DataColumn } from './data-column.model';
|
||||||
@ -34,19 +35,34 @@ export abstract class DataTableSchema {
|
|||||||
|
|
||||||
columns: any;
|
columns: any;
|
||||||
|
|
||||||
|
protected columnsOrder: string[] | undefined;
|
||||||
|
protected columnsOrderedByKey: string = 'id';
|
||||||
|
|
||||||
private layoutPresets = {};
|
private layoutPresets = {};
|
||||||
|
|
||||||
|
private columnsSchemaSubject$ = new ReplaySubject<boolean>();
|
||||||
|
isColumnSchemaCreated$ = this.columnsSchemaSubject$.asObservable();
|
||||||
|
|
||||||
constructor(private appConfigService: AppConfigService,
|
constructor(private appConfigService: AppConfigService,
|
||||||
protected presetKey: string,
|
protected presetKey: string,
|
||||||
protected presetsModel: any) { }
|
protected presetsModel: any) { }
|
||||||
|
|
||||||
public createDatatableSchema(): void {
|
public createDatatableSchema(): void {
|
||||||
this.loadLayoutPresets();
|
this.loadLayoutPresets();
|
||||||
|
|
||||||
if (!this.columns || this.columns.length === 0) {
|
if (!this.columns || this.columns.length === 0) {
|
||||||
this.columns = this.mergeJsonAndHtmlSchema();
|
this.createColumns();
|
||||||
|
this.columnsSchemaSubject$.next(true);
|
||||||
|
} else {
|
||||||
|
this.columnsSchemaSubject$.next(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public createColumns(): void {
|
||||||
|
const columns = this.mergeJsonAndHtmlSchema();
|
||||||
|
this.columns = this.sortColumnsByKey(columns);
|
||||||
|
}
|
||||||
|
|
||||||
public loadLayoutPresets(): void {
|
public loadLayoutPresets(): void {
|
||||||
const externalSettings = this.appConfigService.get(this.presetKey, null);
|
const externalSettings = this.appConfigService.get(this.presetKey, null);
|
||||||
if (externalSettings) {
|
if (externalSettings) {
|
||||||
@ -57,10 +73,18 @@ export abstract class DataTableSchema {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public mergeJsonAndHtmlSchema(): any {
|
public mergeJsonAndHtmlSchema(): any {
|
||||||
let customSchemaColumns = this.getSchemaFromConfig(this.presetColumn).concat(this.getSchemaFromHtml(this.columnList));
|
const configSchemaColumns = this.getSchemaFromConfig(this.presetColumn);
|
||||||
|
const htmlSchemaColumns = this.getSchemaFromHtml(this.columnList);
|
||||||
|
|
||||||
|
let customSchemaColumns = [
|
||||||
|
...configSchemaColumns,
|
||||||
|
...htmlSchemaColumns
|
||||||
|
];
|
||||||
|
|
||||||
if (customSchemaColumns.length === 0) {
|
if (customSchemaColumns.length === 0) {
|
||||||
customSchemaColumns = this.getDefaultLayoutPreset();
|
customSchemaColumns = this.getDefaultLayoutPreset();
|
||||||
}
|
}
|
||||||
|
|
||||||
return customSchemaColumns;
|
return customSchemaColumns;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,4 +111,20 @@ export abstract class DataTableSchema {
|
|||||||
public setPresetsModel(presetsModel: any) {
|
public setPresetsModel(presetsModel: any) {
|
||||||
this.presetsModel = presetsModel;
|
this.presetsModel = presetsModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private sortColumnsByKey(columns: any[]): any[] {
|
||||||
|
const defaultColumns = [...columns];
|
||||||
|
const columnsWithProperOrder = [];
|
||||||
|
|
||||||
|
(this.columnsOrder ?? []).forEach(columnKey => {
|
||||||
|
const originalColumnIndex = defaultColumns.findIndex(defaultColumn => defaultColumn[this.columnsOrderedByKey] === columnKey);
|
||||||
|
|
||||||
|
if (originalColumnIndex > -1) {
|
||||||
|
columnsWithProperOrder.push(defaultColumns[originalColumnIndex]);
|
||||||
|
defaultColumns.splice(originalColumnIndex, 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return [...columnsWithProperOrder, ...defaultColumns];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ import { DataColumn, DataColumnType } from './data-column.model';
|
|||||||
|
|
||||||
// Simple implementation of the DataColumn interface.
|
// Simple implementation of the DataColumn interface.
|
||||||
export class ObjectDataColumn implements DataColumn {
|
export class ObjectDataColumn implements DataColumn {
|
||||||
|
id?: string;
|
||||||
key: string;
|
key: string;
|
||||||
type: DataColumnType;
|
type: DataColumnType;
|
||||||
format: string;
|
format: string;
|
||||||
@ -33,8 +33,10 @@ export class ObjectDataColumn implements DataColumn {
|
|||||||
focus?: boolean;
|
focus?: boolean;
|
||||||
sortingKey?: string;
|
sortingKey?: string;
|
||||||
header?: TemplateRef<any>;
|
header?: TemplateRef<any>;
|
||||||
|
draggable: boolean;
|
||||||
|
|
||||||
constructor(input: any) {
|
constructor(input: any) {
|
||||||
|
this.id = input.id ?? '';
|
||||||
this.key = input.key;
|
this.key = input.key;
|
||||||
this.type = input.type || 'text';
|
this.type = input.type || 'text';
|
||||||
this.format = input.format;
|
this.format = input.format;
|
||||||
@ -47,5 +49,6 @@ export class ObjectDataColumn implements DataColumn {
|
|||||||
this.focus = input.focus;
|
this.focus = input.focus;
|
||||||
this.sortingKey = input.sortingKey;
|
this.sortingKey = input.sortingKey;
|
||||||
this.header = input.header;
|
this.header = input.header;
|
||||||
|
this.draggable = input.draggable ?? false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,8 @@ import { JsonCellComponent } from './components/json-cell/json-cell.component';
|
|||||||
import { ClipboardModule } from '../clipboard/clipboard.module';
|
import { ClipboardModule } from '../clipboard/clipboard.module';
|
||||||
import { DropZoneDirective } from './directives/drop-zone.directive';
|
import { DropZoneDirective } from './directives/drop-zone.directive';
|
||||||
import { DataColumnModule } from '../data-column/data-column.module';
|
import { DataColumnModule } from '../data-column/data-column.module';
|
||||||
|
import { DragDropModule } from '@angular/cdk/drag-drop';
|
||||||
|
import { IconModule } from '../icon/icon.module';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
@ -57,7 +59,9 @@ import { DataColumnModule } from '../data-column/data-column.module';
|
|||||||
ContextMenuModule,
|
ContextMenuModule,
|
||||||
PipeModule,
|
PipeModule,
|
||||||
DirectiveModule,
|
DirectiveModule,
|
||||||
ClipboardModule
|
ClipboardModule,
|
||||||
|
DragDropModule,
|
||||||
|
IconModule
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
DataTableComponent,
|
DataTableComponent,
|
||||||
@ -101,6 +105,5 @@ import { DataColumnModule } from '../data-column/data-column.module';
|
|||||||
CustomNoPermissionTemplateDirective,
|
CustomNoPermissionTemplateDirective,
|
||||||
DropZoneDirective
|
DropZoneDirective
|
||||||
]
|
]
|
||||||
|
|
||||||
})
|
})
|
||||||
export class DataTableModule {}
|
export class DataTableModule {}
|
||||||
|
@ -27,7 +27,9 @@ import {
|
|||||||
LocalPreferenceCloudService,
|
LocalPreferenceCloudService,
|
||||||
PreferenceCloudServiceInterface,
|
PreferenceCloudServiceInterface,
|
||||||
PROCESS_FILTERS_SERVICE_TOKEN,
|
PROCESS_FILTERS_SERVICE_TOKEN,
|
||||||
TASK_FILTERS_SERVICE_TOKEN
|
TASK_FILTERS_SERVICE_TOKEN,
|
||||||
|
PROCESS_LISTS_PREFERENCES_SERVICE_TOKEN,
|
||||||
|
TASK_LIST_PREFERENCES_SERVICE_TOKEN
|
||||||
} from './services/public-api';
|
} from './services/public-api';
|
||||||
import { PeopleCloudModule } from './people/people-cloud.module';
|
import { PeopleCloudModule } from './people/people-cloud.module';
|
||||||
import { CloudFormRenderingService } from './form/components/cloud-form-rendering.service';
|
import { CloudFormRenderingService } from './form/components/cloud-form-rendering.service';
|
||||||
@ -67,7 +69,10 @@ import { ProcessServicesCloudPipeModule } from './pipes/process-services-cloud-p
|
|||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class ProcessServicesCloudModule {
|
export class ProcessServicesCloudModule {
|
||||||
static forRoot(preferenceServiceInstance?: PreferenceCloudServiceInterface): ModuleWithProviders<ProcessServicesCloudModule> {
|
static forRoot(
|
||||||
|
filterPreferenceServiceInstance?: PreferenceCloudServiceInterface,
|
||||||
|
listPreferenceServiceInstance?: PreferenceCloudServiceInterface
|
||||||
|
): ModuleWithProviders<ProcessServicesCloudModule> {
|
||||||
return {
|
return {
|
||||||
ngModule: ProcessServicesCloudModule,
|
ngModule: ProcessServicesCloudModule,
|
||||||
providers: [
|
providers: [
|
||||||
@ -79,8 +84,10 @@ export class ProcessServicesCloudModule {
|
|||||||
source: 'assets/adf-process-services-cloud'
|
source: 'assets/adf-process-services-cloud'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ provide: PROCESS_FILTERS_SERVICE_TOKEN, useExisting: preferenceServiceInstance ?? LocalPreferenceCloudService },
|
{ provide: PROCESS_FILTERS_SERVICE_TOKEN, useExisting: filterPreferenceServiceInstance ?? LocalPreferenceCloudService },
|
||||||
{ provide: TASK_FILTERS_SERVICE_TOKEN, useExisting: preferenceServiceInstance ?? LocalPreferenceCloudService },
|
{ provide: TASK_FILTERS_SERVICE_TOKEN, useExisting: filterPreferenceServiceInstance ?? LocalPreferenceCloudService },
|
||||||
|
{ provide: PROCESS_LISTS_PREFERENCES_SERVICE_TOKEN, useExisting: listPreferenceServiceInstance ?? LocalPreferenceCloudService },
|
||||||
|
{ provide: TASK_LIST_PREFERENCES_SERVICE_TOKEN, useExisting: listPreferenceServiceInstance ?? LocalPreferenceCloudService },
|
||||||
FormRenderingService,
|
FormRenderingService,
|
||||||
{ provide: FormRenderingService, useClass: CloudFormRenderingService }
|
{ provide: FormRenderingService, useClass: CloudFormRenderingService }
|
||||||
]
|
]
|
||||||
|
@ -16,7 +16,8 @@
|
|||||||
(row-select)="onRowSelect($any($event))"
|
(row-select)="onRowSelect($any($event))"
|
||||||
(row-unselect)="onRowUnselect($any($event))"
|
(row-unselect)="onRowUnselect($any($event))"
|
||||||
(row-keyup)="onRowKeyUp($any($event))"
|
(row-keyup)="onRowKeyUp($any($event))"
|
||||||
(sorting-changed)="onSortingChanged($any($event))">
|
(sorting-changed)="onSortingChanged($any($event))"
|
||||||
|
(columnOrderChanged)="onColumnOrderChanged($event)">
|
||||||
<adf-loading-content-template>
|
<adf-loading-content-template>
|
||||||
<ng-template>
|
<ng-template>
|
||||||
<mat-progress-spinner
|
<mat-progress-spinner
|
||||||
|
@ -27,7 +27,7 @@ import { ProcessListCloudService } from '../services/process-list-cloud.service'
|
|||||||
import { ProcessListCloudComponent } from './process-list-cloud.component';
|
import { ProcessListCloudComponent } from './process-list-cloud.component';
|
||||||
import { fakeCustomSchema, fakeProcessCloudList, processListSchemaMock } from '../mock/process-list-service.mock';
|
import { fakeCustomSchema, fakeProcessCloudList, processListSchemaMock } from '../mock/process-list-service.mock';
|
||||||
import { of } from 'rxjs';
|
import { of } from 'rxjs';
|
||||||
import { skip } from 'rxjs/operators';
|
import { shareReplay, skip } from 'rxjs/operators';
|
||||||
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
|
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
import { ProcessListCloudSortingModel } from '../models/process-list-sorting.model';
|
import { ProcessListCloudSortingModel } from '../models/process-list-sorting.model';
|
||||||
@ -102,6 +102,8 @@ describe('ProcessListCloudComponent', () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
component.isColumnSchemaCreated$ = of(true).pipe(shareReplay(1));
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => fixture.destroy());
|
afterEach(() => fixture.destroy());
|
||||||
|
@ -15,16 +15,20 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Component, ViewEncapsulation, OnChanges, AfterContentInit, ContentChild, Output, EventEmitter, SimpleChanges, Input, ViewChild } from '@angular/core';
|
import { Component, ViewEncapsulation, OnChanges, AfterContentInit, ContentChild, Output, EventEmitter, SimpleChanges, Input, ViewChild, Inject } from '@angular/core';
|
||||||
import { DataTableSchema, PaginatedComponent,
|
import { DataTableSchema, PaginatedComponent,
|
||||||
CustomEmptyContentTemplateDirective, AppConfigService,
|
CustomEmptyContentTemplateDirective, AppConfigService,
|
||||||
UserPreferencesService, PaginationModel,
|
UserPreferencesService, PaginationModel,
|
||||||
UserPreferenceValues, DataRowEvent, CustomLoadingContentTemplateDirective, DataCellEvent, DataRowActionEvent, DataTableComponent } from '@alfresco/adf-core';
|
UserPreferenceValues, DataRowEvent, CustomLoadingContentTemplateDirective, DataCellEvent, DataRowActionEvent, DataTableComponent, DataColumn } from '@alfresco/adf-core';
|
||||||
import { ProcessListCloudService } from '../services/process-list-cloud.service';
|
import { ProcessListCloudService } from '../services/process-list-cloud.service';
|
||||||
import { BehaviorSubject } from 'rxjs';
|
import { BehaviorSubject, combineLatest } from 'rxjs';
|
||||||
import { processCloudPresetsDefaultModel } from '../models/process-cloud-preset.model';
|
import { processCloudPresetsDefaultModel } from '../models/process-cloud-preset.model';
|
||||||
import { ProcessQueryCloudRequestModel } from '../models/process-cloud-query-request.model';
|
import { ProcessQueryCloudRequestModel } from '../models/process-cloud-query-request.model';
|
||||||
import { ProcessListCloudSortingModel } from '../models/process-list-sorting.model';
|
import { ProcessListCloudSortingModel } from '../models/process-list-sorting.model';
|
||||||
|
import { map, take } from 'rxjs/operators';
|
||||||
|
import { PreferenceCloudServiceInterface } from '../../../services/preference-cloud.interface';
|
||||||
|
import { PROCESS_LISTS_PREFERENCES_SERVICE_TOKEN } from '../../../services/cloud-token.service';
|
||||||
|
import { ProcessListCloudPreferences } from '../models/process-cloud-preferences';
|
||||||
|
|
||||||
const PRESET_KEY = 'adf-cloud-process-list.presets';
|
const PRESET_KEY = 'adf-cloud-process-list.presets';
|
||||||
|
|
||||||
@ -189,14 +193,17 @@ export class ProcessListCloudComponent extends DataTableSchema implements OnChan
|
|||||||
currentInstanceId: string;
|
currentInstanceId: string;
|
||||||
selectedInstances: any[];
|
selectedInstances: any[];
|
||||||
isLoading = true;
|
isLoading = true;
|
||||||
|
|
||||||
rows: any[] = [];
|
rows: any[] = [];
|
||||||
formattedSorting: any[];
|
formattedSorting: any[];
|
||||||
requestNode: ProcessQueryCloudRequestModel;
|
requestNode: ProcessQueryCloudRequestModel;
|
||||||
|
|
||||||
private defaultSorting = { key: 'startDate', direction: 'desc' };
|
private defaultSorting = { key: 'startDate', direction: 'desc' };
|
||||||
|
|
||||||
constructor(private processListCloudService: ProcessListCloudService,
|
constructor(private processListCloudService: ProcessListCloudService,
|
||||||
appConfigService: AppConfigService,
|
appConfigService: AppConfigService,
|
||||||
private userPreferences: UserPreferencesService) {
|
private userPreferences: UserPreferencesService,
|
||||||
|
@Inject(PROCESS_LISTS_PREFERENCES_SERVICE_TOKEN) private cloudPreferenceService: PreferenceCloudServiceInterface) {
|
||||||
super(appConfigService, PRESET_KEY, processCloudPresetsDefaultModel);
|
super(appConfigService, PRESET_KEY, processCloudPresetsDefaultModel);
|
||||||
this.size = userPreferences.paginationSize;
|
this.size = userPreferences.paginationSize;
|
||||||
this.userPreferences.select(UserPreferenceValues.PaginationSize).subscribe((pageSize) => {
|
this.userPreferences.select(UserPreferenceValues.PaginationSize).subscribe((pageSize) => {
|
||||||
@ -210,7 +217,23 @@ export class ProcessListCloudComponent extends DataTableSchema implements OnChan
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngAfterContentInit() {
|
ngAfterContentInit() {
|
||||||
this.createDatatableSchema();
|
this.cloudPreferenceService.getPreferences(this.appName)
|
||||||
|
.pipe(
|
||||||
|
take(1),
|
||||||
|
map((preferences => {
|
||||||
|
const preferencesList = preferences?.list?.entries ?? [];
|
||||||
|
const columnsOrder = preferencesList.find(preference => preference.entry.key === ProcessListCloudPreferences.columnOrder);
|
||||||
|
|
||||||
|
return {
|
||||||
|
columnsOrder: columnsOrder ? JSON.parse(columnsOrder.entry.value) : undefined
|
||||||
|
};
|
||||||
|
}))
|
||||||
|
)
|
||||||
|
.subscribe(({ columnsOrder }) => {
|
||||||
|
this.columnsOrder = columnsOrder;
|
||||||
|
|
||||||
|
this.createDatatableSchema();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnChanges(changes: SimpleChanges) {
|
ngOnChanges(changes: SimpleChanges) {
|
||||||
@ -237,16 +260,21 @@ export class ProcessListCloudComponent extends DataTableSchema implements OnChan
|
|||||||
|
|
||||||
private load(requestNode: ProcessQueryCloudRequestModel) {
|
private load(requestNode: ProcessQueryCloudRequestModel) {
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
this.processListCloudService.getProcessByRequest(requestNode).subscribe(
|
|
||||||
(processes) => {
|
combineLatest([
|
||||||
this.rows = processes.list.entries;
|
this.processListCloudService.getProcessByRequest(requestNode),
|
||||||
this.success.emit(processes);
|
this.isColumnSchemaCreated$
|
||||||
this.isLoading = false;
|
]).pipe(
|
||||||
this.pagination.next(processes.list.pagination);
|
take(1)
|
||||||
}, (error) => {
|
).subscribe(([processes]) => {
|
||||||
this.error.emit(error);
|
this.rows = processes.list.entries;
|
||||||
this.isLoading = false;
|
this.success.emit(processes);
|
||||||
});
|
this.isLoading = false;
|
||||||
|
this.pagination.next(processes.list.pagination);
|
||||||
|
}, (error) => {
|
||||||
|
this.error.emit(error);
|
||||||
|
this.isLoading = false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private isAnyPropertyChanged(changes: SimpleChanges): boolean {
|
private isAnyPropertyChanged(changes: SimpleChanges): boolean {
|
||||||
@ -297,6 +325,17 @@ export class ProcessListCloudComponent extends DataTableSchema implements OnChan
|
|||||||
this.reload();
|
this.reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onColumnOrderChanged(columnsWithNewOrder: DataColumn[]): void {
|
||||||
|
if (this.appName) {
|
||||||
|
const newColumnsOrder = columnsWithNewOrder.map(column => column.id);
|
||||||
|
this.cloudPreferenceService.updatePreference(
|
||||||
|
this.appName,
|
||||||
|
ProcessListCloudPreferences.columnOrder,
|
||||||
|
newColumnsOrder
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onRowClick(item: DataRowEvent) {
|
onRowClick(item: DataRowEvent) {
|
||||||
this.currentInstanceId = item.value.getValue('id');
|
this.currentInstanceId = item.value.getValue('id');
|
||||||
this.rowClick.emit(this.currentInstanceId);
|
this.rowClick.emit(this.currentInstanceId);
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
// eslint-disable-next-line no-shadow
|
||||||
|
export enum ProcessListCloudPreferences {
|
||||||
|
columnOrder = 'processes-cloud-list-columns-order'
|
||||||
|
}
|
@ -20,6 +20,7 @@ export * from './components/process-list-cloud.component';
|
|||||||
export * from './models/process-cloud-query-request.model';
|
export * from './models/process-cloud-query-request.model';
|
||||||
export * from './models/process-cloud-preset.model';
|
export * from './models/process-cloud-preset.model';
|
||||||
export * from './models/process-list-sorting.model';
|
export * from './models/process-list-sorting.model';
|
||||||
|
export * from './models/process-cloud-preferences';
|
||||||
|
|
||||||
export * from './services/process-list-cloud.service';
|
export * from './services/process-list-cloud.service';
|
||||||
export * from './services/process-task-list-cloud.service';
|
export * from './services/process-task-list-cloud.service';
|
||||||
|
@ -19,6 +19,10 @@ import { InjectionToken } from '@angular/core';
|
|||||||
import { PreferenceCloudServiceInterface } from './preference-cloud.interface';
|
import { PreferenceCloudServiceInterface } from './preference-cloud.interface';
|
||||||
import { TaskListCloudServiceInterface } from './task-list-cloud.service.interface';
|
import { TaskListCloudServiceInterface } from './task-list-cloud.service.interface';
|
||||||
|
|
||||||
|
export const PROCESS_LISTS_PREFERENCES_SERVICE_TOKEN = new InjectionToken<PreferenceCloudServiceInterface>('proccesses-list-preferences-cloud');
|
||||||
|
|
||||||
|
export const TASK_LIST_PREFERENCES_SERVICE_TOKEN = new InjectionToken<PreferenceCloudServiceInterface>('tasks-list-preferences-cloud');
|
||||||
|
|
||||||
export const PROCESS_FILTERS_SERVICE_TOKEN = new InjectionToken<PreferenceCloudServiceInterface>('proccess-filters-cloud');
|
export const PROCESS_FILTERS_SERVICE_TOKEN = new InjectionToken<PreferenceCloudServiceInterface>('proccess-filters-cloud');
|
||||||
|
|
||||||
export const TASK_FILTERS_SERVICE_TOKEN = new InjectionToken<PreferenceCloudServiceInterface>('task-filters-cloud');
|
export const TASK_FILTERS_SERVICE_TOKEN = new InjectionToken<PreferenceCloudServiceInterface>('task-filters-cloud');
|
||||||
|
@ -18,11 +18,9 @@
|
|||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
export interface PreferenceCloudServiceInterface {
|
export interface PreferenceCloudServiceInterface {
|
||||||
|
|
||||||
getPreferences(appName: string, key?: string): Observable<any>;
|
getPreferences(appName: string, key?: string): Observable<any>;
|
||||||
getPreferenceByKey(appName: string, key: string): Observable<any>;
|
getPreferenceByKey(appName: string, key: string): Observable<any>;
|
||||||
createPreference(appName: string, key: string, newPreference: any): Observable<any>;
|
createPreference(appName: string, key: string, newPreference: any): Observable<any>;
|
||||||
updatePreference(appName: string, key: string, updatedPreference: any): Observable<any>;
|
updatePreference(appName: string, key: string, updatedPreference: any): Observable<any>;
|
||||||
deletePreference(appName: string, key: any): Observable<any>;
|
deletePreference(appName: string, key: string): Observable<any>;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,8 @@
|
|||||||
(row-unselect)="onRowUnselect($any($event))"
|
(row-unselect)="onRowUnselect($any($event))"
|
||||||
(rowClick)="onRowClick($any($event))"
|
(rowClick)="onRowClick($any($event))"
|
||||||
(row-keyup)="onRowKeyUp($any($event))"
|
(row-keyup)="onRowKeyUp($any($event))"
|
||||||
(sorting-changed)="onSortingChanged($any($event))">
|
(sorting-changed)="onSortingChanged($any($event))"
|
||||||
|
(columnOrderChanged)="onColumnOrderChanged($event)">
|
||||||
<adf-loading-content-template>
|
<adf-loading-content-template>
|
||||||
<ng-template>
|
<ng-template>
|
||||||
<!-- Add your custom loading template here -->
|
<!-- Add your custom loading template here -->
|
||||||
|
@ -26,8 +26,10 @@ import { taskPresetsCloudDefaultModel } from '../models/task-preset-cloud.model'
|
|||||||
import { TaskQueryCloudRequestModel } from '../../../models/filter-cloud-model';
|
import { TaskQueryCloudRequestModel } from '../../../models/filter-cloud-model';
|
||||||
import { BehaviorSubject, Subject } from 'rxjs';
|
import { BehaviorSubject, Subject } from 'rxjs';
|
||||||
import { TaskListCloudSortingModel } from '../../../models/task-list-sorting.model';
|
import { TaskListCloudSortingModel } from '../../../models/task-list-sorting.model';
|
||||||
import { takeUntil } from 'rxjs/operators';
|
import { map, take, takeUntil } from 'rxjs/operators';
|
||||||
import { TaskCloudService } from '../../services/task-cloud.service';
|
import { TaskCloudService } from '../../services/task-cloud.service';
|
||||||
|
import { PreferenceCloudServiceInterface } from '../../../services/preference-cloud.interface';
|
||||||
|
import { TasksListCloudPreferences } from '../models/tasks-cloud-preferences';
|
||||||
|
|
||||||
@Directive()
|
@Directive()
|
||||||
// eslint-disable-next-line @angular-eslint/directive-class-suffix
|
// eslint-disable-next-line @angular-eslint/directive-class-suffix
|
||||||
@ -120,7 +122,8 @@ export abstract class BaseTaskListCloudComponent extends DataTableSchema impleme
|
|||||||
constructor(appConfigService: AppConfigService,
|
constructor(appConfigService: AppConfigService,
|
||||||
private taskCloudService: TaskCloudService,
|
private taskCloudService: TaskCloudService,
|
||||||
private userPreferences: UserPreferencesService,
|
private userPreferences: UserPreferencesService,
|
||||||
presetKey: string) {
|
presetKey: string,
|
||||||
|
private cloudPreferenceService: PreferenceCloudServiceInterface) {
|
||||||
super(appConfigService, presetKey, taskPresetsCloudDefaultModel);
|
super(appConfigService, presetKey, taskPresetsCloudDefaultModel);
|
||||||
this.size = userPreferences.paginationSize;
|
this.size = userPreferences.paginationSize;
|
||||||
|
|
||||||
@ -153,7 +156,18 @@ export abstract class BaseTaskListCloudComponent extends DataTableSchema impleme
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngAfterContentInit() {
|
ngAfterContentInit() {
|
||||||
this.createDatatableSchema();
|
this.cloudPreferenceService.getPreferences(this.appName).pipe(
|
||||||
|
take(1),
|
||||||
|
map((preferences => {
|
||||||
|
const preferencesList = preferences?.list?.entries ?? [];
|
||||||
|
const searchedPreferences = preferencesList.find(preference => preference.entry.key === TasksListCloudPreferences.columnOrder);
|
||||||
|
return searchedPreferences ? JSON.parse(searchedPreferences.entry.value) : null;
|
||||||
|
}))
|
||||||
|
).subscribe(columnsOrder => {
|
||||||
|
this.columnsOrder = columnsOrder;
|
||||||
|
this.createDatatableSchema();
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
reload() {
|
reload() {
|
||||||
@ -235,6 +249,18 @@ export abstract class BaseTaskListCloudComponent extends DataTableSchema impleme
|
|||||||
this.executeRowAction.emit(row);
|
this.executeRowAction.emit(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onColumnOrderChanged(columnsWithNewOrder: DataColumn[]): void {
|
||||||
|
this.columnsOrder = columnsWithNewOrder.map(column => column.id);
|
||||||
|
|
||||||
|
if (this.appName) {
|
||||||
|
this.cloudPreferenceService.updatePreference(
|
||||||
|
this.appName,
|
||||||
|
TasksListCloudPreferences.columnOrder,
|
||||||
|
this.columnsOrder
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setSorting(sortDetail) {
|
setSorting(sortDetail) {
|
||||||
const sorting = sortDetail ? {
|
const sorting = sortDetail ? {
|
||||||
orderBy: sortDetail.key,
|
orderBy: sortDetail.key,
|
||||||
|
@ -25,7 +25,7 @@ import { of } from 'rxjs';
|
|||||||
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
|
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
import { TaskListCloudSortingModel } from '../../../models/task-list-sorting.model';
|
import { TaskListCloudSortingModel } from '../../../models/task-list-sorting.model';
|
||||||
import { skip } from 'rxjs/operators';
|
import { shareReplay, skip } from 'rxjs/operators';
|
||||||
import { ServiceTaskListCloudService } from '../services/service-task-list-cloud.service';
|
import { ServiceTaskListCloudService } from '../services/service-task-list-cloud.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -111,6 +111,8 @@ describe('ServiceTaskListCloudComponent', () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
component.isColumnSchemaCreated$ = of(true).pipe(shareReplay(1));
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@ -384,6 +386,8 @@ describe('ServiceTaskListCloudComponent', () => {
|
|||||||
componentCustom = fixtureCustom.componentInstance;
|
componentCustom = fixtureCustom.componentInstance;
|
||||||
customCopyComponent = copyFixture.componentInstance;
|
customCopyComponent = copyFixture.componentInstance;
|
||||||
element = copyFixture.debugElement.nativeElement;
|
element = copyFixture.debugElement.nativeElement;
|
||||||
|
|
||||||
|
customCopyComponent.taskList.isColumnSchemaCreated$ = of(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Component, ViewEncapsulation, Input } from '@angular/core';
|
import { Component, ViewEncapsulation, Input, Inject } from '@angular/core';
|
||||||
import {
|
import {
|
||||||
AppConfigService, UserPreferencesService
|
AppConfigService, UserPreferencesService
|
||||||
} from '@alfresco/adf-core';
|
} from '@alfresco/adf-core';
|
||||||
@ -23,6 +23,9 @@ import { ServiceTaskQueryCloudRequestModel } from '../models/service-task-cloud.
|
|||||||
import { BaseTaskListCloudComponent } from './base-task-list-cloud.component';
|
import { BaseTaskListCloudComponent } from './base-task-list-cloud.component';
|
||||||
import { ServiceTaskListCloudService } from '../services/service-task-list-cloud.service';
|
import { ServiceTaskListCloudService } from '../services/service-task-list-cloud.service';
|
||||||
import { TaskCloudService } from '../../services/task-cloud.service';
|
import { TaskCloudService } from '../../services/task-cloud.service';
|
||||||
|
import { combineLatest } from 'rxjs';
|
||||||
|
import { PreferenceCloudServiceInterface, TASK_LIST_PREFERENCES_SERVICE_TOKEN } from '../../../services/public-api';
|
||||||
|
import { take } from 'rxjs/operators';
|
||||||
|
|
||||||
const PRESET_KEY = 'adf-cloud-service-task-list.presets';
|
const PRESET_KEY = 'adf-cloud-service-task-list.presets';
|
||||||
|
|
||||||
@ -39,14 +42,21 @@ export class ServiceTaskListCloudComponent extends BaseTaskListCloudComponent {
|
|||||||
constructor(private serviceTaskListCloudService: ServiceTaskListCloudService,
|
constructor(private serviceTaskListCloudService: ServiceTaskListCloudService,
|
||||||
appConfigService: AppConfigService,
|
appConfigService: AppConfigService,
|
||||||
taskCloudService: TaskCloudService,
|
taskCloudService: TaskCloudService,
|
||||||
userPreferences: UserPreferencesService) {
|
userPreferences: UserPreferencesService,
|
||||||
super(appConfigService, taskCloudService, userPreferences, PRESET_KEY);
|
@Inject(TASK_LIST_PREFERENCES_SERVICE_TOKEN) cloudPreferenceService: PreferenceCloudServiceInterface) {
|
||||||
|
super(appConfigService, taskCloudService, userPreferences, PRESET_KEY, cloudPreferenceService);
|
||||||
}
|
}
|
||||||
|
|
||||||
load(requestNode: ServiceTaskQueryCloudRequestModel) {
|
load(requestNode: ServiceTaskQueryCloudRequestModel) {
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
this.serviceTaskListCloudService.getServiceTaskByRequest(requestNode).subscribe(
|
|
||||||
(tasks) => {
|
combineLatest([
|
||||||
|
this.serviceTaskListCloudService.getServiceTaskByRequest(requestNode),
|
||||||
|
this.isColumnSchemaCreated$
|
||||||
|
]).pipe(
|
||||||
|
take(1)
|
||||||
|
).subscribe(
|
||||||
|
([tasks]) => {
|
||||||
this.rows = tasks.list.entries;
|
this.rows = tasks.list.entries;
|
||||||
this.success.emit(tasks);
|
this.success.emit(tasks);
|
||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
|
@ -26,7 +26,7 @@ import { of } from 'rxjs';
|
|||||||
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
|
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
import { TaskListCloudSortingModel } from '../../../models/task-list-sorting.model';
|
import { TaskListCloudSortingModel } from '../../../models/task-list-sorting.model';
|
||||||
import { skip } from 'rxjs/operators';
|
import { shareReplay, skip } from 'rxjs/operators';
|
||||||
import { TaskListCloudServiceInterface } from '../../../services/task-list-cloud.service.interface';
|
import { TaskListCloudServiceInterface } from '../../../services/task-list-cloud.service.interface';
|
||||||
import { TASK_LIST_CLOUD_TOKEN } from '../../../services/cloud-token.service';
|
import { TASK_LIST_CLOUD_TOKEN } from '../../../services/cloud-token.service';
|
||||||
|
|
||||||
@ -124,6 +124,8 @@ describe('TaskListCloudComponent', () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
component.isColumnSchemaCreated$ = of(true).pipe(shareReplay(1));
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@ -419,6 +421,8 @@ describe('TaskListCloudComponent', () => {
|
|||||||
componentCustom = fixtureCustom.componentInstance;
|
componentCustom = fixtureCustom.componentInstance;
|
||||||
customCopyComponent = copyFixture.componentInstance;
|
customCopyComponent = copyFixture.componentInstance;
|
||||||
element = copyFixture.debugElement.nativeElement;
|
element = copyFixture.debugElement.nativeElement;
|
||||||
|
|
||||||
|
customCopyComponent.taskList.isColumnSchemaCreated$ = of(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@ -542,7 +546,9 @@ describe('TaskListCloudComponent', () => {
|
|||||||
element = fixture.debugElement.nativeElement;
|
element = fixture.debugElement.nativeElement;
|
||||||
taskSpy = spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeGlobalTask));
|
taskSpy = spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeGlobalTask));
|
||||||
|
|
||||||
|
component.isColumnSchemaCreated$ = of(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
fixture.destroy();
|
fixture.destroy();
|
||||||
});
|
});
|
||||||
|
@ -20,8 +20,11 @@ import { AppConfigService, UserPreferencesService } from '@alfresco/adf-core';
|
|||||||
import { TaskQueryCloudRequestModel } from '../../../models/filter-cloud-model';
|
import { TaskQueryCloudRequestModel } from '../../../models/filter-cloud-model';
|
||||||
import { BaseTaskListCloudComponent } from './base-task-list-cloud.component';
|
import { BaseTaskListCloudComponent } from './base-task-list-cloud.component';
|
||||||
import { TaskCloudService } from '../../services/task-cloud.service';
|
import { TaskCloudService } from '../../services/task-cloud.service';
|
||||||
import { TASK_LIST_CLOUD_TOKEN } from '../../../services/cloud-token.service';
|
import { TASK_LIST_CLOUD_TOKEN, TASK_LIST_PREFERENCES_SERVICE_TOKEN } from '../../../services/cloud-token.service';
|
||||||
|
import { PreferenceCloudServiceInterface } from '../../../services/preference-cloud.interface';
|
||||||
import { TaskListCloudServiceInterface } from '../../../services/task-list-cloud.service.interface';
|
import { TaskListCloudServiceInterface } from '../../../services/task-list-cloud.service.interface';
|
||||||
|
import { combineLatest } from 'rxjs';
|
||||||
|
import { take } from 'rxjs/operators';
|
||||||
|
|
||||||
const PRESET_KEY = 'adf-cloud-task-list.presets';
|
const PRESET_KEY = 'adf-cloud-task-list.presets';
|
||||||
|
|
||||||
@ -135,14 +138,21 @@ export class TaskListCloudComponent extends BaseTaskListCloudComponent {
|
|||||||
constructor(@Inject(TASK_LIST_CLOUD_TOKEN) public taskListCloudService: TaskListCloudServiceInterface,
|
constructor(@Inject(TASK_LIST_CLOUD_TOKEN) public taskListCloudService: TaskListCloudServiceInterface,
|
||||||
appConfigService: AppConfigService,
|
appConfigService: AppConfigService,
|
||||||
taskCloudService: TaskCloudService,
|
taskCloudService: TaskCloudService,
|
||||||
userPreferences: UserPreferencesService) {
|
userPreferences: UserPreferencesService,
|
||||||
super(appConfigService, taskCloudService, userPreferences, PRESET_KEY);
|
@Inject(TASK_LIST_PREFERENCES_SERVICE_TOKEN) cloudPreferenceService: PreferenceCloudServiceInterface) {
|
||||||
|
super(appConfigService, taskCloudService, userPreferences, PRESET_KEY, cloudPreferenceService);
|
||||||
}
|
}
|
||||||
|
|
||||||
load(requestNode: TaskQueryCloudRequestModel) {
|
load(requestNode: TaskQueryCloudRequestModel) {
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
this.taskListCloudService.getTaskByRequest(requestNode).subscribe(
|
|
||||||
(tasks) => {
|
combineLatest([
|
||||||
|
this.taskListCloudService.getTaskByRequest(requestNode),
|
||||||
|
this.isColumnSchemaCreated$
|
||||||
|
]).pipe(
|
||||||
|
take(1)
|
||||||
|
).subscribe(
|
||||||
|
([tasks]) => {
|
||||||
this.rows = tasks.list.entries;
|
this.rows = tasks.list.entries;
|
||||||
this.success.emit(tasks);
|
this.success.emit(tasks);
|
||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
// eslint-disable-next-line no-shadow
|
||||||
|
export enum TasksListCloudPreferences {
|
||||||
|
columnOrder = 'tasks-list-cloud-columns-order'
|
||||||
|
}
|
@ -20,6 +20,7 @@ export * from './components/service-task-list-cloud.component';
|
|||||||
|
|
||||||
export * from './models/service-task-cloud.model';
|
export * from './models/service-task-cloud.model';
|
||||||
export * from './models/task-preset-cloud.model';
|
export * from './models/task-preset-cloud.model';
|
||||||
|
export * from './models/tasks-cloud-preferences';
|
||||||
|
|
||||||
export * from './services/task-list-cloud.service';
|
export * from './services/task-list-cloud.service';
|
||||||
export * from './services/service-task-list-cloud.service';
|
export * from './services/service-task-list-cloud.service';
|
||||||
|
@ -22,7 +22,7 @@ import { TaskListCloudComponent } from './components/task-list-cloud.component';
|
|||||||
import { ServiceTaskListCloudComponent } from './components/service-task-list-cloud.component';
|
import { ServiceTaskListCloudComponent } from './components/service-task-list-cloud.component';
|
||||||
import { CoreModule } from '@alfresco/adf-core';
|
import { CoreModule } from '@alfresco/adf-core';
|
||||||
import { TASK_LIST_CLOUD_TOKEN } from '../../services/cloud-token.service';
|
import { TASK_LIST_CLOUD_TOKEN } from '../../services/cloud-token.service';
|
||||||
import { TaskListCloudService } from './public-api';
|
import { TaskListCloudService } from './services/task-list-cloud.service';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
|
Loading…
x
Reference in New Issue
Block a user