* fix upload area snackbar behaviour

* SASS support for components

ability to use '.scss' files from within components

* [ADF-610] Upload button and DnD area should not upload hidden files and folders (#1908)

[ADF-610]  upload cleanup
- more strongly typing
- api improvements

* Upload cleanup and api improvements

- remove old unused settings (formFields variable)
- individual options for uploaded files (i.e. versioning)
- upload button and drag-and-drop area now set individual settings for file versioning

* exclude hidden files from upload

* [ADF-640] reload document list on folder upload (#1895)

* reload document list on folder upload

- extend UploadService with 'folderCreated' event to be able reacting on folder uploads globally
- extend Demo Shell to reload document list on UploadService events (folderCreated)

* readme updates

* [ADF-621] show drop effect on folders only (#1897)

* show drop effect on folders only

- fix `hasValue` api for data rows (avoid 'false' value to be evaluated as missing value)
- support for evaluating drop support for rows
- document list enables upload zones for folders only

* api improvements as per code review

* [ADF-242] Fixed behaviour for saving/deleting reports (#1905)

* [ADF-242] - fix for deleting - saving a report

* [ADF - 242] added test for fixed feature on reports save - delete

* Added translation key

* [ADF-604] Upgrade @angular/material to latest version (#1909)

* update dependencies and module imports

* fix template warnings and fix import issues

* migrate Activiti Form to MdTabsModule

* fix unit tests

* fix tests

* fix unit tests

* fix unit tests

* disable test that fails only on travis

* upgrade activiti form component to angular/material

* fix test (remove MDL class check)

* [ADF-613] Add plain text viewer (#1873)

* add plain text viewer

* different devices optimizations

* returns types

* [ADF-573] support for toggling enabled state (#1912)

* [ADF-602] Accordion component - Add basic documentation (#1913)

* Add basic documentation Accordion component

* Update README.md

* [ADF-680] Added previous page check when page has no more elements (#1911)

* [ADF-242] - fix for deleting - saving a report

* [ADF - 242] added test for fixed feature on reports save - delete

* [ADF-680] - Fixed behaviour when deleting all files on last page of document list

* Start adding test for documentlist check

* Added test for check double page load

* [ADF-680] - removed commented test code

* [ADF-680] Added changes from peer review

* [ADF-680] added return type

* [ADF-667] selection mode and row styles (#1914)

* selection mode and row styles

- single/multiple/none selection modes for DataTable component (and Document List)
- support for custom row styles (inline and classname values)
- fix karma config (material themes)
- readme updates
- package-lock.json files for NPM5 support
- updated DataTable demo to demonstrate selection modes and row styles

* remove package lock files

* move demo projects to webpack (#1915)

* wav and Mp3 enabling viewer (#1916)

* add option only demo shell version change for update version script

* ADF-402 add the show diagram button (#1917)

* [ADF-707] Ability to select a row on a dynamic table (#1921)

* [ADF-710] Create an Process Attachment List component (#1919)

* added new component to list the process attachments with view, download and delete functionality

* added unit test cases for activit-process-attachment-list component

* exported new process attachment list component

* added documentation for process-attachment-list component

* [ADF-712] Task Attachment - Provide a way to attach a new content (#1898)

* create button, download, view functionality added in task attachment list component

* created sevice to attach document to task

* added new component to create/uplaod attachment to task

* added new component to create/uplaod attachment to task

* added test case for create task attachment component

* added test case for create task attachment component

* added input to block upload document  to ECM

* fixed create task attachment spec file issue

* changed alfresco-upload to alfresco-core upload directive

* removed attachCreate button and emitter from task-attachment-list

* removed uploadToEcm input and checkValidity method from alfresco-upload

* added documentation for task-attachment-list and create-task-attachment components

* [ADF-696] Entire accordion group header should be clickable (#1918)

* #ADF-696 Added new input to show/hide expand icon, click event is activated for the complete heading

* #ADF-696 tslint fix

* #ADF-696 Added documentation for new input and removed unwanted div

* [ADF-721] Fix translation reference for dev task (#1923)

* move translation files in the bundles folder

* fix after review
ripristinate tslint and remove override tsconfig

* [ADF-709] add autofocus when a new row is added on dynamic table widget (#1927)

* [ADF-709] add autofocus when a new row is added on dynamic table widget

* [ADF-709] removed wrong reference for template

* [ADF-713] Process Attachment - Provide a way to attach a new content (#1920)

* added service to get all the related content of the process instance

* added new component to create/upload attachment for process instance

* added unit test cases for create-process-attachment component

* exported create-process-attachment component

* added documentation for create-process-attachment component

* Add data-automation-id to multi select checkbox (#1924)

* [ADF-571] upload feature rework (#1922)

* upload feature rework

lots of improvements for upload dialog and underlying services

* readme update

- readme cleanup
- remove some old comments from code
- update readme with new events for Upload Service

* restore prerequisites section in readme

* fix i18n issue with webpack

* exported report and chart models (#1925)

* fix file upload bug (#1928)

- proper extraction of File objects from the FileList

* lock files for npm 5 (#1930)

add lock files for npm v5; does nothing for earlier versions, so is not harmful

* Source Mapping is not working on test debugging (#1931)

* coverage single components run fix

* remove spec.ts from coverage

* make the coverage and the istanbul-instrumenter-loader works only over the console test because a problem on the remapping for the browser test

* move tslint on the main folder of any component

* remove build:w from readme

* stop build tslint error also in spec files

* clear karma file from unnecessary files

* add set -f for build all script in order to accept *

* fix lint problem and failing tests

* fix failing test search component

* add loader test for viewer

* fix tslint error userinfo

* --max_old_space_size=2048 remove

* fix tslint error uploader unused EventEmitter

* remove spec|index|.*mock|.*model|.*event from coverage

* move coverage separate file and get component to calculate coverage as input

* remove old 'banned' demo from login screen (#1929)

* add sleep time flag in publish script

* rollback demo tag

* fix pacakge.json tag

* [ADF-686] add blobFile as input (#1933)

* coverage fix (#1934)

* [ADF-702] Task/Process Filter - Provide a way to change the default filter (#1932)

* [ADF-702] Task/Process Filter - Provide a way to change the default filter

* Provide a way to select a custom menu filter

* Improve activiti process filter

* Add internal link

* Change link name

* add link

* [ADF-744] Attachment List is not displayed within Processes. (#1937)

* Use the adf process attachment list indise demo shell

* Change documentation

* support for healdess chrome (#1939)

* #ADF-696 Now accordion opens/closes on click of group header along with emitting heading click event (#1936)

* add info and link on current last git commit (#1940)

* [ADF-754] toolbar component (#1938)

* toolbar component

- simple toolbar component (core lib)
- readme updates (core lib)
- update demo shell with toolbar component demo (document list)

* update unit tests

* [ADF-763] Add Chrome default browser for karma chrome launcher for Chrome versi… (#1941)

* Add Chrome default browser for karma chrome launcher for Chrome version<59

* Fixing intermittently failing test in ng2-activiti-analytics component

* Adding new icon (sent) for Bootstrap to Material icon mapping (#1943)

* fix blob input in text viewer (#1942)

* GitHub issue & pull request template change (#1945)

* Update ISSUE_TEMPLATE.md

* Update PULL_REQUEST_TEMPLATE.md

* [ADF-689] Fix alfresco-document-menu-action styling (z-index) (#1944)

* fix translation wrong folder creation issue

* [ADF-773] Fix datatable custom template render (#1947)

* [ADF-780] centralised call for process filters api (#1950)

* [ADF-780] centralised call for process filters api

* [ADF-780] updated conversion to string

* [ADF-741] Add the create task attachment component to the demo shell (#1946)

* Add the create task attachment component to the demo shell

* Add translation keys

* Add return to methods

* fix thumbnail task process list (#1951)

* [ADF-643] upload enhancements (#1949)

* rework folder uploading

- flatterns hierarchy on folder upload
- performs a single traversal for the entire folder heirarchy and ends with a comple file list
- allows now dropping folders on existing folders
- overall code improvements

* fix unit tests

* readme updates

* clean old and unused code

* code cleanup

* limit concurrent uploads

* update code as per review

* fix upload button for Safari

* fixes for Safari

- Safari compatibility
- code updates based on review

* fix code

* fix unit tests

* [ADF-589] Login component different bug fixes (#1953)

* Basic style changes

* Further design changes

* Responsive design fixes

* Different sign in button style for the different login steps

* #ADF-780 Fixed getProcessFilterByName to get the correct filter for the given appId and name (#1952)

* fix issues with the require keyword (angular cli) (#1954)

* [ADF-799] add HappyPack to webpack conf (#1956)

* update npm5 lock files

* [ADF-740] Add button for process attachment list (#1955)

* [ADF-740] adding button to allow user to upload related content on process instance

* [ADF-740] add button for attachment content list for process

* changed locatin for translation

* [ADF-740] added test for add button for process attach

* [ADF-740] added PR request changes

* [ADF-802] fix error on uploading file to attachment list (#1957)

* [ADF-802] fix error on uploading file to attachment list

* [ADF-802] improved for loop

* [ADF-797] remove dist folder from npm distributed package , leave src and bundles (#1961)

* [ADF-804] webpack proxy setup to avoid CORS problem (#1960)

* package lock update

* update travis to node 8 (#1965)

* upload service exposes created nodes (#1964)

* [ADF-591] documentation refinements (#1959)

* refine ng2-activiti-analytics

* refine ng2-activiti-diagrams docs

* refine ng2-activiti-form

* refine ng2-activiti-processlist

* refine ng2-activiti-tasklist

* refine ng2-alfresco-core

* refine ng2-alfresco-datatable

* refine ng2-alfresco-datatable

* refine gn2-alfresco-login

* refine ng2-alfresco-search

* refine ng2-alfresco-social

* refine ng2-alfresco-tag

* refine ng2-alfresco-upload

* refine ng2-alfresco-userinfo

* refine ng2-alfresco-viewer

* refine ng2-alfresco-webscript

* various readme cleanups

* fix builds related to node-sass library (#1966)

* update dependencies and remove old lock files

* update sass loader

* updated lock files

* [ADF-578] Remember me functionality (#1962)

* Remember me functionality

* Happy pack to ng2-components' package.json

* Build fix

* Adding tabindices to viewer control elements (#1968)

* karma conf all single browser

* Fix current page number issue (#1970)

* [ADF-524] Datatable loading state (#1958)

* loading state datatable

* modify readme after review

* [ADF-78]  Update CORS help (#1973)

* Fix host configuration in demo-shell when no port is present (#1971)

* remove brachet

* [ADF-494] fixed readonly rendering for forms (#1972)

* [ADF-494] improved disabling for form

* [ADF-494] fixed readonly rendering for forms

* [ADF-814] application configuration service (#1969)

* app configuration service

* api improvements and readme update

* extend readme and add defaults

* unit tests for app config service

* [ADF-716] Task Header - Use a custom view inside the component (#1967)

* Use a generic custom view inside the task header

* Move the component into core component and change name

* Missing file

* Fix unit test

* fix unit test component name

* fix issue with shared Code settings

- remove obsolete rules for .js/.ts
- hide .happypack folder in the project tree

* [ADF-810] fix default value radio button (#1975)

* [ADF-510] Drag&Drop check permission to allow user to upload a file (#1948)

* [ADF-510] added permission check for drag&drop

* Improved code for drag and drop side

* Added test for drag and drop upload area changes

* Added test for document list permissions check

* [ADF-510] rebased branch after changes applied to upload

* [ADF-510] rebased branch and fixed tests

* [ADF-717] upgrade i18n and charting dependencies (#1976)

* remove app-specific polyfill dependencies

remove polyfill dependencies never used by component libraries

* upgrade i18n dependencies

* upgrade ng2-charts dependency

* fix unit tests

* update demo projects

* [ADF-524] Fix empty state after the loading introduction (#1980)

* fix empty state after the loading introduction

* Update document-list.component.spec.ts

remove typo

* [ADF-838] Table of content automatic creation (#1981)

* readonly value set

* Table of content automatic creation (#1982)

* add missing intl dependency for demo shell (#1984)

* [ADF-833] DataTable -  improve the single and double click event (#1979)

* Improve the single and double click event

* Fix unit test

* Task header basic documentation (#1985)

* Disable upload attachment when the task is completed (#1987)

* [ADF-847] upgrade to use application configuration service (#1986)

* migrate core lib to use server-side app config

* fix unit tests

* update Search tests

- update tests
- upgrade tests to use TestBed

* update UserInfo tests

* update Social tests

* update tests

* update unit tests

* cleanup old code

* update about page

* update demo shell readme

* dev and prod configurations

* updated package-lock file and removed duplicates in package.json

* [ADF-851] execute-outcome event for form service (#1989)

* execute-outcome event for form service

* readme updates

* fix loading state excluding other state during the loading (#1991)

* Fix compilation error (#1993)

* [ADF-883] Fix build errors (#1992)

* [ADF-793] Ability to create PDF renditions in case of non supported formats (#1994)

* Style changes and button

* Convert to PDF button

* Convert to PDF button part II.

* Convert within the Not Supported Format component

* Rendition loading skeleton

* Conversion is working.

* Convert button behaviour tests

* Rebasing fix.

* app settings page (#1997)

- custom app setttings service to use isolated storage (demo shell)
- restore settings UI
- redirect angular and rxjs to the same version as components use.

* [ADF-822] Added the npm-prepublish script (#1978)

* added the npm prepublish script

* changed permissions to prepublish script

* changed to npm run prepublish

* prepare the pr

* removed useless code to the script

* remove flags lib from demo shell (#1983)

* remove flags lib from demo shell

greatly reduce demo shell webpack resources by switching off flags (only 3 icons were displayed in the past)

* merge package.json

* add icons

* Fix typo error

* [ADF-794] Add people assignment component (#1977)

* Add people component

* exported people service

* added people-list component to show the involved user list

* changed people-search component layout

* changed people-list usage in people component

* changed people-list data table from custom template to data adapter

* changes people-search component related to people-list

* changes in activiti-people related to people-list and people-search component

* changed data adapter to direct data column setting to data-table

* removed ngChanges and added User and UserEvent models

* added User and UserEvent model in emitter and other emitter handler

* added user event model

* changed activiti-people component with latest UX changes

* addedand changed translate keys to the components

* added hasUser method to check the condition in html

* fixed tslint issue and test case issue in activiti-people component

* added test case for actviti-people-list component

* test case added for activiti-people-search component

* changed activiti-people test cases according to latest UX changes

* added description for activiti-people component

* changed test case to fix component.upgradeElement issue

* changes requested by Vito Albano #1

* splitted getDisplayUser into getDisplayUser and getInitialUsername

* introduce check type definition

* [ADF-897] - ActivitiPeopleList - use the adf prefix (#2001)

* Use the adf as prexif instead of activiti

* Fix typo

* Fix wrong import

* support binding [form] data directly (#1996)

- ability to bind [form] data directly inside `<activiti-form>` component
- ability to parse forms with FormService
- demo of the custom form in demo shell

* [ADF-778] cancel window for upload dialog shows only on complete (#2003)

* [ADF-778] Added new behaviour to upload dialog

* [ADF-778] cancel window for upload dialog shows only on complete

* [ADF-778] changed variable name to showCloseButton

* Create task/process attachment Compilation error (#2004)

* fix tslint errors

minor fix for "Unnecessary semicolon" TSLint rule

* [ADF-842] Fixed type for taskdetails (#2009)

* fix type definition (#2002)

* Use the activiti people with the new look and feel inside the demo shell (#2008)

* add rxjs and @angular in tsconfig.json

* [ADF-843] Form events bus (#1990)

* form events bus

* event test bus fix

* fix test after code review

* fix types errors

* change to public formservice

* make optional formservice

* [ADF-915] Add option to change the JS-API with different version in the update package

* Missing keys (#2011)

* [ADF-845] breadcrumb root option added and style review (#1999)

* breadcrumb root option added and style review

* new breadcrumbs

* split onchange in a method

* update readme with a note for old pefix tag

* fix tslint errors

* fix breadcrumb test

* [ADF-922] Regenerate package-lock.json files for every package and create script for doing that in the future (#2012)

* Updated package-lock.json files

* npm-relock-pkgs.sh

* Update README.md

* Fix ng2-alfresco-search sass problem

* SASS version update (#2013)

* sass update

* update sass loader

* vjsapi option prepublish

* prepublish script deprecation in favour of prepublishOnly node 8 (#2010)

* modify prePublish script with preoPublishOnly

* install rimraf globally

* fix clean scripts demo folders

* move appveyor to node 8

* Appveyor test (#1998)

* reduce memory

* remove max-old-space

* remove increase memory

* create new TaskDetailsModel in loadNextTask (#2017)

* Fix readme document list

* [ADF-907] - Form reacts to data added in input (#2016)

* [ADF-907] Enable activiti form to react on value data changes

* [ADF-907] - Form reacts to data added in input]

* [ADF - 907] added mock json for form

* [ADF-907] added new event of the form to the event list

* [ADF - 907] Added return column to README

* [ADF - 907] Added return column to README

* Script add pkg and clean update

* install globally pkg pre build

* Fix upload related content (#2019)

* regeneration TOC and add automatic list component generator (#2022)

* Fix upload process attachment (#2024)

* update typescript (#2026)

* update viewer readme

* fix type definition variables

* NgZone type passed parameter

* fix tslint error in tasklist

* Add screenshot (#2028)

* fix search miss typing

* bump version 1.6.0 (#2027)
This commit is contained in:
Eugenio Romano
2017-06-29 15:57:37 +01:00
committed by GitHub
parent c6f6227da7
commit b15ab3b988
822 changed files with 168022 additions and 13865 deletions

View File

@@ -26,11 +26,20 @@
/* Empty folder */
:host .no-content-container {
:host .adf-no-content-container {
padding: 0 !important;
}
:host .no-content-container > img {
:host .adf-no-content-container > img {
width: 100%;
}
/* Loading folder */
:host .adf-loading-content-container {
padding: 0 !important;
}
:host .adf-loading-content-container > img {
width: 100%;
}
@@ -109,11 +118,15 @@
}
.alfresco-datatable__row:focus {
outline-offset: -4px;
outline-offset: -1px;
outline-width: 1px;
outline-color: rgb(68,138,255);
outline-style: solid;
}
.alfresco-datatable__row--selected {
color: rgb(68,138,255);
.alfresco-datatable__row--selected,
.alfresco-datatable__row--selected:hover {
background-color: #e0e0e0;
}
.adf-upload__dragging > td {

View File

@@ -29,95 +29,112 @@
</thead>
<tbody>
<tr *ngFor="let row of data.getRows(); let idx = index" tabindex="0"
class="alfresco-datatable__row"
[class.alfresco-datatable__row--selected]="selectedRow === row"
[adf-upload]="allowDropFiles" [adf-upload-data]="row">
<ng-container *ngIf="!loading">
<tr *ngFor="let row of data.getRows(); let idx = index" tabindex="0"
class="alfresco-datatable__row"
[class.alfresco-datatable__row--selected]="row.isSelected"
[adf-upload]="allowDropFiles && rowAllowsDrop(row)" [adf-upload-data]="row"
[ngStyle]="rowStyle"
[ngClass]="rowStyleClass">
<!-- Actions (left) -->
<td *ngIf="actions && actionsPosition === 'left'" class="alfresco-datatable__actions-cell">
<button [id]="'action_menu_' + idx" alfresco-mdl-button class="mdl-button--icon" [attr.data-automation-id]="actions_menu">
<i class="material-icons">more_vert</i>
</button>
<ul alfresco-mdl-menu class="mdl-menu--bottom-left"
[attr.for]="'action_menu_' + idx">
<li class="mdl-menu__item" [attr.disabled]="action.disabled"
[attr.data-automation-id]="action.title"
*ngFor="let action of getRowActions(row)"
(click)="onExecuteRowAction(row, action)">
{{action.title}}
</li>
</ul>
</td>
<!-- Actions (left) -->
<td *ngIf="actions && actionsPosition === 'left'" class="alfresco-datatable__actions-cell">
<button [id]="'action_menu_' + idx" alfresco-mdl-button class="mdl-button--icon"
[attr.data-automation-id]="actions_menu">
<i class="material-icons">more_vert</i>
</button>
<ul alfresco-mdl-menu class="mdl-menu--bottom-left"
[attr.for]="'action_menu_' + idx">
<li class="mdl-menu__item" [attr.disabled]="action.disabled"
[attr.data-automation-id]="action.title"
*ngFor="let action of getRowActions(row)"
(click)="onExecuteRowAction(row, action)">
{{action.title}}
</li>
</ul>
</td>
<td *ngIf="multiselect">
<md-checkbox [(ngModel)]="row.isSelected"></md-checkbox>
</td>
<td *ngFor="let col of data.getColumns()"
class="mdl-data-table__cell--non-numeric non-selectable data-cell {{col.cssClass}}"
(click)="onRowClick(row, $event)"
(dblclick)="onRowDblClick(row, $event)"
[context-menu]="getContextMenuActions(row, col)"
[context-menu-enabled]="contextMenu">
<div *ngIf="!col.template" class="cell-container">
<ng-container [ngSwitch]="col.type">
<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="{{ iconAltTextKey(data.getValue(row, col)) | translate }}"
src="{{ data.getValue(row, col) }}"
(error)="onImageLoadingError($event)">
</div>
<div *ngSwitchCase="'icon'" class="cell-value">
<img class="image-cell"
alt="{{ iconAltTextKey(data.getValue(row, col)) | translate }}"
src="{{ data.getValue(row, col) }}"
(error)="onImageLoadingError($event)">
</div>
<div *ngSwitchCase="'date'" class="cell-value" [attr.data-automation-id]="'date_' + data.getValue(row, col)">
<alfresco-datatable-cell [data]="data" [column]="col" [row]="row"></alfresco-datatable-cell>
</div>
<div *ngSwitchCase="'text'" class="cell-value" [attr.data-automation-id]="'text_' + data.getValue(row, col)">
<alfresco-datatable-cell [data]="data" [column]="col" [row]="row"></alfresco-datatable-cell>
</div>
<td *ngIf="multiselect">
<md-checkbox [(ngModel)]="row.isSelected"></md-checkbox>
</td>
<td *ngFor="let col of data.getColumns()"
class="mdl-data-table__cell--non-numeric non-selectable data-cell {{col.cssClass}}"
(click)="onRowClick(row, $event)"
[context-menu]="getContextMenuActions(row, col)"
[context-menu-enabled]="contextMenu">
<div *ngIf="!col.template" class="cell-container">
<ng-container [ngSwitch]="col.type">
<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="{{ iconAltTextKey(data.getValue(row, col)) | translate }}"
src="{{ data.getValue(row, col) }}"
(error)="onImageLoadingError($event)">
</div>
<div *ngSwitchCase="'icon'" class="cell-value">
<img class="image-cell"
alt="{{ iconAltTextKey(data.getValue(row, col)) | translate }}"
src="{{ data.getValue(row, col) }}"
(error)="onImageLoadingError($event)">
</div>
<div *ngSwitchCase="'date'" class="cell-value"
[attr.data-automation-id]="'date_' + data.getValue(row, col)">
<alfresco-datatable-cell [data]="data" [column]="col" [row]="row"></alfresco-datatable-cell>
</div>
<div *ngSwitchCase="'text'" class="cell-value"
[attr.data-automation-id]="'text_' + data.getValue(row, col)">
<alfresco-datatable-cell [data]="data" [column]="col" [row]="row"></alfresco-datatable-cell>
</div>
<span *ngSwitchDefault class="cell-value">
<!-- empty cell for unknown column type -->
</span>
</ng-container>
</div>
<div *ngIf="col.template" class="cell-container">
<ng-container
[ngTemplateOutlet]="col.template"
[ngOutletContext]="{ $implicit: { data: data, row: row, col: col }, value: data.getValue(row, col) }">
</ng-container>
</div>
</td>
</ng-container>
</div>
<div *ngIf="col.template" class="cell-container">
<ng-container
[ngTemplateOutlet]="col.template"
[ngOutletContext]="{ $implicit: { data: data, row: row, col: col }, value: data.getValue(row, col) }">
</ng-container>
</div>
</td>
<!-- Actions (right) -->
<td *ngIf="actions && actionsPosition === 'right'" class="alfresco-datatable__actions-cell">
<button [id]="'action_menu_' + idx" alfresco-mdl-button class="mdl-button--icon" [attr.data-automation-id]="actions_menu">
<i class="material-icons">more_vert</i>
</button>
<ul alfresco-mdl-menu class="mdl-menu--bottom-right"
[attr.for]="'action_menu_' + idx">
<li class="mdl-menu__item" [attr.disabled]="action.disabled || undefined"
[attr.data-automation-id]="action.title"
*ngFor="let action of getRowActions(row)"
(click)="onExecuteRowAction(row, action)">
{{action.title}}
</li>
</ul>
</td>
<!-- Actions (right) -->
<td *ngIf="actions && actionsPosition === 'right'" class="alfresco-datatable__actions-cell">
<button [id]="'action_menu_' + idx" alfresco-mdl-button class="mdl-button--icon"
[attr.data-automation-id]="actions_menu">
<i class="material-icons">more_vert</i>
</button>
<ul alfresco-mdl-menu class="mdl-menu--bottom-right"
[attr.for]="'action_menu_' + idx">
<li class="mdl-menu__item" [attr.disabled]="action.disabled || undefined"
[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 no-content-container"
</tr>
<tr *ngIf="data.getRows().length === 0">
<td class="mdl-data-table__cell--non-numeric adf-no-content-container"
[attr.colspan]="1 + data.getColumns().length">
<ng-template *ngIf="noContentTemplate"
ngFor [ngForOf]="[data]"
[ngForTemplate]="noContentTemplate">
</ng-template>
</td>
</tr>
</ng-container>
<tr *ngIf="loading">
<td class="mdl-data-table__cell--non-numeric adf-loading-content-container"
[attr.colspan]="1 + data.getColumns().length">
<template *ngIf="noContentTemplate"
ngFor [ngForOf]="[data]"
[ngForTemplate]="noContentTemplate">
</template>
<ng-template *ngIf="loadingTemplate"
ngFor [ngForOf]="[data]"
[ngForTemplate]="loadingTemplate">
</ng-template>
</td>
</tr>
</tbody>

View File

@@ -18,7 +18,7 @@
import { SimpleChange } from '@angular/core';
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
import { CoreModule } from 'ng2-alfresco-core';
import { MdCheckboxChange } from '@angular/material';
import { MdCheckboxModule, MdCheckboxChange } from '@angular/material';
import { DataTableComponent } from './datatable.component';
import { DataTableCellComponent } from './datatable-cell.component';
import {
@@ -39,7 +39,8 @@ describe('DataTable', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
CoreModule.forRoot()
CoreModule.forRoot(),
MdCheckboxModule
],
declarations: [
DataTableCellComponent,
@@ -52,7 +53,6 @@ describe('DataTable', () => {
fixture = TestBed.createComponent(DataTableComponent);
dataTable = fixture.componentInstance;
element = fixture.debugElement.nativeElement;
//fixture.detectChanges();
});
beforeEach(() => {
@@ -66,6 +66,95 @@ describe('DataTable', () => {
};
});
it('should reset selection on mode change', () => {
spyOn(dataTable, 'resetSelection').and.callThrough();
dataTable.data = new ObjectDataTableAdapter(
[
{ name: '1' },
{ name: '2' }
],
[ new ObjectDataColumn({ key: 'name'}) ]
);
const rows = dataTable.data.getRows();
rows[0].isSelected = true;
rows[1].isSelected = true;
expect(rows[0].isSelected).toBeTruthy();
expect(rows[1].isSelected).toBeTruthy();
dataTable.ngOnChanges({
selectionMode: new SimpleChange(null, 'multiple', false)
});
expect(dataTable.resetSelection).toHaveBeenCalled();
});
it('should select only one row with [single] selection mode', () => {
dataTable.selectionMode = 'single';
dataTable.data = new ObjectDataTableAdapter(
[
{ name: '1' },
{ name: '2' }
],
[ new ObjectDataColumn({ key: 'name'}) ]
);
const rows = dataTable.data.getRows();
dataTable.ngOnChanges({});
dataTable.onRowClick(rows[0], null);
expect(rows[0].isSelected).toBeTruthy();
expect(rows[1].isSelected).toBeFalsy();
dataTable.onRowClick(rows[1], null);
expect(rows[0].isSelected).toBeFalsy();
expect(rows[1].isSelected).toBeTruthy();
});
it('should unselect the row with [single] selection mode', () => {
dataTable.selectionMode = 'single';
dataTable.data = new ObjectDataTableAdapter(
[
{ name: '1' },
{ name: '2' }
],
[ new ObjectDataColumn({ key: 'name'}) ]
);
const rows = dataTable.data.getRows();
dataTable.ngOnChanges({});
dataTable.onRowClick(rows[0], null);
expect(rows[0].isSelected).toBeTruthy();
expect(rows[1].isSelected).toBeFalsy();
dataTable.onRowClick(rows[0], null);
expect(rows[0].isSelected).toBeFalsy();
expect(rows[1].isSelected).toBeFalsy();
});
it('should select multiple rows with [multiple] selection mode', () => {
dataTable.selectionMode = 'multiple';
dataTable.data = new ObjectDataTableAdapter(
[
{ name: '1' },
{ name: '2' }
],
[ new ObjectDataColumn({ key: 'name'}) ]
);
const rows = dataTable.data.getRows();
const event = new MouseEvent('click', {
metaKey: true
});
dataTable.ngOnChanges({});
dataTable.onRowClick(rows[0], event);
dataTable.onRowClick(rows[1], event);
expect(rows[0].isSelected).toBeTruthy();
expect(rows[1].isSelected).toBeTruthy();
});
it('should put actions menu to the right by default', () => {
dataTable.data = new ObjectDataTableAdapter([], [
<DataColumn> {},
@@ -98,7 +187,7 @@ describe('DataTable', () => {
it('should initialize default adapter', () => {
let table = new DataTableComponent(null);
expect(table.data).toBeUndefined();
table.ngAfterContentInit();
table.ngOnChanges({'data': new SimpleChange('123', {}, true)});
expect(table.data).toEqual(jasmine.any(ObjectDataTableAdapter));
});
@@ -126,18 +215,65 @@ describe('DataTable', () => {
done();
});
dataTable.ngOnChanges({});
dataTable.onRowClick(row, null);
});
it('should emit row double-click event', done => {
let row = <DataRow> {};
it('should emit double click if there are two single click in 250ms', (done) => {
dataTable.rowDblClick.subscribe(e => {
expect(e.value).toBe(row);
let row = <DataRow> {};
dataTable.ngOnChanges({});
dataTable.rowDblClick.subscribe( () => {
done();
});
dataTable.onRowDblClick(row, null);
dataTable.onRowClick(row, null);
setTimeout(() => {
dataTable.onRowClick(row, null);
}
, 240);
});
it('should emit double click if there are more than two single click in 250ms', (done) => {
let row = <DataRow> {};
dataTable.ngOnChanges({});
dataTable.rowDblClick.subscribe( () => {
done();
});
dataTable.onRowClick(row, null);
setTimeout(() => {
dataTable.onRowClick(row, null);
dataTable.onRowClick(row, null);
}
, 240);
});
it('should emit single click if there are two single click in more than 250ms', (done) => {
let row = <DataRow> {};
let clickCount = 0;
dataTable.ngOnChanges({});
dataTable.rowClick.subscribe( () => {
clickCount += 1;
if (clickCount === 2) {
done();
}
});
dataTable.onRowClick(row, null);
setTimeout(() => {
dataTable.onRowClick(row, null);
}
, 260);
});
it('should emit row-click dom event', (done) => {
@@ -148,6 +284,7 @@ describe('DataTable', () => {
done();
});
dataTable.ngOnChanges({});
dataTable.onRowClick(row, null);
});
@@ -158,8 +295,9 @@ describe('DataTable', () => {
expect(e.detail.value).toBe(row);
done();
});
dataTable.onRowDblClick(row, null);
dataTable.ngOnChanges({});
dataTable.onRowClick(row, null);
dataTable.onRowClick(row, null);
});
it('should prevent default behaviour on row click event', () => {
@@ -171,13 +309,14 @@ describe('DataTable', () => {
it('should prevent default behaviour on row double-click event', () => {
let e = jasmine.createSpyObj('event', ['preventDefault']);
dataTable.ngOnChanges({});
dataTable.ngAfterContentInit();
dataTable.onRowDblClick(null, e);
expect(e.preventDefault).toHaveBeenCalled();
});
it('should not sort if column is missing', () => {
dataTable.ngAfterContentInit();
dataTable.ngOnChanges({'data': new SimpleChange('123', {}, true)});
let adapter = dataTable.data;
spyOn(adapter, 'setSorting').and.callThrough();
dataTable.onColumnHeaderClick(null);
@@ -185,7 +324,7 @@ describe('DataTable', () => {
});
it('should not sort upon clicking non-sortable column header', () => {
dataTable.ngAfterContentInit();
dataTable.ngOnChanges({'data': new SimpleChange('123', {}, true)});
let adapter = dataTable.data;
spyOn(adapter, 'setSorting').and.callThrough();
@@ -198,7 +337,7 @@ describe('DataTable', () => {
});
it('should set sorting upon column header clicked', () => {
dataTable.ngAfterContentInit();
dataTable.ngOnChanges({'data': new SimpleChange('123', {}, true)});
let adapter = dataTable.data;
spyOn(adapter, 'setSorting').and.callThrough();
@@ -217,7 +356,7 @@ describe('DataTable', () => {
});
it('should invert sorting upon column header clicked', () => {
dataTable.ngAfterContentInit();
dataTable.ngOnChanges({'data': new SimpleChange('123', {}, true)});
let adapter = dataTable.data;
let sorting = new DataSorting('column_1', 'asc');
@@ -294,7 +433,7 @@ describe('DataTable', () => {
it('should allow "select all" calls with no rows', () => {
dataTable.multiselect = true;
dataTable.ngAfterContentInit();
dataTable.ngOnChanges({'data': new SimpleChange('123', {}, true)});
dataTable.onSelectAllClick(<MdCheckboxChange> { checked: true });
expect(dataTable.isSelectAllChecked).toBe(true);
@@ -382,13 +521,13 @@ describe('DataTable', () => {
});
it('should require adapter sorting to evaluate sorting state', () => {
dataTable.ngAfterContentInit();
dataTable.ngOnChanges({'data': new SimpleChange('123', {}, true)});
spyOn(dataTable.data, 'getSorting').and.returnValue(null);
expect(dataTable.isColumnSorted(<DataColumn> {}, 'asc')).toBeFalsy();
});
it('should evaluate column sorting state', () => {
dataTable.ngAfterContentInit();
dataTable.ngOnChanges({'data': new SimpleChange('123', {}, true)});
spyOn(dataTable.data, 'getSorting').and.returnValue(new DataSorting('column_1', 'asc'));
expect(dataTable.isColumnSorted(<DataColumn> {key: 'column_1'}, 'asc')).toBeTruthy();
expect(dataTable.isColumnSorted(<DataColumn> {key: 'column_2'}, 'desc')).toBeFalsy();

View File

@@ -15,25 +15,13 @@
* limitations under the License.
*/
import {
Component,
OnChanges,
SimpleChange,
SimpleChanges,
Input,
Output,
EventEmitter,
ElementRef,
TemplateRef,
AfterContentInit,
ContentChild,
Optional
} from '@angular/core';
import { Component, OnChanges, SimpleChange, SimpleChanges, Input, Output, EventEmitter, ElementRef, TemplateRef, AfterContentInit, ContentChild, Optional } from '@angular/core';
import { DataTableAdapter, DataRow, DataColumn, DataSorting, DataRowEvent, ObjectDataTableAdapter, ObjectDataRow } from '../../data/index';
import { DataCellEvent } from './data-cell.event';
import { DataRowActionEvent } from './data-row-action.event';
import { DataColumnListComponent } from 'ng2-alfresco-core';
import { MdCheckboxChange } from '@angular/material';
import { Observable, Observer } from 'rxjs/Rx';
declare var componentHandler;
@@ -52,6 +40,9 @@ export class DataTableComponent implements AfterContentInit, OnChanges {
@Input()
rows: any[] = [];
@Input()
selectionMode: string = 'single'; // none|single|multiple
@Input()
multiselect: boolean = false;
@@ -70,6 +61,12 @@ export class DataTableComponent implements AfterContentInit, OnChanges {
@Input()
allowDropFiles: boolean = false;
@Input()
rowStyle: string;
@Input()
rowStyleClass: string;
@Output()
rowClick: EventEmitter<DataRowEvent> = new EventEmitter<DataRowEvent>();
@@ -85,32 +82,60 @@ export class DataTableComponent implements AfterContentInit, OnChanges {
@Output()
executeRowAction: EventEmitter<DataRowActionEvent> = new EventEmitter<DataRowActionEvent>();
noContentTemplate: TemplateRef<any>;
@Input()
loading: boolean = false;
public noContentTemplate: TemplateRef<any>;
public loadingTemplate: TemplateRef<any>;
isSelectAllChecked: boolean = false;
get selectedRow(): DataRow {
return this.data.selectedRow;
}
private clickObserver: Observer<DataRowEvent>;
private click$: Observable<DataRowEvent>;
constructor(@Optional() private el: ElementRef) {
this.click$ = new Observable<DataRowEvent>(observer => this.clickObserver = observer).share();
}
ngAfterContentInit() {
this.loadTable();
this.setTableSchema();
this.setupMaterialComponents();
}
ngAfterViewInit() {
this.setupMaterialComponents();
}
private setupMaterialComponents(): boolean {
// workaround for MDL issues with dynamic components
if (componentHandler) {
componentHandler.upgradeAllRegistered();
return true;
}
return false;
}
ngOnChanges(changes: SimpleChanges) {
this.initAndSubscribeClickStream();
if (this.isPropertyChanged(changes['data'])) {
this.loadTable();
if (this.isTableEmpty()) {
this.initTable();
}
return;
}
if (this.isPropertyChanged(changes['rows'])) {
if (this.data) {
this.data.setRows(this.convertToRowsData(changes['rows'].currentValue));
if (this.isTableEmpty()) {
this.initTable();
} else {
this.setTableRows(changes['rows'].currentValue);
}
return;
}
if (changes.selectionMode && !changes.selectionMode.isFirstChange()) {
this.resetSelection();
}
}
isPropertyChanged(property: SimpleChange): boolean {
@@ -121,50 +146,107 @@ export class DataTableComponent implements AfterContentInit, OnChanges {
return rows.map(row => new ObjectDataRow(row));
}
loadTable() {
private initAndSubscribeClickStream() {
let singleClickStream = this.click$
.buffer(this.click$.debounceTime(250))
.map(list => list)
.filter(x => x.length === 1);
singleClickStream.subscribe((obj: DataRowEvent[]) => {
let event: DataRowEvent = obj[0];
let el = obj[0].sender.el;
this.rowClick.emit(event);
if (!event.defaultPrevented && el.nativeElement) {
el.nativeElement.dispatchEvent(
new CustomEvent('row-click', {
detail: event,
bubbles: true
})
);
}
});
let multiClickStream = this.click$
.buffer(this.click$.debounceTime(250))
.map(list => list)
.filter(x => x.length >= 2);
multiClickStream.subscribe((obj: DataRowEvent[]) => {
let event: DataRowEvent = obj[0];
let el = obj[0].sender.el;
this.rowDblClick.emit(event);
if (!event.defaultPrevented && el.nativeElement) {
el.nativeElement.dispatchEvent(
new CustomEvent('row-dblclick', {
detail: event,
bubbles: true
})
);
}
});
}
private initTable() {
this.data = new ObjectDataTableAdapter(this.rows, []);
}
isTableEmpty() {
return this.data === undefined || this.data === null;
}
private setTableRows(rows) {
if (this.data) {
this.data.setRows(this.convertToRowsData(rows));
}
}
private setTableSchema() {
let schema: DataColumn[] = [];
if (this.columnList && this.columnList.columns) {
schema = this.columnList.columns.map(c => <DataColumn> c);
}
if (!this.data) {
this.data = new ObjectDataTableAdapter(this.rows, schema);
} else {
this.setHtmlColumnConfigurationOnObjectAdapter(schema);
}
// workaround for MDL issues with dynamic components
if (componentHandler) {
componentHandler.upgradeAllRegistered();
}
}
private setHtmlColumnConfigurationOnObjectAdapter(schema: DataColumn[]) {
if (schema && schema.length > 0) {
if (this.data && schema && schema.length > 0) {
this.data.setColumns(schema);
}
}
onRowClick(row: DataRow, e?: Event) {
onRowClick(row: DataRow, e: MouseEvent) {
if (e) {
e.preventDefault();
}
if (this.data) {
this.data.selectedRow = row;
if (row) {
if (this.data) {
const newValue = !row.isSelected;
const rows = this.data.getRows();
if (this.isSingleSelectionMode()) {
rows.forEach(r => r.isSelected = false);
row.isSelected = newValue;
}
if (this.isMultiSelectionMode()) {
const modifier = e.metaKey || e.ctrlKey;
if (!modifier) {
rows.forEach(r => r.isSelected = false);
}
row.isSelected = newValue;
}
}
let dataRowEvent = new DataRowEvent(row, e, this);
this.clickObserver.next(dataRowEvent);
}
}
let event = new DataRowEvent(row, e, this);
this.rowClick.emit(event);
if (!event.defaultPrevented && this.el.nativeElement) {
this.el.nativeElement.dispatchEvent(
new CustomEvent('row-click', {
detail: event,
bubbles: true
})
);
resetSelection(): void {
if (this.data) {
const rows = this.data.getRows();
if (rows && rows.length > 0) {
rows.forEach(r => r.isSelected = false);
}
}
}
@@ -172,18 +254,8 @@ export class DataTableComponent implements AfterContentInit, OnChanges {
if (e) {
e.preventDefault();
}
let event = new DataRowEvent(row, e, this);
this.rowDblClick.emit(event);
if (!event.defaultPrevented && this.el.nativeElement) {
this.el.nativeElement.dispatchEvent(
new CustomEvent('row-dblclick', {
detail: event,
bubbles: true
})
);
}
let dataRowEvent = new DataRowEvent(row, e, this);
this.clickObserver.next(dataRowEvent);
}
onColumnHeaderClick(column: DataColumn) {
@@ -264,4 +336,20 @@ export class DataTableComponent implements AfterContentInit, OnChanges {
this.executeRowAction.emit(new DataRowActionEvent(row, action));
}
}
rowAllowsDrop(row: DataRow): boolean {
return row.isDropTarget === true;
}
hasSelectionMode(): boolean {
return this.isSingleSelectionMode() || this.isMultiSelectionMode();
}
isSingleSelectionMode(): boolean {
return this.selectionMode && this.selectionMode.toLowerCase() === 'single';
}
isMultiSelectionMode(): boolean {
return this.selectionMode && this.selectionMode.toLowerCase() === 'multiple';
}
}

View File

@@ -16,5 +16,4 @@
*/
export * from './datatable.component';
export * from './no-content-template.component';
export * from './datatable-cell.component';

View File

@@ -32,6 +32,7 @@ export interface DataTableAdapter {
export interface DataRow {
isSelected: boolean;
isDropTarget?: boolean;
hasValue(key: string): boolean;
getValue(key: string): any;
}

View File

@@ -15,10 +15,13 @@
* limitations under the License.
*/
import { TemplateRef } from '@angular/core';
import { DatePipe } from '@angular/common';
import { ObjectUtils } from 'ng2-alfresco-core';
import { DataTableAdapter, DataRow, DataColumn, DataSorting } from './datatable-adapter';
declare var require: any;
// Simple implementation of the DataTableAdapter interface.
export class ObjectDataTableAdapter implements DataTableAdapter {
@@ -196,12 +199,11 @@ export class ObjectDataTableAdapter implements DataTableAdapter {
// Simple implementation of the DataRow interface.
export class ObjectDataRow implements DataRow {
isSelected: boolean = false;
constructor(private obj: any) {
constructor(private obj: any, public isSelected: boolean = false) {
if (!obj) {
throw new Error('Object source not found');
}
}
getValue(key: string): any {
@@ -209,7 +211,7 @@ export class ObjectDataRow implements DataRow {
}
hasValue(key: string): boolean {
return this.getValue(key) ? true : false;
return this.getValue(key) !== undefined;
}
}
@@ -222,6 +224,7 @@ export class ObjectDataColumn implements DataColumn {
title: string;
srTitle: string;
cssClass: string;
template?: TemplateRef<any>;
constructor(obj: any) {
this.key = obj.key;
@@ -230,5 +233,6 @@ export class ObjectDataColumn implements DataColumn {
this.title = obj.title;
this.srTitle = obj.srTitle;
this.cssClass = obj.cssClass;
this.template = obj.template;
}
}

View File

@@ -0,0 +1,19 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export * from './no-content-template.component';
export * from './loading-template.component';

View File

@@ -0,0 +1,41 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { LoadingContentTemplateComponent } from './loading-template.component';
import { Injector } from '@angular/core';
import { getTestBed, TestBed } from '@angular/core/testing';
import { DataTableComponent } from '../components/datatable/datatable.component';
describe('LoadingContentTemplateComponent', () => {
let injector: Injector;
let loadingContentTemplateComponent: LoadingContentTemplateComponent;
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
LoadingContentTemplateComponent,
DataTableComponent
]
});
injector = getTestBed();
loadingContentTemplateComponent = injector.get(LoadingContentTemplateComponent);
});
it('is defined', () => {
expect(loadingContentTemplateComponent).toBeDefined();
});
});

View File

@@ -0,0 +1,36 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Directive, ContentChild, TemplateRef, AfterContentInit } from '@angular/core';
import { DataTableComponent } from '../components/datatable/datatable.component';
@Directive({
selector: 'loading-content-template'
})
export class LoadingContentTemplateComponent implements AfterContentInit {
@ContentChild(TemplateRef)
template: any;
constructor(private dataTable: DataTableComponent) {
}
ngAfterContentInit() {
this.dataTable.loadingTemplate = this.template;
}
}

View File

@@ -15,10 +15,10 @@
* limitations under the License.
*/
import { NoContentTemplateComponent } from '../datatable/no-content-template.component';
import { NoContentTemplateComponent } from './no-content-template.component';
import { Injector } from '@angular/core';
import { getTestBed, TestBed } from '@angular/core/testing';
import { DataTableComponent } from './datatable.component';
import { DataTableComponent } from '../components/datatable/datatable.component';
describe('NoContentTemplateComponent', () => {
let injector: Injector;

View File

@@ -15,13 +15,8 @@
* limitations under the License.
*/
import {
Directive,
ContentChild,
TemplateRef,
AfterContentInit
} from '@angular/core';
import { DataTableComponent } from './datatable.component';
import { Directive, ContentChild, TemplateRef, AfterContentInit } from '@angular/core';
import { DataTableComponent } from '../components/datatable/datatable.component';
@Directive({
selector: 'no-content-template'
@@ -31,8 +26,7 @@ export class NoContentTemplateComponent implements AfterContentInit {
@ContentChild(TemplateRef)
template: any;
constructor(
private dataTable: DataTableComponent) {
constructor(private dataTable: DataTableComponent) {
}
ngAfterContentInit() {

View File

@@ -0,0 +1,3 @@
{
}