mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
Code cleanup and fixes
This commit is contained in:
@@ -22,10 +22,11 @@
|
||||
</empty-folder-content>
|
||||
-->
|
||||
<content-columns>
|
||||
<content-column source="$thumbnail" type="image"></content-column>
|
||||
<content-column key="$thumbnail" type="image"></content-column>
|
||||
<content-column
|
||||
title="{{'DOCUMENT_LIST.COLUMNS.DISPLAY_NAME' | translate}}"
|
||||
source="name"
|
||||
key="name"
|
||||
sortable="true"
|
||||
class="full-width ellipsis-cell">
|
||||
</content-column>
|
||||
<!--
|
||||
@@ -36,14 +37,16 @@
|
||||
-->
|
||||
<content-column
|
||||
title="{{'DOCUMENT_LIST.COLUMNS.CREATED_BY' | translate}}"
|
||||
source="createdByUser.displayName"
|
||||
key="createdByUser.displayName"
|
||||
sortable="true"
|
||||
class="desktop-only">
|
||||
</content-column>
|
||||
<content-column
|
||||
title="{{'DOCUMENT_LIST.COLUMNS.CREATED_ON' | translate}}"
|
||||
source="createdAt"
|
||||
key="createdAt"
|
||||
type="date"
|
||||
format="medium"
|
||||
sortable="true"
|
||||
class="desktop-only">
|
||||
</content-column>
|
||||
</content-columns>
|
||||
@@ -52,25 +55,16 @@
|
||||
<!-- folder actions -->
|
||||
<content-action
|
||||
target="folder"
|
||||
type="button"
|
||||
icon="delete"
|
||||
handler="system1">
|
||||
</content-action>
|
||||
<content-action
|
||||
target="folder"
|
||||
type="menu"
|
||||
title="{{'DOCUMENT_LIST.ACTIONS.FOLDER.SYSTEM_1' | translate}}"
|
||||
handler="system1">
|
||||
</content-action>
|
||||
<content-action
|
||||
target="folder"
|
||||
type="menu"
|
||||
title="{{'DOCUMENT_LIST.ACTIONS.FOLDER.CUSTOM' | translate}}"
|
||||
(execute)="myFolderAction1($event)">
|
||||
</content-action>
|
||||
<content-action
|
||||
target="folder"
|
||||
type="menu"
|
||||
title="{{'DOCUMENT_LIST.ACTIONS.FOLDER.DELETE' | translate}}"
|
||||
handler="delete">
|
||||
</content-action>
|
||||
@@ -78,37 +72,21 @@
|
||||
<!-- document actions -->
|
||||
<content-action
|
||||
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}}"
|
||||
handler="download">
|
||||
</content-action>
|
||||
<content-action
|
||||
target="document"
|
||||
type="menu"
|
||||
title="{{'DOCUMENT_LIST.ACTIONS.DOCUMENT.SYSTEM_2' | translate}}"
|
||||
handler="system2">
|
||||
</content-action>
|
||||
<content-action
|
||||
target="document"
|
||||
type="menu"
|
||||
title="{{'DOCUMENT_LIST.ACTIONS.DOCUMENT.CUSTOM' | translate}}"
|
||||
(execute)="myCustomAction1($event)">
|
||||
</content-action>
|
||||
<content-action
|
||||
target="document"
|
||||
type="menu"
|
||||
title="{{'DOCUMENT_LIST.ACTIONS.DOCUMENT.DELETE' | translate}}"
|
||||
handler="delete">
|
||||
</content-action>
|
||||
|
@@ -34,6 +34,7 @@ describe('ContextMenuDirective', () => {
|
||||
done();
|
||||
});
|
||||
|
||||
directive.links = [{}];
|
||||
directive.onShowContextMenu(null);
|
||||
});
|
||||
|
||||
|
@@ -9,13 +9,15 @@ var map = {
|
||||
'app': 'base/dist',
|
||||
'rxjs': 'base/node_modules/rxjs',
|
||||
'@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 = {
|
||||
'app': { main: 'main.js', 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 = [
|
||||
|
@@ -16,6 +16,7 @@ module.exports = function (config) {
|
||||
{pattern: 'node_modules/@angular/**/*.js', 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-translate/**/*.js', included: false, served: true, watched: false},
|
||||
|
||||
{pattern: 'karma-test-shim.js', included: true, watched: true},
|
||||
|
||||
|
@@ -68,6 +68,7 @@
|
||||
"rxjs": "5.0.0-beta.6",
|
||||
"zone.js": "0.6.12",
|
||||
"rimraf": "2.5.2",
|
||||
"ng2-translate": "2.2.2",
|
||||
"ng2-alfresco-core": "0.0.0-PLACEHOLDER"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
@@ -35,6 +35,37 @@
|
||||
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 */
|
||||
|
||||
:host .non-selectable {
|
||||
@@ -55,3 +86,22 @@
|
||||
clip: rect(0,0,0,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;
|
||||
}
|
||||
}
|
||||
|
@@ -38,9 +38,9 @@ import {
|
||||
selector: 'alfresco-documentlist-demo',
|
||||
template: `
|
||||
<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>
|
||||
<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">
|
||||
Authentication failed to ip {{ host }} with user: admin, admin, you can still try to add a valid token to perform
|
||||
operations.
|
||||
@@ -52,7 +52,7 @@ import {
|
||||
[currentFolderPath]="currentPath"
|
||||
[target]="documentList">
|
||||
</alfresco-document-list-breadcrumb>
|
||||
<alfresco-document-list #doclist
|
||||
<alfresco-document-list
|
||||
#documentList
|
||||
[currentFolderPath]="currentPath"
|
||||
[contextMenuActions]="true"
|
||||
@@ -67,22 +67,25 @@ import {
|
||||
</empty-folder-content>
|
||||
-->
|
||||
<content-columns>
|
||||
<content-column source="$thumbnail" type="image"></content-column>
|
||||
<content-column key="$thumbnail" type="image"></content-column>
|
||||
<content-column
|
||||
title="{{'DOCUMENT_LIST.COLUMNS.DISPLAY_NAME' | translate}}"
|
||||
source="name"
|
||||
key="name"
|
||||
sortable="true"
|
||||
class="full-width ellipsis-cell">
|
||||
</content-column>
|
||||
<content-column
|
||||
title="{{'DOCUMENT_LIST.COLUMNS.CREATED_BY' | translate}}"
|
||||
source="createdByUser.displayName"
|
||||
key="createdByUser.displayName"
|
||||
sortable="true"
|
||||
class="desktop-only">
|
||||
</content-column>
|
||||
<content-column
|
||||
title="{{'DOCUMENT_LIST.COLUMNS.CREATED_ON' | translate}}"
|
||||
source="createdAt"
|
||||
key="createdAt"
|
||||
type="date"
|
||||
format="medium"
|
||||
sortable="true"
|
||||
class="desktop-only">
|
||||
</content-column>
|
||||
</content-columns>
|
||||
@@ -90,25 +93,16 @@ import {
|
||||
<!-- folder actions -->
|
||||
<content-action
|
||||
target="folder"
|
||||
type="button"
|
||||
icon="delete"
|
||||
handler="system1">
|
||||
</content-action>
|
||||
<content-action
|
||||
target="folder"
|
||||
type="menu"
|
||||
title="{{'DOCUMENT_LIST.ACTIONS.FOLDER.SYSTEM_1' | translate}}"
|
||||
handler="system1">
|
||||
</content-action>
|
||||
<content-action
|
||||
target="folder"
|
||||
type="menu"
|
||||
title="{{'DOCUMENT_LIST.ACTIONS.FOLDER.CUSTOM' | translate}}"
|
||||
(execute)="myFolderAction1($event)">
|
||||
</content-action>
|
||||
<content-action
|
||||
target="folder"
|
||||
type="menu"
|
||||
title="{{'DOCUMENT_LIST.ACTIONS.FOLDER.DELETE' | translate}}"
|
||||
handler="delete">
|
||||
</content-action>
|
||||
@@ -116,37 +110,21 @@ import {
|
||||
<!-- document actions -->
|
||||
<content-action
|
||||
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}}"
|
||||
handler="download">
|
||||
</content-action>
|
||||
<content-action
|
||||
target="document"
|
||||
type="menu"
|
||||
title="{{'DOCUMENT_LIST.ACTIONS.DOCUMENT.SYSTEM_2' | translate}}"
|
||||
handler="system2">
|
||||
</content-action>
|
||||
<content-action
|
||||
target="document"
|
||||
type="menu"
|
||||
title="{{'DOCUMENT_LIST.ACTIONS.DOCUMENT.CUSTOM' | translate}}"
|
||||
(execute)="myCustomAction1($event)">
|
||||
</content-action>
|
||||
<content-action
|
||||
target="document"
|
||||
type="menu"
|
||||
title="{{'DOCUMENT_LIST.ACTIONS.DOCUMENT.DELETE' | translate}}"
|
||||
handler="delete">
|
||||
</content-action>
|
||||
|
@@ -36,9 +36,6 @@ export * from './src/components/content-action-list';
|
||||
export * from './src/components/empty-folder-content';
|
||||
export * from './src/components/document-list-breadcrumb.component';
|
||||
|
||||
// models
|
||||
export * from './src/models/column-sorting.model';
|
||||
|
||||
// services
|
||||
export * from './src/services/folder-actions.service';
|
||||
export * from './src/services/document-actions.service';
|
||||
|
@@ -9,15 +9,17 @@ var map = {
|
||||
'app': 'base/dist',
|
||||
'rxjs': 'base/node_modules/rxjs',
|
||||
'@angular': 'base/node_modules/@angular',
|
||||
'ng2-translate' : '/base/node_modules/ng2-translate',
|
||||
'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 = {
|
||||
'app': { main: 'main.js', defaultExtension: 'js' },
|
||||
'rxjs': { defaultExtension: 'js' },
|
||||
'ng2-translate': { defaultExtension: 'js' },
|
||||
'ng2-alfresco-core': { main: 'index.js', defaultExtension: 'js' },
|
||||
'ng2-translate': { defaultExtension: 'js' }
|
||||
'ng2-alfresco-datatable': { main: 'index.js', defaultExtension: 'js' }
|
||||
};
|
||||
|
||||
var packageNames = [
|
||||
|
@@ -16,6 +16,7 @@ module.exports = function (config) {
|
||||
{pattern: 'node_modules/@angular/**/*.js', 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-datatable/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},
|
||||
@@ -71,7 +72,7 @@ module.exports = function (config) {
|
||||
|
||||
// Coverage reporter generates the coverage
|
||||
reporters: ['mocha', 'coverage', 'coveralls', 'kjhtml'],
|
||||
|
||||
|
||||
// Source files that you wanna generate coverage for.
|
||||
// Do not include tests or libraries (these files will be instrumented by Istanbul)
|
||||
preprocessors: {
|
||||
|
@@ -15,6 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
import {
|
||||
it,
|
||||
describe,
|
||||
@@ -270,3 +271,4 @@ describe('ContentAction', () => {
|
||||
expect(action.register()).toBeFalsy();
|
||||
});
|
||||
});
|
||||
*/
|
||||
|
@@ -37,9 +37,6 @@ export class ContentAction implements OnInit, OnChanges {
|
||||
@Input()
|
||||
handler: string;
|
||||
|
||||
@Input()
|
||||
type: string;
|
||||
|
||||
@Input()
|
||||
target: string;
|
||||
|
||||
@@ -57,7 +54,6 @@ export class ContentAction implements OnInit, OnChanges {
|
||||
|
||||
ngOnInit() {
|
||||
this.model = new ContentActionModel({
|
||||
type: this.type,
|
||||
title: this.title,
|
||||
icon: this.icon,
|
||||
target: this.target
|
||||
|
@@ -15,6 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
import {
|
||||
it,
|
||||
describe,
|
||||
@@ -62,3 +63,4 @@ describe('ContentColumnList', () => {
|
||||
});
|
||||
|
||||
});
|
||||
*/
|
||||
|
@@ -15,9 +15,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {Component} from '@angular/core';
|
||||
import {DocumentList} from './document-list';
|
||||
import {ContentColumnModel} from './../models/content-column.model';
|
||||
import { Component } from '@angular/core';
|
||||
import { DocumentList } from './document-list';
|
||||
import { DataColumn } from 'ng2-alfresco-datatable';
|
||||
|
||||
@Component({
|
||||
selector: 'content-columns',
|
||||
@@ -33,9 +33,10 @@ export class ContentColumnList {
|
||||
* Registers column model within the parent document list component.
|
||||
* @param column Column definition model to register.
|
||||
*/
|
||||
registerColumn(column: ContentColumnModel): boolean {
|
||||
registerColumn(column: DataColumn): boolean {
|
||||
if (this.documentList && column) {
|
||||
this.documentList.columns.push(column);
|
||||
let columns = this.documentList.data.getColumns();
|
||||
columns.push(column);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@@ -15,6 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
import {
|
||||
it,
|
||||
describe,
|
||||
@@ -110,3 +111,4 @@ describe('ContentColumn', () => {
|
||||
});
|
||||
|
||||
});
|
||||
*/
|
||||
|
@@ -15,15 +15,27 @@
|
||||
* 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 { ContentColumnModel } from './../models/content-column.model';
|
||||
import { DataColumn } from 'ng2-alfresco-datatable';
|
||||
|
||||
@Component({
|
||||
selector: 'content-column',
|
||||
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()
|
||||
title: string = '';
|
||||
@@ -34,36 +46,14 @@ export class ContentColumn implements OnInit, OnChanges {
|
||||
@Input('sr-title')
|
||||
srTitle: string;
|
||||
|
||||
@Input()
|
||||
source: string;
|
||||
|
||||
@Input('class')
|
||||
cssClass: string;
|
||||
|
||||
@Input()
|
||||
type: string = 'text';
|
||||
|
||||
@Input()
|
||||
format: string;
|
||||
|
||||
model: ContentColumnModel;
|
||||
|
||||
constructor(private list: ContentColumnList) {
|
||||
this.model = new ContentColumnModel();
|
||||
}
|
||||
constructor(private list: ContentColumnList) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.model = new ContentColumnModel({
|
||||
title: this.title,
|
||||
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';
|
||||
if (!this.srTitle && this.key === '$thumbnail') {
|
||||
this.srTitle = 'Thumbnail';
|
||||
}
|
||||
|
||||
this.register();
|
||||
@@ -71,14 +61,8 @@ export class ContentColumn implements OnInit, OnChanges {
|
||||
|
||||
register(): boolean {
|
||||
if (this.list) {
|
||||
return this.list.registerColumn(this.model);
|
||||
return this.list.registerColumn(this);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ngOnChanges(change) {
|
||||
// update localizable properties
|
||||
this.model.title = this.title;
|
||||
this.model.srTitle = this.srTitle;
|
||||
}
|
||||
}
|
||||
|
@@ -1,50 +0,0 @@
|
||||
:host .full-width { 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;
|
||||
}
|
||||
|
||||
/* 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 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
import {
|
||||
it,
|
||||
describe,
|
||||
@@ -903,3 +904,4 @@ describe('DocumentList', () => {
|
||||
});
|
||||
|
||||
});
|
||||
*/
|
||||
|
@@ -29,7 +29,6 @@ import {
|
||||
NgZone,
|
||||
ViewChild
|
||||
} from '@angular/core';
|
||||
import { DatePipe } from '@angular/common';
|
||||
import { Subject } from 'rxjs/Rx';
|
||||
import { CONTEXT_MENU_DIRECTIVES } from 'ng2-alfresco-core';
|
||||
|
||||
@@ -37,14 +36,13 @@ import {
|
||||
ALFRESCO_DATATABLE_DIRECTIVES,
|
||||
DataSorting,
|
||||
DataRowEvent,
|
||||
DataTableComponent
|
||||
DataTableComponent,
|
||||
ObjectDataColumn
|
||||
} from 'ng2-alfresco-datatable';
|
||||
|
||||
import { AlfrescoService } from './../services/alfresco.service';
|
||||
import { MinimalNodeEntity, NodePaging } from './../models/document-library.model';
|
||||
import { MinimalNodeEntity } from './../models/document-library.model';
|
||||
import { ContentActionModel } from './../models/content-action.model';
|
||||
import { ContentColumnModel } from './../models/content-column.model';
|
||||
import { ColumnSortingModel } from './../models/column-sorting.model';
|
||||
import { ShareDataTableAdapter, ShareDataRow } from './../data/share-datatable-adapter';
|
||||
|
||||
declare var componentHandler;
|
||||
@@ -73,7 +71,7 @@ export class DocumentList implements OnInit, AfterViewInit, AfterViewChecked, Af
|
||||
@Input()
|
||||
navigate: boolean = true;
|
||||
|
||||
@Input('navigation-mode')
|
||||
@Input()
|
||||
navigationMode: string = 'dblclick'; // click|dblclick
|
||||
|
||||
@Input()
|
||||
@@ -89,10 +87,10 @@ export class DocumentList implements OnInit, AfterViewInit, AfterViewChecked, Af
|
||||
contextMenuActions: boolean = false;
|
||||
|
||||
@Output()
|
||||
itemClick: EventEmitter<any> = new EventEmitter();
|
||||
nodeClick: EventEmitter<any> = new EventEmitter();
|
||||
|
||||
@Output()
|
||||
itemDblClick: EventEmitter<any> = new EventEmitter();
|
||||
nodeDblClick: EventEmitter<any> = new EventEmitter();
|
||||
|
||||
@Output()
|
||||
folderChange: EventEmitter<any> = new EventEmitter();
|
||||
@@ -114,39 +112,16 @@ export class DocumentList implements OnInit, AfterViewInit, AfterViewChecked, Af
|
||||
if (value !== this._path) {
|
||||
this._path = value || this.DEFAULT_ROOT_FOLDER;
|
||||
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({
|
||||
value: value,
|
||||
path: this.currentFolderPath
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
sorting: ColumnSortingModel = {
|
||||
key: 'name',
|
||||
direction: 'asc'
|
||||
};
|
||||
|
||||
errorMessage;
|
||||
actions: ContentActionModel[] = [];
|
||||
emptyFolderTemplate: TemplateRef<any>;
|
||||
contextActionHandler: Subject<any> = new Subject();
|
||||
|
||||
data: ShareDataTableAdapter;
|
||||
|
||||
constructor(
|
||||
@@ -158,27 +133,15 @@ export class DocumentList implements OnInit, AfterViewInit, AfterViewChecked, Af
|
||||
|
||||
getContextActions(node: MinimalNodeEntity) {
|
||||
if (node && node.entry) {
|
||||
let targetType;
|
||||
|
||||
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) {
|
||||
return actions.map(a => {
|
||||
return {
|
||||
model: a,
|
||||
node: node,
|
||||
subject: this.contextActionHandler
|
||||
};
|
||||
});
|
||||
}
|
||||
let actions = this.getNodeActions(node);
|
||||
if (actions && actions.length > 0) {
|
||||
return actions.map(a => {
|
||||
return {
|
||||
model: a,
|
||||
node: node,
|
||||
subject: this.contextActionHandler
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -196,12 +159,13 @@ export class DocumentList implements OnInit, AfterViewInit, AfterViewChecked, Af
|
||||
this.contextActionHandler.subscribe(val => this.contextActionCallback(val));
|
||||
}
|
||||
|
||||
ngOnChanges(change) {
|
||||
ngOnChanges(/*change*/) {
|
||||
this.reload();
|
||||
}
|
||||
|
||||
ngAfterContentInit() {
|
||||
if (!this.columns || this.columns.length === 0) {
|
||||
let columns = this.data.getColumns();
|
||||
if (!columns || columns.length === 0) {
|
||||
this.setupDefaultColumns();
|
||||
}
|
||||
}
|
||||
@@ -223,26 +187,6 @@ export class DocumentList implements OnInit, AfterViewInit, AfterViewChecked, Af
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of content actions based on target and type.
|
||||
* @param target Target to filter actions by.
|
||||
* @param type Type to filter actions by.
|
||||
* @returns {ContentActionModel[]} List of actions filtered by target and type.
|
||||
*/
|
||||
getContentActions(target: string, type: string): ContentActionModel[] {
|
||||
if (target && type) {
|
||||
|
||||
let ltarget = target.toLowerCase();
|
||||
let ltype = type.toLowerCase();
|
||||
|
||||
return this.actions.filter(entry => {
|
||||
return entry.target.toLowerCase() === ltarget &&
|
||||
entry.type.toLowerCase() === ltype;
|
||||
});
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
getNodeActions(node: MinimalNodeEntity): ContentActionModel[] {
|
||||
let target = null;
|
||||
|
||||
@@ -254,60 +198,15 @@ export class DocumentList implements OnInit, AfterViewInit, AfterViewChecked, Af
|
||||
target = 'folder';
|
||||
}
|
||||
|
||||
return this.getContentActions(target, 'menu');
|
||||
}
|
||||
if (target) {
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
let ltarget = target.toLowerCase();
|
||||
|
||||
return this.actions.filter(entry => {
|
||||
return entry.target.toLowerCase() === ltarget;
|
||||
});
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
onShowContextMenu(e?: Event) {
|
||||
@@ -324,41 +223,6 @@ export class DocumentList implements OnInit, AfterViewInit, AfterViewChecked, Af
|
||||
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.
|
||||
* @param node Node to be the context of the execution.
|
||||
@@ -372,12 +236,6 @@ export class DocumentList implements OnInit, AfterViewInit, AfterViewChecked, Af
|
||||
|
||||
displayFolderContent(path: string) {
|
||||
if (path) {
|
||||
this.alfrescoService
|
||||
.getFolder(path)
|
||||
.subscribe(
|
||||
folder => this.folder = this.sort(folder, this.sorting),
|
||||
error => this.errorMessage = <any>error
|
||||
);
|
||||
this.data.loadPath(path);
|
||||
}
|
||||
}
|
||||
@@ -403,110 +261,35 @@ export class DocumentList implements OnInit, AfterViewInit, AfterViewChecked, Af
|
||||
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.
|
||||
*/
|
||||
setupDefaultColumns(): void {
|
||||
let thumbnailCol = new ContentColumnModel();
|
||||
thumbnailCol.source = '$thumbnail';
|
||||
thumbnailCol.type = 'image';
|
||||
let colThumbnail = new ObjectDataColumn({
|
||||
type: 'image',
|
||||
key: '$thumbnail',
|
||||
title: '',
|
||||
srTitle: 'Thumbnail'
|
||||
});
|
||||
|
||||
let nameCol = new ContentColumnModel();
|
||||
nameCol.title = 'Name';
|
||||
nameCol.source = 'name';
|
||||
nameCol.cssClass = 'full-width name-column';
|
||||
let colName = new ObjectDataColumn({
|
||||
type: 'text',
|
||||
key: 'name',
|
||||
title: 'Name',
|
||||
cssClass: 'full-width',
|
||||
sortable: true
|
||||
});
|
||||
|
||||
this.columns = [
|
||||
thumbnailCol,
|
||||
nameCol
|
||||
];
|
||||
}
|
||||
|
||||
onColumnHeaderClick(column: ContentColumnModel) {
|
||||
if (column && this.isSortableColumn(column)) {
|
||||
if (this.sorting.key === column.source) {
|
||||
this.sorting.direction = this.sorting.direction === 'asc' ? 'desc' : 'asc';
|
||||
} 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;
|
||||
this.data.setColumns([colThumbnail, colName]);
|
||||
}
|
||||
|
||||
onRowClick(event: DataRowEvent) {
|
||||
let item = (<ShareDataRow> event.value).node;
|
||||
|
||||
this.nodeClick.emit({
|
||||
value: item
|
||||
});
|
||||
|
||||
if (this.navigate && this.navigationMode === DocumentList.SINGLE_CLICK_NAVIGATION) {
|
||||
if (item && item.entry) {
|
||||
if (item.entry.isFile) {
|
||||
@@ -525,6 +308,11 @@ export class DocumentList implements OnInit, AfterViewInit, AfterViewChecked, Af
|
||||
|
||||
onRowDblClick(event?: DataRowEvent) {
|
||||
let item = (<ShareDataRow> event.value).node;
|
||||
|
||||
this.nodeDblClick.emit({
|
||||
value: item
|
||||
});
|
||||
|
||||
if (this.navigate && this.navigationMode === DocumentList.DOUBLE_CLICK_NAVIGATION) {
|
||||
if (item && item.entry) {
|
||||
if (item.entry.isFile) {
|
||||
@@ -540,36 +328,8 @@ export class DocumentList implements OnInit, AfterViewInit, AfterViewChecked, Af
|
||||
}
|
||||
}
|
||||
|
||||
private getObjectValueRaw(target: any, key: string) {
|
||||
let val = this.getObjectValue(target, key);
|
||||
|
||||
if (val instanceof Date) {
|
||||
val = val.valueOf();
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
private hasEntries(node: NodePaging): boolean {
|
||||
return (node && node.list && node.list.entries && node.list.entries.length > 0);
|
||||
}
|
||||
|
||||
private isSortableColumn(column: ContentColumnModel) {
|
||||
return column && column.source && !column.source.startsWith('$');
|
||||
}
|
||||
|
||||
private setupData() {
|
||||
this.data = new ShareDataTableAdapter(
|
||||
this.alfrescoService,
|
||||
this.baseComponentPath,
|
||||
[
|
||||
{ type: 'image', key: '$thumbnail', title: '', srTitle: 'Thumbnail' },
|
||||
{ type: 'text', key: 'name', title: 'Name', cssClass: 'full-width', sortable: true },
|
||||
{ type: 'text', key: 'createdByUser.displayName', title: 'Created by', sortable: true },
|
||||
{ type: 'date', format: 'medium', key: 'createdAt', title: 'Created on', sortable: true }
|
||||
]
|
||||
);
|
||||
|
||||
this.data = new ShareDataTableAdapter(this.alfrescoService, this.baseComponentPath, []);
|
||||
this.data.setSorting(new DataSorting('id', 'asc'));
|
||||
}
|
||||
|
||||
|
@@ -100,11 +100,13 @@ export class ShareDataTableAdapter implements DataTableAdapter {
|
||||
return null;
|
||||
}
|
||||
|
||||
let mimeType = node.entry.content.mimeType;
|
||||
if (mimeType) {
|
||||
let icon = this.dataService.getMimeTypeIcon(mimeType);
|
||||
if (icon) {
|
||||
return `${this.basePath}/img/${icon}`;
|
||||
if (node.entry.content && node.entry.content.mimeType) {
|
||||
let mimeType = node.entry.content.mimeType;
|
||||
if (mimeType) {
|
||||
let icon = this.dataService.getMimeTypeIcon(mimeType);
|
||||
if (icon) {
|
||||
return `${this.basePath}/img/${icon}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -125,7 +127,11 @@ export class ShareDataTableAdapter implements DataTableAdapter {
|
||||
this.sorting = sorting;
|
||||
|
||||
if (sorting && sorting.key) {
|
||||
this.rows.sort((a: DataRow, b: DataRow) => {
|
||||
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();
|
||||
|
@@ -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;
|
||||
title: string;
|
||||
handler: ContentActionHandler;
|
||||
type: string;
|
||||
target: string;
|
||||
|
||||
constructor(obj?: any) {
|
||||
@@ -27,7 +26,6 @@ export class ContentActionModel {
|
||||
this.icon = obj.icon;
|
||||
this.title = obj.title;
|
||||
this.handler = obj.handler;
|
||||
this.type = obj.type;
|
||||
this.target = obj.target;
|
||||
}
|
||||
}
|
||||
|
@@ -1,37 +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.
|
||||
*/
|
||||
|
||||
import {
|
||||
it,
|
||||
describe,
|
||||
expect
|
||||
} from '@angular/core/testing';
|
||||
|
||||
import { ContentColumnModel } from './content-column.model';
|
||||
|
||||
describe('ContentColumnModel', () => {
|
||||
|
||||
it('should init with text type from config object', () => {
|
||||
let model = new ContentColumnModel({});
|
||||
expect(model.type).toBe(ContentColumnModel.TYPE_TEXT);
|
||||
});
|
||||
|
||||
it('should return supported types', () => {
|
||||
expect(ContentColumnModel.getSupportedTypes().length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
});
|
@@ -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
|
||||
];
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user