mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-19 17:14:57 +00:00
Merge pull request #372 from Alfresco/dev-denys-340
Integrate datatable in the documentlist #340
This commit is contained in:
commit
3881faec42
@ -17,7 +17,8 @@ before_install:
|
|||||||
- export CHROME_BIN=/usr/bin/google-chrome
|
- export CHROME_BIN=/usr/bin/google-chrome
|
||||||
- export DISPLAY=:99.0
|
- export DISPLAY=:99.0
|
||||||
- sh -e /etc/init.d/xvfb start
|
- sh -e /etc/init.d/xvfb start
|
||||||
- (cd ng2-components/ng2-alfresco-core; npm version patch; sed -i "s/0\\.0\\.0-PLACEHOLDER/^0.1.0/g" package.json; npm install; npm link)
|
- (cd ng2-components/ng2-alfresco-core; npm install; npm link)
|
||||||
|
- (cd ng2-components/ng2-alfresco-datatable; npm install; npm link)
|
||||||
|
|
||||||
env:
|
env:
|
||||||
matrix:
|
matrix:
|
||||||
@ -30,7 +31,7 @@ env:
|
|||||||
- MODULE=ng2-alfresco-viewer
|
- MODULE=ng2-alfresco-viewer
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
- cd ng2-components/$MODULE; npm version patch; sed -i "s/0\\.0\\.0-PLACEHOLDER/^0.1.0/g" package.json; npm install; npm link ng2-alfresco-core; npm run travis
|
- cd ng2-components/$MODULE; npm install; npm link ng2-alfresco-core; npm run travis
|
||||||
- ls -ltrh ./node_modules/
|
- ls -ltrh ./node_modules/
|
||||||
script: npm run test
|
script: npm run test
|
||||||
# Send coverage data to Coveralls
|
# Send coverage data to Coveralls
|
||||||
|
4
demo-shell-ng2/.gitignore
vendored
4
demo-shell-ng2/.gitignore
vendored
@ -5,3 +5,7 @@ app/**/*.js
|
|||||||
app/**/*.js.map
|
app/**/*.js.map
|
||||||
.idea
|
.idea
|
||||||
dist/
|
dist/
|
||||||
|
|
||||||
|
# docker files
|
||||||
|
docker-compose.yml
|
||||||
|
Dockerfile
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
<alfresco-document-list
|
<alfresco-document-list
|
||||||
#documentList
|
#documentList
|
||||||
[currentFolderPath]="currentPath"
|
[currentFolderPath]="currentPath"
|
||||||
|
[contextMenuActions]="true"
|
||||||
|
[contentActions]="true"
|
||||||
(preview)="showFile($event)"
|
(preview)="showFile($event)"
|
||||||
(folderChange)="onFolderChanged($event)">
|
(folderChange)="onFolderChanged($event)">
|
||||||
<!--
|
<!--
|
||||||
@ -20,10 +22,11 @@
|
|||||||
</empty-folder-content>
|
</empty-folder-content>
|
||||||
-->
|
-->
|
||||||
<content-columns>
|
<content-columns>
|
||||||
<content-column source="$thumbnail" type="image"></content-column>
|
<content-column key="$thumbnail" type="image"></content-column>
|
||||||
<content-column
|
<content-column
|
||||||
title="{{'DOCUMENT_LIST.COLUMNS.DISPLAY_NAME' | translate}}"
|
title="{{'DOCUMENT_LIST.COLUMNS.DISPLAY_NAME' | translate}}"
|
||||||
source="name"
|
key="name"
|
||||||
|
sortable="true"
|
||||||
class="full-width ellipsis-cell">
|
class="full-width ellipsis-cell">
|
||||||
</content-column>
|
</content-column>
|
||||||
<!--
|
<!--
|
||||||
@ -34,14 +37,16 @@
|
|||||||
-->
|
-->
|
||||||
<content-column
|
<content-column
|
||||||
title="{{'DOCUMENT_LIST.COLUMNS.CREATED_BY' | translate}}"
|
title="{{'DOCUMENT_LIST.COLUMNS.CREATED_BY' | translate}}"
|
||||||
source="createdByUser.displayName"
|
key="createdByUser.displayName"
|
||||||
|
sortable="true"
|
||||||
class="desktop-only">
|
class="desktop-only">
|
||||||
</content-column>
|
</content-column>
|
||||||
<content-column
|
<content-column
|
||||||
title="{{'DOCUMENT_LIST.COLUMNS.CREATED_ON' | translate}}"
|
title="{{'DOCUMENT_LIST.COLUMNS.CREATED_ON' | translate}}"
|
||||||
source="createdAt"
|
key="createdAt"
|
||||||
type="date"
|
type="date"
|
||||||
format="medium"
|
format="medium"
|
||||||
|
sortable="true"
|
||||||
class="desktop-only">
|
class="desktop-only">
|
||||||
</content-column>
|
</content-column>
|
||||||
</content-columns>
|
</content-columns>
|
||||||
@ -50,25 +55,16 @@
|
|||||||
<!-- folder actions -->
|
<!-- folder actions -->
|
||||||
<content-action
|
<content-action
|
||||||
target="folder"
|
target="folder"
|
||||||
type="button"
|
|
||||||
icon="delete"
|
|
||||||
handler="system1">
|
|
||||||
</content-action>
|
|
||||||
<content-action
|
|
||||||
target="folder"
|
|
||||||
type="menu"
|
|
||||||
title="{{'DOCUMENT_LIST.ACTIONS.FOLDER.SYSTEM_1' | translate}}"
|
title="{{'DOCUMENT_LIST.ACTIONS.FOLDER.SYSTEM_1' | translate}}"
|
||||||
handler="system1">
|
handler="system1">
|
||||||
</content-action>
|
</content-action>
|
||||||
<content-action
|
<content-action
|
||||||
target="folder"
|
target="folder"
|
||||||
type="menu"
|
|
||||||
title="{{'DOCUMENT_LIST.ACTIONS.FOLDER.CUSTOM' | translate}}"
|
title="{{'DOCUMENT_LIST.ACTIONS.FOLDER.CUSTOM' | translate}}"
|
||||||
(execute)="myFolderAction1($event)">
|
(execute)="myFolderAction1($event)">
|
||||||
</content-action>
|
</content-action>
|
||||||
<content-action
|
<content-action
|
||||||
target="folder"
|
target="folder"
|
||||||
type="menu"
|
|
||||||
title="{{'DOCUMENT_LIST.ACTIONS.FOLDER.DELETE' | translate}}"
|
title="{{'DOCUMENT_LIST.ACTIONS.FOLDER.DELETE' | translate}}"
|
||||||
handler="delete">
|
handler="delete">
|
||||||
</content-action>
|
</content-action>
|
||||||
@ -76,37 +72,21 @@
|
|||||||
<!-- document actions -->
|
<!-- document actions -->
|
||||||
<content-action
|
<content-action
|
||||||
target="document"
|
target="document"
|
||||||
type="button"
|
|
||||||
icon="account_circle"
|
|
||||||
handler="my-handler">
|
|
||||||
</content-action>
|
|
||||||
<content-action
|
|
||||||
target="document"
|
|
||||||
type="button"
|
|
||||||
icon="cloud_download"
|
|
||||||
handler="download">
|
|
||||||
</content-action>
|
|
||||||
<content-action
|
|
||||||
target="document"
|
|
||||||
type="menu"
|
|
||||||
title="{{'DOCUMENT_LIST.ACTIONS.DOCUMENT.DOWNLOAD' | translate}}"
|
title="{{'DOCUMENT_LIST.ACTIONS.DOCUMENT.DOWNLOAD' | translate}}"
|
||||||
handler="download">
|
handler="download">
|
||||||
</content-action>
|
</content-action>
|
||||||
<content-action
|
<content-action
|
||||||
target="document"
|
target="document"
|
||||||
type="menu"
|
|
||||||
title="{{'DOCUMENT_LIST.ACTIONS.DOCUMENT.SYSTEM_2' | translate}}"
|
title="{{'DOCUMENT_LIST.ACTIONS.DOCUMENT.SYSTEM_2' | translate}}"
|
||||||
handler="system2">
|
handler="system2">
|
||||||
</content-action>
|
</content-action>
|
||||||
<content-action
|
<content-action
|
||||||
target="document"
|
target="document"
|
||||||
type="menu"
|
|
||||||
title="{{'DOCUMENT_LIST.ACTIONS.DOCUMENT.CUSTOM' | translate}}"
|
title="{{'DOCUMENT_LIST.ACTIONS.DOCUMENT.CUSTOM' | translate}}"
|
||||||
(execute)="myCustomAction1($event)">
|
(execute)="myCustomAction1($event)">
|
||||||
</content-action>
|
</content-action>
|
||||||
<content-action
|
<content-action
|
||||||
target="document"
|
target="document"
|
||||||
type="menu"
|
|
||||||
title="{{'DOCUMENT_LIST.ACTIONS.DOCUMENT.DELETE' | translate}}"
|
title="{{'DOCUMENT_LIST.ACTIONS.DOCUMENT.DELETE' | translate}}"
|
||||||
handler="delete">
|
handler="delete">
|
||||||
</content-action>
|
</content-action>
|
||||||
|
@ -34,6 +34,7 @@ describe('ContextMenuDirective', () => {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
directive.links = [{}];
|
||||||
directive.onShowContextMenu(null);
|
directive.onShowContextMenu(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -26,17 +26,20 @@ import { ContextMenuService } from './../services/context-menu.service';
|
|||||||
})
|
})
|
||||||
export class ContextMenuDirective {
|
export class ContextMenuDirective {
|
||||||
@Input('context-menu')
|
@Input('context-menu')
|
||||||
links;
|
links: any[];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private _contextMenuService: ContextMenuService) {}
|
private _contextMenuService: ContextMenuService) {}
|
||||||
|
|
||||||
onShowContextMenu(event?: MouseEvent) {
|
onShowContextMenu(event?: MouseEvent) {
|
||||||
if (this._contextMenuService) {
|
|
||||||
this._contextMenuService.show.next({event: event, obj: this.links});
|
|
||||||
}
|
|
||||||
if (event) {
|
if (event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.links && this.links.length > 0) {
|
||||||
|
if (this._contextMenuService) {
|
||||||
|
this._contextMenuService.show.next({event: event, obj: this.links});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,14 +16,17 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { DataTableComponent } from './src/components/datatable.component';
|
import { DataTableComponent } from './src/components/datatable.component';
|
||||||
|
import { NoContentTemplateComponent } from './src/components/no-content-template.component';
|
||||||
|
|
||||||
// components
|
// components
|
||||||
export * from './src/components/datatable.component';
|
export * from './src/components/datatable.component';
|
||||||
|
export * from './src/components/no-content-template.component';
|
||||||
|
|
||||||
// data
|
// data
|
||||||
export * from './src/data/datatable-adapter';
|
export * from './src/data/datatable-adapter';
|
||||||
export * from './src/data/object-datatable-adapter';
|
export * from './src/data/object-datatable-adapter';
|
||||||
|
|
||||||
export const ALFRESCO_DATATABLE_DIRECTIVES: [any] = [
|
export const ALFRESCO_DATATABLE_DIRECTIVES: [any] = [
|
||||||
DataTableComponent
|
DataTableComponent,
|
||||||
|
NoContentTemplateComponent
|
||||||
];
|
];
|
||||||
|
@ -9,13 +9,15 @@ var map = {
|
|||||||
'app': 'base/dist',
|
'app': 'base/dist',
|
||||||
'rxjs': 'base/node_modules/rxjs',
|
'rxjs': 'base/node_modules/rxjs',
|
||||||
'@angular': 'base/node_modules/@angular',
|
'@angular': 'base/node_modules/@angular',
|
||||||
'ng2-alfresco-core/dist': '/base/node_modules/ng2-alfresco-core/dist'
|
'ng2-alfresco-core': '/base/node_modules/ng2-alfresco-core/dist',
|
||||||
|
'ng2-translate' : '/base/node_modules/ng2-translate'
|
||||||
};
|
};
|
||||||
|
|
||||||
var packages = {
|
var packages = {
|
||||||
'app': { main: 'main.js', defaultExtension: 'js' },
|
'app': { main: 'main.js', defaultExtension: 'js' },
|
||||||
'rxjs': { defaultExtension: 'js' },
|
'rxjs': { defaultExtension: 'js' },
|
||||||
'ng2-alfresco-core/dist': { defaultExtension: 'js' }
|
'ng2-alfresco-core': { main: 'index.js', defaultExtension: 'js' },
|
||||||
|
'ng2-translate': { defaultExtension: 'js' }
|
||||||
};
|
};
|
||||||
|
|
||||||
var packageNames = [
|
var packageNames = [
|
||||||
|
@ -16,6 +16,7 @@ module.exports = function (config) {
|
|||||||
{pattern: 'node_modules/@angular/**/*.js', included: false, watched: false},
|
{pattern: 'node_modules/@angular/**/*.js', included: false, watched: false},
|
||||||
{pattern: 'node_modules/@angular/**/*.map', included: false, watched: false},
|
{pattern: 'node_modules/@angular/**/*.map', included: false, watched: false},
|
||||||
{pattern: 'node_modules/ng2-alfresco-core/dist/**/*.js', included: false, served: true, watched: false},
|
{pattern: 'node_modules/ng2-alfresco-core/dist/**/*.js', included: false, served: true, watched: false},
|
||||||
|
{pattern: 'node_modules/ng2-translate/**/*.js', included: false, served: true, watched: false},
|
||||||
|
|
||||||
{pattern: 'karma-test-shim.js', included: true, watched: true},
|
{pattern: 'karma-test-shim.js', included: true, watched: true},
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
"posttest": "node_modules/.bin/remap-istanbul -i coverage/report/coverage-final.json -o coverage/report -t html",
|
"posttest": "node_modules/.bin/remap-istanbul -i coverage/report/coverage-final.json -o coverage/report -t html",
|
||||||
"coverage": "npm run test && wsrv -o -p 9875 ./coverage/report",
|
"coverage": "npm run test && wsrv -o -p 9875 ./coverage/report",
|
||||||
"prepublish": "npm run build",
|
"prepublish": "npm run build",
|
||||||
"travis": "echo 'placeholder'"
|
"travis": "npm link ng2-alfresco-core"
|
||||||
},
|
},
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"typings": "./dist/index.d.ts",
|
"typings": "./dist/index.d.ts",
|
||||||
@ -67,7 +67,9 @@
|
|||||||
"reflect-metadata": "0.1.3",
|
"reflect-metadata": "0.1.3",
|
||||||
"rxjs": "5.0.0-beta.6",
|
"rxjs": "5.0.0-beta.6",
|
||||||
"zone.js": "0.6.12",
|
"zone.js": "0.6.12",
|
||||||
"rimraf": "2.5.2"
|
"rimraf": "2.5.2",
|
||||||
|
"ng2-translate": "2.2.2",
|
||||||
|
"ng2-alfresco-core": "0.2.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"material-design-icons": "^2.2.3",
|
"material-design-icons": "^2.2.3",
|
||||||
|
@ -14,11 +14,58 @@
|
|||||||
:host .data-cell {
|
:host .data-cell {
|
||||||
cursor: default;
|
cursor: default;
|
||||||
}
|
}
|
||||||
|
:host .cell-value {}
|
||||||
|
|
||||||
:host .column-header {
|
:host .column-header {
|
||||||
cursor: pointer;
|
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%;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host .ellipsis-cell > div
|
||||||
|
{
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
/*height: 1em;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* visible content */
|
||||||
|
:host .ellipsis-cell > div > span
|
||||||
|
{
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
max-width: 100%;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
line-height: 1em; /* for vertical align of text */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* cell stretching content */
|
||||||
|
:host .ellipsis-cell > div:after
|
||||||
|
{
|
||||||
|
content: attr(title);
|
||||||
|
overflow: hidden;
|
||||||
|
height: 0;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Utils */
|
/* Utils */
|
||||||
|
|
||||||
:host .non-selectable {
|
:host .non-selectable {
|
||||||
@ -39,3 +86,22 @@
|
|||||||
clip: rect(0,0,0,0);
|
clip: rect(0,0,0,0);
|
||||||
border: 0;
|
border: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* small desktop */
|
||||||
|
@media all and (max-width: 1200px) {}
|
||||||
|
|
||||||
|
/* tablet */
|
||||||
|
@media all and (max-width: 1024px) {}
|
||||||
|
|
||||||
|
/* mobile phone */
|
||||||
|
@media all and (max-width: 768px) {
|
||||||
|
.desktop-only {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-device-width: 768px){
|
||||||
|
.desktop-only {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
</th>
|
</th>
|
||||||
<th class="mdl-data-table__cell--non-numeric non-selectable {{col.cssClass}}"
|
<th class="mdl-data-table__cell--non-numeric non-selectable {{col.cssClass}}"
|
||||||
*ngFor="let col of data.getColumns()"
|
*ngFor="let col of data.getColumns()"
|
||||||
|
[attr.data-automation-id]="'auto_id_' + col.key"
|
||||||
[class.column-header]="col.title"
|
[class.column-header]="col.title"
|
||||||
[class.mdl-data-table__header--sorted-ascending]="isColumnSorted(col, 'asc')"
|
[class.mdl-data-table__header--sorted-ascending]="isColumnSorted(col, 'asc')"
|
||||||
[class.mdl-data-table__header--sorted-descending]="isColumnSorted(col, 'desc')"
|
[class.mdl-data-table__header--sorted-descending]="isColumnSorted(col, 'desc')"
|
||||||
@ -41,22 +42,50 @@
|
|||||||
</td>
|
</td>
|
||||||
<td *ngFor="let col of data.getColumns()" [ngSwitch]="col.type"
|
<td *ngFor="let col of data.getColumns()" [ngSwitch]="col.type"
|
||||||
class="mdl-data-table__cell--non-numeric non-selectable data-cell {{col.cssClass}}"
|
class="mdl-data-table__cell--non-numeric non-selectable data-cell {{col.cssClass}}"
|
||||||
(click)="onRowClick(row, $event)" (dblclick)="onRowDblClick(row, $event)">
|
(click)="onRowClick(row, $event)"
|
||||||
<div *ngSwitchCase="'image'">
|
(dblclick)="onRowDblClick(row, $event)"
|
||||||
|
[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>
|
<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)}}">
|
<img *ngIf="!isIconValue(row, col)" class="image-cell" alt="" src="{{data.getValue(row, col)}}">
|
||||||
</div>
|
</div>
|
||||||
<div *ngSwitchCase="'text'">
|
<div *ngSwitchCase="'date'" class="cell-value">
|
||||||
{{data.getValue(row, col)}}
|
{{data.getValue(row, col)}}
|
||||||
</div>
|
</div>
|
||||||
<span *ngSwitchDefault>
|
<div *ngSwitchCase="'text'" class="cell-value">
|
||||||
|
{{data.getValue(row, col)}}
|
||||||
|
</div>
|
||||||
|
<span *ngSwitchDefault class="cell-value">
|
||||||
<!-- empty cell for unknown column type -->
|
<!-- empty cell for unknown column type -->
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
</td>
|
</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>
|
||||||
|
<tr *ngIf="data.getRows().length === 0">
|
||||||
|
<td class="mdl-data-table__cell--non-numeric no-content-container"
|
||||||
|
[attr.colspan]="1 + data.getColumns().length">
|
||||||
|
<template *ngIf="noContentTemplate"
|
||||||
|
ngFor [ngForOf]="[data]"
|
||||||
|
[ngForTemplate]="noContentTemplate">
|
||||||
|
</template>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
@ -22,14 +22,18 @@ import {
|
|||||||
Input,
|
Input,
|
||||||
Output,
|
Output,
|
||||||
EventEmitter,
|
EventEmitter,
|
||||||
AfterViewChecked
|
AfterViewChecked,
|
||||||
|
TemplateRef
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
|
|
||||||
|
import { CONTEXT_MENU_DIRECTIVES } from 'ng2-alfresco-core';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DataTableAdapter,
|
DataTableAdapter,
|
||||||
DataRow,
|
DataRow,
|
||||||
DataColumn,
|
DataColumn,
|
||||||
DataSorting
|
DataSorting,
|
||||||
|
DataRowEvent
|
||||||
} from './../data/datatable-adapter';
|
} from './../data/datatable-adapter';
|
||||||
import { ObjectDataTableAdapter } from '../data/object-datatable-adapter';
|
import { ObjectDataTableAdapter } from '../data/object-datatable-adapter';
|
||||||
|
|
||||||
@ -40,7 +44,8 @@ declare let __moduleName: string;
|
|||||||
moduleId: __moduleName,
|
moduleId: __moduleName,
|
||||||
selector: 'alfresco-datatable',
|
selector: 'alfresco-datatable',
|
||||||
styleUrls: ['./datatable.component.css'],
|
styleUrls: ['./datatable.component.css'],
|
||||||
templateUrl: './datatable.component.html'
|
templateUrl: './datatable.component.html',
|
||||||
|
directives: [CONTEXT_MENU_DIRECTIVES]
|
||||||
})
|
})
|
||||||
export class DataTableComponent implements OnInit, AfterViewChecked {
|
export class DataTableComponent implements OnInit, AfterViewChecked {
|
||||||
|
|
||||||
@ -54,13 +59,24 @@ export class DataTableComponent implements OnInit, AfterViewChecked {
|
|||||||
actions: boolean = false;
|
actions: boolean = false;
|
||||||
|
|
||||||
@Output()
|
@Output()
|
||||||
rowClick: EventEmitter<any> = new EventEmitter();
|
rowClick: EventEmitter<DataRowEvent> = new EventEmitter<DataRowEvent>();
|
||||||
|
|
||||||
@Output()
|
@Output()
|
||||||
rowDblClick: EventEmitter<any> = new EventEmitter();
|
rowDblClick: EventEmitter<DataRowEvent> = new EventEmitter<DataRowEvent>();
|
||||||
|
|
||||||
|
noContentTemplate: TemplateRef<any>;
|
||||||
|
|
||||||
isSelectAllChecked: boolean = false;
|
isSelectAllChecked: boolean = false;
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
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
|
// TODO: left for reference, will be removed during future revisions
|
||||||
constructor(/*private _ngZone?: NgZone*/) {
|
constructor(/*private _ngZone?: NgZone*/) {
|
||||||
}
|
}
|
||||||
@ -84,7 +100,8 @@ export class DataTableComponent implements OnInit, AfterViewChecked {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.rowClick.emit({
|
this.rowClick.emit({
|
||||||
value: row
|
value: row,
|
||||||
|
event: e
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,7 +111,8 @@ export class DataTableComponent implements OnInit, AfterViewChecked {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.rowDblClick.emit({
|
this.rowDblClick.emit({
|
||||||
value: row
|
value: row,
|
||||||
|
event: e
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,14 +152,16 @@ export class DataTableComponent implements OnInit, AfterViewChecked {
|
|||||||
|
|
||||||
isIconValue(row: DataRow, col: DataColumn) {
|
isIconValue(row: DataRow, col: DataColumn) {
|
||||||
if (row && col) {
|
if (row && col) {
|
||||||
return row.getValue(col.key).startsWith('material-icons://');
|
let value = row.getValue(col.key);
|
||||||
|
return value && value.startsWith('material-icons://');
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
asIconValue(row: DataRow, col: DataColumn) {
|
asIconValue(row: DataRow, col: DataColumn) {
|
||||||
if (this.isIconValue(row, col)) {
|
if (this.isIconValue(row, col)) {
|
||||||
return row.getValue(col.key).replace('material-icons://', '');
|
let value = row.getValue(col.key) || '';
|
||||||
|
return value.replace('material-icons://', '');
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -153,4 +173,21 @@ export class DataTableComponent implements OnInit, AfterViewChecked {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getContextMenuActions(row: DataRow, col: DataColumn) {
|
||||||
|
let args = { row: row, col: col, actions: [] };
|
||||||
|
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 });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,22 +16,26 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import {
|
||||||
it,
|
Directive,
|
||||||
describe,
|
ContentChild,
|
||||||
expect
|
TemplateRef,
|
||||||
} from '@angular/core/testing';
|
AfterContentInit
|
||||||
|
} from '@angular/core';
|
||||||
|
import { DataTableComponent } from './datatable.component';
|
||||||
|
|
||||||
import { ContentColumnModel } from './content-column.model';
|
@Directive({
|
||||||
|
selector: 'no-content-template'
|
||||||
|
})
|
||||||
|
export class NoContentTemplateComponent implements AfterContentInit {
|
||||||
|
|
||||||
describe('ContentColumnModel', () => {
|
@ContentChild(TemplateRef)
|
||||||
|
template: any;
|
||||||
|
|
||||||
it('should init with text type from config object', () => {
|
constructor(
|
||||||
let model = new ContentColumnModel({});
|
private dataTable: DataTableComponent) {
|
||||||
expect(model.type).toBe(ContentColumnModel.TYPE_TEXT);
|
}
|
||||||
});
|
|
||||||
|
|
||||||
it('should return supported types', () => {
|
ngAfterContentInit() {
|
||||||
expect(ContentColumnModel.getSupportedTypes().length).toBeGreaterThan(0);
|
this.dataTable.noContentTemplate = this.template;
|
||||||
});
|
}
|
||||||
|
}
|
||||||
});
|
|
@ -16,7 +16,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export interface DataTableAdapter {
|
export interface DataTableAdapter {
|
||||||
|
|
||||||
getRows(): Array<DataRow>;
|
getRows(): Array<DataRow>;
|
||||||
setRows(rows: Array<DataRow>): void;
|
setRows(rows: Array<DataRow>): void;
|
||||||
getColumns(): Array<DataColumn>;
|
getColumns(): Array<DataColumn>;
|
||||||
@ -25,33 +24,32 @@ export interface DataTableAdapter {
|
|||||||
getSorting(): DataSorting;
|
getSorting(): DataSorting;
|
||||||
setSorting(sorting: DataSorting): void;
|
setSorting(sorting: DataSorting): void;
|
||||||
sort(key?: string, direction?: string): void;
|
sort(key?: string, direction?: string): void;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DataRow {
|
export interface DataRow {
|
||||||
|
|
||||||
isSelected: boolean;
|
isSelected: boolean;
|
||||||
hasValue(key: string): boolean;
|
hasValue(key: string): boolean;
|
||||||
getValue(key: string): any;
|
getValue(key: string): any;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DataColumn {
|
export interface DataColumn {
|
||||||
|
|
||||||
key: string;
|
key: string;
|
||||||
type: string; // text|image
|
type: string; // text|image|date
|
||||||
|
format?: string;
|
||||||
sortable?: boolean;
|
sortable?: boolean;
|
||||||
title?: string;
|
title?: string;
|
||||||
srTitle?: string;
|
srTitle?: string;
|
||||||
cssClass?: string;
|
cssClass?: string;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DataSorting {
|
export class DataSorting {
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public key?: string,
|
public key?: string,
|
||||||
public direction?: string) {
|
public direction?: string) {
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DataRowEvent {
|
||||||
|
value?: DataRow;
|
||||||
|
event?: Event;
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { DatePipe } from '@angular/common';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DataTableAdapter,
|
DataTableAdapter,
|
||||||
DataRow,
|
DataRow,
|
||||||
@ -78,7 +80,20 @@ export class ObjectDataTableAdapter implements DataTableAdapter {
|
|||||||
if (!col) {
|
if (!col) {
|
||||||
throw new Error('Column not found');
|
throw new Error('Column not found');
|
||||||
}
|
}
|
||||||
return row.getValue(col.key);
|
|
||||||
|
let value = row.getValue(col.key);
|
||||||
|
|
||||||
|
if (col.type === 'date') {
|
||||||
|
let datePipe = new DatePipe();
|
||||||
|
let format = col.format || 'medium';
|
||||||
|
try {
|
||||||
|
return datePipe.transform(value, format);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`DocumentList: error parsing date ${value} to format ${format}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
getSorting(): DataSorting {
|
getSorting(): DataSorting {
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
"typings": "typings install",
|
"typings": "typings install",
|
||||||
"postinstall": "npm run typings && npm run build",
|
"postinstall": "npm run typings && npm run build",
|
||||||
"start": "concurrently \"npm run build:w\" \"npm run server\" ",
|
"start": "concurrently \"npm run build:w\" \"npm run server\" ",
|
||||||
"server": "wsrv -o -s",
|
"server": "wsrv -o -s -l",
|
||||||
"build": "npm run tslint && rimraf dist && tsc",
|
"build": "npm run tslint && rimraf dist && tsc",
|
||||||
"build:w": "npm run tslint && rimraf dist && tsc -w",
|
"build:w": "npm run tslint && rimraf dist && tsc -w",
|
||||||
"tslint": "npm run tslint-src && npm run tslint-root",
|
"tslint": "npm run tslint-src && npm run tslint-root",
|
||||||
@ -41,7 +41,8 @@
|
|||||||
|
|
||||||
"alfresco-js-api": "^0.1.0",
|
"alfresco-js-api": "^0.1.0",
|
||||||
"ng2-alfresco-core": "^0.1.36",
|
"ng2-alfresco-core": "^0.1.36",
|
||||||
"ng2-alfresco-documentlist": "^0.1.34"
|
"ng2-alfresco-documentlist": "^0.1.34",
|
||||||
|
"ng2-alfresco-datatable": "^0.1.17"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"concurrently": "2.0.0",
|
"concurrently": "2.0.0",
|
||||||
|
@ -38,9 +38,9 @@ import {
|
|||||||
selector: 'alfresco-documentlist-demo',
|
selector: 'alfresco-documentlist-demo',
|
||||||
template: `
|
template: `
|
||||||
<label for="token"><b>Insert a valid access token / ticket:</b></label><br>
|
<label for="token"><b>Insert a valid access token / ticket:</b></label><br>
|
||||||
<input id="token" type="text" size="48" (change)="updateToken();doclist.reload()" [(ngModel)]="token"><br>
|
<input id="token" type="text" size="48" (change)="updateToken();documentList.reload()" [(ngModel)]="token"><br>
|
||||||
<label for="token"><b>Insert the ip of your Alfresco instance:</b></label><br>
|
<label for="token"><b>Insert the ip of your Alfresco instance:</b></label><br>
|
||||||
<input id="token" type="text" size="48" (change)="updateHost();doclist.reload()" [(ngModel)]="host"><br><br>
|
<input id="token" type="text" size="48" (change)="updateHost();documentList.reload()" [(ngModel)]="host"><br><br>
|
||||||
<div *ngIf="!authenticated" style="color:#FF2323">
|
<div *ngIf="!authenticated" style="color:#FF2323">
|
||||||
Authentication failed to ip {{ host }} with user: admin, admin, you can still try to add a valid token to perform
|
Authentication failed to ip {{ host }} with user: admin, admin, you can still try to add a valid token to perform
|
||||||
operations.
|
operations.
|
||||||
@ -52,28 +52,40 @@ import {
|
|||||||
[currentFolderPath]="currentPath"
|
[currentFolderPath]="currentPath"
|
||||||
[target]="documentList">
|
[target]="documentList">
|
||||||
</alfresco-document-list-breadcrumb>
|
</alfresco-document-list-breadcrumb>
|
||||||
<alfresco-document-list #doclist
|
<alfresco-document-list
|
||||||
#documentList
|
#documentList
|
||||||
[currentFolderPath]="currentPath"
|
[currentFolderPath]="currentPath"
|
||||||
|
[contextMenuActions]="true"
|
||||||
|
[contentActions]="true"
|
||||||
|
[multiselect]="true"
|
||||||
(folderChange)="onFolderChanged($event)">
|
(folderChange)="onFolderChanged($event)">
|
||||||
|
<!--
|
||||||
|
<empty-folder-content>
|
||||||
|
<template>
|
||||||
|
<h1>Sorry, no content here</h1>
|
||||||
|
</template>
|
||||||
|
</empty-folder-content>
|
||||||
|
-->
|
||||||
<content-columns>
|
<content-columns>
|
||||||
<content-column source="$thumbnail" type="image"></content-column>
|
<content-column key="$thumbnail" type="image"></content-column>
|
||||||
<content-column
|
<content-column
|
||||||
title="{{'DOCUMENT_LIST.COLUMNS.DISPLAY_NAME' | translate}}"
|
title="{{'DOCUMENT_LIST.COLUMNS.DISPLAY_NAME' | translate}}"
|
||||||
source="name"
|
key="name"
|
||||||
|
sortable="true"
|
||||||
class="full-width ellipsis-cell">
|
class="full-width ellipsis-cell">
|
||||||
</content-column>
|
</content-column>
|
||||||
<content-column
|
<content-column
|
||||||
title="{{'DOCUMENT_LIST.COLUMNS.CREATED_BY' | translate}}"
|
title="{{'DOCUMENT_LIST.COLUMNS.CREATED_BY' | translate}}"
|
||||||
source="createdByUser.displayName"
|
key="createdByUser.displayName"
|
||||||
|
sortable="true"
|
||||||
class="desktop-only">
|
class="desktop-only">
|
||||||
</content-column>
|
</content-column>
|
||||||
<content-column
|
<content-column
|
||||||
title="{{'DOCUMENT_LIST.COLUMNS.CREATED_ON' | translate}}"
|
title="{{'DOCUMENT_LIST.COLUMNS.CREATED_ON' | translate}}"
|
||||||
source="createdAt"
|
key="createdAt"
|
||||||
type="date"
|
type="date"
|
||||||
format="medium"
|
format="medium"
|
||||||
|
sortable="true"
|
||||||
class="desktop-only">
|
class="desktop-only">
|
||||||
</content-column>
|
</content-column>
|
||||||
</content-columns>
|
</content-columns>
|
||||||
@ -81,25 +93,16 @@ import {
|
|||||||
<!-- folder actions -->
|
<!-- folder actions -->
|
||||||
<content-action
|
<content-action
|
||||||
target="folder"
|
target="folder"
|
||||||
type="button"
|
|
||||||
icon="delete"
|
|
||||||
handler="system1">
|
|
||||||
</content-action>
|
|
||||||
<content-action
|
|
||||||
target="folder"
|
|
||||||
type="menu"
|
|
||||||
title="{{'DOCUMENT_LIST.ACTIONS.FOLDER.SYSTEM_1' | translate}}"
|
title="{{'DOCUMENT_LIST.ACTIONS.FOLDER.SYSTEM_1' | translate}}"
|
||||||
handler="system1">
|
handler="system1">
|
||||||
</content-action>
|
</content-action>
|
||||||
<content-action
|
<content-action
|
||||||
target="folder"
|
target="folder"
|
||||||
type="menu"
|
|
||||||
title="{{'DOCUMENT_LIST.ACTIONS.FOLDER.CUSTOM' | translate}}"
|
title="{{'DOCUMENT_LIST.ACTIONS.FOLDER.CUSTOM' | translate}}"
|
||||||
(execute)="myFolderAction1($event)">
|
(execute)="myFolderAction1($event)">
|
||||||
</content-action>
|
</content-action>
|
||||||
<content-action
|
<content-action
|
||||||
target="folder"
|
target="folder"
|
||||||
type="menu"
|
|
||||||
title="{{'DOCUMENT_LIST.ACTIONS.FOLDER.DELETE' | translate}}"
|
title="{{'DOCUMENT_LIST.ACTIONS.FOLDER.DELETE' | translate}}"
|
||||||
handler="delete">
|
handler="delete">
|
||||||
</content-action>
|
</content-action>
|
||||||
@ -107,37 +110,21 @@ import {
|
|||||||
<!-- document actions -->
|
<!-- document actions -->
|
||||||
<content-action
|
<content-action
|
||||||
target="document"
|
target="document"
|
||||||
type="button"
|
|
||||||
icon="account_circle"
|
|
||||||
handler="my-handler">
|
|
||||||
</content-action>
|
|
||||||
<content-action
|
|
||||||
target="document"
|
|
||||||
type="button"
|
|
||||||
icon="cloud_download"
|
|
||||||
handler="download">
|
|
||||||
</content-action>
|
|
||||||
<content-action
|
|
||||||
target="document"
|
|
||||||
type="menu"
|
|
||||||
title="{{'DOCUMENT_LIST.ACTIONS.DOCUMENT.DOWNLOAD' | translate}}"
|
title="{{'DOCUMENT_LIST.ACTIONS.DOCUMENT.DOWNLOAD' | translate}}"
|
||||||
handler="download">
|
handler="download">
|
||||||
</content-action>
|
</content-action>
|
||||||
<content-action
|
<content-action
|
||||||
target="document"
|
target="document"
|
||||||
type="menu"
|
|
||||||
title="{{'DOCUMENT_LIST.ACTIONS.DOCUMENT.SYSTEM_2' | translate}}"
|
title="{{'DOCUMENT_LIST.ACTIONS.DOCUMENT.SYSTEM_2' | translate}}"
|
||||||
handler="system2">
|
handler="system2">
|
||||||
</content-action>
|
</content-action>
|
||||||
<content-action
|
<content-action
|
||||||
target="document"
|
target="document"
|
||||||
type="menu"
|
|
||||||
title="{{'DOCUMENT_LIST.ACTIONS.DOCUMENT.CUSTOM' | translate}}"
|
title="{{'DOCUMENT_LIST.ACTIONS.DOCUMENT.CUSTOM' | translate}}"
|
||||||
(execute)="myCustomAction1($event)">
|
(execute)="myCustomAction1($event)">
|
||||||
</content-action>
|
</content-action>
|
||||||
<content-action
|
<content-action
|
||||||
target="document"
|
target="document"
|
||||||
type="menu"
|
|
||||||
title="{{'DOCUMENT_LIST.ACTIONS.DOCUMENT.DELETE' | translate}}"
|
title="{{'DOCUMENT_LIST.ACTIONS.DOCUMENT.DELETE' | translate}}"
|
||||||
handler="delete">
|
handler="delete">
|
||||||
</content-action>
|
</content-action>
|
||||||
@ -156,7 +143,8 @@ class DocumentListDemo implements OnInit {
|
|||||||
currentPath: string = '/';
|
currentPath: string = '/';
|
||||||
authenticated: boolean;
|
authenticated: boolean;
|
||||||
|
|
||||||
public host: string = 'http://devproducts-platform.alfresco.me';
|
// host: string = 'http://devproducts-platform.alfresco.me';
|
||||||
|
host: string = 'http://127.0.0.1:8080';
|
||||||
|
|
||||||
token: string;
|
token: string;
|
||||||
|
|
||||||
@ -194,11 +182,13 @@ class DocumentListDemo implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
myCustomAction1(event) {
|
myCustomAction1(event) {
|
||||||
alert('Custom document action for ' + event.value.displayName);
|
let entry = event.value.entry;
|
||||||
|
alert(`Custom document action for ${entry.name}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
myFolderAction1(event) {
|
myFolderAction1(event) {
|
||||||
alert('Custom folder action for ' + event.value.displayName);
|
let entry = event.value.entry;
|
||||||
|
alert(`Custom folder action for ${entry.name}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
login() {
|
login() {
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
'ng2-translate': 'node_modules/ng2-translate',
|
'ng2-translate': 'node_modules/ng2-translate',
|
||||||
'ng2-alfresco-core': 'node_modules/ng2-alfresco-core/dist',
|
'ng2-alfresco-core': 'node_modules/ng2-alfresco-core/dist',
|
||||||
|
'ng2-alfresco-datatable': 'node_modules/ng2-alfresco-datatable/dist',
|
||||||
'ng2-alfresco-documentlist': 'node_modules/ng2-alfresco-documentlist/dist'
|
'ng2-alfresco-documentlist': 'node_modules/ng2-alfresco-documentlist/dist'
|
||||||
};
|
};
|
||||||
// packages tells the System loader how to load when no filename and/or no extension
|
// packages tells the System loader how to load when no filename and/or no extension
|
||||||
@ -22,6 +23,7 @@
|
|||||||
|
|
||||||
'ng2-translate': { defaultExtension: 'js' },
|
'ng2-translate': { defaultExtension: 'js' },
|
||||||
'ng2-alfresco-core': { main: 'index.js', defaultExtension: 'js' },
|
'ng2-alfresco-core': { main: 'index.js', defaultExtension: 'js' },
|
||||||
|
'ng2-alfresco-datatable': { main: 'index.js', defaultExtension: 'js' },
|
||||||
'ng2-alfresco-documentlist': { main: 'index.js', defaultExtension: 'js' }
|
'ng2-alfresco-documentlist': { main: 'index.js', defaultExtension: 'js' }
|
||||||
};
|
};
|
||||||
var ngPackageNames = [
|
var ngPackageNames = [
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"watch": [
|
||||||
|
"node_modules/ng2-alfresco-datatable/dist/**/*.{html,htm,css,js}",
|
||||||
|
"node_modules/ng2-alfresco-documentlist/dist/**/*.{html,htm,css,js}"
|
||||||
|
]
|
||||||
|
}
|
@ -25,7 +25,7 @@ import { DocumentListBreadcrumb } from './src/components/document-list-breadcrum
|
|||||||
|
|
||||||
import { FolderActionsService } from './src/services/folder-actions.service';
|
import { FolderActionsService } from './src/services/folder-actions.service';
|
||||||
import { DocumentActionsService } from './src/services/document-actions.service';
|
import { DocumentActionsService } from './src/services/document-actions.service';
|
||||||
import { AlfrescoService } from './src/services/alfresco.service';
|
import { DocumentListService } from './src/services/document-list.service';
|
||||||
|
|
||||||
// components
|
// components
|
||||||
export * from './src/components/document-list';
|
export * from './src/components/document-list';
|
||||||
@ -36,13 +36,10 @@ export * from './src/components/content-action-list';
|
|||||||
export * from './src/components/empty-folder-content';
|
export * from './src/components/empty-folder-content';
|
||||||
export * from './src/components/document-list-breadcrumb.component';
|
export * from './src/components/document-list-breadcrumb.component';
|
||||||
|
|
||||||
// models
|
|
||||||
export * from './src/models/column-sorting.model';
|
|
||||||
|
|
||||||
// services
|
// services
|
||||||
export * from './src/services/folder-actions.service';
|
export * from './src/services/folder-actions.service';
|
||||||
export * from './src/services/document-actions.service';
|
export * from './src/services/document-actions.service';
|
||||||
export * from './src/services/alfresco.service';
|
export * from './src/services/document-list.service';
|
||||||
|
|
||||||
export const DOCUMENT_LIST_DIRECTIVES: [any] = [
|
export const DOCUMENT_LIST_DIRECTIVES: [any] = [
|
||||||
DocumentList,
|
DocumentList,
|
||||||
@ -55,7 +52,7 @@ export const DOCUMENT_LIST_DIRECTIVES: [any] = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export const DOCUMENT_LIST_PROVIDERS: [any] = [
|
export const DOCUMENT_LIST_PROVIDERS: [any] = [
|
||||||
AlfrescoService,
|
DocumentListService,
|
||||||
FolderActionsService,
|
FolderActionsService,
|
||||||
DocumentActionsService
|
DocumentActionsService
|
||||||
];
|
];
|
||||||
|
@ -9,15 +9,17 @@ var map = {
|
|||||||
'app': 'base/dist',
|
'app': 'base/dist',
|
||||||
'rxjs': 'base/node_modules/rxjs',
|
'rxjs': 'base/node_modules/rxjs',
|
||||||
'@angular': 'base/node_modules/@angular',
|
'@angular': 'base/node_modules/@angular',
|
||||||
|
'ng2-translate' : '/base/node_modules/ng2-translate',
|
||||||
'ng2-alfresco-core': '/base/node_modules/ng2-alfresco-core/dist',
|
'ng2-alfresco-core': '/base/node_modules/ng2-alfresco-core/dist',
|
||||||
'ng2-translate' : '/base/node_modules/ng2-translate'
|
'ng2-alfresco-datatable': '/base/node_modules/ng2-alfresco-datatable/dist'
|
||||||
};
|
};
|
||||||
|
|
||||||
var packages = {
|
var packages = {
|
||||||
'app': { main: 'main.js', defaultExtension: 'js' },
|
'app': { main: 'main.js', defaultExtension: 'js' },
|
||||||
'rxjs': { defaultExtension: 'js' },
|
'rxjs': { defaultExtension: 'js' },
|
||||||
|
'ng2-translate': { defaultExtension: 'js' },
|
||||||
'ng2-alfresco-core': { main: 'index.js', defaultExtension: 'js' },
|
'ng2-alfresco-core': { main: 'index.js', defaultExtension: 'js' },
|
||||||
'ng2-translate': { defaultExtension: 'js' }
|
'ng2-alfresco-datatable': { main: 'index.js', defaultExtension: 'js' }
|
||||||
};
|
};
|
||||||
|
|
||||||
var packageNames = [
|
var packageNames = [
|
||||||
|
@ -16,6 +16,7 @@ module.exports = function (config) {
|
|||||||
{pattern: 'node_modules/@angular/**/*.js', included: false, watched: false},
|
{pattern: 'node_modules/@angular/**/*.js', included: false, watched: false},
|
||||||
{pattern: 'node_modules/@angular/**/*.map', included: false, watched: false},
|
{pattern: 'node_modules/@angular/**/*.map', included: false, watched: false},
|
||||||
{pattern: 'node_modules/ng2-alfresco-core/dist/**/*.js', included: false, served: true, watched: false},
|
{pattern: 'node_modules/ng2-alfresco-core/dist/**/*.js', included: false, served: true, watched: false},
|
||||||
|
{pattern: 'node_modules/ng2-alfresco-datatable/dist/**/*.js', included: false, served: true, watched: false},
|
||||||
{pattern: 'node_modules/ng2-translate/**/*.js', included: false, served: true, watched: false},
|
{pattern: 'node_modules/ng2-translate/**/*.js', included: false, served: true, watched: false},
|
||||||
|
|
||||||
{pattern: 'karma-test-shim.js', included: true, watched: true},
|
{pattern: 'karma-test-shim.js', included: true, watched: true},
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
"posttest": "node_modules/.bin/remap-istanbul -i coverage/report/coverage-final.json -o coverage/report -t html",
|
"posttest": "node_modules/.bin/remap-istanbul -i coverage/report/coverage-final.json -o coverage/report -t html",
|
||||||
"coverage": "npm run test && wsrv -o -p 9875 ./coverage/report",
|
"coverage": "npm run test && wsrv -o -p 9875 ./coverage/report",
|
||||||
"prepublish": "npm run build",
|
"prepublish": "npm run build",
|
||||||
"travis": "npm link ng2-alfresco-core"
|
"travis": "npm link ng2-alfresco-core ng2-alfresco-datatable"
|
||||||
},
|
},
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"typings": "./dist/index.d.ts",
|
"typings": "./dist/index.d.ts",
|
||||||
@ -75,6 +75,7 @@
|
|||||||
"rimraf": "2.5.2",
|
"rimraf": "2.5.2",
|
||||||
"ng2-translate": "2.2.2",
|
"ng2-translate": "2.2.2",
|
||||||
"ng2-alfresco-core": "0.2.0",
|
"ng2-alfresco-core": "0.2.0",
|
||||||
|
"ng2-alfresco-datatable": "0.2.0",
|
||||||
"alfresco-js-api": "^0.1.0"
|
"alfresco-js-api": "^0.1.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
@ -103,13 +104,7 @@
|
|||||||
},
|
},
|
||||||
"license-check-config": {
|
"license-check-config": {
|
||||||
"src": [
|
"src": [
|
||||||
"**/*.js",
|
"./dist/**/*.js"
|
||||||
"**/*.ts",
|
|
||||||
"!/**/coverage/**/*",
|
|
||||||
"!/**/demo/**/*",
|
|
||||||
"!/**/node_modules/**/*",
|
|
||||||
"!/**/typings/**/*",
|
|
||||||
"!*.js"
|
|
||||||
],
|
],
|
||||||
"path": "assets/license_header.txt",
|
"path": "assets/license_header.txt",
|
||||||
"blocking": true,
|
"blocking": true,
|
||||||
|
@ -16,14 +16,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs/Observable';
|
||||||
import {AlfrescoService} from '../../src/services/alfresco.service';
|
import { DocumentListService } from './../services/document-list.service';
|
||||||
import {
|
import {
|
||||||
AlfrescoSettingsService,
|
AlfrescoSettingsService,
|
||||||
AlfrescoAuthenticationService,
|
AlfrescoAuthenticationService,
|
||||||
AlfrescoContentService
|
AlfrescoContentService
|
||||||
} from 'ng2-alfresco-core';
|
} from 'ng2-alfresco-core';
|
||||||
|
|
||||||
export class AlfrescoServiceMock extends AlfrescoService {
|
export class DocumentListServiceMock extends DocumentListService {
|
||||||
|
|
||||||
folderToReturn: any = {};
|
folderToReturn: any = {};
|
||||||
getFolderReject: boolean = false;
|
getFolderReject: boolean = false;
|
@ -23,7 +23,7 @@ import {
|
|||||||
} from '@angular/core/testing';
|
} from '@angular/core/testing';
|
||||||
|
|
||||||
import { DocumentList } from './document-list';
|
import { DocumentList } from './document-list';
|
||||||
import { AlfrescoServiceMock } from '../assets/alfresco.service.mock';
|
import { DocumentListServiceMock } from '../assets/document-list.service.mock';
|
||||||
import { ContentActionModel } from './../models/content-action.model';
|
import { ContentActionModel } from './../models/content-action.model';
|
||||||
import { ContentActionList } from './content-action-list';
|
import { ContentActionList } from './content-action-list';
|
||||||
|
|
||||||
@ -33,8 +33,8 @@ describe('ContentColumnList', () => {
|
|||||||
let actionList: ContentActionList;
|
let actionList: ContentActionList;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
let alfrescoServiceMock = new AlfrescoServiceMock();
|
let documentListService = new DocumentListServiceMock();
|
||||||
documentList = new DocumentList(alfrescoServiceMock, null);
|
documentList = new DocumentList(documentListService, null);
|
||||||
actionList = new ContentActionList(documentList);
|
actionList = new ContentActionList(documentList);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ import {
|
|||||||
import { EventEmitter } from '@angular/core';
|
import { EventEmitter } from '@angular/core';
|
||||||
|
|
||||||
import { DocumentList } from './document-list';
|
import { DocumentList } from './document-list';
|
||||||
import { AlfrescoServiceMock } from '../assets/alfresco.service.mock';
|
import { DocumentListServiceMock } from '../assets/document-list.service.mock';
|
||||||
import { ContentActionList } from './content-action-list';
|
import { ContentActionList } from './content-action-list';
|
||||||
import { ContentAction } from './content-action';
|
import { ContentAction } from './content-action';
|
||||||
import { DocumentActionsService } from '../services/document-actions.service';
|
import { DocumentActionsService } from '../services/document-actions.service';
|
||||||
@ -40,11 +40,11 @@ describe('ContentAction', () => {
|
|||||||
let folderActions: FolderActionsService;
|
let folderActions: FolderActionsService;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
let alfrescoServiceMock = new AlfrescoServiceMock();
|
let documentServiceMock = new DocumentListServiceMock();
|
||||||
documentActions = new DocumentActionsService(null, null);
|
documentActions = new DocumentActionsService(null, null);
|
||||||
folderActions = new FolderActionsService(null);
|
folderActions = new FolderActionsService(null);
|
||||||
|
|
||||||
documentList = new DocumentList(alfrescoServiceMock, null);
|
documentList = new DocumentList(documentServiceMock, null);
|
||||||
actionList = new ContentActionList(documentList);
|
actionList = new ContentActionList(documentList);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -59,7 +59,6 @@ describe('ContentAction', () => {
|
|||||||
|
|
||||||
it('should setup and register model', () => {
|
it('should setup and register model', () => {
|
||||||
let action = new ContentAction(actionList, null, null);
|
let action = new ContentAction(actionList, null, null);
|
||||||
action.type = 'button';
|
|
||||||
action.target = 'document';
|
action.target = 'document';
|
||||||
action.title = '<title>';
|
action.title = '<title>';
|
||||||
action.icon = '<icon>';
|
action.icon = '<icon>';
|
||||||
@ -70,7 +69,6 @@ describe('ContentAction', () => {
|
|||||||
expect(documentList.actions.length).toBe(1);
|
expect(documentList.actions.length).toBe(1);
|
||||||
|
|
||||||
let model = documentList.actions[0];
|
let model = documentList.actions[0];
|
||||||
expect(model.type).toBe(action.type);
|
|
||||||
expect(model.target).toBe(action.target);
|
expect(model.target).toBe(action.target);
|
||||||
expect(model.title).toBe(action.title);
|
expect(model.title).toBe(action.title);
|
||||||
expect(model.icon).toBe(action.icon);
|
expect(model.icon).toBe(action.icon);
|
||||||
@ -82,7 +80,6 @@ describe('ContentAction', () => {
|
|||||||
spyOn(documentActions, 'getHandler').and.returnValue(handler);
|
spyOn(documentActions, 'getHandler').and.returnValue(handler);
|
||||||
|
|
||||||
let action = new ContentAction(actionList, documentActions, null);
|
let action = new ContentAction(actionList, documentActions, null);
|
||||||
action.type = 'button';
|
|
||||||
action.target = 'document';
|
action.target = 'document';
|
||||||
action.handler = '<handler>';
|
action.handler = '<handler>';
|
||||||
action.ngOnInit();
|
action.ngOnInit();
|
||||||
@ -99,7 +96,6 @@ describe('ContentAction', () => {
|
|||||||
spyOn(folderActions, 'getHandler').and.returnValue(handler);
|
spyOn(folderActions, 'getHandler').and.returnValue(handler);
|
||||||
|
|
||||||
let action = new ContentAction(actionList, null, folderActions);
|
let action = new ContentAction(actionList, null, folderActions);
|
||||||
action.type = 'button';
|
|
||||||
action.target = 'folder';
|
action.target = 'folder';
|
||||||
action.handler = '<handler>';
|
action.handler = '<handler>';
|
||||||
action.ngOnInit();
|
action.ngOnInit();
|
||||||
@ -116,7 +112,6 @@ describe('ContentAction', () => {
|
|||||||
spyOn(documentActions, 'getHandler').and.stub();
|
spyOn(documentActions, 'getHandler').and.stub();
|
||||||
|
|
||||||
let action = new ContentAction(actionList, documentActions, folderActions);
|
let action = new ContentAction(actionList, documentActions, folderActions);
|
||||||
action.type = 'button';
|
|
||||||
action.handler = '<handler>';
|
action.handler = '<handler>';
|
||||||
|
|
||||||
action.ngOnInit();
|
action.ngOnInit();
|
||||||
@ -138,7 +133,6 @@ describe('ContentAction', () => {
|
|||||||
|
|
||||||
let action = new ContentAction(actionList, documentActions, null);
|
let action = new ContentAction(actionList, documentActions, null);
|
||||||
action.target = 'DoCuMeNt';
|
action.target = 'DoCuMeNt';
|
||||||
action.type = 'button';
|
|
||||||
action.handler = '<handler>';
|
action.handler = '<handler>';
|
||||||
|
|
||||||
action.ngOnInit();
|
action.ngOnInit();
|
||||||
@ -150,7 +144,6 @@ describe('ContentAction', () => {
|
|||||||
|
|
||||||
let action = new ContentAction(actionList, null, folderActions);
|
let action = new ContentAction(actionList, null, folderActions);
|
||||||
action.target = 'FoLdEr';
|
action.target = 'FoLdEr';
|
||||||
action.type = 'button';
|
|
||||||
action.handler = '<handler>';
|
action.handler = '<handler>';
|
||||||
|
|
||||||
action.ngOnInit();
|
action.ngOnInit();
|
||||||
@ -167,7 +160,6 @@ describe('ContentAction', () => {
|
|||||||
|
|
||||||
let action = new ContentAction(actionList, null, null);
|
let action = new ContentAction(actionList, null, null);
|
||||||
action.target = 'document';
|
action.target = 'document';
|
||||||
action.type = 'button';
|
|
||||||
action.execute = emitter;
|
action.execute = emitter;
|
||||||
|
|
||||||
action.ngOnInit();
|
action.ngOnInit();
|
||||||
|
@ -15,7 +15,15 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Component, OnInit, OnChanges, Input, Output, EventEmitter} from '@angular/core';
|
import {
|
||||||
|
Component,
|
||||||
|
OnInit,
|
||||||
|
OnChanges,
|
||||||
|
Input,
|
||||||
|
Output,
|
||||||
|
EventEmitter
|
||||||
|
} from '@angular/core';
|
||||||
|
|
||||||
import { ContentActionModel } from './../models/content-action.model';
|
import { ContentActionModel } from './../models/content-action.model';
|
||||||
import { ContentActionList } from './content-action-list';
|
import { ContentActionList } from './content-action-list';
|
||||||
import { DocumentActionsService } from '../services/document-actions.service';
|
import { DocumentActionsService } from '../services/document-actions.service';
|
||||||
@ -37,9 +45,6 @@ export class ContentAction implements OnInit, OnChanges {
|
|||||||
@Input()
|
@Input()
|
||||||
handler: string;
|
handler: string;
|
||||||
|
|
||||||
@Input()
|
|
||||||
type: string;
|
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
target: string;
|
target: string;
|
||||||
|
|
||||||
@ -57,7 +62,6 @@ export class ContentAction implements OnInit, OnChanges {
|
|||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.model = new ContentActionModel({
|
this.model = new ContentActionModel({
|
||||||
type: this.type,
|
|
||||||
title: this.title,
|
title: this.title,
|
||||||
icon: this.icon,
|
icon: this.icon,
|
||||||
target: this.target
|
target: this.target
|
||||||
|
@ -22,10 +22,11 @@ import {
|
|||||||
beforeEach
|
beforeEach
|
||||||
} from '@angular/core/testing';
|
} from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { DataColumn } from 'ng2-alfresco-datatable';
|
||||||
|
|
||||||
import { DocumentList } from './document-list';
|
import { DocumentList } from './document-list';
|
||||||
import {AlfrescoServiceMock} from '../assets/alfresco.service.mock';
|
import { DocumentListServiceMock } from '../assets/document-list.service.mock';
|
||||||
import { ContentColumnList } from './content-column-list';
|
import { ContentColumnList } from './content-column-list';
|
||||||
import {ContentColumnModel} from '../models/content-column.model';
|
|
||||||
|
|
||||||
describe('ContentColumnList', () => {
|
describe('ContentColumnList', () => {
|
||||||
|
|
||||||
@ -33,23 +34,26 @@ describe('ContentColumnList', () => {
|
|||||||
let columnList: ContentColumnList;
|
let columnList: ContentColumnList;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
let alfrescoServiceMock = new AlfrescoServiceMock();
|
let service = new DocumentListServiceMock();
|
||||||
documentList = new DocumentList(alfrescoServiceMock, null);
|
documentList = new DocumentList(service, null);
|
||||||
columnList = new ContentColumnList(documentList);
|
columnList = new ContentColumnList(documentList);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should register column within parent document list', () => {
|
it('should register column within parent document list', () => {
|
||||||
expect(documentList.columns.length).toBe(0);
|
let columns = documentList.data.getColumns();
|
||||||
|
expect(columns.length).toBe(0);
|
||||||
|
|
||||||
let result = columnList.registerColumn(new ContentColumnModel());
|
let column = <DataColumn> {};
|
||||||
|
let result = columnList.registerColumn(column);
|
||||||
|
|
||||||
expect(result).toBeTruthy();
|
expect(result).toBeTruthy();
|
||||||
expect(documentList.columns.length).toBe(1);
|
expect(columns.length).toBe(1);
|
||||||
|
expect(columns[0]).toBe(column);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should require document list instance to register action', () => {
|
it('should require document list instance to register action', () => {
|
||||||
columnList = new ContentColumnList(null);
|
columnList = new ContentColumnList(null);
|
||||||
let col = new ContentColumnModel();
|
let col = <DataColumn> {};
|
||||||
expect(columnList.registerColumn(col)).toBeFalsy();
|
expect(columnList.registerColumn(col)).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { DocumentList } from './document-list';
|
import { DocumentList } from './document-list';
|
||||||
import {ContentColumnModel} from './../models/content-column.model';
|
import { DataColumn } from 'ng2-alfresco-datatable';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'content-columns',
|
selector: 'content-columns',
|
||||||
@ -33,9 +33,10 @@ export class ContentColumnList {
|
|||||||
* Registers column model within the parent document list component.
|
* Registers column model within the parent document list component.
|
||||||
* @param column Column definition model to register.
|
* @param column Column definition model to register.
|
||||||
*/
|
*/
|
||||||
registerColumn(column: ContentColumnModel): boolean {
|
registerColumn(column: DataColumn): boolean {
|
||||||
if (this.documentList && column) {
|
if (this.documentList && column) {
|
||||||
this.documentList.columns.push(column);
|
let columns = this.documentList.data.getColumns();
|
||||||
|
columns.push(column);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -24,7 +24,7 @@ import {
|
|||||||
|
|
||||||
import { DocumentList } from './document-list';
|
import { DocumentList } from './document-list';
|
||||||
import { ContentColumn } from './content-column';
|
import { ContentColumn } from './content-column';
|
||||||
import {AlfrescoServiceMock} from '../assets/alfresco.service.mock';
|
import { DocumentListServiceMock } from '../assets/document-list.service.mock';
|
||||||
import { ContentColumnList } from './content-column-list';
|
import { ContentColumnList } from './content-column-list';
|
||||||
|
|
||||||
describe('ContentColumn', () => {
|
describe('ContentColumn', () => {
|
||||||
@ -33,8 +33,8 @@ describe('ContentColumn', () => {
|
|||||||
let columnList: ContentColumnList;
|
let columnList: ContentColumnList;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
let alfrescoServiceMock = new AlfrescoServiceMock();
|
let service = new DocumentListServiceMock();
|
||||||
documentList = new DocumentList(alfrescoServiceMock, null);
|
documentList = new DocumentList(service, null);
|
||||||
columnList = new ContentColumnList(documentList);
|
columnList = new ContentColumnList(documentList);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -45,52 +45,18 @@ describe('ContentColumn', () => {
|
|||||||
column.ngOnInit();
|
column.ngOnInit();
|
||||||
|
|
||||||
expect(columnList.registerColumn).toHaveBeenCalled();
|
expect(columnList.registerColumn).toHaveBeenCalled();
|
||||||
});
|
|
||||||
|
|
||||||
it('should setup model properties during registration', () => {
|
let columns = documentList.data.getColumns();
|
||||||
|
expect(columns.length).toBe(1);
|
||||||
let column = new ContentColumn(columnList);
|
expect(columns[0]).toBe(column);
|
||||||
column.title = '<title>';
|
|
||||||
column.srTitle = '<sr-title>';
|
|
||||||
column.source = '<source>';
|
|
||||||
column.cssClass = '<css-class>';
|
|
||||||
column.ngOnInit();
|
|
||||||
|
|
||||||
expect(documentList.columns.length).toBe(1);
|
|
||||||
|
|
||||||
let model = documentList.columns[0];
|
|
||||||
expect(model.title).toBe(column.title);
|
|
||||||
expect(model.srTitle).toBe(column.srTitle);
|
|
||||||
expect(model.source).toBe(column.source);
|
|
||||||
expect(model.cssClass).toBe(column.cssClass);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should setup screen reader title for thumbnail column', () => {
|
it('should setup screen reader title for thumbnail column', () => {
|
||||||
|
|
||||||
let column = new ContentColumn(columnList);
|
let column = new ContentColumn(columnList);
|
||||||
column.source = '$thumbnail';
|
column.key = '$thumbnail';
|
||||||
column.ngOnInit();
|
column.ngOnInit();
|
||||||
|
|
||||||
expect(documentList.columns.length).toBe(1);
|
expect(column.srTitle).toBe('Thumbnail');
|
||||||
|
|
||||||
let model = documentList.columns[0];
|
|
||||||
expect(model.srTitle).toBe('Thumbnail');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should sync localizable fields with model', () => {
|
|
||||||
|
|
||||||
let column = new ContentColumn(columnList);
|
|
||||||
column.title = 'title1';
|
|
||||||
column.srTitle = 'srTitle1';
|
|
||||||
column.ngOnInit();
|
|
||||||
|
|
||||||
expect(column.model.title).toBe(column.title);
|
|
||||||
expect(column.model.srTitle).toBe(column.srTitle);
|
|
||||||
|
|
||||||
column.title = 'title2';
|
|
||||||
column.ngOnChanges(null);
|
|
||||||
|
|
||||||
expect(column.model.title).toBe('title2');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should register on init', () => {
|
it('should register on init', () => {
|
||||||
|
@ -15,15 +15,27 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Component, OnInit, Input, OnChanges } from '@angular/core';
|
import { Component, OnInit, Input } from '@angular/core';
|
||||||
import { ContentColumnList } from './content-column-list';
|
import { ContentColumnList } from './content-column-list';
|
||||||
import { ContentColumnModel } from './../models/content-column.model';
|
import { DataColumn } from 'ng2-alfresco-datatable';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'content-column',
|
selector: 'content-column',
|
||||||
template: ''
|
template: ''
|
||||||
})
|
})
|
||||||
export class ContentColumn implements OnInit, OnChanges {
|
export class ContentColumn implements OnInit, DataColumn {
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
key: string;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
type: string = 'text';
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
format: string;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
sortable: boolean = false;
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
title: string = '';
|
title: string = '';
|
||||||
@ -34,36 +46,14 @@ export class ContentColumn implements OnInit, OnChanges {
|
|||||||
@Input('sr-title')
|
@Input('sr-title')
|
||||||
srTitle: string;
|
srTitle: string;
|
||||||
|
|
||||||
@Input()
|
|
||||||
source: string;
|
|
||||||
|
|
||||||
@Input('class')
|
@Input('class')
|
||||||
cssClass: string;
|
cssClass: string;
|
||||||
|
|
||||||
@Input()
|
constructor(private list: ContentColumnList) {}
|
||||||
type: string = 'text';
|
|
||||||
|
|
||||||
@Input()
|
|
||||||
format: string;
|
|
||||||
|
|
||||||
model: ContentColumnModel;
|
|
||||||
|
|
||||||
constructor(private list: ContentColumnList) {
|
|
||||||
this.model = new ContentColumnModel();
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.model = new ContentColumnModel({
|
if (!this.srTitle && this.key === '$thumbnail') {
|
||||||
title: this.title,
|
this.srTitle = 'Thumbnail';
|
||||||
srTitle: this.srTitle,
|
|
||||||
source: this.source,
|
|
||||||
cssClass: this.cssClass,
|
|
||||||
type: this.type,
|
|
||||||
format: this.format
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!this.model.srTitle && this.model.source === '$thumbnail') {
|
|
||||||
this.model.srTitle = 'Thumbnail';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.register();
|
this.register();
|
||||||
@ -71,14 +61,8 @@ export class ContentColumn implements OnInit, OnChanges {
|
|||||||
|
|
||||||
register(): boolean {
|
register(): boolean {
|
||||||
if (this.list) {
|
if (this.list) {
|
||||||
return this.list.registerColumn(this.model);
|
return this.list.registerColumn(this);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnChanges(change) {
|
|
||||||
// update localizable properties
|
|
||||||
this.model.title = this.title;
|
|
||||||
this.model.srTitle = this.srTitle;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,105 +0,0 @@
|
|||||||
: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;
|
|
||||||
overflow: hidden;
|
|
||||||
height: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* visible content */
|
|
||||||
:host .ellipsis-cell > div > span
|
|
||||||
{
|
|
||||||
display: block;
|
|
||||||
position: absolute;
|
|
||||||
max-width: 100%;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
line-height: 1em; /* for vertical align of text */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* cell stretching content */
|
|
||||||
:host .ellipsis-cell > div:after
|
|
||||||
{
|
|
||||||
content: attr(title);
|
|
||||||
overflow: hidden;
|
|
||||||
height: 0;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* small desktop */
|
|
||||||
@media all and (max-width: 1200px) {}
|
|
||||||
|
|
||||||
/* tablet */
|
|
||||||
@media all and (max-width: 1024px) {}
|
|
||||||
|
|
||||||
/* mobile phone */
|
|
||||||
@media all and (max-width: 768px) {
|
|
||||||
.desktop-only {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-device-width: 768px){
|
|
||||||
.desktop-only {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,103 +1,15 @@
|
|||||||
<table *ngIf="folder" class="mdl-data-table mdl-js-data-table mdl-shadow--2dp full-width">
|
<alfresco-datatable
|
||||||
<thead>
|
[data]="data"
|
||||||
<tr>
|
[actions]="contentActions"
|
||||||
<!-- Columns -->
|
[multiselect]="multiselect"
|
||||||
<th class="mdl-data-table__cell--non-numeric non-selectable {{col.cssClass}}"
|
(showRowContextMenu)="onShowRowContextMenu($event)"
|
||||||
*ngFor="let col of columns"
|
(showRowActionsMenu)="onShowRowActionsMenu($event)"
|
||||||
[class.column-header]="col.title"
|
(executeRowAction)="onExecuteRowAction($event)"
|
||||||
[attr.data-automation-id]="'auto_id_' + col.source"
|
(rowClick)="onRowClick($event)"
|
||||||
[class.mdl-data-table__header--sorted-ascending]="sorting.key === col.source && sorting.direction === 'asc'"
|
(rowDblClick)="onRowDblClick($event)">
|
||||||
[class.mdl-data-table__header--sorted-descending]="sorting.key === col.source && sorting.direction === 'desc'"
|
<no-content-template>
|
||||||
(click)="onColumnHeaderClick(col)">
|
<template>
|
||||||
<span *ngIf="col.srTitle" class="cell-value sr-only">{{col.srTitle}}</span>
|
<img [src]="baseComponentPath + '/img/document-list.empty-folder.png'">
|
||||||
<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>
|
</template>
|
||||||
<img *ngIf="!emptyFolderTemplate"
|
</no-content-template>
|
||||||
[src]="baseComponentPath + '/img/document-list.empty-folder.png'">
|
</alfresco-datatable>
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
@ -15,35 +15,26 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import { it, describe, expect, beforeEach } from '@angular/core/testing';
|
||||||
it,
|
|
||||||
describe,
|
|
||||||
expect,
|
|
||||||
beforeEach
|
|
||||||
} from '@angular/core/testing';
|
|
||||||
import { NgZone } from '@angular/core';
|
import { NgZone } from '@angular/core';
|
||||||
|
import { DataColumn } from 'ng2-alfresco-datatable';
|
||||||
import { DocumentList } from './document-list';
|
import { DocumentList } from './document-list';
|
||||||
import { ContentColumnModel } from '../models/content-column.model';
|
import { DocumentListServiceMock } from './../assets/document-list.service.mock';
|
||||||
import { AlfrescoServiceMock } from '../assets/alfresco.service.mock';
|
|
||||||
import { ContentActionModel } from '../models/content-action.model';
|
import { ContentActionModel } from '../models/content-action.model';
|
||||||
import {
|
import { FileNode, FolderNode } from '../assets/document-library.model.mock';
|
||||||
PageNode,
|
import { MinimalNodeEntity } from '../models/document-library.model';
|
||||||
FileNode,
|
|
||||||
FolderNode
|
|
||||||
} from '../assets/document-library.model.mock';
|
|
||||||
import { ColumnSortingModel } from '../models/column-sorting.model';
|
|
||||||
|
|
||||||
describe('DocumentList', () => {
|
describe('DocumentList', () => {
|
||||||
|
|
||||||
let alfrescoServiceMock: AlfrescoServiceMock;
|
let documentListService: DocumentListServiceMock;
|
||||||
let documentList: DocumentList;
|
let documentList: DocumentList;
|
||||||
let eventMock: any;
|
let eventMock: any;
|
||||||
let componentHandler;
|
let componentHandler;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
alfrescoServiceMock = new AlfrescoServiceMock();
|
documentListService = new DocumentListServiceMock();
|
||||||
let zone = new NgZone(false);
|
let zone = new NgZone(false);
|
||||||
documentList = new DocumentList(alfrescoServiceMock, zone);
|
documentList = new DocumentList(documentListService, zone);
|
||||||
|
|
||||||
eventMock = {
|
eventMock = {
|
||||||
preventDefault: function () {
|
preventDefault: function () {
|
||||||
@ -63,56 +54,67 @@ describe('DocumentList', () => {
|
|||||||
documentList.ngAfterContentInit();
|
documentList.ngAfterContentInit();
|
||||||
|
|
||||||
expect(documentList.setupDefaultColumns).toHaveBeenCalled();
|
expect(documentList.setupDefaultColumns).toHaveBeenCalled();
|
||||||
expect(documentList.columns.length).not.toBe(0);
|
expect(documentList.data.getColumns().length).not.toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should use custom columns instead of default ones', () => {
|
it('should use custom columns instead of default ones', () => {
|
||||||
let column: ContentColumnModel = {
|
let column = <DataColumn> {
|
||||||
title: 'title',
|
title: 'title',
|
||||||
source: 'source',
|
key: 'source',
|
||||||
cssClass: 'css',
|
cssClass: 'css',
|
||||||
srTitle: '',
|
srTitle: '',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
format: ''
|
format: ''
|
||||||
};
|
};
|
||||||
documentList.columns.push(column);
|
|
||||||
|
let columns = documentList.data.getColumns();
|
||||||
|
columns.push(column);
|
||||||
|
|
||||||
documentList.ngAfterContentInit();
|
documentList.ngAfterContentInit();
|
||||||
expect(documentList.columns.length).toBe(1);
|
expect(columns.length).toBe(1);
|
||||||
expect(documentList.columns[0]).toBe(column);
|
expect(columns[0]).toBe(column);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// TODO: move to data adapter
|
||||||
|
/*
|
||||||
it('should fetch folder', () => {
|
it('should fetch folder', () => {
|
||||||
let folder = {
|
let folder = {
|
||||||
'nodeRef': 'workspace://SpacesStore/8bb36efb-c26d-4d2b-9199-ab6922f53c28'
|
'nodeRef': 'workspace://SpacesStore/8bb36efb-c26d-4d2b-9199-ab6922f53c28'
|
||||||
};
|
};
|
||||||
alfrescoServiceMock.folderToReturn = folder;
|
documentListService.folderToReturn = folder;
|
||||||
documentList.ngOnInit();
|
documentList.ngOnInit();
|
||||||
|
|
||||||
expect(documentList.folder).toBe(folder);
|
expect(documentList.folder).toBe(folder);
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TODO: move to data adapter
|
||||||
|
/*
|
||||||
it('should return thumbnail url for a file when thumbnails turned on', () => {
|
it('should return thumbnail url for a file when thumbnails turned on', () => {
|
||||||
let url = 'URL';
|
let url = 'URL';
|
||||||
spyOn(alfrescoServiceMock, 'getDocumentThumbnailUrl').and.returnValue(url);
|
spyOn(documentListService, 'getDocumentThumbnailUrl').and.returnValue(url);
|
||||||
|
|
||||||
let node = new FileNode();
|
let node = new FileNode();
|
||||||
documentList.thumbnails = true;
|
documentList.thumbnails = true;
|
||||||
let result = documentList.getThumbnailUrl(node);
|
let result = documentList.getThumbnailUrl(node);
|
||||||
|
|
||||||
expect(result).toBe(url);
|
expect(result).toBe(url);
|
||||||
expect(alfrescoServiceMock.getDocumentThumbnailUrl).toHaveBeenCalled();
|
expect(documentListService.getDocumentThumbnailUrl).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TODO: move to data adapter
|
||||||
|
/*
|
||||||
it('should return a null thumbnail url for a null item', () => {
|
it('should return a null thumbnail url for a null item', () => {
|
||||||
let url = 'URL';
|
let url = 'URL';
|
||||||
spyOn(alfrescoServiceMock, 'getDocumentThumbnailUrl').and.returnValue(url);
|
spyOn(documentListService, 'getDocumentThumbnailUrl').and.returnValue(url);
|
||||||
|
|
||||||
let result = documentList.getThumbnailUrl(null);
|
let result = documentList.getThumbnailUrl(null);
|
||||||
|
|
||||||
expect(result).toBeNull();
|
expect(result).toBeNull();
|
||||||
expect(alfrescoServiceMock.getDocumentThumbnailUrl).not.toHaveBeenCalled();
|
expect(documentListService.getDocumentThumbnailUrl).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
it('should execute action with node', () => {
|
it('should execute action with node', () => {
|
||||||
let node = new FileNode();
|
let node = new FileNode();
|
||||||
@ -139,100 +141,54 @@ describe('DocumentList', () => {
|
|||||||
expect(action.handler).not.toHaveBeenCalled();
|
expect(action.handler).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should give no content actions for empty target', () => {
|
it('should not give node actions for empty target', () => {
|
||||||
let actions = documentList.getContentActions(null, 'button');
|
let actions = documentList.getNodeActions(null);
|
||||||
expect(actions.length).toBe(0);
|
expect(actions.length).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should give no content actions for empty type', () => {
|
it('should filter content actions for various targets', () => {
|
||||||
let actions = documentList.getContentActions('folder', null);
|
|
||||||
expect(actions.length).toBe(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should filter content actions for various types and targets', () => {
|
|
||||||
let folderButton = new ContentActionModel();
|
|
||||||
folderButton.target = 'folder';
|
|
||||||
folderButton.type = 'button';
|
|
||||||
|
|
||||||
let folderMenu = new ContentActionModel();
|
let folderMenu = new ContentActionModel();
|
||||||
folderMenu.target = 'folder';
|
folderMenu.target = 'folder';
|
||||||
folderMenu.type = 'menu';
|
|
||||||
|
|
||||||
let documentButton = new ContentActionModel();
|
|
||||||
documentButton.target = 'document';
|
|
||||||
documentButton.type = 'button';
|
|
||||||
|
|
||||||
let documentMenu = new ContentActionModel();
|
let documentMenu = new ContentActionModel();
|
||||||
documentMenu.target = 'document';
|
documentMenu.target = 'document';
|
||||||
documentMenu.type = 'menu';
|
|
||||||
|
|
||||||
documentList.actions = [
|
documentList.actions = [
|
||||||
folderButton,
|
|
||||||
folderMenu,
|
folderMenu,
|
||||||
documentButton,
|
|
||||||
documentMenu
|
documentMenu
|
||||||
];
|
];
|
||||||
|
|
||||||
let actions = documentList.getContentActions('folder', 'button');
|
|
||||||
expect(actions.length).toBe(1);
|
|
||||||
expect(actions[0]).toBe(folderButton);
|
|
||||||
|
|
||||||
actions = documentList.getContentActions('folder', 'menu');
|
let actions = documentList.getNodeActions(new FolderNode());
|
||||||
expect(actions.length).toBe(1);
|
expect(actions.length).toBe(1);
|
||||||
expect(actions[0]).toBe(folderMenu);
|
expect(actions[0]).toBe(folderMenu);
|
||||||
|
|
||||||
actions = documentList.getContentActions('document', 'button');
|
actions = documentList.getNodeActions(new FileNode());
|
||||||
expect(actions.length).toBe(1);
|
|
||||||
expect(actions[0]).toBe(documentButton);
|
|
||||||
|
|
||||||
actions = documentList.getContentActions('document', 'menu');
|
|
||||||
expect(actions.length).toBe(1);
|
expect(actions.length).toBe(1);
|
||||||
expect(actions[0]).toBe(documentMenu);
|
expect(actions[0]).toBe(documentMenu);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be case insensitive when filtering content actions', () => {
|
|
||||||
let documentButton = new ContentActionModel();
|
|
||||||
documentButton.target = 'document';
|
|
||||||
documentButton.type = 'button';
|
|
||||||
|
|
||||||
documentList.actions = [documentButton];
|
|
||||||
|
|
||||||
let actions = documentList.getContentActions('DoCuMeNt', 'BUTTON');
|
|
||||||
expect(actions.length).toBe(1);
|
|
||||||
expect(actions[0]).toBe(documentButton);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should find no content actions', () => {
|
it('should find no content actions', () => {
|
||||||
let documentButton = new ContentActionModel();
|
let documentButton = new ContentActionModel();
|
||||||
documentButton.target = 'document';
|
documentButton.target = 'document';
|
||||||
documentButton.type = 'button';
|
|
||||||
|
|
||||||
documentList.actions = [documentButton];
|
documentList.actions = [documentButton];
|
||||||
|
|
||||||
let actions = documentList.getContentActions('unknown', 'value');
|
let node = new MinimalNodeEntity();
|
||||||
expect(actions.length).toBe(0);
|
expect(documentList.getNodeActions(node)).toEqual([]);
|
||||||
|
|
||||||
|
node = new FileNode();
|
||||||
|
node.entry.isFile = false;
|
||||||
|
node.entry.isFolder = false;
|
||||||
|
expect(documentList.getNodeActions(node)).toEqual([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should emit itemClick event', (done) => {
|
it('should emit nodeClick event', (done) => {
|
||||||
let node = new FileNode();
|
let node = new FileNode();
|
||||||
documentList.itemClick.subscribe(e => {
|
documentList.nodeClick.subscribe(e => {
|
||||||
expect(e.value).toBe(node);
|
expect(e.value).toBe(node);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
documentList.onItemClick(node);
|
documentList.onNodeClick(node);
|
||||||
});
|
|
||||||
|
|
||||||
it('should prevent default item single click event', () => {
|
|
||||||
spyOn(eventMock, 'preventDefault').and.stub();
|
|
||||||
|
|
||||||
documentList.onItemClick(null, eventMock);
|
|
||||||
expect(eventMock.preventDefault).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should prevent default item double click event', () => {
|
|
||||||
spyOn(eventMock, 'preventDefault').and.stub();
|
|
||||||
documentList.onItemDblClick(null, eventMock);
|
|
||||||
expect(eventMock.preventDefault).toHaveBeenCalled();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display folder content on click', () => {
|
it('should display folder content on click', () => {
|
||||||
@ -244,7 +200,7 @@ describe('DocumentList', () => {
|
|||||||
spyOn(documentList, 'displayFolderContent').and.stub();
|
spyOn(documentList, 'displayFolderContent').and.stub();
|
||||||
|
|
||||||
documentList.navigationMode = DocumentList.SINGLE_CLICK_NAVIGATION;
|
documentList.navigationMode = DocumentList.SINGLE_CLICK_NAVIGATION;
|
||||||
documentList.onItemClick(node);
|
documentList.onNodeClick(node);
|
||||||
|
|
||||||
expect(documentList.currentFolderPath).toBe(path);
|
expect(documentList.currentFolderPath).toBe(path);
|
||||||
});
|
});
|
||||||
@ -253,7 +209,7 @@ describe('DocumentList', () => {
|
|||||||
expect(documentList.navigate).toBe(true);
|
expect(documentList.navigate).toBe(true);
|
||||||
spyOn(documentList, 'displayFolderContent').and.stub();
|
spyOn(documentList, 'displayFolderContent').and.stub();
|
||||||
|
|
||||||
documentList.onItemClick(null);
|
documentList.onNodeClick(null);
|
||||||
expect(documentList.displayFolderContent).not.toHaveBeenCalled();
|
expect(documentList.displayFolderContent).not.toHaveBeenCalled();
|
||||||
|
|
||||||
});
|
});
|
||||||
@ -263,7 +219,7 @@ describe('DocumentList', () => {
|
|||||||
spyOn(documentList, 'displayFolderContent').and.stub();
|
spyOn(documentList, 'displayFolderContent').and.stub();
|
||||||
|
|
||||||
let node = new FileNode();
|
let node = new FileNode();
|
||||||
documentList.onItemClick(node);
|
documentList.onNodeClick(node);
|
||||||
|
|
||||||
expect(documentList.displayFolderContent).not.toHaveBeenCalled();
|
expect(documentList.displayFolderContent).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
@ -273,7 +229,7 @@ describe('DocumentList', () => {
|
|||||||
|
|
||||||
let node = new FolderNode('<display name>');
|
let node = new FolderNode('<display name>');
|
||||||
documentList.navigate = false;
|
documentList.navigate = false;
|
||||||
documentList.onItemClick(node);
|
documentList.onNodeClick(node);
|
||||||
|
|
||||||
expect(documentList.displayFolderContent).not.toHaveBeenCalled();
|
expect(documentList.displayFolderContent).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
@ -282,33 +238,6 @@ describe('DocumentList', () => {
|
|||||||
expect(documentList.getNodePath(null)).toBe(null);
|
expect(documentList.getNodePath(null)).toBe(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return root object value', () => {
|
|
||||||
let target = {
|
|
||||||
key1: 'value1'
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(documentList.getObjectValue(target, 'key1')).toBe('value1');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return no object value when key is missing', () => {
|
|
||||||
let target = {
|
|
||||||
key1: 'value1'
|
|
||||||
};
|
|
||||||
expect(documentList.getObjectValue(target, 'missing')).toBeUndefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return nested object value', () => {
|
|
||||||
let target = {
|
|
||||||
key1: {
|
|
||||||
key2: {
|
|
||||||
key3: 'value1'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(documentList.getObjectValue(target, 'key1.key2.key3')).toBe('value1');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should display folder content for new folder path', () => {
|
it('should display folder content for new folder path', () => {
|
||||||
spyOn(documentList, 'displayFolderContent').and.stub();
|
spyOn(documentList, 'displayFolderContent').and.stub();
|
||||||
let newPath = '/some/new/path';
|
let newPath = '/some/new/path';
|
||||||
@ -334,42 +263,44 @@ describe('DocumentList', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should emit folder changed event', (done) => {
|
it('should emit folder changed event', (done) => {
|
||||||
|
spyOn(documentList, 'displayFolderContent').and.stub();
|
||||||
documentList.folderChange.subscribe(e => {
|
documentList.folderChange.subscribe(e => {
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
documentList.folder = new PageNode();
|
|
||||||
|
documentList.currentFolderPath = '/some/new/path';
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should emit folder changed event with folder details', (done) => {
|
it('should emit folder changed event with folder details', (done) => {
|
||||||
let folder = new PageNode();
|
spyOn(documentList, 'displayFolderContent').and.stub();
|
||||||
|
|
||||||
let path = '/path';
|
let path = '/path';
|
||||||
|
|
||||||
documentList.folderChange.subscribe(e => {
|
documentList.folderChange.subscribe(e => {
|
||||||
expect(e.value).toBe(folder);
|
|
||||||
expect(e.path).toBe(path);
|
expect(e.path).toBe(path);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
spyOn(documentList, 'displayFolderContent').and.stub();
|
|
||||||
documentList.currentFolderPath = path;
|
documentList.currentFolderPath = path;
|
||||||
documentList.folder = folder;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not emit folder changed event', () => {
|
it('should emit folder changed event only once', () => {
|
||||||
let folder = new PageNode();
|
spyOn(documentList, 'displayFolderContent').and.stub();
|
||||||
|
let path = '/new/path';
|
||||||
let calls = 0;
|
let calls = 0;
|
||||||
documentList.folderChange.subscribe(e => {
|
documentList.folderChange.subscribe(e => {
|
||||||
calls++;
|
calls++;
|
||||||
});
|
});
|
||||||
|
|
||||||
documentList.folder = folder;
|
documentList.currentFolderPath = path;
|
||||||
documentList.folder = folder;
|
documentList.currentFolderPath = path;
|
||||||
|
documentList.currentFolderPath = path;
|
||||||
expect(calls).toBe(1);
|
expect(calls).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should reload on binding changes', () => {
|
it('should reload on binding changes', () => {
|
||||||
spyOn(documentList, 'reload').and.stub();
|
spyOn(documentList, 'reload').and.stub();
|
||||||
documentList.ngOnChanges(null);
|
documentList.ngOnChanges();
|
||||||
expect(documentList.reload).toHaveBeenCalled();
|
expect(documentList.reload).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -396,8 +327,9 @@ describe('DocumentList', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should subscribe to context action handler', () => {
|
it('should subscribe to context action handler', () => {
|
||||||
let value = {};
|
spyOn(documentList, 'displayFolderContent').and.stub();
|
||||||
spyOn(documentList, 'contextActionCallback').and.stub();
|
spyOn(documentList, 'contextActionCallback').and.stub();
|
||||||
|
let value = {};
|
||||||
documentList.ngOnInit();
|
documentList.ngOnInit();
|
||||||
documentList.contextActionHandler.next(value);
|
documentList.contextActionHandler.next(value);
|
||||||
expect(documentList.contextActionCallback).toHaveBeenCalledWith(value);
|
expect(documentList.contextActionCallback).toHaveBeenCalledWith(value);
|
||||||
@ -416,7 +348,7 @@ describe('DocumentList', () => {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
documentList.navigationMode = DocumentList.SINGLE_CLICK_NAVIGATION;
|
documentList.navigationMode = DocumentList.SINGLE_CLICK_NAVIGATION;
|
||||||
documentList.onItemClick(file, null);
|
documentList.onNodeClick(file);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should emit file preview event on double click', (done) => {
|
it('should emit file preview event on double click', (done) => {
|
||||||
@ -426,7 +358,7 @@ describe('DocumentList', () => {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
documentList.navigationMode = DocumentList.DOUBLE_CLICK_NAVIGATION;
|
documentList.navigationMode = DocumentList.DOUBLE_CLICK_NAVIGATION;
|
||||||
documentList.onItemDblClick(file, null);
|
documentList.onNodeDblClick(file);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should perform folder navigation on single click', () => {
|
it('should perform folder navigation on single click', () => {
|
||||||
@ -434,7 +366,7 @@ describe('DocumentList', () => {
|
|||||||
spyOn(documentList, 'performNavigation').and.stub();
|
spyOn(documentList, 'performNavigation').and.stub();
|
||||||
|
|
||||||
documentList.navigationMode = DocumentList.SINGLE_CLICK_NAVIGATION;
|
documentList.navigationMode = DocumentList.SINGLE_CLICK_NAVIGATION;
|
||||||
documentList.onItemClick(folder, null);
|
documentList.onNodeClick(folder);
|
||||||
expect(documentList.performNavigation).toHaveBeenCalled();
|
expect(documentList.performNavigation).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -443,7 +375,7 @@ describe('DocumentList', () => {
|
|||||||
spyOn(documentList, 'performNavigation').and.stub();
|
spyOn(documentList, 'performNavigation').and.stub();
|
||||||
|
|
||||||
documentList.navigationMode = DocumentList.DOUBLE_CLICK_NAVIGATION;
|
documentList.navigationMode = DocumentList.DOUBLE_CLICK_NAVIGATION;
|
||||||
documentList.onItemDblClick(folder, null);
|
documentList.onNodeDblClick(folder);
|
||||||
expect(documentList.performNavigation).toHaveBeenCalled();
|
expect(documentList.performNavigation).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -452,7 +384,7 @@ describe('DocumentList', () => {
|
|||||||
spyOn(documentList, 'performNavigation').and.stub();
|
spyOn(documentList, 'performNavigation').and.stub();
|
||||||
|
|
||||||
documentList.navigationMode = DocumentList.SINGLE_CLICK_NAVIGATION;
|
documentList.navigationMode = DocumentList.SINGLE_CLICK_NAVIGATION;
|
||||||
documentList.onItemDblClick(folder, null);
|
documentList.onNodeDblClick(folder);
|
||||||
|
|
||||||
expect(documentList.performNavigation).not.toHaveBeenCalled();
|
expect(documentList.performNavigation).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
@ -463,15 +395,16 @@ describe('DocumentList', () => {
|
|||||||
|
|
||||||
documentList.navigate = false;
|
documentList.navigate = false;
|
||||||
documentList.navigationMode = DocumentList.DOUBLE_CLICK_NAVIGATION;
|
documentList.navigationMode = DocumentList.DOUBLE_CLICK_NAVIGATION;
|
||||||
documentList.onItemDblClick(folder, null);
|
documentList.onNodeDblClick(folder);
|
||||||
|
|
||||||
expect(documentList.performNavigation).not.toHaveBeenCalled();
|
expect(documentList.performNavigation).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should perform navigation for folder node only', () => {
|
it('should perform navigation for folder node only', () => {
|
||||||
|
spyOn(documentList, 'getNodePath').and.returnValue('/path');
|
||||||
|
|
||||||
let folder = new FolderNode();
|
let folder = new FolderNode();
|
||||||
let file = new FileNode();
|
let file = new FileNode();
|
||||||
spyOn(documentList, 'getNodePath').and.returnValue('/path');
|
|
||||||
|
|
||||||
expect(documentList.performNavigation(folder)).toBeTruthy();
|
expect(documentList.performNavigation(folder)).toBeTruthy();
|
||||||
expect(documentList.performNavigation(file)).toBeFalsy();
|
expect(documentList.performNavigation(file)).toBeFalsy();
|
||||||
@ -488,7 +421,6 @@ describe('DocumentList', () => {
|
|||||||
expect(documentList.getNodePath(file)).toBe('/folder1/file.txt');
|
expect(documentList.getNodePath(file)).toBe('/folder1/file.txt');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('should require valid node for file preview', () => {
|
it('should require valid node for file preview', () => {
|
||||||
let file = new FileNode();
|
let file = new FileNode();
|
||||||
file.entry = null;
|
file.entry = null;
|
||||||
@ -497,11 +429,11 @@ describe('DocumentList', () => {
|
|||||||
documentList.navigationMode = DocumentList.SINGLE_CLICK_NAVIGATION;
|
documentList.navigationMode = DocumentList.SINGLE_CLICK_NAVIGATION;
|
||||||
documentList.preview.subscribe(val => called = true);
|
documentList.preview.subscribe(val => called = true);
|
||||||
|
|
||||||
documentList.onItemClick(file, null);
|
documentList.onNodeClick(file);
|
||||||
expect(called).toBeFalsy();
|
expect(called).toBeFalsy();
|
||||||
|
|
||||||
documentList.navigationMode = DocumentList.DOUBLE_CLICK_NAVIGATION;
|
documentList.navigationMode = DocumentList.DOUBLE_CLICK_NAVIGATION;
|
||||||
documentList.onItemDblClick(file, null);
|
documentList.onNodeDblClick(file);
|
||||||
expect(called).toBeFalsy();
|
expect(called).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -511,10 +443,10 @@ describe('DocumentList', () => {
|
|||||||
spyOn(documentList, 'performNavigation').and.stub();
|
spyOn(documentList, 'performNavigation').and.stub();
|
||||||
|
|
||||||
documentList.navigationMode = DocumentList.SINGLE_CLICK_NAVIGATION;
|
documentList.navigationMode = DocumentList.SINGLE_CLICK_NAVIGATION;
|
||||||
documentList.onItemClick(folder, null);
|
documentList.onNodeClick(folder);
|
||||||
|
|
||||||
documentList.navigationMode = DocumentList.DOUBLE_CLICK_NAVIGATION;
|
documentList.navigationMode = DocumentList.DOUBLE_CLICK_NAVIGATION;
|
||||||
documentList.onItemDblClick(folder, null);
|
documentList.onNodeDblClick(folder);
|
||||||
|
|
||||||
expect(documentList.performNavigation).not.toHaveBeenCalled();
|
expect(documentList.performNavigation).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
@ -525,6 +457,8 @@ describe('DocumentList', () => {
|
|||||||
expect(documentList.displayFolderContent).toHaveBeenCalled();
|
expect(documentList.displayFolderContent).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// TODO: move to data adapter
|
||||||
|
/*
|
||||||
it('should generate thumbnail for unknown content', () => {
|
it('should generate thumbnail for unknown content', () => {
|
||||||
documentList.baseComponentPath = '/root';
|
documentList.baseComponentPath = '/root';
|
||||||
let node = new FileNode();
|
let node = new FileNode();
|
||||||
@ -532,13 +466,19 @@ describe('DocumentList', () => {
|
|||||||
|
|
||||||
expect(documentList.getThumbnailUrl(node)).toBe('/root/img/ft_ic_miscellaneous.svg');
|
expect(documentList.getThumbnailUrl(node)).toBe('/root/img/ft_ic_miscellaneous.svg');
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TODO: move to data adapter
|
||||||
|
/*
|
||||||
it('should generate folder icon path', () => {
|
it('should generate folder icon path', () => {
|
||||||
documentList.baseComponentPath = '/root';
|
documentList.baseComponentPath = '/root';
|
||||||
let folder = new FolderNode();
|
let folder = new FolderNode();
|
||||||
expect(documentList.getThumbnailUrl(folder)).toBe('/root/img/ft_ic_folder.svg');
|
expect(documentList.getThumbnailUrl(folder)).toBe('/root/img/ft_ic_folder.svg');
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TODO: move to data adapter
|
||||||
|
/*
|
||||||
it('should generate file icon path based on mime type', () => {
|
it('should generate file icon path based on mime type', () => {
|
||||||
let fileName = 'custom-icon.svg';
|
let fileName = 'custom-icon.svg';
|
||||||
spyOn(alfrescoServiceMock, 'getMimeTypeIcon').and.returnValue(fileName);
|
spyOn(alfrescoServiceMock, 'getMimeTypeIcon').and.returnValue(fileName);
|
||||||
@ -549,9 +489,12 @@ describe('DocumentList', () => {
|
|||||||
|
|
||||||
expect(documentList.getThumbnailUrl(file)).toBe(`/root/img/${fileName}`);
|
expect(documentList.getThumbnailUrl(file)).toBe(`/root/img/${fileName}`);
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TODO: move to data adapter
|
||||||
|
/*
|
||||||
it('should fallback to default icon for missing mime type', () => {
|
it('should fallback to default icon for missing mime type', () => {
|
||||||
spyOn(alfrescoServiceMock, 'getMimeTypeIcon').and.returnValue(null);
|
spyOn(documentListService, 'getMimeTypeIcon').and.returnValue(null);
|
||||||
documentList.baseComponentPath = '/root';
|
documentList.baseComponentPath = '/root';
|
||||||
|
|
||||||
let file = new FileNode();
|
let file = new FileNode();
|
||||||
@ -559,9 +502,12 @@ describe('DocumentList', () => {
|
|||||||
|
|
||||||
expect(documentList.getThumbnailUrl(file)).toBe('/root/img/ft_ic_miscellaneous.svg');
|
expect(documentList.getThumbnailUrl(file)).toBe('/root/img/ft_ic_miscellaneous.svg');
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TODO: move to data adapter
|
||||||
|
/*
|
||||||
it('should fallback to default icon for unknown mime type', () => {
|
it('should fallback to default icon for unknown mime type', () => {
|
||||||
spyOn(alfrescoServiceMock, 'getMimeTypeIcon').and.returnValue(null);
|
spyOn(documentListService, 'getMimeTypeIcon').and.returnValue(null);
|
||||||
documentList.baseComponentPath = '/root';
|
documentList.baseComponentPath = '/root';
|
||||||
|
|
||||||
let file = new FileNode();
|
let file = new FileNode();
|
||||||
@ -569,17 +515,23 @@ describe('DocumentList', () => {
|
|||||||
|
|
||||||
expect(documentList.getThumbnailUrl(file)).toBe('/root/img/ft_ic_miscellaneous.svg');
|
expect(documentList.getThumbnailUrl(file)).toBe('/root/img/ft_ic_miscellaneous.svg');
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TODO: move to data adapter
|
||||||
|
/*
|
||||||
it('should resolve thumbnail url for a file', () => {
|
it('should resolve thumbnail url for a file', () => {
|
||||||
let url = 'http://<some url>';
|
let url = 'http://<some url>';
|
||||||
spyOn(alfrescoServiceMock, 'getDocumentThumbnailUrl').and.returnValue(url);
|
spyOn(documentListService, 'getDocumentThumbnailUrl').and.returnValue(url);
|
||||||
|
|
||||||
documentList.thumbnails = true;
|
documentList.thumbnails = true;
|
||||||
|
|
||||||
let file = new FileNode();
|
let file = new FileNode();
|
||||||
expect(documentList.getThumbnailUrl(file)).toBe(url);
|
expect(documentList.getThumbnailUrl(file)).toBe(url);
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TODO: move to data adapter
|
||||||
|
/*
|
||||||
it('should return no thumbnail url with missing service', () => {
|
it('should return no thumbnail url with missing service', () => {
|
||||||
let list = new DocumentList(null, null);
|
let list = new DocumentList(null, null);
|
||||||
list.thumbnails = true;
|
list.thumbnails = true;
|
||||||
@ -587,76 +539,10 @@ describe('DocumentList', () => {
|
|||||||
let file = new FileNode();
|
let file = new FileNode();
|
||||||
expect(list.getThumbnailUrl(file)).toBeNull();
|
expect(list.getThumbnailUrl(file)).toBeNull();
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
it('should sort on column header click', () => {
|
// TODO: move to DataTable
|
||||||
let col = new ContentColumnModel();
|
/*
|
||||||
col.source = 'id';
|
|
||||||
|
|
||||||
spyOn(documentList, 'sort').and.callThrough();
|
|
||||||
|
|
||||||
documentList.onColumnHeaderClick(col);
|
|
||||||
|
|
||||||
expect(documentList.sorting).toEqual(
|
|
||||||
jasmine.objectContaining({
|
|
||||||
key: 'id',
|
|
||||||
direction: 'asc'
|
|
||||||
})
|
|
||||||
);
|
|
||||||
expect(documentList.sort).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should invert sorting on column header click', () => {
|
|
||||||
let col = new ContentColumnModel();
|
|
||||||
col.source = 'id';
|
|
||||||
|
|
||||||
spyOn(documentList, 'sort').and.callThrough();
|
|
||||||
|
|
||||||
documentList.sorting = <ColumnSortingModel> { key: 'id', direction: 'asc' };
|
|
||||||
documentList.onColumnHeaderClick(col);
|
|
||||||
|
|
||||||
expect(documentList.sorting).toEqual(
|
|
||||||
jasmine.objectContaining({
|
|
||||||
key: 'id',
|
|
||||||
direction: 'desc'
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
documentList.onColumnHeaderClick(col);
|
|
||||||
expect(documentList.sorting).toEqual(
|
|
||||||
jasmine.objectContaining({
|
|
||||||
key: 'id',
|
|
||||||
direction: 'asc'
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(documentList.sort).toHaveBeenCalledTimes(2);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should use ascending direction for different column header click', () => {
|
|
||||||
let col = new ContentColumnModel();
|
|
||||||
col.source = 'id';
|
|
||||||
|
|
||||||
spyOn(documentList, 'sort').and.callThrough();
|
|
||||||
|
|
||||||
documentList.sorting = <ColumnSortingModel> { key: 'col1', direction: 'desc' };
|
|
||||||
documentList.onColumnHeaderClick(col);
|
|
||||||
|
|
||||||
expect(documentList.sorting).toEqual(
|
|
||||||
jasmine.objectContaining({
|
|
||||||
key: 'id',
|
|
||||||
direction: 'asc'
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(documentList.sort).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not sort by column header when instance is missing', () => {
|
|
||||||
spyOn(documentList, 'sort').and.callThrough();
|
|
||||||
documentList.onColumnHeaderClick(null);
|
|
||||||
expect(documentList.sort).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should convert cell value to formatted date', () => {
|
it('should convert cell value to formatted date', () => {
|
||||||
|
|
||||||
let rawValue = new Date(2015, 6, 15, 21, 43, 11).toString(); // Wed Jul 15 2015 21:43:11 GMT+0100 (BST);
|
let rawValue = new Date(2015, 6, 15, 21, 43, 11).toString(); // Wed Jul 15 2015 21:43:11 GMT+0100 (BST);
|
||||||
@ -673,7 +559,10 @@ describe('DocumentList', () => {
|
|||||||
let value = documentList.getCellValue(file, col);
|
let value = documentList.getCellValue(file, col);
|
||||||
expect(value).toBe(dateValue);
|
expect(value).toBe(dateValue);
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TODO: move to DataTable
|
||||||
|
/*
|
||||||
it('should return date value as string', () => {
|
it('should return date value as string', () => {
|
||||||
let rawValue = new Date(2015, 6, 15, 21, 43, 11).toString(); // Wed Jul 15 2015 21:43:11 GMT+0100 (BST);
|
let rawValue = new Date(2015, 6, 15, 21, 43, 11).toString(); // Wed Jul 15 2015 21:43:11 GMT+0100 (BST);
|
||||||
|
|
||||||
@ -687,7 +576,10 @@ describe('DocumentList', () => {
|
|||||||
let value = documentList.getCellValue(file, col);
|
let value = documentList.getCellValue(file, col);
|
||||||
expect(value).toBe(rawValue);
|
expect(value).toBe(rawValue);
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TODO: move to data adapter
|
||||||
|
/*
|
||||||
it('should convert cell value to thumbnail', () => {
|
it('should convert cell value to thumbnail', () => {
|
||||||
let url = 'http://<address>';
|
let url = 'http://<address>';
|
||||||
spyOn(documentList, 'getThumbnailUrl').and.returnValue(url);
|
spyOn(documentList, 'getThumbnailUrl').and.returnValue(url);
|
||||||
@ -701,14 +593,15 @@ describe('DocumentList', () => {
|
|||||||
let value = documentList.getCellValue(file, col);
|
let value = documentList.getCellValue(file, col);
|
||||||
expect(value).toBe(url);
|
expect(value).toBe(url);
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
it('should require path to display folder content', () => {
|
it('should require path to display folder content', () => {
|
||||||
spyOn(alfrescoServiceMock, 'getFolder').and.callThrough();
|
spyOn(documentListService, 'getFolder').and.callThrough();
|
||||||
|
|
||||||
documentList.displayFolderContent(null);
|
documentList.displayFolderContent(null);
|
||||||
documentList.displayFolderContent('');
|
documentList.displayFolderContent('');
|
||||||
|
|
||||||
expect(alfrescoServiceMock.getFolder).not.toHaveBeenCalled();
|
expect(documentListService.getFolder).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should require node to resolve context menu actions', () => {
|
it('should require node to resolve context menu actions', () => {
|
||||||
@ -722,12 +615,12 @@ describe('DocumentList', () => {
|
|||||||
|
|
||||||
it('should fetch context menu actions for a file node', () => {
|
it('should fetch context menu actions for a file node', () => {
|
||||||
let actionModel = {};
|
let actionModel = {};
|
||||||
spyOn(documentList, 'getContentActions').and.returnValue([actionModel]);
|
spyOn(documentList, 'getNodeActions').and.returnValue([actionModel]);
|
||||||
|
|
||||||
let file = new FileNode();
|
let file = new FileNode();
|
||||||
let actions = documentList.getContextActions(file);
|
let actions = documentList.getContextActions(file);
|
||||||
|
|
||||||
expect(documentList.getContentActions).toHaveBeenCalledWith('document', 'menu');
|
expect(documentList.getNodeActions).toHaveBeenCalledWith(file);
|
||||||
expect(actions.length).toBe(1);
|
expect(actions.length).toBe(1);
|
||||||
expect(actions[0].model).toBe(actionModel);
|
expect(actions[0].model).toBe(actionModel);
|
||||||
expect(actions[0].node).toBe(file);
|
expect(actions[0].node).toBe(file);
|
||||||
@ -736,12 +629,12 @@ describe('DocumentList', () => {
|
|||||||
|
|
||||||
it('should fetch context menu actions for a folder node', () => {
|
it('should fetch context menu actions for a folder node', () => {
|
||||||
let actionModel = {};
|
let actionModel = {};
|
||||||
spyOn(documentList, 'getContentActions').and.returnValue([actionModel]);
|
spyOn(documentList, 'getNodeActions').and.returnValue([actionModel]);
|
||||||
|
|
||||||
let folder = new FolderNode();
|
let folder = new FolderNode();
|
||||||
let actions = documentList.getContextActions(folder);
|
let actions = documentList.getContextActions(folder);
|
||||||
|
|
||||||
expect(documentList.getContentActions).toHaveBeenCalledWith('folder', 'menu');
|
expect(documentList.getNodeActions).toHaveBeenCalledWith(folder);
|
||||||
expect(actions.length).toBe(1);
|
expect(actions.length).toBe(1);
|
||||||
expect(actions[0].model).toBe(actionModel);
|
expect(actions[0].model).toBe(actionModel);
|
||||||
expect(actions[0].node).toBe(folder);
|
expect(actions[0].node).toBe(folder);
|
||||||
@ -749,51 +642,39 @@ describe('DocumentList', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should fetch no context menu actions for unknown type', () => {
|
it('should fetch no context menu actions for unknown type', () => {
|
||||||
spyOn(documentList, 'getContentActions').and.stub();
|
spyOn(documentList, 'getNodeActions').and.stub();
|
||||||
|
|
||||||
let node = new FileNode();
|
let node = new FileNode();
|
||||||
node.entry.isFile = false;
|
node.entry.isFile = false;
|
||||||
node.entry.isFolder = false;
|
node.entry.isFolder = false;
|
||||||
|
|
||||||
let actions = documentList.getContextActions(node);
|
let actions = documentList.getContextActions(node);
|
||||||
|
|
||||||
expect(documentList.getContentActions).not.toHaveBeenCalled();
|
|
||||||
expect(actions).toBeNull();
|
expect(actions).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return null value when no content actions found', () => {
|
it('should return null value when no content actions found', () => {
|
||||||
spyOn(documentList, 'getContentActions').and.returnValue([]);
|
spyOn(documentList, 'getNodeActions').and.returnValue([]);
|
||||||
|
|
||||||
let file = new FileNode();
|
let file = new FileNode();
|
||||||
let actions = documentList.getContextActions(file);
|
let actions = documentList.getContextActions(file);
|
||||||
|
|
||||||
expect(actions).toBeNull();
|
expect(actions).toBeNull();
|
||||||
expect(documentList.getContentActions).toHaveBeenCalled();
|
expect(documentList.getNodeActions).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
it('should update error message when folder content display fails', () => {
|
it('should update error message when folder content display fails', () => {
|
||||||
let error = 'My Error';
|
let error = 'My Error';
|
||||||
alfrescoServiceMock.getFolderReject = true;
|
documentListService.getFolderReject = true;
|
||||||
alfrescoServiceMock.getFolderRejectError = error;
|
documentListService.getFolderRejectError = error;
|
||||||
|
|
||||||
documentList.displayFolderContent('/some/path');
|
documentList.displayFolderContent('/some/path');
|
||||||
expect(documentList.errorMessage).toBe(error);
|
expect(documentList.errorMessage).toBe(error);
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
it('should get object value via property path', () => {
|
// TODO: move to data adapter
|
||||||
let obj = {
|
/*
|
||||||
name: {
|
|
||||||
firstName: '<name>'
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(documentList.getObjectValue(obj, 'name.firstName')).toBe('<name>');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not get object value via invalid path', () => {
|
|
||||||
expect(documentList.getObjectValue({}, 'some.missing.path')).toBeUndefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should log error when having date conversion issues', () => {
|
it('should log error when having date conversion issues', () => {
|
||||||
|
|
||||||
let value = '<wrong-date>';
|
let value = '<wrong-date>';
|
||||||
@ -813,7 +694,10 @@ describe('DocumentList', () => {
|
|||||||
expect(result).toBe(value);
|
expect(result).toBe(value);
|
||||||
expect(console.error).toHaveBeenCalledWith(`DocumentList: error parsing date ${value} to format ${col.format}`);
|
expect(console.error).toHaveBeenCalledWith(`DocumentList: error parsing date ${value} to format ${col.format}`);
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TODO: move to data adapter
|
||||||
|
/*
|
||||||
it('should convert thumbnail if column source defined', () => {
|
it('should convert thumbnail if column source defined', () => {
|
||||||
let file = new FileNode();
|
let file = new FileNode();
|
||||||
let col = new ContentColumnModel({
|
let col = new ContentColumnModel({
|
||||||
@ -823,6 +707,7 @@ describe('DocumentList', () => {
|
|||||||
|
|
||||||
expect(documentList.getCellValue(file, col)).toBe(file.entry.name);
|
expect(documentList.getCellValue(file, col)).toBe(file.entry.name);
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
it('should require current folder path to reload', () => {
|
it('should require current folder path to reload', () => {
|
||||||
|
|
||||||
@ -839,6 +724,8 @@ describe('DocumentList', () => {
|
|||||||
expect(documentList.displayFolderContent).not.toHaveBeenCalled();
|
expect(documentList.displayFolderContent).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// TODO: move to data adapter
|
||||||
|
/*
|
||||||
it('should not sort empty page', () => {
|
it('should not sort empty page', () => {
|
||||||
let page = new PageNode();
|
let page = new PageNode();
|
||||||
spyOn(page.list.entries, 'sort').and.stub();
|
spyOn(page.list.entries, 'sort').and.stub();
|
||||||
@ -846,7 +733,10 @@ describe('DocumentList', () => {
|
|||||||
documentList.sort(page, null);
|
documentList.sort(page, null);
|
||||||
expect(page.list.entries.sort).not.toHaveBeenCalled();
|
expect(page.list.entries.sort).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TODO: move to data adapter
|
||||||
|
/*
|
||||||
it('should put folders to top on sort', () => {
|
it('should put folders to top on sort', () => {
|
||||||
let folder = new FolderNode();
|
let folder = new FolderNode();
|
||||||
let file1 = new FileNode('file1');
|
let file1 = new FileNode('file1');
|
||||||
@ -873,7 +763,10 @@ describe('DocumentList', () => {
|
|||||||
expect(page.list.entries[1]).toBe(file2);
|
expect(page.list.entries[1]).toBe(file2);
|
||||||
expect(page.list.entries[2]).toBe(file1);
|
expect(page.list.entries[2]).toBe(file1);
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TODO: move to data adapter
|
||||||
|
/*
|
||||||
it('should sort by dates up to ms', () => {
|
it('should sort by dates up to ms', () => {
|
||||||
let file1 = new FileNode();
|
let file1 = new FileNode();
|
||||||
file1.entry['dateProp'] = new Date(2016, 6, 30, 13, 14, 1);
|
file1.entry['dateProp'] = new Date(2016, 6, 30, 13, 14, 1);
|
||||||
@ -901,5 +794,6 @@ describe('DocumentList', () => {
|
|||||||
expect(page.list.entries[0]).toBe(file1);
|
expect(page.list.entries[0]).toBe(file1);
|
||||||
expect(page.list.entries[1]).toBe(file2);
|
expect(page.list.entries[1]).toBe(file2);
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -22,19 +22,27 @@ import {
|
|||||||
Output,
|
Output,
|
||||||
EventEmitter,
|
EventEmitter,
|
||||||
AfterContentInit,
|
AfterContentInit,
|
||||||
|
AfterViewInit,
|
||||||
AfterViewChecked,
|
AfterViewChecked,
|
||||||
OnChanges,
|
OnChanges,
|
||||||
TemplateRef,
|
TemplateRef,
|
||||||
NgZone
|
NgZone,
|
||||||
|
ViewChild
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { DatePipe } from '@angular/common';
|
|
||||||
import { Subject } from 'rxjs/Rx';
|
import { Subject } from 'rxjs/Rx';
|
||||||
import { CONTEXT_MENU_DIRECTIVES } from 'ng2-alfresco-core';
|
import { CONTEXT_MENU_DIRECTIVES } from 'ng2-alfresco-core';
|
||||||
import { AlfrescoService } from './../services/alfresco.service';
|
|
||||||
import { MinimalNodeEntity, NodePaging } from './../models/document-library.model';
|
import {
|
||||||
|
ALFRESCO_DATATABLE_DIRECTIVES,
|
||||||
|
DataRowEvent,
|
||||||
|
DataTableComponent,
|
||||||
|
ObjectDataColumn
|
||||||
|
} from 'ng2-alfresco-datatable';
|
||||||
|
|
||||||
|
import { DocumentListService } from './../services/document-list.service';
|
||||||
|
import { MinimalNodeEntity } from './../models/document-library.model';
|
||||||
import { ContentActionModel } from './../models/content-action.model';
|
import { ContentActionModel } from './../models/content-action.model';
|
||||||
import { ContentColumnModel } from './../models/content-column.model';
|
import { ShareDataTableAdapter, ShareDataRow } from './../data/share-datatable-adapter';
|
||||||
import { ColumnSortingModel } from './../models/column-sorting.model';
|
|
||||||
|
|
||||||
declare var componentHandler;
|
declare var componentHandler;
|
||||||
declare let __moduleName: string;
|
declare let __moduleName: string;
|
||||||
@ -44,13 +52,13 @@ declare let __moduleName: string;
|
|||||||
selector: 'alfresco-document-list',
|
selector: 'alfresco-document-list',
|
||||||
styleUrls: ['./document-list.css'],
|
styleUrls: ['./document-list.css'],
|
||||||
templateUrl: './document-list.html',
|
templateUrl: './document-list.html',
|
||||||
providers: [AlfrescoService],
|
providers: [DocumentListService],
|
||||||
directives: [CONTEXT_MENU_DIRECTIVES],
|
directives: [CONTEXT_MENU_DIRECTIVES, ALFRESCO_DATATABLE_DIRECTIVES],
|
||||||
host: {
|
host: {
|
||||||
'(contextmenu)': 'onShowContextMenu($event)'
|
'(contextmenu)': 'onShowContextMenu($event)'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
export class DocumentList implements OnInit, AfterViewChecked, AfterContentInit, OnChanges {
|
export class DocumentList implements OnInit, AfterViewInit, AfterViewChecked, AfterContentInit, OnChanges {
|
||||||
|
|
||||||
static SINGLE_CLICK_NAVIGATION: string = 'click';
|
static SINGLE_CLICK_NAVIGATION: string = 'click';
|
||||||
static DOUBLE_CLICK_NAVIGATION: string = 'dblclick';
|
static DOUBLE_CLICK_NAVIGATION: string = 'dblclick';
|
||||||
@ -62,17 +70,26 @@ export class DocumentList implements OnInit, AfterViewChecked, AfterContentInit,
|
|||||||
@Input()
|
@Input()
|
||||||
navigate: boolean = true;
|
navigate: boolean = true;
|
||||||
|
|
||||||
@Input('navigation-mode')
|
@Input()
|
||||||
navigationMode: string = 'dblclick'; // click|dblclick
|
navigationMode: string = 'dblclick'; // click|dblclick
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
thumbnails: boolean = false;
|
thumbnails: boolean = false;
|
||||||
|
|
||||||
@Output()
|
@Input()
|
||||||
itemClick: EventEmitter<any> = new EventEmitter();
|
multiselect: boolean = false;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
contentActions: boolean = false;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
contextMenuActions: boolean = false;
|
||||||
|
|
||||||
@Output()
|
@Output()
|
||||||
itemDblClick: EventEmitter<any> = new EventEmitter();
|
nodeClick: EventEmitter<any> = new EventEmitter();
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
nodeDblClick: EventEmitter<any> = new EventEmitter();
|
||||||
|
|
||||||
@Output()
|
@Output()
|
||||||
folderChange: EventEmitter<any> = new EventEmitter();
|
folderChange: EventEmitter<any> = new EventEmitter();
|
||||||
@ -80,6 +97,9 @@ export class DocumentList implements OnInit, AfterViewChecked, AfterContentInit,
|
|||||||
@Output()
|
@Output()
|
||||||
preview: EventEmitter<any> = new EventEmitter();
|
preview: EventEmitter<any> = new EventEmitter();
|
||||||
|
|
||||||
|
@ViewChild(DataTableComponent)
|
||||||
|
dataTable: DataTableComponent;
|
||||||
|
|
||||||
private _path = this.DEFAULT_ROOT_FOLDER;
|
private _path = this.DEFAULT_ROOT_FOLDER;
|
||||||
|
|
||||||
get currentFolderPath(): string {
|
get currentFolderPath(): string {
|
||||||
@ -91,57 +111,28 @@ export class DocumentList implements OnInit, AfterViewChecked, AfterContentInit,
|
|||||||
if (value !== this._path) {
|
if (value !== this._path) {
|
||||||
this._path = value || this.DEFAULT_ROOT_FOLDER;
|
this._path = value || this.DEFAULT_ROOT_FOLDER;
|
||||||
this.displayFolderContent(this._path);
|
this.displayFolderContent(this._path);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
errorMessage;
|
|
||||||
|
|
||||||
actions: ContentActionModel[] = [];
|
|
||||||
columns: ContentColumnModel[] = [];
|
|
||||||
emptyFolderTemplate: TemplateRef<any>;
|
|
||||||
|
|
||||||
private _folder: NodePaging;
|
|
||||||
|
|
||||||
get folder(): NodePaging {
|
|
||||||
return this._folder;
|
|
||||||
}
|
|
||||||
|
|
||||||
set folder(value: NodePaging) {
|
|
||||||
let isChanged = this._folder !== value;
|
|
||||||
this._folder = value;
|
|
||||||
if (isChanged) {
|
|
||||||
this.folderChange.emit({
|
this.folderChange.emit({
|
||||||
value: value,
|
|
||||||
path: this.currentFolderPath
|
path: this.currentFolderPath
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sorting: ColumnSortingModel = {
|
errorMessage;
|
||||||
key: 'name',
|
actions: ContentActionModel[] = [];
|
||||||
direction: 'asc'
|
emptyFolderTemplate: TemplateRef<any>;
|
||||||
};
|
|
||||||
|
|
||||||
contextActionHandler: Subject<any> = new Subject();
|
contextActionHandler: Subject<any> = new Subject();
|
||||||
|
data: ShareDataTableAdapter;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private alfrescoService: AlfrescoService,
|
private documentListService: DocumentListService,
|
||||||
private ngZone: NgZone) {}
|
private ngZone: NgZone) {
|
||||||
|
|
||||||
|
this.data = new ShareDataTableAdapter(this.documentListService, this.baseComponentPath, []);
|
||||||
|
}
|
||||||
|
|
||||||
getContextActions(node: MinimalNodeEntity) {
|
getContextActions(node: MinimalNodeEntity) {
|
||||||
if (node && node.entry) {
|
if (node && node.entry) {
|
||||||
let targetType;
|
let actions = this.getNodeActions(node);
|
||||||
|
|
||||||
if (node.entry.isFolder) {
|
|
||||||
targetType = 'folder';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node.entry.isFile) {
|
|
||||||
targetType = 'document';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (targetType) {
|
|
||||||
let actions = this.getContentActions(targetType, 'menu');
|
|
||||||
if (actions && actions.length > 0) {
|
if (actions && actions.length > 0) {
|
||||||
return actions.map(a => {
|
return actions.map(a => {
|
||||||
return {
|
return {
|
||||||
@ -152,7 +143,6 @@ export class DocumentList implements OnInit, AfterViewChecked, AfterContentInit,
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,20 +153,31 @@ export class DocumentList implements OnInit, AfterViewChecked, AfterContentInit,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
|
this.data.thumbnails = this.thumbnails;
|
||||||
this.displayFolderContent(this.currentFolderPath);
|
this.displayFolderContent(this.currentFolderPath);
|
||||||
this.contextActionHandler.subscribe(val => this.contextActionCallback(val));
|
this.contextActionHandler.subscribe(val => this.contextActionCallback(val));
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnChanges(change) {
|
ngOnChanges() {
|
||||||
this.reload();
|
this.reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
ngAfterContentInit() {
|
ngAfterContentInit() {
|
||||||
if (!this.columns || this.columns.length === 0) {
|
let columns = this.data.getColumns();
|
||||||
|
if (!columns || columns.length === 0) {
|
||||||
this.setupDefaultColumns();
|
this.setupDefaultColumns();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngAfterViewInit() {
|
||||||
|
if (this.dataTable) {
|
||||||
|
if (this.emptyFolderTemplate) {
|
||||||
|
this.dataTable.noContentTemplate = this.emptyFolderTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ngAfterViewChecked() {
|
ngAfterViewChecked() {
|
||||||
// workaround for MDL issues with dynamic components
|
// workaround for MDL issues with dynamic components
|
||||||
if (componentHandler) {
|
if (componentHandler) {
|
||||||
@ -185,79 +186,31 @@ export class DocumentList implements OnInit, AfterViewChecked, AfterContentInit,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
getNodeActions(node: MinimalNodeEntity): ContentActionModel[] {
|
||||||
* Get a list of content actions based on target and type.
|
let target = null;
|
||||||
* @param target Target to filter actions by.
|
|
||||||
* @param type Type to filter actions by.
|
if (node && node.entry) {
|
||||||
* @returns {ContentActionModel[]} List of actions filtered by target and type.
|
if (node.entry.isFile) {
|
||||||
*/
|
target = 'document';
|
||||||
getContentActions(target: string, type: string): ContentActionModel[] {
|
}
|
||||||
if (target && type) {
|
|
||||||
|
if (node.entry.isFolder) {
|
||||||
|
target = 'folder';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target) {
|
||||||
|
|
||||||
let ltarget = target.toLowerCase();
|
let ltarget = target.toLowerCase();
|
||||||
let ltype = type.toLowerCase();
|
|
||||||
|
|
||||||
return this.actions.filter(entry => {
|
return this.actions.filter(entry => {
|
||||||
return entry.target.toLowerCase() === ltarget &&
|
return entry.target.toLowerCase() === ltarget;
|
||||||
entry.type.toLowerCase() === ltype;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Invoked when list row is clicked.
|
|
||||||
* @param item Underlying node item
|
|
||||||
* @param e DOM event (optional)
|
|
||||||
*/
|
|
||||||
onItemClick(item: MinimalNodeEntity, e?: Event) {
|
|
||||||
if (e) {
|
|
||||||
e.preventDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.itemClick.emit({
|
|
||||||
value: item
|
|
||||||
});
|
|
||||||
|
|
||||||
if (this.navigate && this.navigationMode === DocumentList.SINGLE_CLICK_NAVIGATION) {
|
|
||||||
if (item && item.entry) {
|
|
||||||
if (item.entry.isFile) {
|
|
||||||
this.preview.emit({
|
|
||||||
value: item
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.entry.isFolder) {
|
|
||||||
this.performNavigation(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onItemDblClick(item: MinimalNodeEntity, e?: Event) {
|
|
||||||
if (e) {
|
|
||||||
e.preventDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.itemDblClick.emit({
|
|
||||||
value: item
|
|
||||||
});
|
|
||||||
|
|
||||||
if (this.navigate && this.navigationMode === DocumentList.DOUBLE_CLICK_NAVIGATION) {
|
|
||||||
if (item && item.entry) {
|
|
||||||
if (item.entry.isFile) {
|
|
||||||
this.preview.emit({
|
|
||||||
value: item
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.entry.isFolder) {
|
|
||||||
this.performNavigation(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onShowContextMenu(e?: Event) {
|
onShowContextMenu(e?: Event) {
|
||||||
if (e) {
|
if (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@ -272,41 +225,6 @@ export class DocumentList implements OnInit, AfterViewChecked, AfterContentInit,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets thumbnail URL for the given node.
|
|
||||||
* @param node Node to get URL for.
|
|
||||||
* @returns {string} URL address.
|
|
||||||
*/
|
|
||||||
getThumbnailUrl(node: MinimalNodeEntity): string {
|
|
||||||
if (node && node.entry) {
|
|
||||||
let entry = node.entry;
|
|
||||||
|
|
||||||
if (entry.isFolder) {
|
|
||||||
return `${this.baseComponentPath}/img/ft_ic_folder.svg`;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entry.isFile) {
|
|
||||||
if (this.thumbnails) {
|
|
||||||
if (this.alfrescoService) {
|
|
||||||
return this.alfrescoService.getDocumentThumbnailUrl(node);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entry.content && entry.content.mimeType) {
|
|
||||||
let icon = this.alfrescoService.getMimeTypeIcon(entry.content.mimeType);
|
|
||||||
if (icon) {
|
|
||||||
return `${this.baseComponentPath}/img/${icon}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return `${this.baseComponentPath}/img/ft_ic_miscellaneous.svg`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoked when executing content action for a document or folder.
|
* Invoked when executing content action for a document or folder.
|
||||||
* @param node Node to be the context of the execution.
|
* @param node Node to be the context of the execution.
|
||||||
@ -319,14 +237,7 @@ export class DocumentList implements OnInit, AfterViewChecked, AfterContentInit,
|
|||||||
}
|
}
|
||||||
|
|
||||||
displayFolderContent(path: string) {
|
displayFolderContent(path: string) {
|
||||||
if (path) {
|
this.data.loadPath(path);
|
||||||
this.alfrescoService
|
|
||||||
.getFolder(path)
|
|
||||||
.subscribe(
|
|
||||||
folder => this.folder = this.sort(folder, this.sorting),
|
|
||||||
error => this.errorMessage = <any>error
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
reload() {
|
reload() {
|
||||||
@ -350,122 +261,109 @@ export class DocumentList implements OnInit, AfterViewChecked, AfterContentInit,
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a value from an object by composed key
|
|
||||||
* documentList.getObjectValue({ item: { nodeType: 'cm:folder' }}, 'item.nodeType') ==> 'cm:folder'
|
|
||||||
* @param target
|
|
||||||
* @param key
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
getObjectValue(target: any, key: string): any {
|
|
||||||
let keys = key.split('.');
|
|
||||||
key = '';
|
|
||||||
|
|
||||||
do {
|
|
||||||
key += keys.shift();
|
|
||||||
let value = target[key];
|
|
||||||
if (value !== undefined && (typeof value === 'object' || !keys.length)) {
|
|
||||||
target = value;
|
|
||||||
key = '';
|
|
||||||
} else if (!keys.length) {
|
|
||||||
target = undefined;
|
|
||||||
} else {
|
|
||||||
key += '.';
|
|
||||||
}
|
|
||||||
} while (keys.length);
|
|
||||||
|
|
||||||
return target;
|
|
||||||
}
|
|
||||||
|
|
||||||
getCellValue(row: MinimalNodeEntity, col: ContentColumnModel): any {
|
|
||||||
let value = this.getObjectValueRaw(row.entry, col.source);
|
|
||||||
|
|
||||||
if (col.type === 'date') {
|
|
||||||
let datePipe = new DatePipe();
|
|
||||||
try {
|
|
||||||
return datePipe.transform(value, col.format);
|
|
||||||
} catch (err) {
|
|
||||||
console.error(`DocumentList: error parsing date ${value} to format ${col.format}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (col.type === 'image') {
|
|
||||||
|
|
||||||
if (col.source === '$thumbnail') {
|
|
||||||
return this.getThumbnailUrl(row);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a set of predefined columns.
|
* Creates a set of predefined columns.
|
||||||
*/
|
*/
|
||||||
setupDefaultColumns(): void {
|
setupDefaultColumns(): void {
|
||||||
let thumbnailCol = new ContentColumnModel();
|
let colThumbnail = new ObjectDataColumn({
|
||||||
thumbnailCol.source = '$thumbnail';
|
type: 'image',
|
||||||
thumbnailCol.type = 'image';
|
key: '$thumbnail',
|
||||||
|
title: '',
|
||||||
|
srTitle: 'Thumbnail'
|
||||||
|
});
|
||||||
|
|
||||||
let nameCol = new ContentColumnModel();
|
let colName = new ObjectDataColumn({
|
||||||
nameCol.title = 'Name';
|
type: 'text',
|
||||||
nameCol.source = 'name';
|
key: 'name',
|
||||||
nameCol.cssClass = 'full-width name-column';
|
title: 'Name',
|
||||||
|
cssClass: 'full-width',
|
||||||
|
sortable: true
|
||||||
|
});
|
||||||
|
|
||||||
this.columns = [
|
this.data.setColumns([colThumbnail, colName]);
|
||||||
thumbnailCol,
|
|
||||||
nameCol
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onColumnHeaderClick(column: ContentColumnModel) {
|
onPreviewFile(node: MinimalNodeEntity) {
|
||||||
if (column && this.isSortableColumn(column)) {
|
if (node) {
|
||||||
if (this.sorting.key === column.source) {
|
this.preview.emit({
|
||||||
this.sorting.direction = this.sorting.direction === 'asc' ? 'desc' : 'asc';
|
value: node
|
||||||
} else {
|
|
||||||
this.sorting = <ColumnSortingModel> {
|
|
||||||
key: column.source,
|
|
||||||
direction: 'asc'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
this.sort(this.folder, this.sorting);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sort(node: NodePaging, options: ColumnSortingModel) {
|
|
||||||
if (this.hasEntries(node)) {
|
|
||||||
node.list.entries.sort((a: MinimalNodeEntity, b: MinimalNodeEntity) => {
|
|
||||||
if (a.entry.isFolder !== b.entry.isFolder) {
|
|
||||||
return a.entry.isFolder ? -1 : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
let left = this.getObjectValueRaw(a.entry, options.key).toString();
|
|
||||||
let right = this.getObjectValueRaw(b.entry, options.key).toString();
|
|
||||||
|
|
||||||
return options.direction === 'asc'
|
|
||||||
? left.localeCompare(right)
|
|
||||||
: right.localeCompare(left);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return node;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private getObjectValueRaw(target: any, key: string) {
|
onNodeClick(node: MinimalNodeEntity) {
|
||||||
let val = this.getObjectValue(target, key);
|
this.nodeClick.emit({
|
||||||
|
value: node
|
||||||
|
});
|
||||||
|
|
||||||
if (val instanceof Date) {
|
if (this.navigate && this.navigationMode === DocumentList.SINGLE_CLICK_NAVIGATION) {
|
||||||
val = val.valueOf();
|
if (node && node.entry) {
|
||||||
|
if (node.entry.isFile) {
|
||||||
|
this.onPreviewFile(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
return val;
|
if (node.entry.isFolder) {
|
||||||
|
this.performNavigation(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private hasEntries(node: NodePaging): boolean {
|
onRowClick(event: DataRowEvent) {
|
||||||
return (node && node.list && node.list.entries && node.list.entries.length > 0);
|
let item = (<ShareDataRow> event.value).node;
|
||||||
|
this.onNodeClick(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
private isSortableColumn(column: ContentColumnModel) {
|
onNodeDblClick(node: MinimalNodeEntity) {
|
||||||
return column && column.source && !column.source.startsWith('$');
|
this.nodeDblClick.emit({
|
||||||
|
value: node
|
||||||
|
});
|
||||||
|
|
||||||
|
if (this.navigate && this.navigationMode === DocumentList.DOUBLE_CLICK_NAVIGATION) {
|
||||||
|
if (node && node.entry) {
|
||||||
|
if (node.entry.isFile) {
|
||||||
|
this.onPreviewFile(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.entry.isFolder) {
|
||||||
|
this.performNavigation(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onRowDblClick(event?: DataRowEvent) {
|
||||||
|
let item = (<ShareDataRow> event.value).node;
|
||||||
|
this.onNodeDblClick(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -0,0 +1,240 @@
|
|||||||
|
/*!
|
||||||
|
* @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 { DatePipe } from '@angular/common';
|
||||||
|
import {
|
||||||
|
DataTableAdapter,
|
||||||
|
DataRow, DataColumn, DataSorting
|
||||||
|
} from 'ng2-alfresco-datatable';
|
||||||
|
|
||||||
|
import { NodePaging, MinimalNodeEntity } from './../models/document-library.model';
|
||||||
|
import { DocumentListService } from './../services/document-list.service';
|
||||||
|
|
||||||
|
export class ShareDataTableAdapter implements DataTableAdapter {
|
||||||
|
|
||||||
|
private sorting: DataSorting;
|
||||||
|
private rows: DataRow[];
|
||||||
|
private columns: DataColumn[];
|
||||||
|
|
||||||
|
thumbnails: boolean = false;
|
||||||
|
|
||||||
|
constructor(private documentListService: DocumentListService,
|
||||||
|
private basePath: string,
|
||||||
|
schema: DataColumn[]) {
|
||||||
|
this.rows = [];
|
||||||
|
this.columns = schema || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
getRows(): Array<DataRow> {
|
||||||
|
return this.rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
setRows(rows: Array<DataRow>) {
|
||||||
|
this.rows = rows || [];
|
||||||
|
this.sort();
|
||||||
|
}
|
||||||
|
|
||||||
|
getColumns(): Array<DataColumn> {
|
||||||
|
return this.columns;
|
||||||
|
}
|
||||||
|
|
||||||
|
setColumns(columns: Array<DataColumn>) {
|
||||||
|
this.columns = columns || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
getValue(row: DataRow, col: DataColumn): any {
|
||||||
|
if (!row) {
|
||||||
|
throw new Error('Row not found');
|
||||||
|
}
|
||||||
|
if (!col) {
|
||||||
|
throw new Error('Column not found');
|
||||||
|
}
|
||||||
|
let value = row.getValue(col.key);
|
||||||
|
|
||||||
|
if (col.type === 'date') {
|
||||||
|
let datePipe = new DatePipe();
|
||||||
|
let format = col.format || 'medium';
|
||||||
|
try {
|
||||||
|
return datePipe.transform(value, format);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`DocumentList: error parsing date ${value} to format ${format}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (col.type === 'image') {
|
||||||
|
|
||||||
|
if (col.key === '$thumbnail') {
|
||||||
|
let node = (<ShareDataRow> row).node;
|
||||||
|
|
||||||
|
if (node.entry.isFolder) {
|
||||||
|
return `${this.basePath}/img/ft_ic_folder.svg`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.entry.isFile) {
|
||||||
|
|
||||||
|
if (this.thumbnails) {
|
||||||
|
if (this.documentListService) {
|
||||||
|
return this.documentListService.getDocumentThumbnailUrl(node);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.entry.content && node.entry.content.mimeType) {
|
||||||
|
let mimeType = node.entry.content.mimeType;
|
||||||
|
if (mimeType) {
|
||||||
|
let icon = this.documentListService.getMimeTypeIcon(mimeType);
|
||||||
|
if (icon) {
|
||||||
|
return `${this.basePath}/img/${icon}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${this.basePath}/img/ft_ic_miscellaneous.svg`;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
getSorting(): DataSorting {
|
||||||
|
return this.sorting;
|
||||||
|
}
|
||||||
|
|
||||||
|
setSorting(sorting: DataSorting): void {
|
||||||
|
this.sorting = sorting;
|
||||||
|
|
||||||
|
if (sorting && sorting.key) {
|
||||||
|
this.rows.sort((a: ShareDataRow, b: ShareDataRow) => {
|
||||||
|
if (a.node.entry.isFolder !== b.node.entry.isFolder) {
|
||||||
|
return a.node.entry.isFolder ? -1 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
let left = a.getValue(sorting.key);
|
||||||
|
if (left) {
|
||||||
|
left = (left instanceof Date) ? left.valueOf().toString() : left.toString();
|
||||||
|
} else {
|
||||||
|
left = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
let right = b.getValue(sorting.key);
|
||||||
|
if (right) {
|
||||||
|
right = (right instanceof Date) ? right.valueOf().toString() : right.toString();
|
||||||
|
} else {
|
||||||
|
right = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return sorting.direction === 'asc'
|
||||||
|
? left.localeCompare(right)
|
||||||
|
: right.localeCompare(left);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sort(key?: string, direction?: string): void {
|
||||||
|
let sorting = this.sorting || new DataSorting();
|
||||||
|
if (key) {
|
||||||
|
sorting.key = key;
|
||||||
|
sorting.direction = direction || 'asc';
|
||||||
|
}
|
||||||
|
this.setSorting(sorting);
|
||||||
|
}
|
||||||
|
|
||||||
|
loadPath(path: string) {
|
||||||
|
if (path && this.documentListService) {
|
||||||
|
this.documentListService
|
||||||
|
.getFolder(path)
|
||||||
|
.subscribe(val => {
|
||||||
|
let page = <NodePaging>val;
|
||||||
|
let rows = [];
|
||||||
|
|
||||||
|
if (page && page.list) {
|
||||||
|
let data = page.list.entries;
|
||||||
|
if (data && data.length > 0) {
|
||||||
|
rows = data.map(item => new ShareDataRow(item));
|
||||||
|
// Sort by first sortable or just first column
|
||||||
|
let sortable = this.columns.filter(c => c.sortable);
|
||||||
|
if (sortable.length > 0) {
|
||||||
|
this.sort(sortable[0].key, 'asc');
|
||||||
|
} else {
|
||||||
|
this.sort(this.columns[0].key, 'asc');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.rows = rows;
|
||||||
|
},
|
||||||
|
error => console.log(error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ShareDataRow implements DataRow {
|
||||||
|
isSelected: boolean = false;
|
||||||
|
|
||||||
|
get node(): MinimalNodeEntity {
|
||||||
|
return this.obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(private obj: MinimalNodeEntity) {
|
||||||
|
if (!obj) {
|
||||||
|
throw new Error('Object source not found');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a value from an object by composed key
|
||||||
|
* documentList.getObjectValue({ item: { nodeType: 'cm:folder' }}, 'item.nodeType') ==> 'cm:folder'
|
||||||
|
* @param target
|
||||||
|
* @param key
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
getObjectValue(target: any, key: string): any {
|
||||||
|
|
||||||
|
if (!target) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
let keys = key.split('.');
|
||||||
|
key = '';
|
||||||
|
|
||||||
|
do {
|
||||||
|
key += keys.shift();
|
||||||
|
let value = target[key];
|
||||||
|
if (value !== undefined && (typeof value === 'object' || !keys.length)) {
|
||||||
|
target = value;
|
||||||
|
key = '';
|
||||||
|
} else if (!keys.length) {
|
||||||
|
target = undefined;
|
||||||
|
} else {
|
||||||
|
key += '.';
|
||||||
|
}
|
||||||
|
} while (keys.length);
|
||||||
|
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
getValue(key: string): any {
|
||||||
|
return this.getObjectValue(this.obj.entry, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
hasValue(key: string): boolean {
|
||||||
|
return this.getValue(key) ? true : false;
|
||||||
|
}
|
||||||
|
}
|
@ -1,31 +0,0 @@
|
|||||||
/*!
|
|
||||||
* @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 class ColumnSortingModel {
|
|
||||||
|
|
||||||
static DEFAULT_DIRECTION: string = 'asc';
|
|
||||||
|
|
||||||
key: string;
|
|
||||||
direction: string = ColumnSortingModel.DEFAULT_DIRECTION;
|
|
||||||
|
|
||||||
constructor(opts?: any) {
|
|
||||||
if (opts) {
|
|
||||||
this.key = opts.key;
|
|
||||||
this.direction = opts.direction || ColumnSortingModel.DEFAULT_DIRECTION;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -19,7 +19,6 @@ export class ContentActionModel {
|
|||||||
icon: string;
|
icon: string;
|
||||||
title: string;
|
title: string;
|
||||||
handler: ContentActionHandler;
|
handler: ContentActionHandler;
|
||||||
type: string;
|
|
||||||
target: string;
|
target: string;
|
||||||
|
|
||||||
constructor(obj?: any) {
|
constructor(obj?: any) {
|
||||||
@ -27,7 +26,6 @@ export class ContentActionModel {
|
|||||||
this.icon = obj.icon;
|
this.icon = obj.icon;
|
||||||
this.title = obj.title;
|
this.title = obj.title;
|
||||||
this.handler = obj.handler;
|
this.handler = obj.handler;
|
||||||
this.type = obj.type;
|
|
||||||
this.target = obj.target;
|
this.target = obj.target;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,51 +0,0 @@
|
|||||||
/*!
|
|
||||||
* @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 class ContentColumnModel {
|
|
||||||
|
|
||||||
static TYPE_TEXT: string = 'text';
|
|
||||||
static TYPE_DATE: string = 'date';
|
|
||||||
static TYPE_IMAGE: string = 'image';
|
|
||||||
// static TYPE_NUMBER: string = 'number';
|
|
||||||
|
|
||||||
title: string;
|
|
||||||
srTitle: string;
|
|
||||||
source: string;
|
|
||||||
cssClass: string;
|
|
||||||
type: string = ContentColumnModel.TYPE_TEXT;
|
|
||||||
format: string = 'medium';
|
|
||||||
|
|
||||||
constructor(obj?: any) {
|
|
||||||
if (obj) {
|
|
||||||
this.title = obj.title;
|
|
||||||
this.srTitle = obj.srTitle;
|
|
||||||
this.source = obj.source;
|
|
||||||
this.cssClass = obj.cssClass;
|
|
||||||
this.type = obj.type || ContentColumnModel.TYPE_TEXT;
|
|
||||||
this.format = obj.format;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static getSupportedTypes(): string[] {
|
|
||||||
return [
|
|
||||||
ContentColumnModel.TYPE_TEXT,
|
|
||||||
ContentColumnModel.TYPE_DATE,
|
|
||||||
ContentColumnModel.TYPE_IMAGE
|
|
||||||
// ContentColumnModel.TYPE_NUMBER
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
@ -24,8 +24,8 @@ import {
|
|||||||
import { AlfrescoContentService } from 'ng2-alfresco-core';
|
import { AlfrescoContentService } from 'ng2-alfresco-core';
|
||||||
import { ContentActionHandler } from '../models/content-action.model';
|
import { ContentActionHandler } from '../models/content-action.model';
|
||||||
import { DocumentActionsService } from './document-actions.service';
|
import { DocumentActionsService } from './document-actions.service';
|
||||||
import { AlfrescoServiceMock } from '../assets/alfresco.service.mock';
|
import { DocumentListServiceMock } from '../assets/document-list.service.mock';
|
||||||
import { AlfrescoService } from './alfresco.service';
|
import { DocumentListService } from './document-list.service';
|
||||||
import {
|
import {
|
||||||
FileNode,
|
FileNode,
|
||||||
FolderNode
|
FolderNode
|
||||||
@ -34,13 +34,13 @@ import {
|
|||||||
describe('DocumentActionsService', () => {
|
describe('DocumentActionsService', () => {
|
||||||
|
|
||||||
let service: DocumentActionsService;
|
let service: DocumentActionsService;
|
||||||
let alfrescoService: AlfrescoService;
|
let documentListService: DocumentListService;
|
||||||
let contentService: AlfrescoContentService;
|
let contentService: AlfrescoContentService;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
alfrescoService = new AlfrescoServiceMock();
|
documentListService = new DocumentListServiceMock();
|
||||||
contentService = new AlfrescoContentService(null, null);
|
contentService = new AlfrescoContentService(null, null);
|
||||||
service = new DocumentActionsService(alfrescoService, contentService);
|
service = new DocumentActionsService(documentListService, contentService);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should register default download action', () => {
|
it('should register default download action', () => {
|
||||||
@ -147,7 +147,7 @@ describe('DocumentActionsService', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should require content service for download action', () => {
|
it('should require content service for download action', () => {
|
||||||
let actionService = new DocumentActionsService(alfrescoService, null);
|
let actionService = new DocumentActionsService(documentListService, null);
|
||||||
let file = new FileNode();
|
let file = new FileNode();
|
||||||
let result = actionService.getHandler('download')(file);
|
let result = actionService.getHandler('download')(file);
|
||||||
expect(result).toBeFalsy();
|
expect(result).toBeFalsy();
|
||||||
@ -159,44 +159,44 @@ describe('DocumentActionsService', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should delete file node', () => {
|
it('should delete file node', () => {
|
||||||
spyOn(alfrescoService, 'deleteNode').and.callThrough();
|
spyOn(documentListService, 'deleteNode').and.callThrough();
|
||||||
|
|
||||||
let file = new FileNode();
|
let file = new FileNode();
|
||||||
service.getHandler('delete')(file);
|
service.getHandler('delete')(file);
|
||||||
|
|
||||||
expect(alfrescoService.deleteNode).toHaveBeenCalledWith(file.entry.id);
|
expect(documentListService.deleteNode).toHaveBeenCalledWith(file.entry.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should support deletion only file node', () => {
|
it('should support deletion only file node', () => {
|
||||||
spyOn(alfrescoService, 'deleteNode').and.callThrough();
|
spyOn(documentListService, 'deleteNode').and.callThrough();
|
||||||
|
|
||||||
let folder = new FolderNode();
|
let folder = new FolderNode();
|
||||||
service.getHandler('delete')(folder);
|
service.getHandler('delete')(folder);
|
||||||
expect(alfrescoService.deleteNode).not.toHaveBeenCalled();
|
expect(documentListService.deleteNode).not.toHaveBeenCalled();
|
||||||
|
|
||||||
let file = new FileNode();
|
let file = new FileNode();
|
||||||
service.getHandler('delete')(file);
|
service.getHandler('delete')(file);
|
||||||
expect(alfrescoService.deleteNode).toHaveBeenCalled();
|
expect(documentListService.deleteNode).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should require node id to delete', () => {
|
it('should require node id to delete', () => {
|
||||||
spyOn(alfrescoService, 'deleteNode').and.callThrough();
|
spyOn(documentListService, 'deleteNode').and.callThrough();
|
||||||
|
|
||||||
let file = new FileNode();
|
let file = new FileNode();
|
||||||
file.entry.id = null;
|
file.entry.id = null;
|
||||||
service.getHandler('delete')(file);
|
service.getHandler('delete')(file);
|
||||||
|
|
||||||
expect(alfrescoService.deleteNode).not.toHaveBeenCalled();
|
expect(documentListService.deleteNode).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should reload target upon node deletion', () => {
|
it('should reload target upon node deletion', () => {
|
||||||
spyOn(alfrescoService, 'deleteNode').and.callThrough();
|
spyOn(documentListService, 'deleteNode').and.callThrough();
|
||||||
|
|
||||||
let target = jasmine.createSpyObj('obj', ['reload']);
|
let target = jasmine.createSpyObj('obj', ['reload']);
|
||||||
let file = new FileNode();
|
let file = new FileNode();
|
||||||
service.getHandler('delete')(file, target);
|
service.getHandler('delete')(file, target);
|
||||||
|
|
||||||
expect(alfrescoService.deleteNode).toHaveBeenCalled();
|
expect(documentListService.deleteNode).toHaveBeenCalled();
|
||||||
expect(target.reload).toHaveBeenCalled();
|
expect(target.reload).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { ContentActionHandler } from '../models/content-action.model';
|
import { ContentActionHandler } from '../models/content-action.model';
|
||||||
import {AlfrescoService} from './alfresco.service';
|
import { DocumentListService } from './document-list.service';
|
||||||
import { AlfrescoContentService } from 'ng2-alfresco-core';
|
import { AlfrescoContentService } from 'ng2-alfresco-core';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
@ -25,7 +25,7 @@ export class DocumentActionsService {
|
|||||||
private handlers: { [id: string]: ContentActionHandler; } = {};
|
private handlers: { [id: string]: ContentActionHandler; } = {};
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private alfrescoService?: AlfrescoService,
|
private documentListService?: DocumentListService,
|
||||||
private contentService?: AlfrescoContentService
|
private contentService?: AlfrescoContentService
|
||||||
) {
|
) {
|
||||||
this.setupActionHandlers();
|
this.setupActionHandlers();
|
||||||
@ -49,7 +49,7 @@ export class DocumentActionsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
canExecuteAction(obj: any): boolean {
|
canExecuteAction(obj: any): boolean {
|
||||||
return this.alfrescoService && obj && obj.entry.isFile === true;
|
return this.documentListService && obj && obj.entry.isFile === true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private setupActionHandlers() {
|
private setupActionHandlers() {
|
||||||
@ -86,7 +86,7 @@ export class DocumentActionsService {
|
|||||||
|
|
||||||
private deleteNode(obj: any, target?: any) {
|
private deleteNode(obj: any, target?: any) {
|
||||||
if (this.canExecuteAction(obj) && obj.entry && obj.entry.id) {
|
if (this.canExecuteAction(obj) && obj.entry && obj.entry.id) {
|
||||||
this.alfrescoService.deleteNode(obj.entry.id).subscribe(() => {
|
this.documentListService.deleteNode(obj.entry.id).subscribe(() => {
|
||||||
if (target && typeof target.reload === 'function') {
|
if (target && typeof target.reload === 'function') {
|
||||||
target.reload();
|
target.reload();
|
||||||
}
|
}
|
||||||
|
@ -27,12 +27,11 @@ import {
|
|||||||
AlfrescoContentService
|
AlfrescoContentService
|
||||||
} from 'ng2-alfresco-core';
|
} from 'ng2-alfresco-core';
|
||||||
import { FileNode } from '../assets/document-library.model.mock';
|
import { FileNode } from '../assets/document-library.model.mock';
|
||||||
import { AlfrescoService } from './alfresco.service';
|
import { DocumentListService } from './document-list.service';
|
||||||
|
|
||||||
// TODO: rename to DocumentListService
|
describe('DocumentListService', () => {
|
||||||
describe('AlfrescoService', () => {
|
|
||||||
|
|
||||||
let service: AlfrescoService;
|
let service: DocumentListService;
|
||||||
let settingsService: AlfrescoSettingsService;
|
let settingsService: AlfrescoSettingsService;
|
||||||
let authService: AlfrescoAuthenticationService;
|
let authService: AlfrescoAuthenticationService;
|
||||||
let contentService: AlfrescoContentService;
|
let contentService: AlfrescoContentService;
|
||||||
@ -42,7 +41,7 @@ describe('AlfrescoService', () => {
|
|||||||
settingsService = new AlfrescoSettingsService();
|
settingsService = new AlfrescoSettingsService();
|
||||||
authService = new AlfrescoAuthenticationService(settingsService);
|
authService = new AlfrescoAuthenticationService(settingsService);
|
||||||
contentService = new AlfrescoContentService(settingsService, authService);
|
contentService = new AlfrescoContentService(settingsService, authService);
|
||||||
service = new AlfrescoService(settingsService, authService, contentService);
|
service = new DocumentListService(settingsService, authService, contentService);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should require node to get thumbnail url', () => {
|
it('should require node to get thumbnail url', () => {
|
||||||
@ -50,7 +49,7 @@ describe('AlfrescoService', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should require content service to get thumbnail url', () => {
|
it('should require content service to get thumbnail url', () => {
|
||||||
service = new AlfrescoService(settingsService, authService, null);
|
service = new DocumentListService(settingsService, authService, null);
|
||||||
let file = new FileNode();
|
let file = new FileNode();
|
||||||
expect(service.getDocumentThumbnailUrl(file)).toBeNull();
|
expect(service.getDocumentThumbnailUrl(file)).toBeNull();
|
||||||
});
|
});
|
||||||
@ -72,9 +71,9 @@ describe('AlfrescoService', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should resolve default icon for mime type', () => {
|
it('should resolve default icon for mime type', () => {
|
||||||
expect(service.getMimeTypeIcon(null)).toBe(AlfrescoService.DEFAULT_MIME_TYPE_ICON);
|
expect(service.getMimeTypeIcon(null)).toBe(DocumentListService.DEFAULT_MIME_TYPE_ICON);
|
||||||
expect(service.getMimeTypeIcon('')).toBe(AlfrescoService.DEFAULT_MIME_TYPE_ICON);
|
expect(service.getMimeTypeIcon('')).toBe(DocumentListService.DEFAULT_MIME_TYPE_ICON);
|
||||||
expect(service.getMimeTypeIcon('missing/type')).toBe(AlfrescoService.DEFAULT_MIME_TYPE_ICON);
|
expect(service.getMimeTypeIcon('missing/type')).toBe(DocumentListService.DEFAULT_MIME_TYPE_ICON);
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
@ -27,12 +27,8 @@ import {
|
|||||||
|
|
||||||
declare let AlfrescoApi: any;
|
declare let AlfrescoApi: any;
|
||||||
|
|
||||||
// TODO: consider renaming to something like 'DocumentListService'
|
|
||||||
/**
|
|
||||||
* Internal service used by Document List component.
|
|
||||||
*/
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AlfrescoService {
|
export class DocumentListService {
|
||||||
|
|
||||||
static DEFAULT_MIME_TYPE_ICON: string = 'ft_ic_miscellaneous.svg';
|
static DEFAULT_MIME_TYPE_ICON: string = 'ft_ic_miscellaneous.svg';
|
||||||
|
|
||||||
@ -120,7 +116,7 @@ export class AlfrescoService {
|
|||||||
|
|
||||||
getMimeTypeIcon(mimeType: string): string {
|
getMimeTypeIcon(mimeType: string): string {
|
||||||
let icon = this.mimeTypeIcons[mimeType];
|
let icon = this.mimeTypeIcons[mimeType];
|
||||||
return icon || AlfrescoService.DEFAULT_MIME_TYPE_ICON;
|
return icon || DocumentListService.DEFAULT_MIME_TYPE_ICON;
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleError(error: Response) {
|
private handleError(error: Response) {
|
@ -27,17 +27,17 @@ import {
|
|||||||
FileNode,
|
FileNode,
|
||||||
FolderNode
|
FolderNode
|
||||||
} from '../assets/document-library.model.mock';
|
} from '../assets/document-library.model.mock';
|
||||||
import { AlfrescoService } from './alfresco.service';
|
import { DocumentListService } from './document-list.service';
|
||||||
import { AlfrescoServiceMock } from '../assets/alfresco.service.mock';
|
import { DocumentListServiceMock } from '../assets/document-list.service.mock';
|
||||||
|
|
||||||
describe('FolderActionsService', () => {
|
describe('FolderActionsService', () => {
|
||||||
|
|
||||||
let service: FolderActionsService;
|
let service: FolderActionsService;
|
||||||
let alfrescoService: AlfrescoService;
|
let documentListService: DocumentListService;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
alfrescoService = new AlfrescoServiceMock();
|
documentListService = new DocumentListServiceMock();
|
||||||
service = new FolderActionsService(alfrescoService);
|
service = new FolderActionsService(documentListService);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should register custom action handler', () => {
|
it('should register custom action handler', () => {
|
||||||
@ -105,44 +105,44 @@ describe('FolderActionsService', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should delete folder node', () => {
|
it('should delete folder node', () => {
|
||||||
spyOn(alfrescoService, 'deleteNode').and.callThrough();
|
spyOn(documentListService, 'deleteNode').and.callThrough();
|
||||||
|
|
||||||
let folder = new FolderNode();
|
let folder = new FolderNode();
|
||||||
service.getHandler('delete')(folder);
|
service.getHandler('delete')(folder);
|
||||||
|
|
||||||
expect(alfrescoService.deleteNode).toHaveBeenCalledWith(folder.entry.id);
|
expect(documentListService.deleteNode).toHaveBeenCalledWith(folder.entry.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should support deletion only folder node', () => {
|
it('should support deletion only folder node', () => {
|
||||||
spyOn(alfrescoService, 'deleteNode').and.callThrough();
|
spyOn(documentListService, 'deleteNode').and.callThrough();
|
||||||
|
|
||||||
let file = new FileNode();
|
let file = new FileNode();
|
||||||
service.getHandler('delete')(file);
|
service.getHandler('delete')(file);
|
||||||
expect(alfrescoService.deleteNode).not.toHaveBeenCalled();
|
expect(documentListService.deleteNode).not.toHaveBeenCalled();
|
||||||
|
|
||||||
let folder = new FolderNode();
|
let folder = new FolderNode();
|
||||||
service.getHandler('delete')(folder);
|
service.getHandler('delete')(folder);
|
||||||
expect(alfrescoService.deleteNode).toHaveBeenCalled();
|
expect(documentListService.deleteNode).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should require node id to delete', () => {
|
it('should require node id to delete', () => {
|
||||||
spyOn(alfrescoService, 'deleteNode').and.callThrough();
|
spyOn(documentListService, 'deleteNode').and.callThrough();
|
||||||
|
|
||||||
let folder = new FolderNode();
|
let folder = new FolderNode();
|
||||||
folder.entry.id = null;
|
folder.entry.id = null;
|
||||||
service.getHandler('delete')(folder);
|
service.getHandler('delete')(folder);
|
||||||
|
|
||||||
expect(alfrescoService.deleteNode).not.toHaveBeenCalled();
|
expect(documentListService.deleteNode).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should reload target upon node deletion', () => {
|
it('should reload target upon node deletion', () => {
|
||||||
spyOn(alfrescoService, 'deleteNode').and.callThrough();
|
spyOn(documentListService, 'deleteNode').and.callThrough();
|
||||||
|
|
||||||
let target = jasmine.createSpyObj('obj', ['reload']);
|
let target = jasmine.createSpyObj('obj', ['reload']);
|
||||||
let folder = new FolderNode();
|
let folder = new FolderNode();
|
||||||
service.getHandler('delete')(folder, target);
|
service.getHandler('delete')(folder, target);
|
||||||
|
|
||||||
expect(alfrescoService.deleteNode).toHaveBeenCalled();
|
expect(documentListService.deleteNode).toHaveBeenCalled();
|
||||||
expect(target.reload).toHaveBeenCalled();
|
expect(target.reload).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -17,13 +17,13 @@
|
|||||||
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { ContentActionHandler } from '../models/content-action.model';
|
import { ContentActionHandler } from '../models/content-action.model';
|
||||||
import {AlfrescoService} from './alfresco.service';
|
import { DocumentListService } from './document-list.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class FolderActionsService {
|
export class FolderActionsService {
|
||||||
private handlers: { [id: string]: ContentActionHandler; } = {};
|
private handlers: { [id: string]: ContentActionHandler; } = {};
|
||||||
|
|
||||||
constructor(private _alfrescoService?: AlfrescoService) {
|
constructor(private documentListService?: DocumentListService) {
|
||||||
this.setupActionHandlers();
|
this.setupActionHandlers();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,7 +45,7 @@ export class FolderActionsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
canExecuteAction(obj: any): boolean {
|
canExecuteAction(obj: any): boolean {
|
||||||
return this._alfrescoService && obj && obj.entry.isFolder === true;
|
return this.documentListService && obj && obj.entry.isFolder === true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private setupActionHandlers() {
|
private setupActionHandlers() {
|
||||||
@ -68,7 +68,7 @@ export class FolderActionsService {
|
|||||||
|
|
||||||
private deleteNode(obj: any, target?: any) {
|
private deleteNode(obj: any, target?: any) {
|
||||||
if (this.canExecuteAction(obj) && obj.entry && obj.entry.id) {
|
if (this.canExecuteAction(obj) && obj.entry && obj.entry.id) {
|
||||||
this._alfrescoService.deleteNode(obj.entry.id).subscribe(() => {
|
this.documentListService.deleteNode(obj.entry.id).subscribe(() => {
|
||||||
if (target && typeof target.reload === 'function') {
|
if (target && typeof target.reload === 'function') {
|
||||||
target.reload();
|
target.reload();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user