mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
#340 document list now wraps and extends datatable
This commit is contained in:
@@ -10,6 +10,8 @@
|
||||
<alfresco-document-list
|
||||
#documentList
|
||||
[currentFolderPath]="currentPath"
|
||||
[contextMenuActions]="true"
|
||||
[contentActions]="true"
|
||||
(preview)="showFile($event)"
|
||||
(folderChange)="onFolderChanged($event)">
|
||||
<!--
|
||||
|
@@ -14,9 +14,25 @@
|
||||
:host .data-cell {
|
||||
cursor: default;
|
||||
}
|
||||
:host .cell-value {}
|
||||
|
||||
:host .column-header {
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
-webkit-user-select: none; /* Chrome/Safari/Opera */
|
||||
-moz-user-select: none; /* Firefox */
|
||||
-ms-user-select: none; /* IE/Edge */
|
||||
-webkit-touch-callout: none; /* iOS Safari */
|
||||
}
|
||||
|
||||
/* Empty folder */
|
||||
|
||||
:host .no-content-container {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
:host .no-content-container > img {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Utils */
|
||||
|
@@ -15,6 +15,7 @@
|
||||
</th>
|
||||
<th class="mdl-data-table__cell--non-numeric non-selectable {{col.cssClass}}"
|
||||
*ngFor="let col of data.getColumns()"
|
||||
[attr.data-automation-id]="'auto_id_' + col.key"
|
||||
[class.column-header]="col.title"
|
||||
[class.mdl-data-table__header--sorted-ascending]="isColumnSorted(col, 'asc')"
|
||||
[class.mdl-data-table__header--sorted-descending]="isColumnSorted(col, 'desc')"
|
||||
@@ -43,7 +44,7 @@
|
||||
class="mdl-data-table__cell--non-numeric non-selectable data-cell {{col.cssClass}}"
|
||||
(click)="onRowClick(row, $event)"
|
||||
(dblclick)="onRowDblClick(row, $event)"
|
||||
[context-menu]="getContextActions(row, col)">
|
||||
[context-menu]="getContextMenuActions(row, col)">
|
||||
<div *ngSwitchCase="'image'" class="cell-value">
|
||||
<i *ngIf="isIconValue(row, col)" class="material-icons icon-cell">{{asIconValue(row, col)}}</i>
|
||||
<img *ngIf="!isIconValue(row, col)" class="image-cell" alt="" src="{{data.getValue(row, col)}}">
|
||||
@@ -60,11 +61,25 @@
|
||||
|
||||
</td>
|
||||
|
||||
<td *ngIf="actions"><!-- todo: actions --></td>
|
||||
<td *ngIf="actions">
|
||||
<!-- action menu -->
|
||||
<button [id]="'action_menu_' + idx" class="mdl-button mdl-js-button mdl-button--icon">
|
||||
<i class="material-icons">more_vert</i>
|
||||
</button>
|
||||
<ul class="mdl-menu mdl-menu--bottom-right mdl-js-menu mdl-js-ripple-effect"
|
||||
[attr.for]="'action_menu_' + idx">
|
||||
<li class="mdl-menu__item"
|
||||
[attr.data-automation-id]="action.title"
|
||||
*ngFor="let action of getRowActions(row)"
|
||||
(click)="onExecuteRowAction(row, action)">
|
||||
{{action.title}}
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
<tr *ngIf="data.getRows().length === 0">
|
||||
<td class="mdl-data-table__cell--non-numeric empty-folder-content"
|
||||
<td class="mdl-data-table__cell--non-numeric no-content-container"
|
||||
[attr.colspan]="1 + data.getColumns().length">
|
||||
<template *ngIf="noContentTemplate"
|
||||
ngFor [ngForOf]="[data]"
|
||||
|
@@ -26,7 +26,6 @@ import {
|
||||
TemplateRef
|
||||
} from '@angular/core';
|
||||
|
||||
// import { Subject } from 'rxjs/Rx';
|
||||
import { CONTEXT_MENU_DIRECTIVES } from 'ng2-alfresco-core';
|
||||
|
||||
import {
|
||||
@@ -70,7 +69,13 @@ export class DataTableComponent implements OnInit, AfterViewChecked {
|
||||
isSelectAllChecked: boolean = false;
|
||||
|
||||
@Output()
|
||||
showContextMenu: EventEmitter<any> = new EventEmitter();
|
||||
showRowContextMenu: EventEmitter<any> = new EventEmitter();
|
||||
|
||||
@Output()
|
||||
showRowActionsMenu: EventEmitter<any> = new EventEmitter();
|
||||
|
||||
@Output()
|
||||
executeRowAction: EventEmitter<any> = new EventEmitter();
|
||||
|
||||
// TODO: left for reference, will be removed during future revisions
|
||||
constructor(/*private _ngZone?: NgZone*/) {
|
||||
@@ -169,9 +174,20 @@ export class DataTableComponent implements OnInit, AfterViewChecked {
|
||||
return false;
|
||||
}
|
||||
|
||||
getContextActions(row: DataRow, col: DataColumn) {
|
||||
getContextMenuActions(row: DataRow, col: DataColumn) {
|
||||
let args = { row: row, col: col, actions: [] };
|
||||
this.showContextMenu.emit({ args: args });
|
||||
this.showRowContextMenu.emit({ args: args });
|
||||
return args.actions;
|
||||
}
|
||||
|
||||
getRowActions(row: DataRow, col: DataColumn) {
|
||||
let args = { row: row, col: col, actions: [] };
|
||||
this.showRowActionsMenu.emit({ args: args });
|
||||
return args.actions;
|
||||
}
|
||||
|
||||
onExecuteRowAction(row: DataRow, action: any) {
|
||||
let args = { row: row, action: action };
|
||||
this.executeRowAction.emit({ args: args });
|
||||
}
|
||||
}
|
||||
|
@@ -55,6 +55,9 @@ import {
|
||||
<alfresco-document-list #doclist
|
||||
#documentList
|
||||
[currentFolderPath]="currentPath"
|
||||
[contextMenuActions]="true"
|
||||
[contentActions]="true"
|
||||
[multiselect]="true"
|
||||
(folderChange)="onFolderChanged($event)">
|
||||
<!--
|
||||
<empty-folder-content>
|
||||
|
@@ -1,60 +1,5 @@
|
||||
:host .full-width { width: 100%; }
|
||||
|
||||
:host .thumbnail {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
:host .column-header {
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
-webkit-user-select: none; /* Chrome/Safari/Opera */
|
||||
-moz-user-select: none; /* Firefox */
|
||||
-ms-user-select: none; /* IE/Edge */
|
||||
-webkit-touch-callout: none; /* iOS Safari */
|
||||
}
|
||||
|
||||
:host .parent-folder-link { cursor: default; }
|
||||
:host .parent-folder-link > td { text-align: left; }
|
||||
|
||||
:host .data-cell {
|
||||
cursor: default;
|
||||
}
|
||||
:host .cell-value {}
|
||||
|
||||
/* Empty folder */
|
||||
|
||||
:host .empty-folder-content {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
:host .empty-folder-content > img {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Utils */
|
||||
|
||||
:host .non-selectable {
|
||||
user-select: none;
|
||||
-webkit-user-select: none; /* Chrome/Safari/Opera */
|
||||
-moz-user-select: none; /* Firefox */
|
||||
-ms-user-select: none; /* IE/Edge */
|
||||
-webkit-touch-callout: none; /* iOS Safari */
|
||||
}
|
||||
|
||||
:host .sr-only {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0,0,0,0);
|
||||
border: 0;
|
||||
}
|
||||
|
||||
|
||||
:host .ellipsis-cell > div
|
||||
{
|
||||
position: relative;
|
||||
|
@@ -1,6 +1,10 @@
|
||||
<alfresco-datatable
|
||||
[data]="data"
|
||||
(showContextMenu)="onRowContextMenu($event)"
|
||||
[actions]="contentActions"
|
||||
[multiselect]="multiselect"
|
||||
(showRowContextMenu)="onShowRowContextMenu($event)"
|
||||
(showRowActionsMenu)="onShowRowActionsMenu($event)"
|
||||
(executeRowAction)="onExecuteRowAction($event)"
|
||||
(rowClick)="onRowClick($event)"
|
||||
(rowDblClick)="onRowDblClick($event)">
|
||||
<no-content-template>
|
||||
@@ -9,107 +13,3 @@
|
||||
</template>
|
||||
</no-content-template>
|
||||
</alfresco-datatable>
|
||||
|
||||
<table *ngIf="folder" class="mdl-data-table mdl-js-data-table mdl-shadow--2dp full-width">
|
||||
<thead>
|
||||
<tr>
|
||||
<!-- Columns -->
|
||||
<th class="mdl-data-table__cell--non-numeric non-selectable {{col.cssClass}}"
|
||||
*ngFor="let col of columns"
|
||||
[class.column-header]="col.title"
|
||||
[attr.data-automation-id]="'auto_id_' + col.source"
|
||||
[class.mdl-data-table__header--sorted-ascending]="sorting.key === col.source && sorting.direction === 'asc'"
|
||||
[class.mdl-data-table__header--sorted-descending]="sorting.key === col.source && sorting.direction === 'desc'"
|
||||
(click)="onColumnHeaderClick(col)">
|
||||
<span *ngIf="col.srTitle" class="cell-value sr-only">{{col.srTitle}}</span>
|
||||
<span *ngIf="col.title" class="cell-value">{{col.title}}</span>
|
||||
</th>
|
||||
<!-- Actions -->
|
||||
<th>
|
||||
<span class="sr-only">Actions</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let content of folder.list.entries; let idx = index"
|
||||
[attr.data-automation-id]="getObjectValue(content.entry, 'name')">
|
||||
<!-- Columns -->
|
||||
<td *ngFor="let col of columns" [ngSwitch]="col.type"
|
||||
class="mdl-data-table__cell--non-numeric non-selectable data-cell {{col.cssClass}}"
|
||||
(click)="onItemClick(content, $event)"
|
||||
(dblclick)="onItemDblClick(content, $event)"
|
||||
[context-menu]="getContextActions(content)"
|
||||
[attr.data-automation-id]="col.source === '$thumbnail' ? '$thumbnail' : col.source + '_' + getObjectValue(content.entry, col.source)">
|
||||
<div *ngSwitchCase="'image'" class="cell-value">
|
||||
<img class="thumbnail" [src]="getCellValue(content, col)">
|
||||
</div>
|
||||
<div *ngSwitchCase="'date'" class="cell-value">
|
||||
<span>{{ getCellValue(content, col) }}</span>
|
||||
</div>
|
||||
<div *ngSwitchDefault class="cell-value">
|
||||
<span>{{ getCellValue(content, col) }}</span>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<!-- Actions: folder -->
|
||||
<td *ngIf="content.entry.isFolder">
|
||||
<!-- action buttons -->
|
||||
<button class="mdl-button mdl-js-button mdl-button--icon"
|
||||
*ngFor="let action of getContentActions('folder', 'button')"
|
||||
(click)="executeContentAction(content, action)">
|
||||
<i class="material-icons">{{action.icon}}</i>
|
||||
</button>
|
||||
|
||||
<!-- action menu -->
|
||||
<button [id]="'folder_action_menu_' + idx" class="mdl-button mdl-js-button mdl-button--icon">
|
||||
<i class="material-icons">more_vert</i>
|
||||
</button>
|
||||
<ul class="mdl-menu mdl-menu--bottom-right mdl-js-menu mdl-js-ripple-effect"
|
||||
[attr.for]="'folder_action_menu_' + idx">
|
||||
<li class="mdl-menu__item"
|
||||
[attr.data-automation-id]="action.title"
|
||||
*ngFor="let action of getContentActions('folder', 'menu')"
|
||||
(click)="executeContentAction(content, action)">
|
||||
{{action.title}}
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
<!-- Actions: document -->
|
||||
<td *ngIf="!content.entry.isFolder">
|
||||
<!-- action buttons -->
|
||||
<button class="mdl-button mdl-js-button mdl-button--icon"
|
||||
*ngFor="let action of getContentActions('document', 'button')"
|
||||
(click)="executeContentAction(content, action)">
|
||||
<i class="material-icons">{{action.icon}}</i>
|
||||
</button>
|
||||
|
||||
<!-- action menu -->
|
||||
<button [id]="'document_action_menu_' + idx" class="mdl-button mdl-js-button mdl-button--icon">
|
||||
<i class="material-icons">more_vert</i>
|
||||
</button>
|
||||
<ul class="mdl-menu mdl-menu--bottom-right mdl-js-menu mdl-js-ripple-effect"
|
||||
[attr.for]="'document_action_menu_' + idx">
|
||||
<li class="mdl-menu__item"
|
||||
[attr.data-automation-id]="action.title"
|
||||
*ngFor="let action of getContentActions('document', 'menu')"
|
||||
(click)="executeContentAction(content, action)">
|
||||
{{action.title}}
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr *ngIf="folder?.list?.entries?.length === 0">
|
||||
<td class="mdl-data-table__cell--non-numeric empty-folder-content"
|
||||
[attr.colspan]="1 + columns?.length">
|
||||
<template *ngIf="emptyFolderTemplate"
|
||||
ngFor [ngForOf]="[folder]"
|
||||
[ngForTemplate]="emptyFolderTemplate">
|
||||
</template>
|
||||
<img *ngIf="!emptyFolderTemplate"
|
||||
[src]="baseComponentPath + '/img/document-list.empty-folder.png'">
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
@@ -79,6 +79,15 @@ export class DocumentList implements OnInit, AfterViewInit, AfterViewChecked, Af
|
||||
@Input()
|
||||
thumbnails: boolean = false;
|
||||
|
||||
@Input()
|
||||
multiselect: boolean = false;
|
||||
|
||||
@Input()
|
||||
contentActions: boolean = false;
|
||||
|
||||
@Input()
|
||||
contextMenuActions: boolean = false;
|
||||
|
||||
@Output()
|
||||
itemClick: EventEmitter<any> = new EventEmitter();
|
||||
|
||||
@@ -182,6 +191,7 @@ export class DocumentList implements OnInit, AfterViewInit, AfterViewChecked, Af
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.data.thumbnails = this.thumbnails;
|
||||
this.displayFolderContent(this.currentFolderPath);
|
||||
this.contextActionHandler.subscribe(val => this.contextActionCallback(val));
|
||||
}
|
||||
@@ -198,10 +208,10 @@ export class DocumentList implements OnInit, AfterViewInit, AfterViewChecked, Af
|
||||
|
||||
ngAfterViewInit() {
|
||||
if (this.dataTable) {
|
||||
// this.dataTable.contextActionResolver = this.resolveContextAction;
|
||||
if (this.emptyFolderTemplate) {
|
||||
this.dataTable.noContentTemplate = this.emptyFolderTemplate;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -233,6 +243,20 @@ export class DocumentList implements OnInit, AfterViewInit, AfterViewChecked, Af
|
||||
return [];
|
||||
}
|
||||
|
||||
getNodeActions(node: MinimalNodeEntity): ContentActionModel[] {
|
||||
let target = null;
|
||||
|
||||
if (node.entry.isFile) {
|
||||
target = 'document';
|
||||
}
|
||||
|
||||
if (node.entry.isFolder) {
|
||||
target = 'folder';
|
||||
}
|
||||
|
||||
return this.getContentActions(target, 'menu');
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when list row is clicked.
|
||||
* @param item Underlying node item
|
||||
@@ -549,11 +573,33 @@ export class DocumentList implements OnInit, AfterViewInit, AfterViewChecked, Af
|
||||
this.data.setSorting(new DataSorting('id', 'asc'));
|
||||
}
|
||||
|
||||
onRowContextMenu(event) {
|
||||
onShowRowContextMenu(event) {
|
||||
if (this.contextMenuActions) {
|
||||
let args = event.args;
|
||||
let node = (<ShareDataRow> args.row).node;
|
||||
if (node) {
|
||||
args.actions = this.getContextActions(node) || [];
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
onShowRowActionsMenu(event) {
|
||||
if (this.contentActions) {
|
||||
let args = event.args;
|
||||
let node = (<ShareDataRow> args.row).node;
|
||||
if (node) {
|
||||
args.actions = this.getNodeActions(node) || [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onExecuteRowAction(event) {
|
||||
if (this.contentActions) {
|
||||
let args = event.args;
|
||||
let node = (<ShareDataRow> args.row).node;
|
||||
let action = (<ContentActionModel> args.action);
|
||||
this.executeContentAction(node, action);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -25,13 +25,14 @@ import {
|
||||
import { NodePaging, MinimalNodeEntity } from './../models/document-library.model';
|
||||
import { AlfrescoService as DataService } from './../services/alfresco.service';
|
||||
|
||||
|
||||
export class ShareDataTableAdapter implements DataTableAdapter {
|
||||
|
||||
private sorting: DataSorting;
|
||||
private rows: DataRow[];
|
||||
private columns: DataColumn[];
|
||||
|
||||
thumbnails: boolean = false;
|
||||
|
||||
constructor(private dataService: DataService,
|
||||
private basePath: string,
|
||||
schema: DataColumn[]) {
|
||||
@@ -84,14 +85,22 @@ export class ShareDataTableAdapter implements DataTableAdapter {
|
||||
if (col.type === 'image') {
|
||||
|
||||
if (col.key === '$thumbnail') {
|
||||
let isFolder = <boolean> row.getValue('isFolder');
|
||||
if (isFolder) {
|
||||
let node = (<ShareDataRow> row).node;
|
||||
|
||||
if (node.entry.isFolder) {
|
||||
return `${this.basePath}/img/ft_ic_folder.svg`;
|
||||
}
|
||||
|
||||
let isFile = <boolean> row.getValue('isFile');
|
||||
if (isFile) {
|
||||
let mimeType = row.getValue('content.mimeType');
|
||||
if (node.entry.isFile) {
|
||||
|
||||
if (this.thumbnails) {
|
||||
if (this.dataService) {
|
||||
return this.dataService.getDocumentThumbnailUrl(node);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
let mimeType = node.entry.content.mimeType;
|
||||
if (mimeType) {
|
||||
let icon = this.dataService.getMimeTypeIcon(mimeType);
|
||||
if (icon) {
|
||||
|
Reference in New Issue
Block a user