mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-06-30 18:15:11 +00:00
#82 Initial implementation of the DataTable component
forked Document List into a separate generic DataTable component, work in progress
This commit is contained in:
parent
6183712028
commit
a73591773b
15
ng2-components/ng2-alfresco-datatable/.editorconfig
Normal file
15
ng2-components/ng2-alfresco-datatable/.editorconfig
Normal file
@ -0,0 +1,15 @@
|
||||
# http://editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
insert_final_newline = false
|
||||
trim_trailing_whitespace = false
|
10
ng2-components/ng2-alfresco-datatable/.gitignore
vendored
Normal file
10
ng2-components/ng2-alfresco-datatable/.gitignore
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
npm-debug.log
|
||||
node_modules/
|
||||
.idea/
|
||||
typings
|
||||
coverage/
|
||||
dist/
|
||||
src/**/*.js
|
||||
src/**/*.js.map
|
||||
ng2-alfresco-datatable.js
|
||||
ng2-alfresco-datatable.js.map
|
6
ng2-components/ng2-alfresco-datatable/.travis.yml
Executable file
6
ng2-components/ng2-alfresco-datatable/.travis.yml
Executable file
@ -0,0 +1,6 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- '5'
|
||||
script: npm run coverage
|
||||
# Send coverage data to Coveralls
|
||||
after_script: "cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js"
|
177
ng2-components/ng2-alfresco-datatable/LICENSE
Normal file
177
ng2-components/ng2-alfresco-datatable/LICENSE
Normal file
@ -0,0 +1,177 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
40
ng2-components/ng2-alfresco-datatable/README.md
Normal file
40
ng2-components/ng2-alfresco-datatable/README.md
Normal file
@ -0,0 +1,40 @@
|
||||
# DataTable Component for Angular 2
|
||||
|
||||
<p>
|
||||
<a href='https://raw.githubusercontent.com/Alfresco/dev-platform-webcomponents/master/ng2-components/ng2-alfresco-upload/LICENSE'>
|
||||
<img src='https://img.shields.io/hexpm/l/plug.svg' alt='license' />
|
||||
</a>
|
||||
<a href='https://www.alfresco.com/'>
|
||||
<img src='https://img.shields.io/badge/style-component-green.svg?label=alfresco' alt='my blog' />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
## Install
|
||||
|
||||
```sh
|
||||
npm install --save ng2-alfresco-core ng2-alfresco-datatable
|
||||
```
|
||||
|
||||
## Build from sources
|
||||
|
||||
Alternatively you can build component from sources with the following commands:
|
||||
|
||||
```sh
|
||||
npm install
|
||||
npm run build
|
||||
```
|
||||
|
||||
## Running unit tests
|
||||
|
||||
```sh
|
||||
npm test
|
||||
```
|
||||
|
||||
This task rebuilds all the code, runs tslint, license checks and other quality check tools
|
||||
before performing unit testing.
|
||||
|
||||
## Code coverage
|
||||
|
||||
```sh
|
||||
npm run coverage
|
||||
```
|
@ -0,0 +1,16 @@
|
||||
/*!
|
||||
* @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.
|
||||
*/
|
70
ng2-components/ng2-alfresco-datatable/karma-test-shim.js
Normal file
70
ng2-components/ng2-alfresco-datatable/karma-test-shim.js
Normal file
@ -0,0 +1,70 @@
|
||||
// Tun on full stack traces in errors to help debugging
|
||||
Error.stackTraceLimit = Infinity;
|
||||
|
||||
jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000;
|
||||
|
||||
// // Cancel Karma's synchronous start,
|
||||
// // we will call `__karma__.start()` later, once all the specs are loaded.
|
||||
__karma__.loaded = function() {};
|
||||
|
||||
System.config({
|
||||
packages: {
|
||||
'base/dist': {
|
||||
defaultExtension: 'js',
|
||||
format: 'register',
|
||||
map: Object.keys(window.__karma__.files).filter(onlyAppFiles).reduce(createPathRecords, {})
|
||||
}
|
||||
},
|
||||
map: {
|
||||
'ng2-alfresco-core': '/base/dist/node_modules/ng2-alfresco-core'
|
||||
}
|
||||
});
|
||||
|
||||
System.import('angular2/src/platform/browser/browser_adapter')
|
||||
.then(function(browser_adapter) { browser_adapter.BrowserDomAdapter.makeCurrent(); })
|
||||
.then(function() { return Promise.all(resolveTestFiles()); })
|
||||
.then(
|
||||
function() {
|
||||
__karma__.start();
|
||||
},
|
||||
function(error) {
|
||||
__karma__.error(error.stack || error);
|
||||
}
|
||||
);
|
||||
|
||||
function createPathRecords(pathsMapping, appPath) {
|
||||
// creates local module name mapping to global path with karma's fingerprint in path, e.g.:
|
||||
// './vg-player/vg-player':
|
||||
// '/base/dist/vg-player/vg-player.js?f4523daf879cfb7310ef6242682ccf10b2041b3e'
|
||||
var moduleName = './' + resolveKeyPathForMapping('base/dist/', appPath);
|
||||
moduleName = moduleName.replace(/\.js$/, '');
|
||||
pathsMapping[moduleName] = appPath + '?' + window.__karma__.files[appPath];
|
||||
return pathsMapping;
|
||||
}
|
||||
|
||||
function onlyAppFiles(filePath) {
|
||||
return /\/base\/dist\/(?!.*\.spec\.js$).*\.js$/.test(filePath);
|
||||
}
|
||||
|
||||
function onlySpecFiles(path) {
|
||||
return /\.spec\.js$/.test(path);
|
||||
}
|
||||
|
||||
function resolveTestFiles() {
|
||||
return Object.keys(window.__karma__.files) // All files served by Karma.
|
||||
.filter(onlySpecFiles)
|
||||
.map(function(moduleName) {
|
||||
// loads all spec files via their global module names (e.g.
|
||||
// 'base/dist/vg-player/vg-player.spec')
|
||||
return System.import(moduleName);
|
||||
});
|
||||
}
|
||||
|
||||
function resolveKeyPathForMapping(basePathWhereToStart, appPath) {
|
||||
var location = appPath.indexOf(basePathWhereToStart);
|
||||
if (location > -1) {
|
||||
return appPath.substring(basePathWhereToStart.length + 1);
|
||||
} else {
|
||||
return appPath;
|
||||
}
|
||||
}
|
78
ng2-components/ng2-alfresco-datatable/karma.conf.js
Normal file
78
ng2-components/ng2-alfresco-datatable/karma.conf.js
Normal file
@ -0,0 +1,78 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = function (config) {
|
||||
config.set({
|
||||
|
||||
basePath: '.',
|
||||
|
||||
frameworks: ['jasmine'],
|
||||
|
||||
files: [
|
||||
// paths loaded by Karma
|
||||
{pattern: 'node_modules/angular2/bundles/angular2-polyfills.js', included: true, watched: true},
|
||||
{pattern: 'node_modules/systemjs/dist/system.src.js', included: true, watched: true},
|
||||
{pattern: 'node_modules/rxjs/bundles/Rx.js', included: true, watched: true},
|
||||
{pattern: 'node_modules/angular2/bundles/angular2.dev.js', included: true, watched: true},
|
||||
{pattern: 'node_modules/angular2/bundles/testing.dev.js', included: true, watched: true},
|
||||
{pattern: 'node_modules/angular2/bundles/http.dev.js', included: true, watched: true},
|
||||
{pattern: 'node_modules/alfresco-core-rest-api/bundle.js', included: true, watched: false},
|
||||
|
||||
{pattern: 'karma-test-shim.js', included: true, watched: true},
|
||||
|
||||
// paths loaded via module imports
|
||||
{pattern: 'dist/**/*.js', included: false, watched: true},
|
||||
{pattern: 'dist/**/*.html', included: true, served: true, watched: true},
|
||||
{pattern: 'dist/**/*.css', included: true, served: true, watched: true},
|
||||
|
||||
// paths to support debugging with source maps in dev tools
|
||||
{pattern: 'src/**/*.ts', included: false, watched: false},
|
||||
{pattern: 'dist/**/*.js.map', included: false, watched: false}
|
||||
],
|
||||
|
||||
// proxied base paths
|
||||
proxies: {
|
||||
// required for component assets fetched by Angular's compiler
|
||||
'/src/': '/base/src/'
|
||||
},
|
||||
|
||||
port: 9876,
|
||||
|
||||
// level of logging
|
||||
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
|
||||
logLevel: config.LOG_INFO,
|
||||
|
||||
colors: true,
|
||||
|
||||
autoWatch: true,
|
||||
|
||||
browsers: ['Chrome'],
|
||||
|
||||
// Karma plugins loaded
|
||||
plugins: [
|
||||
'karma-jasmine',
|
||||
'karma-coverage',
|
||||
'karma-chrome-launcher',
|
||||
'karma-mocha-reporter'
|
||||
],
|
||||
|
||||
// Coverage reporter generates the coverage
|
||||
reporters: ['mocha', 'coverage'],
|
||||
|
||||
// Source files that you wanna generate coverage for.
|
||||
// Do not include tests or libraries (these files will be instrumented by Istanbul)
|
||||
preprocessors: {
|
||||
'dist/**/!(*spec).js': ['coverage']
|
||||
},
|
||||
|
||||
coverageReporter: {
|
||||
dir: 'coverage/',
|
||||
reporters: [
|
||||
{type: 'text-summary'},
|
||||
{type: 'json', subdir: '.', file: 'coverage-final.json'},
|
||||
{type: 'html'}
|
||||
]
|
||||
},
|
||||
|
||||
singleRun: true
|
||||
})
|
||||
};
|
@ -0,0 +1,58 @@
|
||||
/*!
|
||||
* @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 { DataTableComponent } from './src/components/datatable.component';
|
||||
import { DataColumnComponent } from './src/components/data-column.component';
|
||||
import { DataColumnListComponent } from './src/components/data-column-list.component';
|
||||
import { DataActionComponent } from './src/components/data-action.component';
|
||||
import { DataActionListComponent } from './src/components/data-action-list.component';
|
||||
|
||||
import { FolderActionsService } from './src/services/folder-actions.service';
|
||||
import { DocumentActionsService } from './src/services/document-actions.service';
|
||||
import { AlfrescoService } from './src/services/alfresco.service';
|
||||
|
||||
// components
|
||||
export * from './src/components/datatable.component';
|
||||
export * from './src/components/data-column.component';
|
||||
export * from './src/components/data-column-list.component';
|
||||
export * from './src/components/data-action.component';
|
||||
export * from './src/components/data-action-list.component';
|
||||
|
||||
// models
|
||||
export * from './src/models/data-action.model';
|
||||
export * from './src/models/data-column.model';
|
||||
export * from './src/models/column-sorting.model';
|
||||
|
||||
// services
|
||||
export * from './src/services/folder-actions.service';
|
||||
export * from './src/services/document-actions.service';
|
||||
export * from './src/services/alfresco.service';
|
||||
|
||||
|
||||
export const ALFRESCO_DATATABLE_DIRECTIVES: [any] = [
|
||||
DataTableComponent,
|
||||
DataColumnComponent,
|
||||
DataColumnListComponent,
|
||||
DataActionComponent,
|
||||
DataActionListComponent
|
||||
];
|
||||
|
||||
export const ALFRESCO_DATATABLE_PROVIDERS: [any] = [
|
||||
AlfrescoService,
|
||||
FolderActionsService,
|
||||
DocumentActionsService
|
||||
];
|
89
ng2-components/ng2-alfresco-datatable/package.json
Normal file
89
ng2-components/ng2-alfresco-datatable/package.json
Normal file
@ -0,0 +1,89 @@
|
||||
{
|
||||
"name": "ng2-alfresco-datatable",
|
||||
"description": "Alfresco Angular2 DataTable Component",
|
||||
"version": "0.1.0",
|
||||
"author": "Alfresco Software, Ltd.",
|
||||
"scripts": {
|
||||
"postinstall": "npm run typings",
|
||||
"typings": "typings install",
|
||||
"start": "npm run test && http-server -c-1 -o -p 8875 .",
|
||||
"build": "npm run tslint && typings install && rm -rf dist && tsc && npm run copytemplates && license-check",
|
||||
"tslint": "npm run tslint-test && npm run tslint-src && npm run tslint-root",
|
||||
"tslint-test": "tslint -c tslint.json test/**/*.ts",
|
||||
"tslint-src": "tslint -c tslint.json src/**/*.ts",
|
||||
"tslint-root": "tslint -c tslint.json *.ts",
|
||||
"copytemplates": "npm run copy-html && npm run copy-css",
|
||||
"copy-html": "copyfiles './src/**/*.html' dist",
|
||||
"copy-css": "copyfiles './src/**/*.css' dist",
|
||||
"licensecheck": "license-check",
|
||||
"tsc": "tsc",
|
||||
"pretest": "npm run build",
|
||||
"test": "karma start karma.conf.js",
|
||||
"posttest": "node_modules/.bin/remap-istanbul -i coverage/coverage-final.json -o coverage -t html",
|
||||
"coverage": "http-server -c-1 -o -p 9875 ./coverage"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Alfresco/dev-platform-webcomponents.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/Alfresco/dev-platform-webcomponents/issues"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Denys Vuika",
|
||||
"email": "denis.vuyka@gmail.com"
|
||||
}
|
||||
],
|
||||
"keywords": [
|
||||
"ng2",
|
||||
"angular",
|
||||
"angular2",
|
||||
"alfresco"
|
||||
],
|
||||
"dependencies": {
|
||||
"angular2": "2.0.0-beta.15",
|
||||
"systemjs": "0.19.26",
|
||||
"es6-shim": "^0.35.0",
|
||||
"reflect-metadata": "0.1.2",
|
||||
"rxjs": "5.0.0-beta.2",
|
||||
"zone.js": "^0.6.12",
|
||||
"es6-module-loader": "^0.17.8"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"angular2": "2.0.0-beta.15"
|
||||
},
|
||||
"devDependencies": {
|
||||
"copyfiles": "^0.2.1",
|
||||
"coveralls": "^2.11.9",
|
||||
"http-server": "0.8.5",
|
||||
"jasmine-core": "2.4.1",
|
||||
"karma": "~0.13.22",
|
||||
"karma-chrome-launcher": "~1.0.1",
|
||||
"karma-coverage": "^1.0.0",
|
||||
"karma-jasmine": "~1.0.2",
|
||||
"karma-mocha-reporter": "^2.0.3",
|
||||
"license-check": "^1.0.4",
|
||||
"remap-istanbul": "^0.6.3",
|
||||
"traceur": "^0.0.91",
|
||||
"tslint": "^3.8.1",
|
||||
"typescript": "^1.8.10",
|
||||
"typings": "^0.7.12"
|
||||
},
|
||||
"license-check-config": {
|
||||
"src": [
|
||||
"**/*.js",
|
||||
"**/*.ts",
|
||||
"!/**/coverage/**/*",
|
||||
"!/**/demo/**/*",
|
||||
"!/**/node_modules/**/*",
|
||||
"!/**/typings/**/*",
|
||||
"!*.js"
|
||||
],
|
||||
"path": "assets/license_header.txt",
|
||||
"blocking": false,
|
||||
"logInfo": false,
|
||||
"logError": true
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {Http} from 'angular2/http';
|
||||
import {Observable} from 'rxjs/Observable';
|
||||
|
||||
import {AlfrescoSettingsService} from 'ng2-alfresco-core/services';
|
||||
import {AlfrescoService} from './../../src/services/alfresco.service';
|
||||
|
||||
export class AlfrescoServiceMock extends AlfrescoService {
|
||||
|
||||
_folderToReturn: any = {};
|
||||
|
||||
constructor(
|
||||
http: Http = null,
|
||||
settings: AlfrescoSettingsService = null
|
||||
) {
|
||||
super(http, settings);
|
||||
}
|
||||
|
||||
getFolder(folder: string) {
|
||||
return Observable.create(observer => {
|
||||
observer.next(this._folderToReturn);
|
||||
observer.complete();
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/*!
|
||||
* @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 {Component} from 'angular2/core';
|
||||
|
||||
import { DataTableComponent } from './datatable.component';
|
||||
import { DataActionModel } from './../models/data-action.model';
|
||||
|
||||
@Component({
|
||||
selector: 'data-actions',
|
||||
template: ''
|
||||
})
|
||||
export class DataActionListComponent {
|
||||
|
||||
constructor(
|
||||
private dataTable: DataTableComponent) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers action handler within the parent document list component.
|
||||
* @param action Action model to register.
|
||||
*/
|
||||
registerAction(action: DataActionModel): void {
|
||||
if (this.dataTable && action) {
|
||||
this.dataTable.actions.push(action);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,179 @@
|
||||
/*!
|
||||
* @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,
|
||||
beforeEach
|
||||
} from 'angular2/testing';
|
||||
import {EventEmitter} from 'angular2/core';
|
||||
|
||||
import { AlfrescoServiceMock } from '../assets/alfresco.service.mock';
|
||||
import { DataTableComponent } from './datatable.component';
|
||||
import { DataActionListComponent } from './data-action-list.component';
|
||||
import { DataActionComponent } from './data-action.component';
|
||||
import {DocumentActionsService} from '../services/document-actions.service';
|
||||
import {FolderActionsService} from '../services/folder-actions.service';
|
||||
|
||||
describe('ContentAction', () => {
|
||||
|
||||
let dataTable: DataTableComponent;
|
||||
let actionList: DataActionListComponent;
|
||||
|
||||
beforeEach(() => {
|
||||
let alfrescoServiceMock = new AlfrescoServiceMock();
|
||||
dataTable = new DataTableComponent(alfrescoServiceMock);
|
||||
actionList = new DataActionListComponent(dataTable);
|
||||
});
|
||||
|
||||
it('should register within parent actions list', () => {
|
||||
spyOn(actionList, 'registerAction').and.stub();
|
||||
|
||||
let action = new DataActionComponent(actionList, null, null);
|
||||
action.ngOnInit();
|
||||
|
||||
expect(actionList.registerAction).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should setup and register model', () => {
|
||||
let action = new DataActionComponent(actionList, null, null);
|
||||
action.type = 'button';
|
||||
action.target = 'document';
|
||||
action.title = '<title>';
|
||||
action.icon = '<icon>';
|
||||
|
||||
expect(dataTable.actions.length).toBe(0);
|
||||
action.ngOnInit();
|
||||
|
||||
expect(dataTable.actions.length).toBe(1);
|
||||
|
||||
let model = dataTable.actions[0];
|
||||
expect(model.type).toBe(action.type);
|
||||
expect(model.target).toBe(action.target);
|
||||
expect(model.title).toBe(action.title);
|
||||
expect(model.icon).toBe(action.icon);
|
||||
});
|
||||
|
||||
it('should get action handler from document actions service', () => {
|
||||
|
||||
let handler = function() {};
|
||||
let documentActions = new DocumentActionsService(null);
|
||||
spyOn(documentActions, 'getHandler').and.returnValue(handler);
|
||||
|
||||
let action = new DataActionComponent(actionList, documentActions, null);
|
||||
action.type = 'button';
|
||||
action.target = 'document';
|
||||
action.handler = '<handler>';
|
||||
action.ngOnInit();
|
||||
|
||||
expect(documentActions.getHandler).toHaveBeenCalledWith(action.handler);
|
||||
expect(dataTable.actions.length).toBe(1);
|
||||
|
||||
let model = dataTable.actions[0];
|
||||
expect(model.handler).toBe(handler);
|
||||
});
|
||||
|
||||
it('should get action handler from folder actions service', () => {
|
||||
let handler = function() {};
|
||||
let folderActions = new FolderActionsService();
|
||||
spyOn(folderActions, 'getHandler').and.returnValue(handler);
|
||||
|
||||
let action = new DataActionComponent(actionList, null, folderActions);
|
||||
action.type = 'button';
|
||||
action.target = 'folder';
|
||||
action.handler = '<handler>';
|
||||
action.ngOnInit();
|
||||
|
||||
expect(folderActions.getHandler).toHaveBeenCalledWith(action.handler);
|
||||
expect(dataTable.actions.length).toBe(1);
|
||||
|
||||
let model = dataTable.actions[0];
|
||||
expect(model.handler).toBe(handler);
|
||||
});
|
||||
|
||||
it('should require target to get system handler', () => {
|
||||
let folderActions = new FolderActionsService();
|
||||
spyOn(folderActions, 'getHandler').and.stub();
|
||||
|
||||
let documentActions = new DocumentActionsService(null);
|
||||
spyOn(documentActions, 'getHandler').and.stub();
|
||||
|
||||
let action = new DataActionComponent(actionList, documentActions, folderActions);
|
||||
action.type = 'button';
|
||||
action.handler = '<handler>';
|
||||
|
||||
action.ngOnInit();
|
||||
expect(dataTable.actions.length).toBe(1);
|
||||
expect(folderActions.getHandler).not.toHaveBeenCalled();
|
||||
expect(documentActions.getHandler).not.toHaveBeenCalled();
|
||||
|
||||
action.target = 'document';
|
||||
action.ngOnInit();
|
||||
expect(documentActions.getHandler).toHaveBeenCalled();
|
||||
|
||||
action.target = 'folder';
|
||||
action.ngOnInit();
|
||||
expect(folderActions.getHandler).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should be case insensitive for document target', () => {
|
||||
let documentActions = new DocumentActionsService(null);
|
||||
spyOn(documentActions, 'getHandler').and.stub();
|
||||
|
||||
let action = new DataActionComponent(actionList, documentActions, null);
|
||||
action.target = 'DoCuMeNt';
|
||||
action.type = 'button';
|
||||
action.handler = '<handler>';
|
||||
|
||||
action.ngOnInit();
|
||||
expect(documentActions.getHandler).toHaveBeenCalledWith(action.handler);
|
||||
});
|
||||
|
||||
it('should be case insensitive for folder target', () => {
|
||||
let folderActions = new FolderActionsService();
|
||||
spyOn(folderActions, 'getHandler').and.stub();
|
||||
|
||||
let action = new DataActionComponent(actionList, null, folderActions);
|
||||
action.target = 'FoLdEr';
|
||||
action.type = 'button';
|
||||
action.handler = '<handler>';
|
||||
|
||||
action.ngOnInit();
|
||||
expect(folderActions.getHandler).toHaveBeenCalledWith(action.handler);
|
||||
});
|
||||
|
||||
it('should use custom "execute" emitter', (done) => {
|
||||
let emitter = new EventEmitter();
|
||||
|
||||
emitter.subscribe(e => {
|
||||
expect(e.value).toBe('<obj>');
|
||||
done();
|
||||
});
|
||||
|
||||
let action = new DataActionComponent(actionList, null, null);
|
||||
action.target = 'document';
|
||||
action.type = 'button';
|
||||
action.execute = emitter;
|
||||
|
||||
action.ngOnInit();
|
||||
expect(dataTable.actions.length).toBe(1);
|
||||
|
||||
let model = dataTable.actions[0];
|
||||
model.handler('<obj>');
|
||||
});
|
||||
});
|
@ -0,0 +1,101 @@
|
||||
/*!
|
||||
* @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 {
|
||||
Component,
|
||||
OnInit,
|
||||
Input,
|
||||
Output,
|
||||
EventEmitter
|
||||
} from 'angular2/core';
|
||||
|
||||
import { DataActionModel, DataActionHandler } from './../models/data-action.model';
|
||||
import { DataActionListComponent } from './data-action-list.component';
|
||||
import {DocumentActionsService} from '../services/document-actions.service';
|
||||
import {FolderActionsService} from '../services/folder-actions.service';
|
||||
|
||||
@Component({
|
||||
selector: 'data-action',
|
||||
template: ''
|
||||
})
|
||||
export class DataActionComponent implements OnInit {
|
||||
|
||||
@Input()
|
||||
title: string = 'Action';
|
||||
|
||||
@Input()
|
||||
icon: string;
|
||||
|
||||
@Input()
|
||||
handler: string;
|
||||
|
||||
@Input()
|
||||
type: string;
|
||||
|
||||
@Input()
|
||||
target: string;
|
||||
|
||||
@Output()
|
||||
execute = new EventEmitter();
|
||||
|
||||
constructor(
|
||||
private list: DataActionListComponent,
|
||||
private documentActions: DocumentActionsService,
|
||||
private folderActions: FolderActionsService) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
let model = new DataActionModel();
|
||||
model.type = this.type;
|
||||
model.title = this.title;
|
||||
model.icon = this.icon;
|
||||
model.target = this.target;
|
||||
|
||||
if (this.handler) {
|
||||
model.handler = this.getSystemHandler(this.target, this.handler);
|
||||
} else if (this.execute) {
|
||||
model.handler = (document: any): void => {
|
||||
this.execute.emit({
|
||||
value: document
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
this.list.registerAction(model);
|
||||
}
|
||||
|
||||
private getSystemHandler(target: string, name: string): DataActionHandler {
|
||||
if (target) {
|
||||
let ltarget = target.toLowerCase();
|
||||
|
||||
if (ltarget === 'document') {
|
||||
if (this.documentActions) {
|
||||
return this.documentActions.getHandler(name);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
if (ltarget === 'folder') {
|
||||
if (this.folderActions) {
|
||||
return this.folderActions.getHandler(name);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
/*!
|
||||
* @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,
|
||||
beforeEach
|
||||
} from 'angular2/testing';
|
||||
|
||||
import { DataTableComponent } from './datatable.component';
|
||||
import { AlfrescoServiceMock } from '../assets/alfresco.service.mock';
|
||||
import { DataColumnListComponent } from './data-column-list.component';
|
||||
import { DataColumnModel } from '../models/data-column.model';
|
||||
|
||||
describe('ContentColumnList', () => {
|
||||
|
||||
let dataTable: DataTableComponent;
|
||||
let dataColumnList: DataColumnListComponent;
|
||||
|
||||
beforeEach(() => {
|
||||
let alfrescoServiceMock = new AlfrescoServiceMock();
|
||||
dataTable = new DataTableComponent(alfrescoServiceMock);
|
||||
dataColumnList = new DataColumnListComponent(dataTable);
|
||||
});
|
||||
|
||||
it('should register column within parent document list', () => {
|
||||
expect(dataTable.columns.length).toBe(0);
|
||||
|
||||
dataColumnList.registerColumn(new DataColumnModel());
|
||||
|
||||
expect(dataTable.columns.length).toBe(1);
|
||||
});
|
||||
|
||||
});
|
@ -0,0 +1,41 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Component } from 'angular2/core';
|
||||
import { DataTableComponent } from './datatable.component';
|
||||
import { DataColumnModel } from '../models/data-column.model';
|
||||
|
||||
@Component({
|
||||
selector: 'data-columns',
|
||||
template: ''
|
||||
})
|
||||
export class DataColumnListComponent {
|
||||
|
||||
constructor(
|
||||
private dataTable: DataTableComponent) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers column model within the parent document list component.
|
||||
* @param column Column definition model to register.
|
||||
*/
|
||||
registerColumn(column: DataColumnModel): void {
|
||||
if (this.dataTable && column) {
|
||||
this.dataTable.columns.push(column);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
/*!
|
||||
* @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,
|
||||
beforeEach
|
||||
} from 'angular2/testing';
|
||||
|
||||
import {AlfrescoServiceMock} from '../assets/alfresco.service.mock';
|
||||
import { DataTableComponent } from './datatable.component';
|
||||
import { DataColumnComponent } from './data-column.component';
|
||||
import { DataColumnListComponent } from './data-column-list.component';
|
||||
|
||||
describe('ContentColumn', () => {
|
||||
|
||||
let dataTable: DataTableComponent;
|
||||
let columnList: DataColumnListComponent;
|
||||
|
||||
beforeEach(() => {
|
||||
let alfrescoServiceMock = new AlfrescoServiceMock();
|
||||
dataTable = new DataTableComponent(alfrescoServiceMock);
|
||||
columnList = new DataColumnListComponent(dataTable);
|
||||
});
|
||||
|
||||
it('should register model within parent column list', () => {
|
||||
spyOn(columnList, 'registerColumn').and.callThrough();
|
||||
|
||||
let column = new DataColumnComponent(columnList);
|
||||
column.ngOnInit();
|
||||
|
||||
expect(columnList.registerColumn).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should setup model properties during registration', () => {
|
||||
|
||||
let column = new DataColumnComponent(columnList);
|
||||
column.title = '<title>';
|
||||
column.srTitle = '<sr-title>';
|
||||
column.source = '<source>';
|
||||
column.cssClass = '<css-class>';
|
||||
column.ngOnInit();
|
||||
|
||||
expect(dataTable.columns.length).toBe(1);
|
||||
|
||||
let model = dataTable.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', () => {
|
||||
|
||||
let column = new DataColumnComponent(columnList);
|
||||
column.source = '$thumbnail';
|
||||
column.ngOnInit();
|
||||
|
||||
expect(dataTable.columns.length).toBe(1);
|
||||
|
||||
let model = dataTable.columns[0];
|
||||
expect(model.srTitle).toBe('Thumbnail');
|
||||
});
|
||||
|
||||
});
|
@ -0,0 +1,63 @@
|
||||
/*!
|
||||
* @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 { Component, OnInit, Input } from 'angular2/core';
|
||||
|
||||
import { DataColumnListComponent } from './data-column-list.component';
|
||||
import { DataColumnModel } from './../models/data-column.model';
|
||||
|
||||
@Component({
|
||||
selector: 'data-column',
|
||||
template: ''
|
||||
})
|
||||
export class DataColumnComponent implements OnInit {
|
||||
|
||||
@Input()
|
||||
title: string = '';
|
||||
|
||||
/**
|
||||
* Title to be used for screen readers.
|
||||
*/
|
||||
@Input('sr-title')
|
||||
srTitle: string;
|
||||
|
||||
@Input()
|
||||
source: string;
|
||||
|
||||
@Input('class')
|
||||
cssClass: string;
|
||||
|
||||
constructor(
|
||||
private columns: DataColumnListComponent) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
let model = new DataColumnModel();
|
||||
model.title = this.title;
|
||||
model.srTitle = this.srTitle;
|
||||
model.source = this.source;
|
||||
model.cssClass = this.cssClass;
|
||||
|
||||
if (!model.srTitle && model.source === '$thumbnail') {
|
||||
model.srTitle = 'Thumbnail';
|
||||
}
|
||||
|
||||
if (this.columns) {
|
||||
this.columns.registerColumn(model);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
:host .full-width { width: 100%; }
|
||||
|
||||
:host .folder-thumbnail {
|
||||
font-size: 48px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
:host .document-thumbnail {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
: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: pointer; }
|
||||
:host .parent-folder-link > td { text-align: left; }
|
||||
|
||||
:host .folder-row-cell,
|
||||
:host .document-row-cell {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
:host .folder-row-cell.name-column,
|
||||
:host .document-row-cell.name-column {
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
:host .folder-row-cell.name-column:hover,
|
||||
:host .document-row-cell.name-column:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* breadcrumb */
|
||||
|
||||
:host .breadcrumb {
|
||||
text-align: left;
|
||||
padding: 8px 15px;
|
||||
list-style: none;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 4px;
|
||||
margin: 0 0 4px;
|
||||
}
|
||||
|
||||
:host .breadcrumb > li {
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
:host .breadcrumb > li+li:before {
|
||||
content: "/\00a0";
|
||||
padding: 0 0 0 5px;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
:host .breadcrumb > .active {
|
||||
color: #777;
|
||||
}
|
@ -0,0 +1,100 @@
|
||||
<ol *ngIf="breadcrumb" class="breadcrumb">
|
||||
<li *ngFor="#r of route; #last = last" [class.active]="last" [ngSwitch]="last">
|
||||
<span *ngSwitchWhen="true">{{r.name}}</span>
|
||||
<a *ngSwitchDefault href="#" (click)="goToRoute(r, $event)">{{r.name}}</a>
|
||||
</li>
|
||||
</ol>
|
||||
<table *ngIf="folder" class="mdl-data-table mdl-js-data-table mdl-shadow--2dp full-width">
|
||||
<thead>
|
||||
<tr>
|
||||
<!-- Columns -->
|
||||
<th class="mdl-data-table__cell--non-numeric {{col.cssClass}}"
|
||||
*ngFor="#col of columns"
|
||||
[class.column-header]="col.title"
|
||||
[class.mdl-data-table__header--sorted-ascending]="sorting.key === col.source && sorting.direction === 'asc'"
|
||||
[class.mdl-data-table__header--sorted-descending]="sorting.key === col.source && sorting.direction === 'desc'"
|
||||
(click)="onColumnHeaderClick(col)">
|
||||
<span *ngIf="col.srTitle" class="sr-only">{{col.srTitle}}</span>
|
||||
<span *ngIf="col.title">{{col.title}}</span>
|
||||
</th>
|
||||
<!-- Actions -->
|
||||
<th>
|
||||
<span class="sr-only">Actions</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="parent-folder-link" *ngIf="canNavigateParent()" (click)="onNavigateParentClick($event)">
|
||||
<td [attr.colspan]="1 + columns?.length">
|
||||
<button class="mdl-button mdl-js-button mdl-button--icon"
|
||||
(click)="onNavigateParentClick($event)">
|
||||
<i class="material-icons">arrow_upward</i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr *ngFor="#content of folder.list.entries; #idx = index">
|
||||
<!-- Columns -->
|
||||
<td *ngFor="#col of columns" [ngSwitch]="col.source"
|
||||
class="mdl-data-table__cell--non-numeric {{content.entry.isFolder ? 'folder-row-cell' : 'document-row-cell'}} {{col.cssClass}}"
|
||||
(click)="onItemClick(content, $event)">
|
||||
<div *ngSwitchWhen="'$thumbnail'">
|
||||
<div *ngIf="content.entry.isFolder">
|
||||
<i class="material-icons folder-thumbnail">{{folderIcon || 'folder_open'}}</i>
|
||||
</div>
|
||||
<div *ngIf="!content.entry.isFolder">
|
||||
<img class="document-thumbnail" alt="" src="{{getDocumentThumbnailUrl(content)}}">
|
||||
</div>
|
||||
</div>
|
||||
<span *ngSwitchDefault>
|
||||
{{getObjectValue(content.entry, col.source)}}
|
||||
</span>
|
||||
</td>
|
||||
|
||||
<!-- Actions: folder -->
|
||||
<td *ngIf="content.entry.isFolder">
|
||||
<!-- action buttons -->
|
||||
<button class="mdl-button mdl-js-button mdl-button--icon"
|
||||
*ngFor="#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"
|
||||
*ngFor="#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="#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"
|
||||
*ngFor="#action of getContentActions('document', 'menu')"
|
||||
(click)="executeContentAction(content, action)">
|
||||
{{action.title}}
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
@ -0,0 +1,359 @@
|
||||
/*!
|
||||
* @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,
|
||||
beforeEach
|
||||
} from 'angular2/testing';
|
||||
|
||||
import { DataTableComponent } from './datatable.component';
|
||||
import { DataColumnModel } from './../models/data-column.model';
|
||||
import { AlfrescoServiceMock } from '../assets/alfresco.service.mock';
|
||||
import { MinimalNodeEntity, MinimalNodeEntryEntity } from '../models/document-library.model';
|
||||
import { DataActionModel } from './../models/data-action.model';
|
||||
|
||||
describe('DocumentList', () => {
|
||||
|
||||
let alfrescoServiceMock: AlfrescoServiceMock;
|
||||
let dataTable: DataTableComponent;
|
||||
let eventMock: any;
|
||||
|
||||
beforeEach(() => {
|
||||
alfrescoServiceMock = new AlfrescoServiceMock();
|
||||
dataTable = new DataTableComponent(alfrescoServiceMock);
|
||||
|
||||
eventMock = {
|
||||
preventDefault: function () {
|
||||
console.log('mock preventDefault');
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
it('should setup default columns', () => {
|
||||
spyOn(dataTable, 'setupDefaultColumns').and.callThrough();
|
||||
|
||||
dataTable.ngAfterContentInit();
|
||||
|
||||
expect(dataTable.setupDefaultColumns).toHaveBeenCalled();
|
||||
expect(dataTable.columns.length).not.toBe(0);
|
||||
});
|
||||
|
||||
it('should use custom columns instead of default ones', () => {
|
||||
let column: DataColumnModel = {
|
||||
title: 'title',
|
||||
source: 'source',
|
||||
cssClass: 'css',
|
||||
srTitle: ''
|
||||
};
|
||||
dataTable.columns.push(column);
|
||||
|
||||
dataTable.ngAfterContentInit();
|
||||
expect(dataTable.columns.length).toBe(1);
|
||||
expect(dataTable.columns[0]).toBe(column);
|
||||
});
|
||||
|
||||
it('should setup default root for breadcrumb', () => {
|
||||
dataTable.ngOnInit();
|
||||
expect(dataTable.route.length).toBe(1);
|
||||
expect(dataTable.route[0]).toBe(dataTable.rootFolder);
|
||||
});
|
||||
|
||||
it('should display custom root path', () => {
|
||||
spyOn(dataTable, 'displayFolderContent').and.stub();
|
||||
|
||||
let root = {
|
||||
name: '<root>',
|
||||
path: '<path>'
|
||||
};
|
||||
|
||||
dataTable.currentFolderPath = root.path;
|
||||
dataTable.rootFolder = root;
|
||||
dataTable.ngOnInit();
|
||||
expect(dataTable.displayFolderContent).toHaveBeenCalledWith(root.path);
|
||||
});
|
||||
|
||||
it('should fetch folder', () => {
|
||||
let folder = {
|
||||
'nodeRef': 'workspace://SpacesStore/8bb36efb-c26d-4d2b-9199-ab6922f53c28'
|
||||
};
|
||||
alfrescoServiceMock._folderToReturn = folder;
|
||||
dataTable.ngOnInit();
|
||||
|
||||
expect(dataTable.folder).toBe(folder);
|
||||
});
|
||||
|
||||
it('should get content url', () => {
|
||||
let url = 'URL';
|
||||
spyOn(alfrescoServiceMock, 'getContentUrl').and.returnValue(url);
|
||||
|
||||
let result = dataTable.getContentUrl(null);
|
||||
|
||||
expect(result).toBe(url);
|
||||
expect(alfrescoServiceMock.getContentUrl).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should return no content url without service', () => {
|
||||
let table = new DataTableComponent(null);
|
||||
let node = new MinimalNodeEntity();
|
||||
expect(table.getContentUrl(node)).toBeNull();
|
||||
});
|
||||
|
||||
it('should get thumbnail url', () => {
|
||||
let url = 'URL';
|
||||
spyOn(alfrescoServiceMock, 'getDocumentThumbnailUrl').and.returnValue(url);
|
||||
|
||||
let result = dataTable.getDocumentThumbnailUrl(null);
|
||||
|
||||
expect(result).toBe(url);
|
||||
expect(alfrescoServiceMock.getDocumentThumbnailUrl).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should get no thumbnail url without service', () => {
|
||||
let table = new DataTableComponent(null);
|
||||
let node = new MinimalNodeEntity();
|
||||
expect(table.getDocumentThumbnailUrl(node)).toBeNull();
|
||||
});
|
||||
|
||||
it('should execute action with node', () => {
|
||||
let node = new MinimalNodeEntity();
|
||||
let action = new DataActionModel();
|
||||
action.handler = function () {
|
||||
console.log('mock handler');
|
||||
};
|
||||
|
||||
spyOn(action, 'handler').and.stub();
|
||||
|
||||
dataTable.executeContentAction(node, action);
|
||||
expect(action.handler).toHaveBeenCalledWith(node);
|
||||
|
||||
});
|
||||
|
||||
it('should execute action without node provided', () => {
|
||||
let action = new DataActionModel();
|
||||
action.handler = function () {
|
||||
console.log('mock handler');
|
||||
};
|
||||
|
||||
spyOn(action, 'handler').and.stub();
|
||||
dataTable.executeContentAction(null, action);
|
||||
expect(action.handler).toHaveBeenCalledWith(null);
|
||||
});
|
||||
|
||||
it('should update current folder path', () => {
|
||||
expect(dataTable.currentFolderPath).toBe(dataTable.rootFolder.path);
|
||||
|
||||
let path = '<path>';
|
||||
dataTable.displayFolderContent(path);
|
||||
|
||||
expect(dataTable.currentFolderPath).toBe(path);
|
||||
});
|
||||
|
||||
it('should give no content actions for empty target', () => {
|
||||
let actions = dataTable.getContentActions(null, 'button');
|
||||
expect(actions.length).toBe(0);
|
||||
});
|
||||
|
||||
it('should give no content actions for empty type', () => {
|
||||
let actions = dataTable.getContentActions('folder', null);
|
||||
expect(actions.length).toBe(0);
|
||||
});
|
||||
|
||||
it('should filter content actions for various types and targets', () => {
|
||||
let folderButton = new DataActionModel();
|
||||
folderButton.target = 'folder';
|
||||
folderButton.type = 'button';
|
||||
|
||||
let folderMenu = new DataActionModel();
|
||||
folderMenu.target = 'folder';
|
||||
folderMenu.type = 'menu';
|
||||
|
||||
let documentButton = new DataActionModel();
|
||||
documentButton.target = 'document';
|
||||
documentButton.type = 'button';
|
||||
|
||||
let documentMenu = new DataActionModel();
|
||||
documentMenu.target = 'document';
|
||||
documentMenu.type = 'menu';
|
||||
|
||||
dataTable.actions = [
|
||||
folderButton,
|
||||
folderMenu,
|
||||
documentButton,
|
||||
documentMenu
|
||||
];
|
||||
|
||||
let actions = dataTable.getContentActions('folder', 'button');
|
||||
expect(actions.length).toBe(1);
|
||||
expect(actions[0]).toBe(folderButton);
|
||||
|
||||
actions = dataTable.getContentActions('folder', 'menu');
|
||||
expect(actions.length).toBe(1);
|
||||
expect(actions[0]).toBe(folderMenu);
|
||||
|
||||
actions = dataTable.getContentActions('document', 'button');
|
||||
expect(actions.length).toBe(1);
|
||||
expect(actions[0]).toBe(documentButton);
|
||||
|
||||
actions = dataTable.getContentActions('document', 'menu');
|
||||
expect(actions.length).toBe(1);
|
||||
expect(actions[0]).toBe(documentMenu);
|
||||
});
|
||||
|
||||
it('should be case insensitive when filtering content actions', () => {
|
||||
let documentButton = new DataActionModel();
|
||||
documentButton.target = 'document';
|
||||
documentButton.type = 'button';
|
||||
|
||||
dataTable.actions = [documentButton];
|
||||
|
||||
let actions = dataTable.getContentActions('DoCuMeNt', 'BUTTON');
|
||||
expect(actions.length).toBe(1);
|
||||
expect(actions[0]).toBe(documentButton);
|
||||
});
|
||||
|
||||
it('should find no content actions', () => {
|
||||
let documentButton = new DataActionModel();
|
||||
documentButton.target = 'document';
|
||||
documentButton.type = 'button';
|
||||
|
||||
dataTable.actions = [documentButton];
|
||||
|
||||
let actions = dataTable.getContentActions('unknown', 'value');
|
||||
expect(actions.length).toBe(0);
|
||||
});
|
||||
|
||||
it('should emit itemClick event', (done) => {
|
||||
let node: MinimalNodeEntity = new MinimalNodeEntity();
|
||||
dataTable.itemClick.subscribe(e => {
|
||||
expect(e.value).toBe(node);
|
||||
done();
|
||||
});
|
||||
dataTable.onItemClick(node);
|
||||
});
|
||||
|
||||
it('should prevent default events for item click', () => {
|
||||
spyOn(eventMock, 'preventDefault').and.stub();
|
||||
|
||||
dataTable.onItemClick(null, eventMock);
|
||||
expect(eventMock.preventDefault).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should display folder content on click', () => {
|
||||
let path = '/';
|
||||
|
||||
let node = new MinimalNodeEntity();
|
||||
node.entry = new MinimalNodeEntryEntity();
|
||||
node.entry.isFolder = true;
|
||||
node.entry.name = '<display name>';
|
||||
|
||||
spyOn(dataTable, 'getNodePath').and.returnValue(path);
|
||||
spyOn(dataTable, 'displayFolderContent').and.stub();
|
||||
|
||||
dataTable.onItemClick(node);
|
||||
|
||||
expect(dataTable.displayFolderContent).toHaveBeenCalledWith(path);
|
||||
|
||||
let routeEntry = dataTable.route.pop();
|
||||
expect(routeEntry.name).toBe(node.entry.name);
|
||||
expect(routeEntry.path).toBe(path);
|
||||
});
|
||||
|
||||
it('should not display folder content when no target node provided', () => {
|
||||
expect(dataTable.navigate).toBe(true);
|
||||
spyOn(dataTable, 'displayFolderContent').and.stub();
|
||||
|
||||
dataTable.onItemClick(null);
|
||||
expect(dataTable.displayFolderContent).not.toHaveBeenCalled();
|
||||
|
||||
});
|
||||
|
||||
it('should display folder content only on folder node click', () => {
|
||||
expect(dataTable.navigate).toBe(true);
|
||||
spyOn(dataTable, 'displayFolderContent').and.stub();
|
||||
|
||||
let node = new MinimalNodeEntity();
|
||||
node.entry = new MinimalNodeEntryEntity();
|
||||
node.entry.isFolder = false;
|
||||
|
||||
dataTable.onItemClick(node);
|
||||
|
||||
expect(dataTable.displayFolderContent).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not display folder content on click when navigation is off', () => {
|
||||
spyOn(dataTable, 'displayFolderContent').and.stub();
|
||||
|
||||
let node = new MinimalNodeEntity();
|
||||
node.entry = new MinimalNodeEntryEntity();
|
||||
node.entry.isFolder = true;
|
||||
node.entry.name = '<display name>';
|
||||
|
||||
dataTable.navigate = false;
|
||||
dataTable.onItemClick(node);
|
||||
|
||||
expect(dataTable.displayFolderContent).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should require node to get path', () => {
|
||||
expect(dataTable.getNodePath(null)).toBe(null);
|
||||
});
|
||||
|
||||
/*
|
||||
it('should get node path', () => {
|
||||
let location = new LocationEntity();
|
||||
location.site = 'swsdp';
|
||||
location.container = 'documentLibrary';
|
||||
location.path = '\/';
|
||||
|
||||
let node = new DocumentEntity();
|
||||
node.fileName = 'fileName';
|
||||
node.location = location;
|
||||
|
||||
expect(documentList.getNodePath(node)).toBe('swsdp/documentLibrary/fileName');
|
||||
});
|
||||
*/
|
||||
|
||||
it('should return root object value', () => {
|
||||
let target = {
|
||||
key1: 'value1'
|
||||
};
|
||||
|
||||
expect(dataTable.getObjectValue(target, 'key1')).toBe('value1');
|
||||
});
|
||||
|
||||
it('should return no object value when key is missing', () => {
|
||||
let target = {
|
||||
key1: 'value1'
|
||||
};
|
||||
expect(dataTable.getObjectValue(target, 'missing')).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should return nested object value', () => {
|
||||
let target = {
|
||||
key1: {
|
||||
key2: {
|
||||
key3: 'value1'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
expect(dataTable.getObjectValue(target, 'key1.key2.key3')).toBe('value1');
|
||||
});
|
||||
|
||||
});
|
@ -0,0 +1,377 @@
|
||||
/*!
|
||||
* @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 {
|
||||
Component,
|
||||
OnInit,
|
||||
Input,
|
||||
Output,
|
||||
EventEmitter,
|
||||
AfterContentInit,
|
||||
AfterViewChecked
|
||||
} from 'angular2/core';
|
||||
|
||||
import { AlfrescoService } from './../services/alfresco.service';
|
||||
import { MinimalNodeEntity, NodePaging } from './../models/document-library.model';
|
||||
import { DataActionModel } from './../models/data-action.model';
|
||||
import { DataColumnModel } from './../models/data-column.model';
|
||||
import { ColumnSortingModel } from './../models/column-sorting.model';
|
||||
|
||||
declare var componentHandler;
|
||||
declare let __moduleName: string;
|
||||
|
||||
@Component({
|
||||
moduleId: __moduleName,
|
||||
selector: 'alfresco-datatable',
|
||||
styleUrls: ['./datatable.component.css'],
|
||||
templateUrl: './datatable.component.html',
|
||||
providers: [AlfrescoService]
|
||||
})
|
||||
export class DataTableComponent implements OnInit, AfterViewChecked, AfterContentInit {
|
||||
|
||||
DEFAULT_ROOT_FOLDER: string = '/Sites/swsdp/documentLibrary';
|
||||
|
||||
@Input()
|
||||
navigate: boolean = true;
|
||||
|
||||
@Input()
|
||||
breadcrumb: boolean = false;
|
||||
|
||||
@Input('folder-icon')
|
||||
folderIcon: string;
|
||||
|
||||
@Output()
|
||||
itemClick: EventEmitter<any> = new EventEmitter();
|
||||
|
||||
@Output()
|
||||
folderClick: EventEmitter<any> = new EventEmitter();
|
||||
|
||||
rootFolder = {
|
||||
name: '',
|
||||
path: ''
|
||||
};
|
||||
|
||||
@Input()
|
||||
currentFolderPath: string = '';
|
||||
|
||||
folder: NodePaging;
|
||||
errorMessage;
|
||||
|
||||
route: any[] = [];
|
||||
|
||||
actions: DataActionModel[] = [];
|
||||
columns: DataColumnModel[] = [];
|
||||
|
||||
sorting: ColumnSortingModel = {
|
||||
key: 'name',
|
||||
direction: 'asc'
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines whether navigation to parent folder is available.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
canNavigateParent(): boolean {
|
||||
return this.navigate && !this.breadcrumb &&
|
||||
this.currentFolderPath !== this.rootFolder.path;
|
||||
}
|
||||
|
||||
constructor(
|
||||
private _alfrescoService: AlfrescoService) {
|
||||
}
|
||||
|
||||
_createRootFolder(): any {
|
||||
let folderArray = this.currentFolderPath.split('/');
|
||||
let nameFolder = folderArray[folderArray.length - 1];
|
||||
return {
|
||||
name: nameFolder,
|
||||
path: this.currentFolderPath
|
||||
};
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.currentFolderPath = this.currentFolderPath || this.DEFAULT_ROOT_FOLDER;
|
||||
this.rootFolder = this._createRootFolder();
|
||||
this.route.push(this.rootFolder);
|
||||
this.displayFolderContent(this.rootFolder.path);
|
||||
}
|
||||
|
||||
ngOnChanges(change) {
|
||||
this.reload();
|
||||
}
|
||||
|
||||
ngAfterContentInit() {
|
||||
if (!this.columns || this.columns.length === 0) {
|
||||
this.setupDefaultColumns();
|
||||
}
|
||||
}
|
||||
|
||||
ngAfterViewChecked() {
|
||||
// workaround for MDL issues with dynamic components
|
||||
if (componentHandler) {
|
||||
componentHandler.upgradeAllRegistered();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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): DataActionModel[] {
|
||||
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 [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when 'parent folder' element is clicked.
|
||||
* @param e DOM event
|
||||
*/
|
||||
onNavigateParentClick(e) {
|
||||
if (e) {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
if (this.navigate) {
|
||||
this.route.pop();
|
||||
let parent = this.route.length > 0 ? this.route[this.route.length - 1] : this.rootFolder;
|
||||
if (parent) {
|
||||
this.folderClick.emit({
|
||||
value: parent.path
|
||||
});
|
||||
this.displayFolderContent(parent.path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when list row is clicked.
|
||||
* @param item Underlying node item
|
||||
* @param e DOM event (optional)
|
||||
*/
|
||||
onItemClick(item: MinimalNodeEntity, e = null) {
|
||||
if (e) {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
this.itemClick.emit({
|
||||
value: item
|
||||
});
|
||||
|
||||
if (this.navigate && item && item.entry) {
|
||||
if (item.entry.isFolder) {
|
||||
let path = this.getNodePath(item);
|
||||
|
||||
this.folderClick.emit({
|
||||
value: path
|
||||
});
|
||||
|
||||
this.route.push({
|
||||
name: item.entry.name,
|
||||
path: path
|
||||
});
|
||||
this.displayFolderContent(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when a breadcrumb route is clicked.
|
||||
* @param r Route to navigate to
|
||||
* @param e DOM event
|
||||
*/
|
||||
goToRoute(r, e) {
|
||||
if (e) {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
if (this.navigate) {
|
||||
let idx = this.route.indexOf(r);
|
||||
if (idx > -1) {
|
||||
this.route.splice(idx + 1);
|
||||
this.displayFolderContent(r.path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets content URL for the given node.
|
||||
* @param node Node to get URL for.
|
||||
* @returns {string} URL address.
|
||||
*/
|
||||
getContentUrl(node: MinimalNodeEntity): string {
|
||||
if (this._alfrescoService) {
|
||||
return this._alfrescoService.getContentUrl(node);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets thumbnail URL for the given document node.
|
||||
* @param node Node to get URL for.
|
||||
* @returns {string} URL address.
|
||||
*/
|
||||
getDocumentThumbnailUrl(node: MinimalNodeEntity): string {
|
||||
if (this._alfrescoService) {
|
||||
return this._alfrescoService.getDocumentThumbnailUrl(node);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when executing content action for a document or folder.
|
||||
* @param node Node to be the context of the execution.
|
||||
* @param action Action to be executed against the context.
|
||||
*/
|
||||
executeContentAction(node: MinimalNodeEntity, action: DataActionModel) {
|
||||
if (action) {
|
||||
action.handler(node);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads and displays folder content
|
||||
* @param path Node path
|
||||
*/
|
||||
displayFolderContent(path) {
|
||||
if (path !== null) {
|
||||
this.currentFolderPath = path;
|
||||
this._alfrescoService
|
||||
.getFolder(path)
|
||||
.subscribe(
|
||||
folder => this.folder = this.sort(folder, this.sorting),
|
||||
error => this.errorMessage = <any>error
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
reload() {
|
||||
if (this.currentFolderPath) {
|
||||
this.displayFolderContent(this.currentFolderPath);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a path for a given node.
|
||||
* @param node
|
||||
* @returns {string}
|
||||
*/
|
||||
getNodePath(node: MinimalNodeEntity): string {
|
||||
if (node) {
|
||||
let pathWithCompanyHome = node.entry.path.name;
|
||||
return pathWithCompanyHome.replace('/Company Home', '') + '/' + node.entry.name;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a set of predefined columns.
|
||||
*/
|
||||
setupDefaultColumns(): void {
|
||||
let thumbnailCol = new DataColumnModel();
|
||||
thumbnailCol.source = '$thumbnail';
|
||||
|
||||
let nameCol = new DataColumnModel();
|
||||
nameCol.title = 'Name';
|
||||
nameCol.source = 'name';
|
||||
nameCol.cssClass = 'full-width name-column';
|
||||
|
||||
this.columns = [
|
||||
thumbnailCol,
|
||||
nameCol
|
||||
];
|
||||
}
|
||||
|
||||
onColumnHeaderClick(column: DataColumnModel) {
|
||||
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 options.direction === 'asc'
|
||||
? (a.entry.isFolder ? -1 : 1)
|
||||
: (a.entry.isFolder ? 1 : -1);
|
||||
}
|
||||
|
||||
let left = this.getObjectValue(a.entry, options.key).toString();
|
||||
let right = this.getObjectValue(b.entry, options.key).toString();
|
||||
|
||||
return options.direction === 'asc'
|
||||
? left.localeCompare(right)
|
||||
: right.localeCompare(left);
|
||||
});
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
private _hasEntries(node: NodePaging): boolean {
|
||||
return (node && node.list && node.list.entries && node.list.entries.length > 0);
|
||||
}
|
||||
|
||||
private _isSortableColumn(column: DataColumnModel) {
|
||||
return column && column.source && !column.source.startsWith('$');
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
/*!
|
||||
* @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 {
|
||||
key: string;
|
||||
direction: string = 'asc';
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
/*!
|
||||
* @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 DataActionModel {
|
||||
icon: string;
|
||||
title: string;
|
||||
handler: DataActionHandler;
|
||||
type: string;
|
||||
target: string;
|
||||
}
|
||||
|
||||
export interface DataActionHandler {
|
||||
(obj: any): any;
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
/*!
|
||||
* @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 DataColumnModel {
|
||||
title: string;
|
||||
srTitle: string;
|
||||
source: string;
|
||||
cssClass: string;
|
||||
}
|
@ -0,0 +1,117 @@
|
||||
/*!
|
||||
* @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.
|
||||
*/
|
||||
|
||||
// note: contains only limited subset of available fields
|
||||
|
||||
export class FolderEntity {
|
||||
items: DocumentEntity[];
|
||||
}
|
||||
|
||||
export class DocumentEntity {
|
||||
nodeRef: string;
|
||||
nodeType: string;
|
||||
type: string;
|
||||
mimetype: string;
|
||||
isFolder: boolean;
|
||||
isLink: boolean;
|
||||
fileName: string;
|
||||
displayName: string;
|
||||
status: string;
|
||||
title: string;
|
||||
description: string;
|
||||
author: string;
|
||||
createdOn: string;
|
||||
createdBy: string;
|
||||
createdByUser: string;
|
||||
modifiedOn: string;
|
||||
modifiedBy: string;
|
||||
modifiedByUser: string;
|
||||
lockedBy: string;
|
||||
lockedByUser: string;
|
||||
size: number;
|
||||
version: string;
|
||||
contentUrl: string;
|
||||
webdavUrl: string;
|
||||
actionSet: string;
|
||||
tags: string[];
|
||||
activeWorkflows: string;
|
||||
location: LocationEntity;
|
||||
}
|
||||
|
||||
export class LocationEntity {
|
||||
repositoryId: string;
|
||||
site: string;
|
||||
siteTitle: string;
|
||||
container: string;
|
||||
path: string;
|
||||
file: string;
|
||||
parent: LocationParentEntity;
|
||||
}
|
||||
|
||||
export class LocationParentEntity {
|
||||
nodeRef: string;
|
||||
}
|
||||
|
||||
export class NodePaging {
|
||||
list: NodePagingList;
|
||||
}
|
||||
|
||||
export class NodePagingList {
|
||||
entries: MinimalNodeEntity[];
|
||||
}
|
||||
|
||||
export class MinimalNodeEntity {
|
||||
entry: MinimalNodeEntryEntity;
|
||||
}
|
||||
|
||||
export class MinimalNodeEntryEntity {
|
||||
id: string;
|
||||
parentId: string;
|
||||
name: string;
|
||||
nodeType: string;
|
||||
isFolder: boolean;
|
||||
isFile: boolean;
|
||||
modifiedAt: string;
|
||||
modifiedByUser: UserInfo;
|
||||
createdAt: string;
|
||||
createdByUser: UserInfo;
|
||||
content: ContentInfo;
|
||||
path: PathInfoEntity;
|
||||
}
|
||||
|
||||
export class UserInfo {
|
||||
displayName: string;
|
||||
id: string;
|
||||
}
|
||||
|
||||
export class ContentInfo {
|
||||
mimeType: string;
|
||||
mimeTypeName: string;
|
||||
sizeInBytes: number;
|
||||
encoding: string;
|
||||
}
|
||||
|
||||
export class PathInfoEntity {
|
||||
elements: PathElementEntity;
|
||||
isComplete: boolean;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export class PathElementEntity {
|
||||
id: string;
|
||||
name: string;
|
||||
}
|
@ -0,0 +1,120 @@
|
||||
/*!
|
||||
* @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 { Injectable } from 'angular2/core';
|
||||
import { Http, Response } from 'angular2/http';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
|
||||
import { AlfrescoSettingsService } from 'ng2-alfresco-core/services';
|
||||
import { NodePaging, MinimalNodeEntity } from './../models/document-library.model';
|
||||
|
||||
declare let AlfrescoApi: any;
|
||||
|
||||
/**
|
||||
* Internal service used by Document List component.
|
||||
*/
|
||||
@Injectable()
|
||||
export class AlfrescoService {
|
||||
|
||||
private _host: string = 'http://127.0.0.1:8080';
|
||||
private _baseUrlPath: string = '/alfresco/api/-default-/public/alfresco/versions/1';
|
||||
|
||||
constructor(private http: Http,
|
||||
private settings: AlfrescoSettingsService) {
|
||||
if (settings) {
|
||||
this._host = settings.host;
|
||||
}
|
||||
}
|
||||
|
||||
public get host(): string {
|
||||
return this._host;
|
||||
}
|
||||
|
||||
public set host(value: string) {
|
||||
this._host = value;
|
||||
}
|
||||
|
||||
private getBaseUrl(): string {
|
||||
return this.host + this._baseUrlPath;
|
||||
}
|
||||
|
||||
private getAlfrescoTicket() {
|
||||
return localStorage.getItem('token');
|
||||
}
|
||||
|
||||
private getAlfrescoClient() {
|
||||
let defaultClient = new AlfrescoApi.ApiClient();
|
||||
defaultClient.basePath = this.getBaseUrl();
|
||||
|
||||
// Configure HTTP basic authorization: basicAuth
|
||||
let basicAuth = defaultClient.authentications['basicAuth'];
|
||||
basicAuth.username = 'ROLE_TICKET';
|
||||
basicAuth.password = this.getAlfrescoTicket();
|
||||
|
||||
return defaultClient;
|
||||
}
|
||||
|
||||
private getNodesPromise(folder: string) {
|
||||
let alfrescoClient = this.getAlfrescoClient();
|
||||
let apiInstance = new AlfrescoApi.NodesApi(alfrescoClient);
|
||||
let nodeId = '-root-';
|
||||
let opts = {
|
||||
relativePath: folder,
|
||||
include: ['path']
|
||||
};
|
||||
return apiInstance.getNodeChildren(nodeId, opts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the folder node with the content.
|
||||
* @param folder Path to folder.
|
||||
* @returns {Observable<NodePaging>} Folder entity.
|
||||
*/
|
||||
getFolder(folder: string) {
|
||||
return Observable.fromPromise(this.getNodesPromise(folder))
|
||||
.map(res => <NodePaging> res)
|
||||
.do(data => console.log('Node data', data)) // eyeball results in the console
|
||||
.catch(this.handleError);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get thumbnail URL for the given document node.
|
||||
* @param document Node to get URL for.
|
||||
* @returns {string} URL address.
|
||||
*/
|
||||
getDocumentThumbnailUrl(document: MinimalNodeEntity) {
|
||||
return this.getContentUrl(document) + '/thumbnails/doclib?c=queue&ph=true&lastModified=1&alf_ticket=' + this.getAlfrescoTicket();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get content URL for the given node.
|
||||
* @param document Node to get URL for.
|
||||
* @returns {string} URL address.
|
||||
*/
|
||||
getContentUrl(document: MinimalNodeEntity) {
|
||||
return this._host +
|
||||
'/alfresco/service/api/node/workspace/SpacesStore/' +
|
||||
document.entry.id + '/content';
|
||||
}
|
||||
|
||||
private handleError(error: Response) {
|
||||
// in a real world app, we may send the error to some remote logging infrastructure
|
||||
// instead of just logging it to the console
|
||||
console.error(error);
|
||||
return Observable.throw(error || 'Server error');
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
/*!
|
||||
* @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,
|
||||
beforeEach
|
||||
} from 'angular2/testing';
|
||||
|
||||
import { DataActionHandler } from './../models/data-action.model';
|
||||
import { DocumentActionsService } from './document-actions.service';
|
||||
import { AlfrescoServiceMock } from '../assets/alfresco.service.mock';
|
||||
|
||||
describe('DocumentActionsService', () => {
|
||||
|
||||
let service: DocumentActionsService;
|
||||
|
||||
beforeEach(() => {
|
||||
let alfrescoServiceMock = new AlfrescoServiceMock();
|
||||
service = new DocumentActionsService(alfrescoServiceMock);
|
||||
});
|
||||
|
||||
it('should register default download action', () => {
|
||||
expect(service.getHandler('download')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('should register custom action handler', () => {
|
||||
let handler: DataActionHandler = function (obj: any) {};
|
||||
service.setHandler('<key>', handler);
|
||||
expect(service.getHandler('<key>')).toBe(handler);
|
||||
});
|
||||
|
||||
it('should not find handler that is not registered', () => {
|
||||
expect(service.getHandler('<missing>')).toBeNull();
|
||||
});
|
||||
|
||||
it('should be case insensitive for keys', () => {
|
||||
let handler: DataActionHandler = function (obj: any) {};
|
||||
service.setHandler('<key>', handler);
|
||||
expect(service.getHandler('<KEY>')).toBe(handler);
|
||||
|
||||
});
|
||||
});
|
@ -0,0 +1,72 @@
|
||||
/*!
|
||||
* @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 {Injectable} from 'angular2/core';
|
||||
|
||||
import { DataActionHandler } from './../models/data-action.model';
|
||||
import { AlfrescoService } from './alfresco.service';
|
||||
|
||||
@Injectable()
|
||||
export class DocumentActionsService {
|
||||
private handlers: { [id: string]: DataActionHandler; } = {};
|
||||
|
||||
constructor(private _alfrescoService: AlfrescoService) {
|
||||
this.setupActionHandlers();
|
||||
}
|
||||
|
||||
getHandler(key: string): DataActionHandler {
|
||||
if (key) {
|
||||
let lkey = key.toLowerCase();
|
||||
return this.handlers[lkey] || null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
setHandler(key: string, handler: DataActionHandler): void {
|
||||
if (key) {
|
||||
let lkey = key.toLowerCase();
|
||||
this.handlers[lkey] = handler;
|
||||
}
|
||||
}
|
||||
|
||||
private setupActionHandlers() {
|
||||
this.handlers['download'] = this.download.bind(this);
|
||||
|
||||
// todo: just for dev/demo purposes, to be replaced with real actions
|
||||
this.handlers['system1'] = this.handleStandardAction1.bind(this);
|
||||
this.handlers['system2'] = this.handleStandardAction2.bind(this);
|
||||
}
|
||||
|
||||
private handleStandardAction1(obj: any) {
|
||||
window.alert('standard document action 1');
|
||||
}
|
||||
|
||||
private handleStandardAction2(obj: any) {
|
||||
window.alert('standard document action 2');
|
||||
}
|
||||
|
||||
private download(obj: any) {
|
||||
if (this._alfrescoService && obj && !obj.isFolder) {
|
||||
let link = document.createElement('a');
|
||||
document.body.appendChild(link);
|
||||
link.setAttribute('download', 'download');
|
||||
link.href = this._alfrescoService.getContentUrl(obj);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/*!
|
||||
* @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,
|
||||
beforeEach
|
||||
} from 'angular2/testing';
|
||||
|
||||
import { FolderActionsService } from './folder-actions.service';
|
||||
import { DataActionHandler } from './../models/data-action.model';
|
||||
|
||||
describe('FolderActionsService', () => {
|
||||
|
||||
let service: FolderActionsService;
|
||||
|
||||
beforeEach(() => {
|
||||
service = new FolderActionsService();
|
||||
});
|
||||
|
||||
it('should register custom action handler', () => {
|
||||
let handler: DataActionHandler = function (obj: any) {};
|
||||
service.setHandler('<key>', handler);
|
||||
expect(service.getHandler('<key>')).toBe(handler);
|
||||
});
|
||||
|
||||
it('should not find handler that is not registered', () => {
|
||||
expect(service.getHandler('<missing>')).toBeNull();
|
||||
});
|
||||
|
||||
it('should be case insensitive for keys', () => {
|
||||
let handler: DataActionHandler = function (obj: any) {};
|
||||
service.setHandler('<key>', handler);
|
||||
expect(service.getHandler('<KEY>')).toBe(handler);
|
||||
|
||||
});
|
||||
|
||||
});
|
@ -0,0 +1,53 @@
|
||||
/*!
|
||||
* @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 {Injectable} from 'angular2/core';
|
||||
import { DataActionHandler } from './../models/data-action.model';
|
||||
|
||||
@Injectable()
|
||||
export class FolderActionsService {
|
||||
private handlers: { [id: string]: DataActionHandler; } = {};
|
||||
|
||||
constructor() {
|
||||
// todo: just for dev/demo purposes, to be replaced with real actions
|
||||
this.handlers['system1'] = this.handleStandardAction1.bind(this);
|
||||
this.handlers['system2'] = this.handleStandardAction2.bind(this);
|
||||
}
|
||||
|
||||
getHandler(key: string): DataActionHandler {
|
||||
if (key) {
|
||||
let lkey = key.toLowerCase();
|
||||
return this.handlers[lkey] || null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
setHandler(key: string, handler: DataActionHandler): void {
|
||||
if (key) {
|
||||
let lkey = key.toLowerCase();
|
||||
this.handlers[lkey] = handler;
|
||||
}
|
||||
}
|
||||
|
||||
private handleStandardAction1(document: any) {
|
||||
window.alert('standard folder action 1');
|
||||
}
|
||||
|
||||
private handleStandardAction2(document: any) {
|
||||
window.alert('standard folder action 2');
|
||||
}
|
||||
}
|
18
ng2-components/ng2-alfresco-datatable/tsconfig.json
Normal file
18
ng2-components/ng2-alfresco-datatable/tsconfig.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"module": "system",
|
||||
"moduleResolution": "node",
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"sourceMap": true,
|
||||
"removeComments": true,
|
||||
"declaration": true,
|
||||
"outDir": "dist"
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"typings/main",
|
||||
"typings/main.d.ts"
|
||||
]
|
||||
}
|
119
ng2-components/ng2-alfresco-datatable/tslint.json
Normal file
119
ng2-components/ng2-alfresco-datatable/tslint.json
Normal file
@ -0,0 +1,119 @@
|
||||
{
|
||||
"rules": {
|
||||
"align": [
|
||||
true,
|
||||
"parameters",
|
||||
"statements"
|
||||
],
|
||||
"ban": false,
|
||||
"class-name": true,
|
||||
"comment-format": [
|
||||
true,
|
||||
"check-space"
|
||||
],
|
||||
"curly": true,
|
||||
"eofline": true,
|
||||
"forin": true,
|
||||
"indent": [
|
||||
true,
|
||||
"spaces"
|
||||
],
|
||||
"interface-name": false,
|
||||
"jsdoc-format": true,
|
||||
"label-position": true,
|
||||
"label-undefined": true,
|
||||
"max-line-length": [
|
||||
true,
|
||||
140
|
||||
],
|
||||
"member-ordering": [
|
||||
true,
|
||||
"static-before-instance",
|
||||
"variables-before-functions"
|
||||
],
|
||||
"no-any": false,
|
||||
"no-arg": true,
|
||||
"no-bitwise": false,
|
||||
"no-conditional-assignment": true,
|
||||
"no-consecutive-blank-lines": false,
|
||||
"no-console": [
|
||||
true,
|
||||
"debug",
|
||||
"info",
|
||||
"time",
|
||||
"timeEnd",
|
||||
"trace"
|
||||
],
|
||||
"no-construct": true,
|
||||
"no-constructor-vars": false,
|
||||
"no-debugger": true,
|
||||
"no-duplicate-key": true,
|
||||
"no-duplicate-variable": true,
|
||||
"no-empty": false,
|
||||
"no-eval": true,
|
||||
"no-inferrable-types": false,
|
||||
"no-internal-module": true,
|
||||
"no-require-imports": true,
|
||||
"no-shadowed-variable": true,
|
||||
"no-switch-case-fall-through": true,
|
||||
"no-trailing-whitespace": true,
|
||||
"no-unreachable": true,
|
||||
"no-unused-expression": true,
|
||||
"no-unused-variable": true,
|
||||
"no-use-before-declare": true,
|
||||
"no-var-keyword": true,
|
||||
"no-var-requires": true,
|
||||
"object-literal-sort-keys": false,
|
||||
"one-line": [
|
||||
true,
|
||||
"check-open-brace",
|
||||
"check-catch",
|
||||
"check-else",
|
||||
"check-whitespace"
|
||||
],
|
||||
"quotemark": [
|
||||
true,
|
||||
"single",
|
||||
"avoid-escape"
|
||||
],
|
||||
"radix": true,
|
||||
"semicolon": true,
|
||||
"switch-default": true,
|
||||
"trailing-comma": [
|
||||
true,
|
||||
{
|
||||
"multiline": "never",
|
||||
"singleline": "never"
|
||||
}
|
||||
],
|
||||
"triple-equals": [
|
||||
true,
|
||||
"allow-null-check"
|
||||
],
|
||||
"typedef": false,
|
||||
"typedef-whitespace": [
|
||||
true,
|
||||
{
|
||||
"call-signature": "nospace",
|
||||
"index-signature": "nospace",
|
||||
"parameter": "nospace",
|
||||
"property-declaration": "nospace",
|
||||
"variable-declaration": "nospace"
|
||||
}
|
||||
],
|
||||
"use-strict": false,
|
||||
"variable-name": [
|
||||
true,
|
||||
"check-format",
|
||||
"allow-leading-underscore",
|
||||
"ban-keywords"
|
||||
],
|
||||
"whitespace": [
|
||||
true,
|
||||
"check-branch",
|
||||
"check-decl",
|
||||
"check-operator",
|
||||
"check-separator"
|
||||
]
|
||||
}
|
||||
}
|
6
ng2-components/ng2-alfresco-datatable/typings.json
Normal file
6
ng2-components/ng2-alfresco-datatable/typings.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"ambientDependencies": {
|
||||
"es6-shim": "github:DefinitelyTyped/DefinitelyTyped/es6-shim/es6-shim.d.ts#7de6c3dd94feaeb21f20054b9f30d5dabc5efabd",
|
||||
"jasmine": "github:DefinitelyTyped/DefinitelyTyped/jasmine/jasmine.d.ts#5c182b9af717f73146399c2485f70f1e2ac0ff2b"
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user