[ADF-2322] Card view datatable and documentlist (#2968)

* move table in style

* Enable the cardview mode

* add button in demo shell to change view
add missing translation terms toolbar

* missing comma

* add example in demo shell

* style loading and images

* border card container

* document list tests

* test check class and input

* test fix

* fix test process services

* more documentation

* rirpristinate base pacakge integgration

* remove test color
This commit is contained in:
Eugenio Romano 2018-02-21 09:57:01 +00:00 committed by GitHub
parent ff887772e3
commit 62d5dd1b30
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 699 additions and 273 deletions

View File

@ -43,6 +43,7 @@
"DESCRIPTION_UPLOAD" : "Enable upload", "DESCRIPTION_UPLOAD" : "Enable upload",
"ENABLE_INFINITE_SCROLL":"Enable Infinite Scrolling", "ENABLE_INFINITE_SCROLL":"Enable Infinite Scrolling",
"MULTISELECT_DESCRIPTION" : "Use Cmd (Mac) or Ctrl (Windows) to toggle selection of multiple items", "MULTISELECT_DESCRIPTION" : "Use Cmd (Mac) or Ctrl (Windows) to toggle selection of multiple items",
"RECENT" : "Recent Files",
"COLUMNS": { "COLUMNS": {
"DISPLAY_NAME": "Display name", "DISPLAY_NAME": "Display name",
"TAG": "Tag", "TAG": "Tag",
@ -50,6 +51,13 @@
"CREATED_ON": "Created on", "CREATED_ON": "Created on",
"CREATED": "Created" "CREATED": "Created"
}, },
"TOOLBAR": {
"CARDVIEW":"Card view mode",
"NEW_FOLDER":"New folder",
"EDIT_FOLDER":"Edit folder",
"DOWNLOAD":"Download",
"DELETE":"Delete"
},
"ACTIONS": { "ACTIONS": {
"DOWNLOAD": "Download", "DOWNLOAD": "Download",
"FOLDER": { "FOLDER": {

View File

@ -1,15 +1,33 @@
<div class="container"> <div class="container">
<div class="adf-recent-container">
<mat-list>
<mat-list-item><mat-icon>history</mat-icon>{{ 'DOCUMENT_LIST.RECENT' | translate }}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<adf-document-list
[currentFolderId]="'-recent-'"
locationFormat="/files"
[cardview]="true"
[showHeader]="false"
[maxItems]="5"
(preview)="showFile($event)"
selectionMode="null">
</adf-document-list>
</div>
<div class="adf-site-container-style" id="site-container"> <div class="adf-site-container-style" id="site-container">
<adf-sites-dropdown (change)="getSiteContent($event)" [hideMyFiles]="false"> <adf-sites-dropdown (change)="getSiteContent($event)" [hideMyFiles]="false">
</adf-sites-dropdown> </adf-sites-dropdown>
</div> </div>
<div class="document-list-container" fxLayout="row" fxLayoutAlign="start stretch" fxLayoutGap="16px"> <div class="document-list-container" fxLayout="row" fxLayoutAlign="start stretch" fxLayoutGap="16px">
<adf-upload-drag-area fxFlex="1 1 auto" <adf-upload-drag-area fxFlex="1 1 auto"
[disabled]="disableDragArea" [disabled]="disableDragArea"
[parentId]="getDocumentListCurrentFolderId()" [parentId]="getDocumentListCurrentFolderId()"
[versioning]="versioning" [versioning]="versioning"
[adf-node-permission]="'create'" [adf-node-permission]="'create'"
[adf-nodes]="disableDragArea ? getCurrentDocumentListNode() : []"> [adf-nodes]="disableDragArea ? getCurrentDocumentListNode() : []">
<div *ngIf="errorMessage" class="error-message"> <div *ngIf="errorMessage" class="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>
@ -35,26 +53,35 @@
<adf-toolbar-divider fxFlex="0 0 auto"></adf-toolbar-divider> <adf-toolbar-divider fxFlex="0 0 auto"></adf-toolbar-divider>
<div fxFlex="0 0 auto" class="adf-document-action-buttons" fxShow fxHide.lt-sm="true"> <div fxFlex="0 0 auto" class="adf-document-action-buttons" fxShow fxHide.lt-sm="true">
<button
mat-icon-button
title="{{ 'DOCUMENT_LIST.TOOLBAR.CARDVIEW' | translate }}"
(click)="toogleCardview()">
<mat-icon>view_comfy</mat-icon>
</button>
<button <button
mat-icon-button mat-icon-button
[disabled]="!canCreateContent(documentList.folderNode)" [disabled]="!canCreateContent(documentList.folderNode)"
title="{{ 'DOCUMENT_LIST.TOOLBAR.NEW_FOLDER' | translate }}"
[adf-create-folder]="getDocumentListCurrentFolderId()"> [adf-create-folder]="getDocumentListCurrentFolderId()">
<mat-icon>create_new_folder</mat-icon> <mat-icon>create_new_folder</mat-icon>
</button> </button>
<button mat-icon-button <button mat-icon-button
[disabled]="!canEditFolder(documentList.selection)" [disabled]="!canEditFolder(documentList.selection)"
title="{{ 'DOCUMENT_LIST.TOOLBAR.EDIT_FOLDER' | translate }}"
[adf-edit-folder]="documentList.selection[0]?.entry"> [adf-edit-folder]="documentList.selection[0]?.entry">
<mat-icon>create</mat-icon> <mat-icon>create</mat-icon>
</button> </button>
<button mat-icon-button <button mat-icon-button
[disabled]="!hasSelection(documentList.selection)" [disabled]="!hasSelection(documentList.selection)"
title="Download" title="{{ 'DOCUMENT_LIST.TOOLBAR.DOWNLOAD' | translate }}"
[adfNodeDownload]="documentList.selection"> [adfNodeDownload]="documentList.selection">
<mat-icon>get_app</mat-icon> <mat-icon>get_app</mat-icon>
</button> </button>
<button mat-icon-button <button mat-icon-button
adf-node-permission="delete" adf-node-permission="delete"
[adf-nodes]="documentList.selection" [adf-nodes]="documentList.selection"
title="{{ 'DOCUMENT_LIST.TOOLBAR.DELETE' | translate }}"
(delete)="documentList.reload()" (delete)="documentList.reload()"
[adf-delete]="documentList.selection"> [adf-delete]="documentList.selection">
<mat-icon>delete</mat-icon> <mat-icon>delete</mat-icon>
@ -91,29 +118,34 @@
<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
(click)="toogleCardview()">
<mat-icon>view_comfy</mat-icon>
<span>{{ 'DOCUMENT_LIST.TOOLBAR.CARDVIEW' | translate }}</span>
</button>
<button mat-menu-item <button mat-menu-item
[adf-create-folder]="getDocumentListCurrentFolderId()"> [adf-create-folder]="getDocumentListCurrentFolderId()">
<mat-icon>create_new_folder</mat-icon> <mat-icon>create_new_folder</mat-icon>
<span>New folder</span> <span>{{ 'DOCUMENT_LIST.TOOLBAR.NEW_FOLDER' | translate }}</span>
</button> </button>
<button mat-menu-item <button mat-menu-item
[disabled]="!canEditFolder(documentList.selection)" [disabled]="!canEditFolder(documentList.selection)"
[adf-edit-folder]="documentList.selection[0]?.entry"> [adf-edit-folder]="documentList.selection[0]?.entry">
<mat-icon>create</mat-icon> <mat-icon>create</mat-icon>
<span>Edit folder</span> <span>{{ 'DOCUMENT_LIST.TOOLBAR.EDIT_FOLDER' | translate }}</span>
</button> </button>
<button mat-menu-item <button mat-menu-item
[disabled]="!hasSelection(documentList.selection)" [disabled]="!hasSelection(documentList.selection)"
title="Download" title="Download"
(click)="downloadNodes(documentList.selection)"> (click)="downloadNodes(documentList.selection)">
<mat-icon>get_app</mat-icon> <mat-icon>get_app</mat-icon>
<span>Download</span> <span>{{ 'DOCUMENT_LIST.TOOLBAR.DOWNLOAD' | translate }}</span>
</button> </button>
<button mat-menu-item <button mat-menu-item
adf-node-permission="delete" adf-node-permission="delete"
[adf-nodes]="documentList.selection"> [adf-nodes]="documentList.selection">
<mat-icon>delete</mat-icon> <mat-icon>delete</mat-icon>
<span>Delete</span> <span>{{ 'DOCUMENT_LIST.TOOLBAR.DELETE' | translate }}</span>
</button> </button>
</mat-menu> </mat-menu>
</adf-toolbar> </adf-toolbar>
@ -128,6 +160,7 @@
[allowDropFiles]="true" [allowDropFiles]="true"
[selectionMode]="selectionMode" [selectionMode]="selectionMode"
[multiselect]="multiselect" [multiselect]="multiselect"
[cardview]="cardview"
[node]="nodeResult" [node]="nodeResult"
(error)="onNavigationError($event)" (error)="onNavigationError($event)"
(success)="resetError()" (success)="resetError()"
@ -276,13 +309,13 @@
<ng-template #choose_document_template> <ng-template #choose_document_template>
<div class="adf-manage-versions-empty"> <div class="adf-manage-versions-empty">
<mat-icon class="adf-manage-versions-empty-icon">face</mat-icon> <mat-icon class="adf-manage-versions-empty-icon">face</mat-icon>
{{'VERSION.CHOOSE_FILE' | translate}} {{'VERSION.CHOOSE_FILE' | translate}}
</div> </div>
</ng-template> </ng-template>
<ng-template #no_permission_to_versions> <ng-template #no_permission_to_versions>
<div class="adf-manage-versions-no-permission"> <div class="adf-manage-versions-no-permission">
<mat-icon class="adf-manage-versions-no-permission-icon">warning</mat-icon> <mat-icon class="adf-manage-versions-no-permission-icon">warning</mat-icon>
{{'VERSION.NO_PERMISSION' | translate}} {{'VERSION.NO_PERMISSION' | translate}}
</div> </div>
</ng-template> </ng-template>
</div> </div>
@ -292,7 +325,7 @@
<context-menu-holder></context-menu-holder> <context-menu-holder></context-menu-holder>
<div *ngIf="processId" > <div *ngIf="processId">
<adf-start-process <adf-start-process
[values]="formValues" [values]="formValues"
[appId]="processId"> [appId]="processId">
@ -338,9 +371,9 @@
</section> </section>
<section> <section>
<mat-slide-toggle [color]="'primary'" [(ngModel)]="maxSizeShow">{{'DOCUMENT_LIST.MAX_SIZE' | <mat-slide-toggle [color]="'primary'" [(ngModel)]="maxSizeShow">{{'DOCUMENT_LIST.MAX_SIZE' |
translate}} translate}}
</mat-slide-toggle> </mat-slide-toggle>
</section> </section>
<section> <section>
@ -358,15 +391,15 @@
<h5>Upload</h5> <h5>Upload</h5>
<section *ngIf="acceptedFilesTypeShow"> <section *ngIf="acceptedFilesTypeShow">
<mat-form-field floatPlaceholder="float"> <mat-form-field floatPlaceholder="float">
<input matInput <input matInput
placeholder="Extension accepted" placeholder="Extension accepted"
[(ngModel)]="acceptedFilesType" [(ngModel)]="acceptedFilesType"
data-automation-id="accepted-files-type"> 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 matInput type="number" placeholder="Max file size" [(ngModel)]="maxFilesSize" <input matInput type="number" placeholder="Max file size" [(ngModel)]="maxFilesSize"
data-automation-id="max-files-size"> data-automation-id="max-files-size">
</mat-form-field> </mat-form-field>
</section> </section>

View File

@ -30,8 +30,8 @@ adf-document-list ::ng-deep adf-datatable tr.document-list__disable {
background: red !important; background: red !important;
} }
adf-document-list ::ng-deep adf-datatable > table > tbody > tr.is-selected > td.adf-data-table-cell.adf-data-table-cell--image.image-table-cell > div > div > mat-icon > svg { adf-document-list ::ng-deep .adf-datatable-selected > svg {
fill: #00bcd4; fill: #00bcd4 !important;
} }
.adf-site-container-style { .adf-site-container-style {
@ -116,6 +116,10 @@ adf-document-list ::ng-deep adf-datatable > table > tbody > tr.is-selected > td.
letter-spacing: -1px; letter-spacing: -1px;
} }
.adf-recent-container{
border: 1px solid rgba(0, 0, 0, 0.07);
}
@media (max-width: $minimumDocumentListWidth) { @media (max-width: $minimumDocumentListWidth) {
adf-document-list ::ng-deep adf-datatable { adf-document-list ::ng-deep adf-datatable {
& ::ng-deep .adf-data-table-cell--fileSize { & ::ng-deep .adf-data-table-cell--fileSize {

View File

@ -49,6 +49,7 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
fileNodeId: any; fileNodeId: any;
showViewer = false; showViewer = false;
showVersions = false; showVersions = false;
cardview = false;
toolbarColor = 'default'; toolbarColor = 'default';
@ -423,4 +424,8 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
onPrevPage(event: Pagination): void { onPrevPage(event: Pagination): void {
this.turnedPreviousPage.emit(event); this.turnedPreviousPage.emit(event);
} }
toogleCardview(event: Pagination): void {
this.cardview = !this.cardview;
}
} }

View File

@ -18,14 +18,6 @@
"lib": [ "lib": [
"es2016", "es2016",
"dom" "dom"
], ]
"paths": {
"rxjs/*": [
"../node_modules/rxjs/*"
],
"@angular/*": [
"../node_modules/@angular/*"
]
}
} }
} }

View File

@ -18,6 +18,7 @@ See it live: [DataTable Quickstart](https://embed.plnkr.co/80qr4YFBeHjLMdAV0F6l/
- [Supplying data for the table](#supplying-data-for-the-table) - [Supplying data for the table](#supplying-data-for-the-table)
- [Customizing columns](#customizing-columns) - [Customizing columns](#customizing-columns)
- [DataTable DOM Events](#datatable-dom-events) - [DataTable DOM Events](#datatable-dom-events)
- [Card view](#card-view)
- [Custom Empty content template](#custom-empty-content-template) - [Custom Empty content template](#custom-empty-content-template)
- [Loading content template](#loading-content-template) - [Loading content template](#loading-content-template)
- [Events](#events-1) - [Events](#events-1)
@ -133,8 +134,9 @@ export class DataTableDemo {
| allowDropFiles | boolean | false | Toggle file drop support for rows (see **ng2-alfresco-core/UploadDirective** for more details) | | allowDropFiles | boolean | false | Toggle file drop support for rows (see **ng2-alfresco-core/UploadDirective** for more details) |
| loading | boolean | false | Flag that indicates if the datatable is in loading state and needs to show the loading template. Read the documentation above to see how to configure a loading template | | loading | boolean | false | Flag that indicates if the datatable is in loading state and needs to show the loading template. Read the documentation above to see how to configure a loading template |
| showHeader | boolean | true | Toggles header visibility | | showHeader | boolean | true | Toggles header visibility |
| cardview | boolean | true | enable the cardview mode |
| selection | DataRow\[] | \[] | Contains selected rows | | selection | DataRow\[] | \[] | Contains selected rows |
### Events ### Events
| Name | Description | | Name | Description |
@ -192,6 +194,20 @@ onRowClick(event) {
![](docassets/images/datatable-dom-events.png) ![](docassets/images/datatable-dom-events.png)
### Card view
If you want enable the card view mode you need to set to true the input parameter [cardview] :
```html
<adf-datatable
[data]="data"
[cardview]="true">
</adf-datatable
```
![card-view](docassets/images/document-list-card-view.png)
### Custom Empty content template ### Custom Empty content template
You can add a template that will be shown when there are no results in your datatable: You can add a template that will be shown when there are no results in your datatable:

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

View File

@ -14,6 +14,7 @@ Displays the documents from a repository.
- [Details](#details) - [Details](#details)
- [DOM Events](#dom-events) - [DOM Events](#dom-events)
- [Card view](#card-view)
- [Pagination strategy](#pagination-strategy) - [Pagination strategy](#pagination-strategy)
- [Data Sources](#data-sources) - [Data Sources](#data-sources)
- [Setting default folder](#setting-default-folder) - [Setting default folder](#setting-default-folder)
@ -46,7 +47,7 @@ Displays the documents from a repository.
``` ```
### Properties ### Properties
| Name | Type | Default value | Description | | Name | Type | Default value | Description |
| ---- | ---- | ------------- | ----------- | | ---- | ---- | ------------- | ----------- |
| permissionsStyle | `PermissionStyleModel[]` | `[]` | Define a set of CSS styles styles to apply depending on the permission of the user on that node. See the Permission Style model page for further details and examples. | | permissionsStyle | `PermissionStyleModel[]` | `[]` | Define a set of CSS styles styles to apply depending on the permission of the user on that node. See the Permission Style model page for further details and examples. |
@ -73,6 +74,8 @@ Displays the documents from a repository.
| maxItems | `number` | | Default value is stored into user preference settings | | maxItems | `number` | | Default value is stored into user preference settings |
| skipCount | `number` | `0` | Number of elements to skip over for pagination purposes | | skipCount | `number` | `0` | Number of elements to skip over for pagination purposes |
| enableInfiniteScrolling | `boolean` | `false` | Set document list to work in infinite scrolling mode | | enableInfiniteScrolling | `boolean` | `false` | Set document list to work in infinite scrolling mode |
| showHeader | `boolean` | `true` | Toggles header visibility |
| cardview | `boolean` | `false` | Enable the cardview mode |
### Events ### Events
@ -127,6 +130,20 @@ Below is a basic example of handling DOM events in the parent elements.
</div> </div>
``` ```
### Card view
If you want enable the card view mode you need to set to true the input parameter [cardview] :
```html
<adf-document-list
[currentFolderId]="'-my-'"
[cardview]="true">
</adf-document-list>
```
![card-view](docassets/images/document-list-card-view.png)
### Pagination strategy ### Pagination strategy
The Document List by default supports 2 type of pagination, the **finite** and the **infinite** pagination. The Document List by default supports 2 type of pagination, the **finite** and the **infinite** pagination.

View File

@ -31,7 +31,7 @@
"@angular/platform-browser-dynamic": "5.0.0", "@angular/platform-browser-dynamic": "5.0.0",
"@angular/router": "5.0.0", "@angular/router": "5.0.0",
"@ngx-translate/core": "8.0.0", "@ngx-translate/core": "8.0.0",
"alfresco-js-api": "^2.1.0-4c702fe0041642c09f12fb939014cf70671d8ed8", "alfresco-js-api": "2.0.0",
"chart.js": "2.5.0", "chart.js": "2.5.0",
"classlist.js": "1.1.20150312", "classlist.js": "1.1.20150312",
"core-js": "2.4.1", "core-js": "2.4.1",

View File

@ -17,14 +17,6 @@
"lib": [ "lib": [
"es2016", "es2016",
"dom" "dom"
], ]
"paths": {
"rxjs/*": [
"../node_modules/rxjs/*"
],
"@angular/*": [
"../node_modules/@angular/*"
]
}
} }
} }

View File

@ -9,8 +9,9 @@
[rowStyle]="rowStyle" [rowStyle]="rowStyle"
[rowStyleClass]="rowStyleClass" [rowStyleClass]="rowStyleClass"
[loading]="loading" [loading]="loading"
[cardview]="cardview"
[noPermission]="noPermission" [noPermission]="noPermission"
[showHeader]="!isEmpty()" [showHeader]="!isEmpty() && showHeader"
(showRowContextMenu)="onShowRowContextMenu($event)" (showRowContextMenu)="onShowRowContextMenu($event)"
(showRowActionsMenu)="onShowRowActionsMenu($event)" (showRowActionsMenu)="onShowRowActionsMenu($event)"
(executeRowAction)="onExecuteRowAction($event)" (executeRowAction)="onExecuteRowAction($event)"

View File

@ -2,7 +2,7 @@
$foreground: map-get($theme, foreground); $foreground: map-get($theme, foreground);
$accent: map-get($theme, accent); $accent: map-get($theme, accent);
adf-datatable > table > tbody > tr.is-selected > td.adf-data-table-cell.adf-data-table-cell--image.image-table-cell > div > div > mat-icon > svg { .adf-datatable-selected > svg {
fill: mat-color($accent); fill: mat-color($accent);
margin-top: -4px; margin-top: -4px;
margin-left: -4px; margin-left: -4px;

View File

@ -181,7 +181,65 @@ describe('DocumentList', () => {
fixture.whenStable().then(() => { fixture.whenStable().then(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(element.querySelector('#adf-document-list-loading')).toBeDefined(); expect(element.querySelector('.adf-document-list-loading')).toBeDefined();
done();
});
});
it('should hide the header if showHeader is false', (done) => {
documentList.showHeader = false;
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(element.querySelector('.adf-datatable-header')).toBe(null);
done();
});
});
it('should show the header if showHeader is true', (done) => {
documentList.showHeader = true;
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(element.querySelector('.adf-datatable-header')).toBeDefined();
done();
});
});
it('should reset selection upon reload', () => {
spyOn(documentList, 'resetSelection').and.callThrough();
documentList.reload();
fixture.detectChanges();
expect(documentList.resetSelection).toHaveBeenCalled();
});
it('should use the cardview style if cardview is true', (done) => {
documentList.cardview = true;
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(element.querySelector('.adf-data-table-card')).toBeDefined();
done();
});
});
it('should use the base document list style if cardview is false', (done) => {
documentList.cardview = false;
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(element.querySelector('.adf-data-table-card')).toBe(null);
expect(element.querySelector('.adf-data-table')).toBeDefined();
done(); done();
}); });
}); });

View File

@ -71,6 +71,10 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
@ContentChild(DataColumnListComponent) columnList: DataColumnListComponent; @ContentChild(DataColumnListComponent) columnList: DataColumnListComponent;
/* Enable the cardview mode */
@Input()
cardview: boolean = false;
/** Define a set of CSS styles styles to apply depending on the permission /** Define a set of CSS styles styles to apply depending on the permission
* of the user on that node. See the Permission Style model * of the user on that node. See the Permission Style model
* page for further details and examples. * page for further details and examples.
@ -86,6 +90,10 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
@Input() @Input()
navigate: boolean = true; navigate: boolean = true;
/** Toggles the header */
@Input()
showHeader: boolean = true;
/** User interaction for folder navigation or file preview. Valid values are "click" and "dblclick". */ /** User interaction for folder navigation or file preview. Valid values are "click" and "dblclick". */
@Input() @Input()
navigationMode: string = DocumentListComponent.DOUBLE_CLICK_NAVIGATION; // click|dblclick navigationMode: string = DocumentListComponent.DOUBLE_CLICK_NAVIGATION; // click|dblclick

View File

@ -1,187 +1,212 @@
<table <div
*ngIf="data" *ngIf="data" class="full-width adf-data-table-card"
class="full-width adf-data-table"> [class.adf-data-table-card]="cardview"
[class.adf-data-table]="!cardview">
<thead *ngIf="showHeader"> <div *ngIf="showHeader && !loading" class="adf-datatable-header">
<tr> <div class="adf-datatable-row" *ngIf="!cardview">
<!-- Actions (left) -->
<th *ngIf="actions && actionsPosition === 'left'" class="actions-column">
<span class="sr-only">Actions</span>
</th>
<!-- Columns -->
<th *ngIf="multiselect">
<mat-checkbox [checked]="isSelectAllChecked" (change)="onSelectAllClick($event)"></mat-checkbox>
</th>
<th class="adf-data-table-cell--{{col.type || 'text'}} {{col.cssClass}}"
*ngFor="let col of data.getColumns()"
[class.sortable]="col.sortable"
[attr.data-automation-id]="'auto_id_' + col.key"
[class.adf-data-table__header--sorted-asc]="isColumnSorted(col, 'asc')"
[class.adf-data-table__header--sorted-desc]="isColumnSorted(col, 'desc')"
(click)="onColumnHeaderClick(col)"
(keyup.enter)="onColumnHeaderClick(col)"
role="button"
tabindex="0"
title="{{ col.title | translate }}">
<span *ngIf="col.srTitle" class="sr-only">{{ col.srTitle | translate }}</span>
<span *ngIf="col.title">{{ col.title | translate}}</span>
</th>
<!-- Actions (right) -->
<th *ngIf="actions && actionsPosition === 'right'" class="actions-column">
<span class="sr-only">Actions</span>
</th>
</tr>
</thead>
<tbody>
<ng-container *ngIf="!loading && !noPermission">
<tr *ngFor="let row of data.getRows(); let idx = index"
role="button"
[class.is-selected]="row.isSelected"
[adf-upload]="allowDropFiles && rowAllowsDrop(row)" [adf-upload-data]="row"
[ngStyle]="rowStyle"
[ngClass]="getRowStyle(row)"
(keyup)="onRowKeyUp(row, $event)">
<!-- Actions (left) --> <!-- Actions (left) -->
<td *ngIf="actions && actionsPosition === 'left'"> <div *ngIf="actions && actionsPosition === 'left'" class="actions-column adf-datatable-table-cell-header">
<button mat-icon-button [matMenuTriggerFor]="menu" <span class="sr-only">Actions</span>
[attr.data-automation-id]="'action_menu_' + idx"> </div>
<mat-icon>more_vert</mat-icon> <!-- Columns -->
</button> <div *ngIf="multiselect" class="adf-datatable-table-cell-header">
<mat-menu #menu="matMenu"> <mat-checkbox [checked]="isSelectAllChecked" (change)="onSelectAllClick($event)"></mat-checkbox>
<button mat-menu-item *ngFor="let action of getRowActions(row)" </div>
[attr.data-automation-id]="action.title" <div class="adf-data-table-cell--{{col.type || 'text'}} {{col.cssClass}} adf-datatable-table-cell-header"
[disabled]="action.disabled" *ngFor="let col of data.getColumns()"
(click)="onExecuteRowAction(row, action)"> [class.sortable]="col.sortable"
<mat-icon *ngIf="action.icon">{{ action.icon }}</mat-icon> [attr.data-automation-id]="'auto_id_' + col.key"
<span>{{ action.title | translate }}</span> [class.adf-data-table__header--sorted-asc]="isColumnSorted(col, 'asc')"
[class.adf-data-table__header--sorted-desc]="isColumnSorted(col, 'desc')"
(click)="onColumnHeaderClick(col)"
(keyup.enter)="onColumnHeaderClick(col)"
role="button"
tabindex="0"
title="{{ col.title | translate }}">
<span *ngIf="col.srTitle" class="sr-only">{{ col.srTitle | translate }}</span>
<span *ngIf="col.title">{{ col.title | translate}}</span>
</div>
<!-- Actions (right) -->
<div *ngIf="actions && actionsPosition === 'right'" class="actions-column adf-datatable-table-cell-header">
<span class="sr-only">Actions</span>
</div>
</div>
<mat-form-field *ngIf="cardview">
<mat-select [value]="getSortingKey()">
<mat-option *ngFor="let col of data.getColumns()"
[value]="col.key"
(click)="onColumnHeaderClick(col)"
(keyup.enter)="onColumnHeaderClick(col)">
{{ col.title | translate}}
</mat-option>
</mat-select>
</mat-form-field>
</div>
<div class="adf-datatable-body">
<ng-container *ngIf="!loading && !noPermission">
<div *ngFor="let row of data.getRows(); let idx = index"
class="adf-datatable-row"
role="button"
[class.is-selected]="row.isSelected"
[adf-upload]="allowDropFiles && rowAllowsDrop(row)" [adf-upload-data]="row"
[ngStyle]="rowStyle"
[ngClass]="getRowStyle(row)"
(keyup)="onRowKeyUp(row, $event)">
<!-- Actions (left) -->
<div *ngIf="actions && actionsPosition === 'left'" class="adf-datatable-table-cell">
<button mat-icon-button [matMenuTriggerFor]="menu"
[attr.id]="'action_menu_left_' + idx"
[attr.data-automation-id]="'action_menu_' + idx">
<mat-icon>more_vert</mat-icon>
</button> </button>
</mat-menu> <mat-menu #menu="matMenu">
</td> <button mat-menu-item *ngFor="let action of getRowActions(row)"
[attr.data-automation-id]="action.title"
[disabled]="action.disabled"
(click)="onExecuteRowAction(row, action)">
<mat-icon *ngIf="action.icon">{{ action.icon }}</mat-icon>
<span>{{ action.title | translate }}</span>
</button>
</mat-menu>
</div>
<td *ngIf="multiselect"> <div *ngIf="multiselect" class="adf-datatable-table-cell adf-datatable-table-checkbox">
<mat-checkbox <mat-checkbox
[checked]="row.isSelected" [checked]="row.isSelected"
(change)="onCheckboxChange(row, $event)"> (change)="onCheckboxChange(row, $event)">
</mat-checkbox> </mat-checkbox>
</td> </div>
<td *ngFor="let col of data.getColumns()" <div *ngFor="let col of data.getColumns()"
class="adf-data-table-cell adf-data-table-cell--{{col.type || 'text'}} {{col.cssClass}}" class="adf-data-table-cell adf-datatable-table-cell adf-data-table-cell--{{col.type || 'text'}} {{col.cssClass}}"
tabindex="0" [attr.title]="col.title | translate"
(click)="onRowClick(row, $event)" [attr.filename]="getFilename(row)"
[context-menu]="getContextMenuActions(row, col)" tabindex="0"
[context-menu-enabled]="contextMenu"> (click)="onRowClick(row, $event)"
<div *ngIf="!col.template" class="cell-container"> [context-menu]="getContextMenuActions(row, col)"
<ng-container [ngSwitch]="col.type"> [context-menu-enabled]="contextMenu">
<div *ngSwitchCase="'image'" class="cell-value"> <div *ngIf="!col.template" class="cell-container">
<mat-icon *ngIf="isIconValue(row, col)">{{ asIconValue(row, col) }}</mat-icon> <ng-container [ngSwitch]="col.type">
<mat-icon *ngIf="!isIconValue(row, col) && row.isSelected" svgIcon="selected" > <div *ngSwitchCase="'image'" class="cell-value">
</mat-icon> <mat-icon *ngIf="isIconValue(row, col)">{{ asIconValue(row, col) }}</mat-icon>
<mat-icon class="adf-datatable-selected"
*ngIf="!isIconValue(row, col) && row.isSelected" svgIcon="selected">
</mat-icon>
<img *ngIf="!isIconValue(row, col) && !row.isSelected" <img *ngIf="!isIconValue(row, col) && !row.isSelected"
alt="{{ iconAltTextKey(data.getValue(row, col)) | translate }}" alt="{{ iconAltTextKey(data.getValue(row, col)) | translate }}"
src="{{ data.getValue(row, col) }}" src="{{ data.getValue(row, col) }}"
(error)="onImageLoadingError($event)"> (error)="onImageLoadingError($event)">
</div> </div>
<div *ngSwitchCase="'icon'" class="cell-value"> <div *ngSwitchCase="'icon'" class="cell-value">
<span class="sr-only">{{ iconAltTextKey(data.getValue(row, col)) | translate }}</span> <span class="sr-only">{{ iconAltTextKey(data.getValue(row, col)) | translate }}</span>
<mat-icon>{{ data.getValue(row, col) }}</mat-icon> <mat-icon>{{ data.getValue(row, col) }}</mat-icon>
</div> </div>
<div *ngSwitchCase="'date'" class="cell-value" <div *ngSwitchCase="'date'" class="cell-value"
[attr.data-automation-id]="'date_' + data.getValue(row, col)"> [attr.data-automation-id]="'date_' + data.getValue(row, col)">
<adf-date-cell <adf-date-cell
[data]="data" [data]="data"
[column]="col" [column]="col"
[row]="row" [row]="row"
[tooltip]="getCellTooltip(row, col)"> [tooltip]="getCellTooltip(row, col)">
</adf-date-cell> </adf-date-cell>
</div> </div>
<div *ngSwitchCase="'location'" class="cell-value" <div *ngSwitchCase="'location'" class="cell-value"
[attr.data-automation-id]="'location' + data.getValue(row, col)"> [attr.data-automation-id]="'location' + data.getValue(row, col)">
<adf-location-cell <adf-location-cell
[data]="data" [data]="data"
[column]="col" [column]="col"
[row]="row" [row]="row"
[tooltip]="getCellTooltip(row, col)"> [tooltip]="getCellTooltip(row, col)">
</adf-location-cell> </adf-location-cell>
</div> </div>
<div *ngSwitchCase="'fileSize'" class="cell-value" <div *ngSwitchCase="'fileSize'" class="cell-value"
[attr.data-automation-id]="'fileSize_' + data.getValue(row, col)"> [attr.data-automation-id]="'fileSize_' + data.getValue(row, col)">
<adf-filesize-cell <adf-filesize-cell
[data]="data" [data]="data"
[column]="col" [column]="col"
[row]="row" [row]="row"
[tooltip]="getCellTooltip(row, col)"> [tooltip]="getCellTooltip(row, col)">
</adf-filesize-cell> </adf-filesize-cell>
</div> </div>
<div *ngSwitchCase="'text'" class="cell-value" <div *ngSwitchCase="'text'" class="cell-value"
[attr.data-automation-id]="'text_' + data.getValue(row, col)"> [attr.data-automation-id]="'text_' + data.getValue(row, col)">
<adf-datatable-cell <adf-datatable-cell
[data]="data" [data]="data"
[column]="col" [column]="col"
[row]="row" [row]="row"
[tooltip]="getCellTooltip(row, col)"> [tooltip]="getCellTooltip(row, col)">
</adf-datatable-cell> </adf-datatable-cell>
</div> </div>
<span *ngSwitchDefault class="cell-value"> <span *ngSwitchDefault class="cell-value">
<!-- empty cell for unknown column type --> <!-- empty cell for unknown column type -->
</span> </span>
</ng-container> </ng-container>
</div>
<div *ngIf="col.template" class="cell-container">
<ng-container
[ngTemplateOutlet]="col.template"
[ngTemplateOutletContext]="{ $implicit: { data: data, row: row, col: col }, value: data.getValue(row, col) }">
</ng-container>
</div>
</div> </div>
<div *ngIf="col.template" class="cell-container">
<ng-container
[ngTemplateOutlet]="col.template"
[ngTemplateOutletContext]="{ $implicit: { data: data, row: row, col: col }, value: data.getValue(row, col) }">
</ng-container>
</div>
</td>
<!-- Actions (right) --> <!-- Actions (right) -->
<td *ngIf="actions && actionsPosition === 'right'" class="alfresco-datatable__actions-cell"> <div *ngIf="actions && actionsPosition === 'right'"
<button mat-icon-button [matMenuTriggerFor]="menu" class="adf-datatable-table-cell alfresco-datatable__actions-cell">
[attr.data-automation-id]="'action_menu_' + idx"> <button mat-icon-button [matMenuTriggerFor]="menu"
<mat-icon>more_vert</mat-icon> [attr.id]="'action_menu_right_' + idx"
</button> [attr.data-automation-id]="'action_menu_' + idx">
<mat-menu #menu="matMenu"> <mat-icon>more_vert</mat-icon>
<button mat-menu-item *ngFor="let action of getRowActions(row)"
[attr.data-automation-id]="action.title"
[disabled]="action.disabled"
(click)="onExecuteRowAction(row, action)">
<mat-icon *ngIf="action.icon">{{ action.icon }}</mat-icon>
<span>{{ action.title | translate }}</span>
</button> </button>
</mat-menu> <mat-menu #menu="matMenu">
</td> <button mat-menu-item *ngFor="let action of getRowActions(row)"
[attr.data-automation-id]="action.title"
[disabled]="action.disabled"
(click)="onExecuteRowAction(row, action)">
<mat-icon *ngIf="action.icon">{{ action.icon }}</mat-icon>
<span>{{ action.title | translate }}</span>
</button>
</mat-menu>
</div>
</tr> </div>
<tr *ngIf="data.getRows().length === 0"> <div *ngIf="data.getRows().length === 0"
<td class="adf-no-content-container" [class.adf-datatable-row]="!cardview"
[attr.colspan]="1 + data.getColumns().length"> [class.adf-data-table-card-empty]="cardview">
<ng-template *ngIf="noContentTemplate" <div class="adf-no-content-container adf-datatable-table-cell"
[attr.colspan]="1 + data.getColumns().length">
<ng-template *ngIf="noContentTemplate"
ngFor [ngForOf]="[data]"
[ngForTemplate]="noContentTemplate">
</ng-template>
<ng-content select="adf-empty-list"></ng-content>
</div>
</div>
</ng-container>
<div *ngIf="!loading && noPermission"
[class.adf-datatable-row]="!cardview"
[class.adf-data-table-card-permissions]="cardview">
class="adf-no-permission__row">
<div class="adf-no-permission__cell adf-no-content-container adf-datatable-table-cell">
<ng-template *ngIf="noPermissionTemplate"
ngFor [ngForOf]="[data]" ngFor [ngForOf]="[data]"
[ngForTemplate]="noContentTemplate"> [ngForTemplate]="noPermissionTemplate">
</ng-template> </ng-template>
<ng-content select="adf-empty-list"></ng-content> </div>
</td> </div>
</tr> <div *ngIf="loading"
</ng-container> [class.adf-datatable-row]="!cardview"
<tr *ngIf="!loading && noPermission" class="adf-no-permission__row"> [class.adf-data-table-card-loading]="cardview">
<td class="adf-no-permission__cell"> <div class="adf-datatable-table-cell"
<ng-template *ngIf="noPermissionTemplate" [attr.colspan]="1 + data.getColumns().length">
ngFor [ngForOf]="[data]" <ng-template *ngIf="loadingTemplate"
[ngForTemplate]="noPermissionTemplate"> ngFor [ngForOf]="[data]"
</ng-template> [ngForTemplate]="loadingTemplate">
</td> </ng-template>
</tr> </div>
<tr *ngIf="loading"> </div>
<td class="adf-loading-content-container" </div>
[attr.colspan]="1 + data.getColumns().length"> </div>
<ng-template *ngIf="loadingTemplate"
ngFor [ngForOf]="[data]"
[ngForTemplate]="loadingTemplate">
</ng-template>
</td>
</tr>
</tbody>
</table>

View File

@ -1,4 +1,3 @@
@mixin adf-datatable-theme($theme) { @mixin adf-datatable-theme($theme) {
$foreground: map-get($theme, foreground); $foreground: map-get($theme, foreground);
$background: map-get($theme, background); $background: map-get($theme, background);
@ -26,7 +25,148 @@
$data-table-cell-top: $data-table-card-padding / 2; $data-table-cell-top: $data-table-card-padding / 2;
$data-table-drag-border: 1px dashed rgb(68, 138, 255); $data-table-drag-border: 1px dashed rgb(68, 138, 255);
.adf-data-table-card {
border: 1px solid mat-color($foreground, divider);
.sr-only {
}
.adf-datatable-body {
flex-flow: row wrap;
display: flex;
width: 100%;
flex-direction: row;
justify-content: space-between;
&:after {
content: "";
flex: auto;
}
.adf-datatable-row {
transition: all 0.3s ease;
position: relative;
display: flex;
flex-direction: column;
flex: 0 1 24%;
width: 288px !important;
max-width: 288px !important;
min-width: 288px !important;
height: 200px !important;
overflow: hidden !important;
margin: 6px;
padding: 15px;
@include mat-elevation-transition;
@include mat-overridable-elevation(2);
}
.is-selected {
background: mat-color($primary, 100);
padding-bottom: 31px;
}
.adf-data-table-card-permission {
width: 100%;
min-height: 250px;
.adf-datatable-table-cell {
height: 240px !important;
}
}
.adf-data-table-card-loading {
width: 100%;
min-height: 250px;
.adf-datatable-table-cell {
height: 240px !important;
}
}
.adf-data-table-card-empty {
width: 100%;
min-height: 380px;
.adf-datatable-table-cell {
height: 370px !important;
}
}
.adf-datatable-table-cell {
text-align: left;
flex: 0 1 24%;
height: 136px !important;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
outline: none;
&:before {
margin-left: 10px;
text-align: left;
content: attr(title);
color: mat-color($foreground, text, 0.4);
float: left;
width: 140px;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
}
.alfresco-datatable__actions-cell {
position: absolute;
height: 42px !important;
width: 42px !important;
right: 0px;
text-align: right;
}
.image-table-cell {
margin: 8px;
padding: 4px;
overflow: visible;
border-bottom-color: mat-color($foreground, divider);
border-bottom-width: 1px;
border-bottom-style: solid;
.cell-container {
float: left;
width: 42px;
}
&:after {
margin: 2px;
content: attr(filename);
float: left;
width: 140px;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
}
.adf-datatable-table-checkbox {
margin: 8px;
}
}
.adf-datatable-header {
margin-right: 18px;
float: right;
}
}
.adf-data-table { .adf-data-table {
display: table;
width: 100%; width: 100%;
position: relative; position: relative;
border: $data-table-dividers; border: $data-table-dividers;
@ -38,12 +178,36 @@
border-collapse: unset; border-collapse: unset;
border-spacing: 0; border-spacing: 0;
thead { .adf-datatable-row {
padding-bottom: 3px; display: table-row;
vertical-align: inherit;
border-color: inherit;
} }
tbody { .adf-datatable-body {
tr { display: table-row-group;
vertical-align: middle;
border-color: inherit;
}
.adf-datatable-table-cell {
display: table-cell;
}
.adf-datatable-table-cell-header {
display: table-cell;
}
.adf-datatable-header {
padding-bottom: 3px;
display: table-header-group;
vertical-align: middle;
border-color: inherit;
}
.adf-datatable-body {
.adf-datatable-row {
cursor: pointer; cursor: pointer;
position: relative; position: relative;
height: $data-table-row-height; height: $data-table-row-height;
@ -73,7 +237,7 @@
} }
} }
td, th { .adf-datatable-table-cell, .adf-datatable-table-cell-header {
padding: 0 $data-table-column-padding 12px $data-table-column-padding; padding: 0 $data-table-column-padding 12px $data-table-column-padding;
text-align: right; text-align: right;
@ -93,7 +257,7 @@
} }
} }
td { .adf-datatable-table-cell {
color: mat-color($foreground, text); color: mat-color($foreground, text);
position: relative; position: relative;
vertical-align: middle; vertical-align: middle;
@ -105,7 +269,7 @@
@include no-select; @include no-select;
} }
th { .adf-datatable-table-cell-header {
@include no-select; @include no-select;
cursor: pointer; cursor: pointer;
position: relative; position: relative;
@ -153,7 +317,7 @@
.adf-data-table-cell { .adf-data-table-cell {
text-align: left; text-align: left;
height: 100%; height: 100%;
&--text { &--text {
text-align: left; text-align: left;
@ -182,7 +346,7 @@
.cell-container { .cell-container {
display: flex; display: flex;
align-items: center; align-items: center;
} }
} }
@ -202,6 +366,7 @@
/* Loading folder */ /* Loading folder */
.adf-loading-content-container { .adf-loading-content-container {
padding: 0 !important; padding: 0 !important;
width: 100%;
& > img { & > img {
width: 100%; width: 100%;

View File

@ -51,6 +51,86 @@ describe('DataTable', () => {
element = fixture.debugElement.nativeElement; element = fixture.debugElement.nativeElement;
}); });
it('should use the cardview style if cardview is true', () => {
let newData = new ObjectDataTableAdapter(
[
{ name: '1' },
{ name: '2' }
],
[new ObjectDataColumn({ key: 'name' })]
);
dataTable.cardview = true;
dataTable.ngOnChanges({
data: new SimpleChange(null, newData, false)
});
fixture.detectChanges();
expect(element.querySelector('.adf-data-table-card')).not.toBeNull();
expect(element.querySelector('.adf-data-table')).toBeNull();
});
it('should use the cardview style if cardview is false', () => {
let newData = new ObjectDataTableAdapter(
[
{ name: '1' },
{ name: '2' }
],
[new ObjectDataColumn({ key: 'name' })]
);
dataTable.cardview = false;
dataTable.ngOnChanges({
data: new SimpleChange(null, newData, false)
});
fixture.detectChanges();
expect(element.querySelector('.adf-data-table-card')).toBeNull();
expect(element.querySelector('.adf-data-table')).not.toBeNull();
});
it('should hide the header if showHeader is false', () => {
let newData = new ObjectDataTableAdapter(
[
{ name: '1' },
{ name: '2' }
],
[new ObjectDataColumn({ key: 'name' })]
);
dataTable.showHeader = false;
dataTable.loading = false;
dataTable.ngOnChanges({
data: new SimpleChange(null, newData, false)
});
fixture.detectChanges();
expect(element.querySelector('.adf-datatable-header')).toBe(null);
});
it('should show the header if showHeader is true', () => {
let newData = new ObjectDataTableAdapter(
[
{ name: '1' },
{ name: '2' }
],
[new ObjectDataColumn({ key: 'name' })]
);
dataTable.showHeader = true;
dataTable.loading = false;
dataTable.ngOnChanges({
data: new SimpleChange(null, newData, false)
});
fixture.detectChanges();
expect(element.querySelector('.adf-datatable-header')).toBeDefined();
});
it('should emit "sorting-changed" DOM event', (done) => { it('should emit "sorting-changed" DOM event', (done) => {
const column = new ObjectDataColumn({ key: 'name', sortable: true, direction: 'asc' }); const column = new ObjectDataColumn({ key: 'name', sortable: true, direction: 'asc' });
dataTable.data = new ObjectDataTableAdapter( dataTable.data = new ObjectDataTableAdapter(
@ -206,32 +286,40 @@ describe('DataTable', () => {
}); });
it('should put actions menu to the right by default', () => { it('should put actions menu to the right by default', () => {
dataTable.data = new ObjectDataTableAdapter([], [ dataTable.data = new ObjectDataTableAdapter(
<DataColumn> {}, [
<DataColumn> {}, { name: '1' },
<DataColumn> {} { name: '2' },
]); { name: '3' },
{ name: '4' }
],
[new ObjectDataColumn({ key: 'name' })]
);
dataTable.actions = true; dataTable.actions = true;
fixture.detectChanges(); fixture.detectChanges();
let headers = element.querySelectorAll('th'); let actions = element.querySelectorAll('[id^=action_menu_right]');
expect(headers.length).toBe(4); expect(actions.length).toBe(4);
expect(headers[headers.length - 1].classList.contains('actions-column')).toBeTruthy();
}); });
it('should put actions menu to the left', () => { it('should put actions menu to the left', () => {
dataTable.data = new ObjectDataTableAdapter([], [ dataTable.data = new ObjectDataTableAdapter(
<DataColumn> {}, [
<DataColumn> {}, { name: '1' },
<DataColumn> {} { name: '2' },
]); { name: '3' },
{ name: '4' }
],
[new ObjectDataColumn({ key: 'name' })]
);
dataTable.actions = true; dataTable.actions = true;
dataTable.actionsPosition = 'left'; dataTable.actionsPosition = 'left';
fixture.detectChanges(); fixture.detectChanges();
let headers = element.querySelectorAll('th'); let actions = element.querySelectorAll('[id^=action_menu_left]');
expect(headers.length).toBe(4); expect(actions.length).toBe(4);
expect(headers[0].classList.contains('actions-column')).toBeTruthy();
}); });
it('should initialize default adapter', () => { it('should initialize default adapter', () => {

View File

@ -53,6 +53,10 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck
@Input() @Input()
data: DataTableAdapter; data: DataTableAdapter;
/* Enable the cardview mode */
@Input()
cardview: boolean = false;
/* The rows that the datatable will show */ /* The rows that the datatable will show */
@Input() @Input()
rows: any[] = []; rows: any[] = [];
@ -483,6 +487,16 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck
return `${row.cssClass} ${this.rowStyleClass}`; return `${row.cssClass} ${this.rowStyleClass}`;
} }
getFilename(row: DataRow): string {
return row.getValue('name');
}
getSortingKey(): string {
if (this.data.getSorting()) {
return this.data.getSorting().key;
}
}
private selectRow(row: DataRow, value: boolean) { private selectRow(row: DataRow, value: boolean) {
if (row) { if (row) {
row.isSelected = value; row.isSelected = value;

View File

@ -16,7 +16,6 @@
*/ */
import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { TranslationService } from '../../index'; import { TranslationService } from '../../index';
import { DataTableModule } from '../../datatable/datatable.module'; import { DataTableModule } from '../../datatable/datatable.module';
import { DataColumnModule } from '../../data-column/data-column.module'; import { DataColumnModule } from '../../data-column/data-column.module';
@ -31,6 +30,7 @@ describe('TaskAttachmentList', () => {
let component: FormListComponent; let component: FormListComponent;
let fixture: ComponentFixture<FormListComponent>; let fixture: ComponentFixture<FormListComponent>;
let service: FormService; let service: FormService;
let element: any;
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
@ -59,7 +59,7 @@ describe('TaskAttachmentList', () => {
fixture = TestBed.createComponent(FormListComponent); fixture = TestBed.createComponent(FormListComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
element = fixture.debugElement.nativeElement;
service = TestBed.get(FormService); service = TestBed.get(FormService);
})); }));
@ -71,12 +71,11 @@ describe('TaskAttachmentList', () => {
])); ]));
component.ngOnChanges({}); component.ngOnChanges({});
fixture.detectChanges();
fixture.whenStable() fixture.whenStable().then(() => {
.then(() => { expect(element.querySelectorAll('.adf-datatable-body > .adf-datatable-row').length).toBe(2);
fixture.detectChanges(); });
expect(fixture.debugElement.queryAll(By.css('adf-datatable tbody tr')).length).toBe(2); });
});
}));
}); });

View File

@ -155,10 +155,10 @@ describe('ProcessAttachmentListComponent', () => {
it('should display attachments when the process has attachments', async(() => { it('should display attachments when the process has attachments', async(() => {
let change = new SimpleChange(null, '123', true); let change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'processInstanceId': change }); component.ngOnChanges({ 'processInstanceId': change });
fixture.detectChanges();
fixture.whenStable().then(() => { fixture.whenStable().then(() => {
fixture.detectChanges(); expect(fixture.debugElement.queryAll(By.css('.adf-datatable-body > .adf-datatable-row')).length).toBe(2);
expect(fixture.debugElement.queryAll(By.css('adf-datatable tbody tr')).length).toBe(2);
}); });
})); }));

View File

@ -138,10 +138,10 @@ describe('TaskAttachmentList', () => {
it('should display attachments when the task has attachments', async(() => { it('should display attachments when the task has attachments', async(() => {
let change = new SimpleChange(null, '123', true); let change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'taskId': change }); component.ngOnChanges({ 'taskId': change });
fixture.detectChanges();
fixture.whenStable().then(() => { fixture.whenStable().then(() => {
fixture.detectChanges(); expect(fixture.debugElement.queryAll(By.css('.adf-datatable-body > .adf-datatable-row')).length).toBe(2);
expect(fixture.debugElement.queryAll(By.css('adf-datatable tbody tr')).length).toBe(2);
}); });
})); }));

View File

@ -94,7 +94,7 @@ describe('PeopleSearchComponent', () => {
fixture.whenStable().then(() => { fixture.whenStable().then(() => {
fixture.detectChanges(); fixture.detectChanges();
let gatewayElement: any = element.querySelector('#search-people-list tbody'); let gatewayElement: any = element.querySelector('#search-people-list .adf-datatable-body');
expect(gatewayElement).not.toBeNull(); expect(gatewayElement).not.toBeNull();
expect(gatewayElement.children.length).toBe(2); expect(gatewayElement.children.length).toBe(2);
done(); done();
@ -136,7 +136,7 @@ describe('PeopleSearchComponent', () => {
fixture.whenStable() fixture.whenStable()
.then(() => { .then(() => {
fixture.detectChanges(); fixture.detectChanges();
let gatewayElement: any = element.querySelector('#search-people-list tbody'); let gatewayElement: any = element.querySelector('#search-people-list .adf-datatable-body');
expect(gatewayElement).not.toBeNull(); expect(gatewayElement).not.toBeNull();
expect(gatewayElement.children.length).toBe(1); expect(gatewayElement.children.length).toBe(1);
done(); done();

View File

@ -113,7 +113,7 @@ describe('PeopleComponent', () => {
it('should show people involved', async(() => { it('should show people involved', async(() => {
fixture.whenStable() fixture.whenStable()
.then(() => { .then(() => {
let gatewayElement: any = element.querySelector('#assignment-people-list tbody'); let gatewayElement: any = element.querySelector('#assignment-people-list .adf-datatable-body');
expect(gatewayElement).not.toBeNull(); expect(gatewayElement).not.toBeNull();
expect(gatewayElement.children.length).toBe(2); expect(gatewayElement.children.length).toBe(2);
}); });
@ -127,7 +127,7 @@ describe('PeopleComponent', () => {
fixture.whenStable() fixture.whenStable()
.then(() => { .then(() => {
fixture.detectChanges(); fixture.detectChanges();
let gatewayElement: any = element.querySelector('#assignment-people-list tbody'); let gatewayElement: any = element.querySelector('#assignment-people-list .adf-datatable-body');
expect(gatewayElement).not.toBeNull(); expect(gatewayElement).not.toBeNull();
expect(gatewayElement.children.length).toBe(1); expect(gatewayElement.children.length).toBe(1);
}); });
@ -141,7 +141,7 @@ describe('PeopleComponent', () => {
fixture.whenStable() fixture.whenStable()
.then(() => { .then(() => {
fixture.detectChanges(); fixture.detectChanges();
let gatewayElement: any = element.querySelector('#assignment-people-list tbody'); let gatewayElement: any = element.querySelector('#assignment-people-list .adf-datatable-body');
expect(gatewayElement).not.toBeNull(); expect(gatewayElement).not.toBeNull();
expect(gatewayElement.children.length).toBe(3); expect(gatewayElement.children.length).toBe(3);
}); });
@ -220,7 +220,7 @@ describe('PeopleComponent', () => {
fixture.whenStable() fixture.whenStable()
.then(() => { .then(() => {
fixture.detectChanges(); fixture.detectChanges();
let gatewayElement: any = element.querySelector('#assignment-people-list tbody'); let gatewayElement: any = element.querySelector('#assignment-people-list .adf-datatable-body');
expect(gatewayElement).not.toBeNull(); expect(gatewayElement).not.toBeNull();
expect(gatewayElement.children.length).toBe(2); expect(gatewayElement.children.length).toBe(2);
}); });
@ -234,7 +234,7 @@ describe('PeopleComponent', () => {
fixture.whenStable() fixture.whenStable()
.then(() => { .then(() => {
fixture.detectChanges(); fixture.detectChanges();
let gatewayElement: any = element.querySelector('#assignment-people-list tbody'); let gatewayElement: any = element.querySelector('#assignment-people-list .adf-datatable-body');
expect(gatewayElement).not.toBeNull(); expect(gatewayElement).not.toBeNull();
expect(gatewayElement.children.length).toBe(2); expect(gatewayElement.children.length).toBe(2);
}); });

View File

@ -161,10 +161,10 @@ export class TaskListComponent implements OnChanges, OnInit, AfterContentInit, P
isStreamLoaded = false; isStreamLoaded = false;
constructor(private taskListService: TaskListService, constructor(private taskListService: TaskListService,
private appConfig: AppConfigService, private appConfig: AppConfigService,
private userPreferences: UserPreferencesService) { private userPreferences: UserPreferencesService) {
this.size = this.userPreferences.paginationSize; this.size = this.userPreferences.paginationSize;
this.pagination = new BehaviorSubject<Pagination>(<Pagination>{ this.pagination = new BehaviorSubject<Pagination>(<Pagination> {
maxItems: this.size, maxItems: this.size,
skipCount: 0, skipCount: 0,
totalItems: 0 totalItems: 0
@ -450,4 +450,4 @@ export class TaskListComponent implements OnChanges, OnInit, AfterContentInit, P
get supportedPageSizes(): number[] { get supportedPageSizes(): number[] {
return this.userPreferences.getDifferentPageSizes(); return this.userPreferences.getDifferentPageSizes();
} }
} }

View File

@ -11,7 +11,8 @@
], ],
"ban": [ "ban": [
true, true,
"eval" "eval",
"fdescribe"
], ],
"class-name": true, "class-name": true,
"comment-format": [ "comment-format": [