mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
6
.github/ISSUE_TEMPLATE.md
vendored
6
.github/ISSUE_TEMPLATE.md
vendored
@@ -12,11 +12,11 @@ Please ask before on our gitter channel https://gitter.im/Alfresco/alfresco-ng2-
|
||||
- [ ] Support request
|
||||
- [ ] Documentation
|
||||
```
|
||||
**Current behavior:**
|
||||
<!-- Describe the current behavior. -->
|
||||
**Current behaviour:**
|
||||
<!-- Describe the current behaviour. -->
|
||||
|
||||
**Expected behavior:**
|
||||
<!-- Describe the expected behavior. -->
|
||||
<!-- Describe the expected behaviour. -->
|
||||
|
||||
**Steps to reproduce the issue:**
|
||||
<!-- Describe the steps to reproduce the issue. -->
|
||||
|
4
.github/PULL_REQUEST_TEMPLATE.md
vendored
4
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -20,11 +20,11 @@
|
||||
[ ] Other... Please describe:
|
||||
```
|
||||
|
||||
**What is the current behavior?** (You can also link to an open issue here)
|
||||
**What is the current behaviour?** (You can also link to an open issue here)
|
||||
|
||||
|
||||
|
||||
**What is the new behavior?**
|
||||
**What is the new behaviour?**
|
||||
|
||||
|
||||
|
||||
|
@@ -12,7 +12,7 @@
|
||||
|
||||
## Installing
|
||||
|
||||
To correctly use this demo check that on your machine is running [Node](https://nodejs.org/en/) version 6.9.2 LTS or higher.
|
||||
To correctly use this demo check that on your machine is running [Node](https://nodejs.org/en/) version 5.x.x or higher.
|
||||
|
||||
```sh
|
||||
git clone https://github.com/Alfresco/alfresco-ng2-components.git
|
||||
@@ -26,7 +26,7 @@ npm install
|
||||
npm start
|
||||
```
|
||||
|
||||
This command compiles and starts the project in watch mode.
|
||||
This command compiles and starts the project in watch mode.
|
||||
Browser will automatically reload upon changes.
|
||||
Upon start you can navigate to `http://localhost:3000` with your preferred browser.
|
||||
|
||||
@@ -41,7 +41,7 @@ npm run build
|
||||
npm run start:dist
|
||||
```
|
||||
|
||||
This command builds broject in `production` mode.
|
||||
This command builds project in `production` mode.
|
||||
All output is placed to `dist` folder and can be served your preferred web server.
|
||||
You should need no additional files outside the `dist` folder.
|
||||
|
||||
@@ -81,4 +81,20 @@ Directory structure:
|
||||
│ └── fr.json
|
||||
```
|
||||
|
||||
## Custom-files
|
||||
|
||||
If you need to add custom files on your project you can add this files in the folders public
|
||||
|
||||
```
|
||||
.
|
||||
├── public/
|
||||
│ ├── images/
|
||||
│ ├── css/
|
||||
│ └── js/
|
||||
```
|
||||
|
||||
the public folder above wil be copied in the root of your project and you can refer to them for example as
|
||||
|
||||
* './images/custom_image.png'
|
||||
* './js/custom_script.js'
|
||||
* './css/custom_style.css'
|
||||
|
@@ -1,3 +0,0 @@
|
||||
#Windows Installation of *Alfresco Angular 2 Components* project
|
||||
|
||||
See https://github.com/Alfresco/alfresco-ng2-components/blob/master/Prerequisites.md
|
@@ -19,7 +19,7 @@
|
||||
<nav class="mdl-navigation mdl-layout--large-screen-only">
|
||||
<a class="mdl-navigation__link" data-automation-id="home" href="" routerLink="/">Home</a>
|
||||
<a class="mdl-navigation__link" data-automation-id="files" href="" routerLink="/files">DocumentList</a>
|
||||
<a class="mdl-navigation__link" data-automation-id="activiti" href="" routerLink="/activiti">Activiti</a>
|
||||
<a class="mdl-navigation__link" data-automation-id="activiti" href="" routerLink="/activiti">Process Services</a>
|
||||
<a class="mdl-navigation__link" data-automation-id="login" href="" routerLink="/login">Login</a>
|
||||
<a class="mdl-navigation__link" data-automation-id="settings" href="" routerLink="/settings">Settings</a>
|
||||
</nav>
|
||||
@@ -39,14 +39,14 @@
|
||||
<span class="flag-icon flag-icon-gb"></span>
|
||||
<label tabindex="0"> English</label>
|
||||
</a>
|
||||
<a class="mdl-navigation__link" (click)="changeLanguage('gr')">
|
||||
<span class="flag-icon flag-icon-gr"></span>
|
||||
<label tabindex="0"> Greek</label>
|
||||
</a>
|
||||
<a class="mdl-navigation__link" (click)="changeLanguage('it')">
|
||||
<span class="flag-icon flag-icon-it"></span>
|
||||
<label tabindex="0"> Italian</label>
|
||||
</a>
|
||||
<a class="mdl-navigation__link" (click)="changeLanguage('ru')">
|
||||
<span class="flag-icon flag-icon-ru"></span>
|
||||
<label tabindex="0"> Russian</label>
|
||||
</a>
|
||||
</nav>
|
||||
<span class="mdl-layout-title">Components</span>
|
||||
<nav class="mdl-navigation">
|
||||
|
@@ -43,13 +43,7 @@ export class AppComponent {
|
||||
this.setProvider();
|
||||
|
||||
if (translateService) {
|
||||
if (process.env.ENV === 'production') {
|
||||
translateService.addTranslationFolder('custom', 'i18n/custom-translation');
|
||||
translateService.addTranslationFolder('ng2-alfresco-login', 'i18n/custom-translation/alfresco-login');
|
||||
} else {
|
||||
translateService.addTranslationFolder('custom', 'custom-translation');
|
||||
translateService.addTranslationFolder('ng2-alfresco-login', 'custom-translation/alfresco-login');
|
||||
}
|
||||
translateService.addTranslationFolder('app', 'resources');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +69,7 @@ export class AppComponent {
|
||||
);
|
||||
}
|
||||
|
||||
navigateToLogin(){
|
||||
navigateToLogin() {
|
||||
this.router.navigate(['/login']);
|
||||
this.hideDrawer();
|
||||
}
|
||||
|
@@ -35,6 +35,7 @@ import { AnalyticsModule } from 'ng2-activiti-analytics';
|
||||
import { AppComponent } from './app.component';
|
||||
import { routing } from './app.routes';
|
||||
import { CustomEditorsModule } from './components/activiti/custom-editor/custom-editor.component';
|
||||
import { Editor3DModule } from 'ng2-3d-editor';
|
||||
|
||||
import {
|
||||
HomeComponent,
|
||||
@@ -71,7 +72,8 @@ import {
|
||||
ActivitiProcessListModule.forRoot(),
|
||||
UserInfoComponentModule.forRoot(),
|
||||
AnalyticsModule.forRoot(),
|
||||
CustomEditorsModule
|
||||
CustomEditorsModule,
|
||||
Editor3DModule.forRoot()
|
||||
],
|
||||
declarations: [
|
||||
AppComponent,
|
||||
@@ -94,4 +96,3 @@ import {
|
||||
bootstrap: [ AppComponent ]
|
||||
})
|
||||
export class AppModule { }
|
||||
|
||||
|
@@ -119,7 +119,10 @@
|
||||
<activiti-analytics *ngIf="report"
|
||||
[appId]="appId"
|
||||
[reportId]="report.id"
|
||||
(editReport)="onEditReport($event)">
|
||||
[hideParameters]="false"
|
||||
(editReport)="onEditReport($event)"
|
||||
(reportSaved)="onReportSaved()"
|
||||
(reportDeleted)="onReportDeleted()">
|
||||
</activiti-analytics>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -154,7 +154,7 @@ export class ActivitiDemoComponent implements AfterViewInit {
|
||||
}
|
||||
|
||||
onTaskFilterClick(event: FilterRepresentationModel) {
|
||||
if(event){
|
||||
if (event) {
|
||||
this.taskFilter = event;
|
||||
}
|
||||
}
|
||||
@@ -202,6 +202,21 @@ export class ActivitiDemoComponent implements AfterViewInit {
|
||||
this.analyticsreportlist.reload();
|
||||
}
|
||||
|
||||
onReportSaved() {
|
||||
this.analyticsreportlist.reload();
|
||||
}
|
||||
|
||||
onReportDeleted() {
|
||||
this.analyticsreportlist.reload();
|
||||
this.selectFirstElementInReportList();
|
||||
}
|
||||
|
||||
selectFirstElementInReportList() {
|
||||
if (!this.analyticsreportlist.isReportsEmpty()) {
|
||||
this.analyticsreportlist.selectReport(this.analyticsreportlist.reports[0]);
|
||||
}
|
||||
}
|
||||
|
||||
navigateStartProcess() {
|
||||
this.resetProcessFilters();
|
||||
this.reloadProcessFilters();
|
||||
|
@@ -35,6 +35,15 @@
|
||||
</template>
|
||||
-->
|
||||
</content-column>
|
||||
<content-column
|
||||
title="{{'DOCUMENT_LIST.COLUMNS.TAG' | translate}}"
|
||||
key="id"
|
||||
sortable="true"
|
||||
class="full-width ellipsis-cell">
|
||||
<template let-entry="$implicit">
|
||||
<alfresco-tag-node-list [nodeId]="entry.data.getValue(entry.row, entry.col)"></alfresco-tag-node-list>
|
||||
</template>
|
||||
</content-column>
|
||||
<content-column
|
||||
title="{{'DOCUMENT_LIST.COLUMNS.CREATED_BY' | translate}}"
|
||||
key="createdByUser.displayName"
|
||||
@@ -165,7 +174,13 @@
|
||||
<alfresco-viewer [(showViewer)]="fileShowed"
|
||||
[fileNodeId]="fileNodeId"
|
||||
[overlayMode]="true">
|
||||
<div class="mdl-spinner mdl-js-spinner is-active"></div>
|
||||
|
||||
<extension-viewer [supportedExtensions]="['obj','3DS']" #extension>
|
||||
<template let-urlFileContent="urlFileContent" let-extension="extension" >
|
||||
<threed-viewer [urlFile]="urlFileContent" [extension]="extension" ></threed-viewer>
|
||||
</template>
|
||||
</extension-viewer>
|
||||
|
||||
</alfresco-viewer>
|
||||
</div>
|
||||
|
||||
|
@@ -29,6 +29,13 @@
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
|
||||
.home--card__text {
|
||||
font-size: 16px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
|
||||
.home--feature-list {
|
||||
list-style: none;
|
||||
padding-left: 0;
|
||||
|
@@ -3,11 +3,11 @@
|
||||
<div class="mdl-card__title mdl-card--expand" routerLink="/files">
|
||||
<h2 class="mdl-card__title-text">
|
||||
<i class="material-icons home--card__icon">dvr</i>
|
||||
<span>DocumentList - ECM</span>
|
||||
<span class="home--card__text">DocumentList - Content Services</span>
|
||||
</h2>
|
||||
</div>
|
||||
<div class="mdl-card__supporting-text">
|
||||
Demonstrates multiple Alfresco ECM components used together to display the files of your ECM instance:
|
||||
Demonstrates multiple Alfresco Content Services components used together to display the files of your Content Services instance:
|
||||
<ul class="home--feature-list">
|
||||
<li>
|
||||
<i class="material-icons home--feature-list__icon">brightness_1</i>
|
||||
@@ -39,11 +39,11 @@
|
||||
<div class="mdl-card__title mdl-card--expand" routerLink="/activiti">
|
||||
<h2 class="mdl-card__title-text">
|
||||
<i class="material-icons home--card__icon">apps</i>
|
||||
<span>Activiti - BPM</span>
|
||||
<span class="home--card__text">Process Services</span>
|
||||
</h2>
|
||||
</div>
|
||||
<div class="mdl-card__supporting-text">
|
||||
Demonstrates multiple Alfresco BPM components used together to show your BPM process and tasks:
|
||||
Demonstrates multiple Alfresco Process Services components used together to show your Process Services process and tasks:
|
||||
<ul class="home--feature-list">
|
||||
<li>
|
||||
<i class="material-icons home--feature-list__icon">brightness_1</i>
|
||||
@@ -91,7 +91,7 @@
|
||||
<div class="mdl-card__title mdl-card--expand" routerLink="/datatable">
|
||||
<h2 class="mdl-card__title-text">
|
||||
<i class="material-icons home--card__icon">view_module</i>
|
||||
<span>DataTable-ECM&BPM</span>
|
||||
<span class="home--card__text">DataTable - Content Services & Process Services</span>
|
||||
</h2>
|
||||
</div>
|
||||
<div class="mdl-card__supporting-text">
|
||||
@@ -111,11 +111,11 @@
|
||||
<div class="mdl-card__title mdl-card--expand" routerLink="/uploader">
|
||||
<h2 class="mdl-card__title-text">
|
||||
<i class="material-icons home--card__icon">file_upload</i>
|
||||
<span>Uploader - ECM</span>
|
||||
<span class="home--card__text">Uploader - Content Services</span>
|
||||
</h2>
|
||||
</div>
|
||||
<div class="mdl-card__supporting-text">
|
||||
Basic table uploader component for the ECM and BPM:
|
||||
Basic table uploader component for the Content Services & Process Services:
|
||||
<ul class="home--feature-list">
|
||||
<li>
|
||||
<i class="material-icons home--feature-list__icon">brightness_1</i>
|
||||
@@ -131,11 +131,11 @@
|
||||
<div class="mdl-card__title mdl-card--expand" routerLink="/login">
|
||||
<h2 class="mdl-card__title-text">
|
||||
<i class="material-icons home--card__icon">account_circle</i>
|
||||
<span>Login - ECM & BPM</span>
|
||||
<span class="home--card__text">Login - Content Services & Process Services</span>
|
||||
</h2>
|
||||
</div>
|
||||
<div class="mdl-card__supporting-text">
|
||||
Login component for the ECM and BPM:
|
||||
Login component for the Content Services and Process Services:
|
||||
<ul class="home--feature-list">
|
||||
<li>
|
||||
<i class="material-icons home--feature-list__icon">brightness_1</i>
|
||||
@@ -151,11 +151,11 @@
|
||||
<div class="mdl-card__title mdl-card--expand" routerLink="/webscript">
|
||||
<h2 class="mdl-card__title-text">
|
||||
<i class="material-icons home--card__icon">extension</i>
|
||||
<span>Webscript - ECM</span>
|
||||
<span class="home--card__text">Webscript - Content Services</span>
|
||||
</h2>
|
||||
</div>
|
||||
<div class="mdl-card__supporting-text">
|
||||
Displays and creates webscripts in your ECM instance:
|
||||
Displays and creates webscripts in your Content Services instance:
|
||||
<ul class="home--feature-list">
|
||||
<li>
|
||||
<i class="material-icons home--feature-list__icon">brightness_1</i>
|
||||
@@ -171,11 +171,11 @@
|
||||
<div class="mdl-card__title mdl-card--expand" routerLink="/tag">
|
||||
<h2 class="mdl-card__title-text">
|
||||
<i class="material-icons home--card__icon">local_offer</i>
|
||||
<span>Tag - ECM</span>
|
||||
<span class="home--card__text">Tag - Content Services</span>
|
||||
</h2>
|
||||
</div>
|
||||
<div class="mdl-card__supporting-text">
|
||||
Displays and adds tags to the node of your ECM instance:
|
||||
Displays and adds tags to the node of your Content Services instance:
|
||||
<ul class="home--feature-list">
|
||||
<li>
|
||||
<i class="material-icons home--feature-list__icon">brightness_1</i>
|
||||
|
@@ -23,6 +23,7 @@
|
||||
.toggle {
|
||||
width: 120px;
|
||||
margin: 20px;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
@media (min-width: 721px) {
|
||||
|
@@ -5,14 +5,14 @@
|
||||
<label for="switch1" class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
|
||||
<input type="checkbox" id="switch1" [checked]="isECM" class="mdl-switch__input"
|
||||
(click)="toggleECM()">
|
||||
<span class="mdl-switch__label">ECM</span>
|
||||
<span class="mdl-switch__label">Content Services</span>
|
||||
</label>
|
||||
</p>
|
||||
<p class="toggle">
|
||||
<label for="switch2" class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
|
||||
<input type="checkbox" id="switch2" [checked]="isBPM" class="mdl-switch__input"
|
||||
(click)="toggleBPM()">
|
||||
<span class="mdl-switch__label">BPM</span>
|
||||
<span class="mdl-switch__label">Process Services</span>
|
||||
</label>
|
||||
</p>
|
||||
<p class="toggle">
|
||||
@@ -49,14 +49,14 @@
|
||||
<label for="switch1-mobile" class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
|
||||
<input type="checkbox" id="switch1-mobile" [checked]="isECM" class="mdl-switch__input"
|
||||
(click)="toggleECM()">
|
||||
<span class="mdl-switch__label">ECM</span>
|
||||
<span class="mdl-switch__label">Content Services</span>
|
||||
</label>
|
||||
</p>
|
||||
<p>
|
||||
<label for="switch2-mobile" class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
|
||||
<input type="checkbox" id="switch2-mobile" [checked]="isBPM" class="mdl-switch__input"
|
||||
(click)="toggleBPM()">
|
||||
<span class="mdl-switch__label">BPM</span>
|
||||
<span class="mdl-switch__label">Process Services</span>
|
||||
</label>
|
||||
</p>
|
||||
<p>
|
||||
|
@@ -17,7 +17,6 @@
|
||||
|
||||
import { Component } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { MinimalNodeEntity } from 'alfresco-js-api';
|
||||
|
||||
@Component({
|
||||
selector: 'search-component',
|
||||
|
@@ -7,7 +7,7 @@
|
||||
</div>
|
||||
<div class="mdl-card__actions mdl-card--border">
|
||||
<div class="mdl-card__supporting-text">
|
||||
ECM host URL configuration
|
||||
Content Services host URL configuration
|
||||
</div>
|
||||
<nav class="mdl-navigation">
|
||||
<div class="icon material-icons icon-margin">link</div>
|
||||
@@ -16,7 +16,7 @@
|
||||
</nav>
|
||||
|
||||
<div class="mdl-card__supporting-text">
|
||||
BPM host URL configuration
|
||||
Process Services host URL configuration
|
||||
</div>
|
||||
<nav class="mdl-navigation">
|
||||
<div class="icon material-icons icon-margin">link</div>
|
||||
|
@@ -62,3 +62,4 @@ if (process.env.ENV === 'production') {
|
||||
}
|
||||
|
||||
require('pdfjs-dist/web/pdf_viewer.js');
|
||||
require('three/build/three.min.js');
|
||||
|
@@ -9,13 +9,13 @@ var CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||
|
||||
const rootPath = helpers.root('node_modules');
|
||||
|
||||
let pattern = '+(alfresco-js-api|ng2-alfresco|ng2-activiti)*';
|
||||
let options = {
|
||||
var pattern = '+(alfresco-js-api|ng2-alfresco|ng2-activiti)*';
|
||||
var options = {
|
||||
cwd: rootPath,
|
||||
realpath: true
|
||||
};
|
||||
|
||||
let alfrescoLibs = glob.sync(pattern, options);
|
||||
var alfrescoLibs = glob.sync(pattern, options);
|
||||
// console.dir(alfrescoLibs);
|
||||
|
||||
module.exports = {
|
||||
@@ -159,42 +159,15 @@ module.exports = {
|
||||
to: 'js/material.min.js',
|
||||
flatten: true
|
||||
}, {
|
||||
context: 'public',
|
||||
from: 'css/material.orange-blue.min.css',
|
||||
to: 'css/material.orange-blue.min.css',
|
||||
flatten: true
|
||||
}, {
|
||||
context: 'node_modules',
|
||||
from: 'material-design-icons/iconfont/',
|
||||
to: 'css/iconfont/',
|
||||
flatten: true
|
||||
}, {
|
||||
context: 'public',
|
||||
from: 'js/typedarray.js',
|
||||
to: 'js/typedarray.js',
|
||||
flatten: true
|
||||
}, {
|
||||
context: 'public',
|
||||
from: 'js/Blob.js',
|
||||
to: 'js/Blob.js',
|
||||
flatten: true
|
||||
}, {
|
||||
context: 'public',
|
||||
from: 'js/formdata.js',
|
||||
to: 'js/formdata.js',
|
||||
flatten: true
|
||||
}, {
|
||||
context: 'public',
|
||||
from: 'js/promisePolyfill.js',
|
||||
to: 'js/promisePolyfill.js',
|
||||
flatten: true
|
||||
}, {
|
||||
context: 'public',
|
||||
from: 'css/muli-font.css',
|
||||
to: 'css/muli-font.css',
|
||||
flatten: true
|
||||
from: '',
|
||||
to: ''
|
||||
}
|
||||
|
||||
]),
|
||||
|
||||
new webpack.optimize.CommonsChunkPlugin({
|
||||
|
@@ -25,9 +25,9 @@ module.exports = webpackMerge(commonConfig, {
|
||||
to: 'pdf.worker.js'
|
||||
},
|
||||
{
|
||||
context: 'custom-translation',
|
||||
context: 'resources/i18n',
|
||||
from: '**/*.json',
|
||||
to: 'i18n/custom-translation'
|
||||
to: 'resources/i18n'
|
||||
},
|
||||
// Copy i18n folders for all modules with ng2-alfresco- prefix
|
||||
{
|
||||
|
@@ -40,15 +40,15 @@ module.exports = webpackMerge(commonConfig, {
|
||||
|
||||
// Reference: http://webpack.github.io/docs/list-of-plugins.html#uglifyjsplugin
|
||||
// Minify all javascript, switch loaders to minimizing mode
|
||||
new webpack.optimize.UglifyJsPlugin({ // https://github.com/angular/angular/issues/10618
|
||||
mangle: {
|
||||
keep_fnames: true
|
||||
},
|
||||
compressor: {
|
||||
screw_ie8: true,
|
||||
warnings: false
|
||||
}
|
||||
}),
|
||||
// new webpack.optimize.UglifyJsPlugin({
|
||||
// mangle: {
|
||||
// keep_fnames: true
|
||||
// },
|
||||
// compressor: {
|
||||
// screw_ie8: true,
|
||||
// warnings: false
|
||||
// }
|
||||
// }),
|
||||
|
||||
// Extract css files
|
||||
// Reference: https://github.com/webpack/extract-text-webpack-plugin
|
||||
@@ -66,9 +66,9 @@ module.exports = webpackMerge(commonConfig, {
|
||||
to: 'pdf.worker.js'
|
||||
},
|
||||
{
|
||||
context: 'custom-translation',
|
||||
context: 'resources/i18n',
|
||||
from: '**/*.json',
|
||||
to: 'i18n/custom-translation'
|
||||
to: 'resources/i18n'
|
||||
},
|
||||
// Copy i18n folders for all modules with ng2-alfresco- prefix
|
||||
{
|
||||
|
@@ -4,13 +4,13 @@ var glob = require('glob');
|
||||
|
||||
const rootPath = helpers.root('node_modules');
|
||||
|
||||
let pattern = '+(alfresco-js-api|ng2-alfresco|ng2-activiti)*';
|
||||
let options = {
|
||||
var pattern = '+(alfresco-js-api|ng2-alfresco|ng2-activiti)*';
|
||||
var options = {
|
||||
cwd: rootPath,
|
||||
realpath: true
|
||||
};
|
||||
|
||||
let alfrescoLibs = glob.sync(pattern, options);
|
||||
var alfrescoLibs = glob.sync(pattern, options);
|
||||
|
||||
module.exports = {
|
||||
devtool: 'inline-source-map',
|
||||
|
@@ -1,29 +0,0 @@
|
||||
{
|
||||
"LOGIN": {
|
||||
"LOGO": "Alfresco",
|
||||
"LABEL": {
|
||||
"LOGIN": "Login",
|
||||
"USERNAME": "Username",
|
||||
"PASSWORD": "Password",
|
||||
"REMEMBER": "Remember"
|
||||
},
|
||||
"MESSAGES": {
|
||||
"USERNAME-REQUIRED": "Required",
|
||||
"USERNAME-MIN": "Your username needs to be at least {{customMinLenght}} characters.",
|
||||
"PASSWORD-REQUIRED": "Enter your password to sign in",
|
||||
"LOGIN-ERROR-CREDENTIALS": "You have entered an invalid username or password",
|
||||
"LOGIN-ERROR-PROVIDERS": "Providers cannot be undefined",
|
||||
"LOGIN-SUCCESS": "Login successful",
|
||||
"LOGIN-ERROR-CORS": "CORS exception, check your server configuration",
|
||||
"LOGIN-ERROR-CSRF": "CSRF exception, set [disableCsrf]=\"true\" in alfresco-login component",
|
||||
"LOGIN-ECM-LICENSE": "The ECM is in read-only mode"
|
||||
},
|
||||
"BUTTON": {
|
||||
"LOGIN": "SIGN IN"
|
||||
},
|
||||
"ACTION": {
|
||||
"HELP": "NEED HELP?",
|
||||
"REGISTER": "REGISTER"
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,28 +0,0 @@
|
||||
{
|
||||
"LOGIN": {
|
||||
"LABEL": {
|
||||
"LOGIN": "Autenticazione",
|
||||
"USERNAME": "Nome utente",
|
||||
"PASSWORD": "Password",
|
||||
"REMEMBER": "Ricordami"
|
||||
},
|
||||
"MESSAGES": {
|
||||
"USERNAME-REQUIRED": "Campo obbligatorio",
|
||||
"USERNAME-MIN": "Inserire un nome utente di minimo 4 caratteri.",
|
||||
"PASSWORD-REQUIRED": "Campo obbligatorio",
|
||||
"LOGIN-ERROR-CREDENTIALS": "Nome utente o password non validi",
|
||||
"LOGIN-ERROR-PROVIDERS": "Providers non può essere nullo",
|
||||
"LOGIN-SUCCESS": "Login effettuata con successo",
|
||||
"LOGIN-ERROR-CORS": "CORS exception, controlla le configurazioni del tuo server",
|
||||
"LOGIN-ERROR-CSRF": "CSRF exception, set [disableCsrf]=\"true\" in alfresco-login component",
|
||||
"LOGIN-ECM-LICENSE": "l'ECM e' in read-only mode"
|
||||
},
|
||||
"BUTTON": {
|
||||
"LOGIN": "Accedi"
|
||||
},
|
||||
"ACTION": {
|
||||
"HELP": "BISOGNO DI AIUTO?",
|
||||
"REGISTER": "REGISTRATI"
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "Alfresco-Angular2-Demo",
|
||||
"description": "Demo shell for Alfresco Angular2 components",
|
||||
"version": "1.1.0",
|
||||
"version": "1.2.0",
|
||||
"author": "Alfresco Software, Ltd.",
|
||||
"scripts": {
|
||||
"clean": "npm install rimraf && npm run clean-build && rimraf dist node_modules typings dist",
|
||||
@@ -9,10 +9,10 @@
|
||||
"start:dist": "wsrv -s dist/ -p 3000 -a 0.0.0.0",
|
||||
"clean-build": "rimraf 'app/{,**/}**.js' 'app/{,**/}**.js.map' 'app/{,**/}**.d.ts'",
|
||||
"test": "karma start",
|
||||
"build": "npm run server-versions && rimraf dist && webpack --config config/webpack.prod.js --progress --profile --bail",
|
||||
"build": "npm run tslint && npm run server-versions && rimraf dist && webpack --config config/webpack.prod.js --progress --profile --bail",
|
||||
"server-versions": "rimraf versions.json && npm list --depth=0 --json=true --prod=true > versions.json || exit 0",
|
||||
"aws": "node app.js",
|
||||
"tslint": "tslint -c tslint.json *.ts && tslint -c tslint.json 'app/{,**/}**.ts'",
|
||||
"tslint": "tslint -c tslint.json *.ts && tslint -c tslint.json 'app/{,**/}**.ts' -e 'app/vendor.ts' -e 'app/polyfills.ts' ",
|
||||
"licensecheck": "license-check"
|
||||
},
|
||||
"repository": {
|
||||
@@ -78,27 +78,28 @@
|
||||
"ng2-charts": "1.1.0",
|
||||
"raphael": "^2.2.6",
|
||||
"md-date-time-picker": "^2.2.0",
|
||||
"alfresco-js-api": "~1.1.0",
|
||||
"ng2-activiti-analytics": "1.1.0",
|
||||
"ng2-alfresco-core": "1.1.0",
|
||||
"ng2-alfresco-datatable": "1.1.0",
|
||||
"ng2-alfresco-documentlist": "1.1.0",
|
||||
"ng2-alfresco-login": "1.1.0",
|
||||
"ng2-alfresco-search": "1.1.0",
|
||||
"ng2-alfresco-upload": "1.1.0",
|
||||
"ng2-alfresco-viewer": "1.1.0",
|
||||
"ng2-activiti-form": "1.1.0",
|
||||
"ng2-activiti-tasklist": "1.1.0",
|
||||
"ng2-alfresco-userinfo": "1.1.0",
|
||||
"ng2-activiti-processlist": "1.1.0",
|
||||
"ng2-alfresco-webscript": "1.1.0",
|
||||
"ng2-alfresco-tag": "1.1.0",
|
||||
"alfresco-js-api": "~1.2.0",
|
||||
"ng2-3d-editor": "0.0.15",
|
||||
"ng2-activiti-analytics": "1.2.0",
|
||||
"ng2-alfresco-core": "1.2.0",
|
||||
"ng2-alfresco-datatable": "1.2.0",
|
||||
"ng2-alfresco-documentlist": "1.2.0",
|
||||
"ng2-alfresco-login": "1.2.0",
|
||||
"ng2-alfresco-search": "1.2.0",
|
||||
"ng2-alfresco-upload": "1.2.0",
|
||||
"ng2-alfresco-viewer": "1.2.0",
|
||||
"ng2-activiti-form": "1.2.0",
|
||||
"ng2-activiti-tasklist": "1.2.0",
|
||||
"ng2-alfresco-userinfo": "1.2.0",
|
||||
"ng2-activiti-processlist": "1.2.0",
|
||||
"ng2-alfresco-webscript": "1.2.0",
|
||||
"ng2-alfresco-tag": "1.2.0",
|
||||
"dialog-polyfill": "^0.4.3",
|
||||
"element.scrollintoviewifneeded-polyfill": "^1.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jasmine": "^2.5.35",
|
||||
"@types/node": "^6.0.45",
|
||||
"@types/jasmine": "2.5.35",
|
||||
"@types/node": "6.0.45",
|
||||
"angular2-template-loader": "^0.6.0",
|
||||
"awesome-typescript-loader": "^2.2.4",
|
||||
"classlist-polyfill": "^1.0.3",
|
||||
|
@@ -4,6 +4,7 @@
|
||||
"DOCUMENT_LIST": {
|
||||
"COLUMNS": {
|
||||
"DISPLAY_NAME": "Display name",
|
||||
"TAG": "Tag",
|
||||
"CREATED_BY": "Created by",
|
||||
"CREATED_ON": "Created on"
|
||||
},
|
@@ -4,6 +4,7 @@
|
||||
"DOCUMENT_LIST": {
|
||||
"COLUMNS": {
|
||||
"DISPLAY_NAME": "Mostra name",
|
||||
"TAG": "Tag",
|
||||
"CREATED_BY": "Creato da",
|
||||
"CREATED_ON": "Creato il"
|
||||
},
|
@@ -3,7 +3,6 @@
|
||||
"align": [
|
||||
true,
|
||||
"parameters",
|
||||
"arguments",
|
||||
"statements"
|
||||
],
|
||||
"ban": false,
|
||||
@@ -29,15 +28,14 @@
|
||||
],
|
||||
"member-ordering": [
|
||||
true,
|
||||
"public-before-private",
|
||||
"static-before-instance",
|
||||
"variables-before-functions"
|
||||
],
|
||||
"no-any": false,
|
||||
"no-arg": true,
|
||||
"no-bitwise": true,
|
||||
"no-bitwise": false,
|
||||
"no-conditional-assignment": true,
|
||||
"no-consecutive-blank-lines": false,
|
||||
"no-consecutive-blank-lines": true,
|
||||
"no-console": [
|
||||
true,
|
||||
"debug",
|
||||
@@ -51,7 +49,7 @@
|
||||
"no-debugger": true,
|
||||
"no-duplicate-key": true,
|
||||
"no-duplicate-variable": true,
|
||||
"no-empty": true,
|
||||
"no-empty": false,
|
||||
"no-eval": true,
|
||||
"no-inferrable-types": false,
|
||||
"no-internal-module": true,
|
||||
@@ -64,7 +62,7 @@
|
||||
"no-unused-variable": true,
|
||||
"no-use-before-declare": true,
|
||||
"no-var-keyword": true,
|
||||
"no-var-requires": false,
|
||||
"no-var-requires": true,
|
||||
"object-literal-sort-keys": false,
|
||||
"one-line": [
|
||||
true,
|
||||
|
@@ -104,15 +104,14 @@ Follow the 3 steps below:
|
||||
- ng2-activiti-diagrams
|
||||
- ng2-activiti-analytics
|
||||
|
||||
Please refer to the following example file: [systemjs.config.js](demo/systemjs
|
||||
.config.js) .
|
||||
Please refer to the following example file: [systemjs.config.js](demo/systemjs.config.js) .
|
||||
|
||||
## Basic usage example Activiti Analytics List
|
||||
|
||||
The component shows the list of all the available reports
|
||||
|
||||
```html
|
||||
<analytics-report-list></analytics-report-list>
|
||||
<analytics-report-list [layoutType]="'LIST'"></analytics-report-list>
|
||||
```
|
||||
|
||||
Usage example of this component :
|
||||
@@ -132,7 +131,7 @@ import { AnalyticsModule } from 'ng2-activiti-analytics';
|
||||
<div class="page-content">
|
||||
<div class="mdl-grid">
|
||||
<div class="mdl-cell mdl-cell--8-col task-column mdl-shadow--2dp">
|
||||
<analytics-report-list></analytics-report-list>
|
||||
<analytics-report-list [layoutType]="'LIST'"></analytics-report-list>
|
||||
</div>
|
||||
</div>
|
||||
</div>`
|
||||
@@ -179,7 +178,9 @@ platformBrowserDynamic().bootstrapModule(AppModule);
|
||||
|
||||
#### Options
|
||||
|
||||
No options.
|
||||
| Name | Type | Required | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `layoutType` | {string} | required | Define the layout of the apps. There are two possible values: GRID or LIST. LIST is the default value|
|
||||
|
||||
## Basic usage example Activiti Analytics
|
||||
|
||||
@@ -206,7 +207,7 @@ import { AnalyticsModule } from 'ng2-activiti-analytics';
|
||||
<div class="page-content">
|
||||
<div class="mdl-grid">
|
||||
<div class="mdl-cell mdl-cell--8-col task-column mdl-shadow--2dp">
|
||||
<activiti-analytics [appId]="1001" [reportId]="2006"></activiti-analytics>
|
||||
<activiti-analytics [appId]="1001" [reportId]="2006" [hideParameters]="false"></activiti-analytics>
|
||||
</div>
|
||||
</div>
|
||||
</div>`
|
||||
@@ -249,6 +250,8 @@ platformBrowserDynamic().bootstrapModule(AppModule);
|
||||
| --- | --- |
|
||||
|`onSuccess` | The event is emitted when the report parameters are loaded |
|
||||
|`onError` | The event is emitted when an error occur during the loading |
|
||||
|`reportSaved` | The event is emitted when a report is saved |
|
||||
|`reportDeleted` | The event is emitted when a report is deleted |
|
||||
|
||||
#### Options
|
||||
|
||||
@@ -256,8 +259,40 @@ platformBrowserDynamic().bootstrapModule(AppModule);
|
||||
| --- | --- |
|
||||
|`appId` | The application id |
|
||||
|`reportId` | The report id |
|
||||
|`hideParameters` | Boolean to hide or show the analytics parameters |
|
||||
|`debug` | Flag to enable or disable the Form values in the console log |
|
||||
|
||||
You can also use the activiti analytic component to show straight away the charts without show the parameters setting the hideParameters to true
|
||||
|
||||
```html
|
||||
<activiti-analytics [appId]="appId" [reportId]="reportId" [hideParameters]="true"></activiti-analytics>
|
||||
```
|
||||
|
||||

|
||||
|
||||
## Basic usage example Analytics Generator
|
||||
|
||||
The component generate and show the charts
|
||||
|
||||
```html
|
||||
<activiti-analytics-generator [reportId]="reportId" [reportParamQuery]="reportParamQuery"></activiti-analytics>
|
||||
```
|
||||
|
||||
#### Events
|
||||
|
||||
| Name | Description |
|
||||
| --- | --- |
|
||||
|`onSuccess` | The event is emitted when the charts are loaded |
|
||||
|`onError` | The event is emitted when an error occur during the loading |
|
||||
|
||||
#### Options
|
||||
|
||||
| Name | Description |
|
||||
| --- | --- |
|
||||
|`reportId` | The report id |
|
||||
|`reportParamQuery` | The object contains all the parameters that the report needs |
|
||||
|
||||
|
||||
## Build from sources
|
||||
|
||||
Alternatively you can build component from sources with the following commands:
|
||||
|
@@ -12,6 +12,7 @@
|
||||
"server": "wsrv -o -s -l",
|
||||
"build": "npm run tslint && npm run clean-build && npm run tsc",
|
||||
"build:w": "npm run tslint && rimraf dist && npm run tsc:w",
|
||||
"travis": "npm link ng2-alfresco-core ng2-activiti-diagrams",
|
||||
"tsc": "tsc",
|
||||
"tsc:w": "tsc -w",
|
||||
"tslint": "tslint -c tslint.json *.ts && tslint -c tslint.json src/{,**/}**.ts -e '{,**/}**.d.ts'"
|
||||
@@ -58,10 +59,10 @@
|
||||
"moment": "2.15.1",
|
||||
"raphael": "^2.2.6",
|
||||
"ng2-translate": "2.5.0",
|
||||
"alfresco-js-api": "~1.1.0",
|
||||
"ng2-alfresco-core": "1.1.0",
|
||||
"ng2-activiti-diagrams": "1.1.0",
|
||||
"ng2-activiti-analytics": "^1.1.0"
|
||||
"alfresco-js-api": "~1.2.0",
|
||||
"ng2-alfresco-core": "1.2.0",
|
||||
"ng2-activiti-diagrams": "1.2.0",
|
||||
"ng2-activiti-analytics": "1.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jasmine": "^2.2.33",
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 69 KiB |
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "ng2-activiti-analytics",
|
||||
"description": "Activiti Angular2 Analytics Component",
|
||||
"version": "1.1.0",
|
||||
"version": "1.2.0",
|
||||
"author": "Alfresco Software, Ltd.",
|
||||
"scripts": {
|
||||
"clean": "npm install rimraf && npm run clean-build && rimraf dist node_modules typings",
|
||||
@@ -62,14 +62,14 @@
|
||||
"ng2-charts": "1.1.0",
|
||||
"moment": "2.15.1",
|
||||
"raphael": "^2.2.6",
|
||||
"alfresco-js-api": "~1.1.0",
|
||||
"alfresco-js-api": "~1.2.0",
|
||||
"ng2-translate": "2.5.0",
|
||||
"ng2-alfresco-core": "1.1.0",
|
||||
"ng2-activiti-diagrams": "1.1.0"
|
||||
"ng2-alfresco-core": "1.2.0",
|
||||
"ng2-activiti-diagrams": "1.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jasmine": "^2.2.33",
|
||||
"@types/node": "^6.0.42",
|
||||
"@types/jasmine": "2.5.35",
|
||||
"@types/node": "6.0.45",
|
||||
"autoprefixer": "^6.5.4",
|
||||
"concurrently": "^2.2.0",
|
||||
"cpx": "1.3.1",
|
||||
|
@@ -139,6 +139,13 @@ export var reportDefParamTask = {
|
||||
'definition': '{ "parameters" :[{"id":"taskName","name":null,"nameKey":null,"type":"task","value":null,"dependsOn":"processDefinitionId"}]}'
|
||||
};
|
||||
|
||||
export var reportNoParameterDefinitions = {
|
||||
'id': 2006,
|
||||
'name': 'Fake Task service level agreement',
|
||||
'created': '2016-10-05T15:39:40.222+0000',
|
||||
'definition': '{ "parameters" : []}'
|
||||
};
|
||||
|
||||
export var reportDefParamTaskOptions = ['Fake task name 1', 'Fake task name 2'];
|
||||
|
||||
export var fieldProcessDef = new ReportParameterDetailsModel(
|
||||
|
@@ -3,3 +3,8 @@
|
||||
.analytics-row__entry {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.report-icons {
|
||||
margin: 20px 20px 20px 20px;
|
||||
float: right;
|
||||
}
|
||||
|
@@ -1,9 +1,18 @@
|
||||
<div *ngIf="reports">
|
||||
<div *ngFor="let report of reports">
|
||||
<h4>{{report.title}}</h4>
|
||||
<div class="report-icons">
|
||||
<button mdTooltip="{{report.title}}" (click)="selectCurrent(idx)"
|
||||
[class.mdl-button--accent]="isCurrent(idx)"
|
||||
class="mdl-button mdl-js-button"
|
||||
*ngFor="let report of reports; let idx = index">
|
||||
<i class="material-icons">{{report.icon}}</i>
|
||||
</button>
|
||||
</div>
|
||||
<div style="clear: both"> </div>
|
||||
<div *ngFor="let report of reports; let idx = index">
|
||||
<div [ngSwitch]="report.type">
|
||||
<div *ngSwitchCase="'pie'">
|
||||
<div class="col-md-6">
|
||||
<div class="col-md-6" *ngIf="isCurrent(idx)">
|
||||
<h4>{{report.title}}</h4>
|
||||
<div *ngIf="!report.hasData()">{{'ANALYTICS.MESSAGES.NO-DATA-FOUND' | translate}}</div>
|
||||
<div *ngIf="report.hasData()">
|
||||
<div *ngIf="report.hasZeroValues()">{{'ANALYTICS.MESSAGES.ZERO-DATA-FOUND' | translate}}</div>
|
||||
@@ -14,44 +23,51 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngSwitchCase="'table'">
|
||||
<div *ngIf="!report.hasDatasets()">{{'ANALYTICS.MESSAGES.NO-DATA-FOUND' | translate}}</div>
|
||||
<div [attr.id]="'chart-table-' + report.id" *ngIf="report.hasDatasets()">
|
||||
<table class="table table-responsive table-condensed" style="width: 100%">
|
||||
<tr>
|
||||
<th *ngFor="let label of report.labels">{{label | translate}}</th>
|
||||
</tr>
|
||||
<tr *ngFor="let rows of report.datasets" style="text-align: center;">
|
||||
<td *ngFor="let row of rows">{{row | translate }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div *ngSwitchCase="'table'" >
|
||||
<div *ngIf="isCurrent(idx)">
|
||||
<h4>{{report.title}}</h4>
|
||||
<div *ngIf="!report.hasDatasets()">{{'ANALYTICS.MESSAGES.NO-DATA-FOUND' | translate}}</div>
|
||||
<div [attr.id]="'chart-table-' + report.id" *ngIf="report.hasDatasets()">
|
||||
<table class="table table-responsive table-condensed" style="width: 80%;margin-left: 20px">
|
||||
<tr>
|
||||
<th *ngFor="let label of report.labels">{{label | translate}}</th>
|
||||
</tr>
|
||||
<tr *ngFor="let rows of report.datasets">
|
||||
<td *ngFor="let row of rows">{{row | translate }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngSwitchCase="'masterDetailTable'">
|
||||
<div *ngIf="!report.hasDatasets()">{{'ANALYTICS.MESSAGES.NO-DATA-FOUND' | translate}}</div>
|
||||
<div [attr.id]="'chart-master-detail-table-' + report.id" *ngIf="report.hasDatasets()">
|
||||
<table class="table table-responsive table-condensed" style="width: 100%">
|
||||
<tr>
|
||||
<th *ngFor="let label of report.labels">{{label | translate}}</th>
|
||||
</tr>
|
||||
<tr *ngFor="let rows of report.datasets" class="analytics-row__entry" style="text-align: center;">
|
||||
<td *ngFor="let row of rows" (click)="toggleDetailsTable()">{{row | translate }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div [attr.id]="'chart-master-detail-' + report.id" *ngIf="isShowDetails()">
|
||||
<table class="table table-responsive table-condensed" style="width: 100%">
|
||||
<tr>
|
||||
<th *ngFor="let label of report.detailsTable.labels">{{label | translate}}</th>
|
||||
</tr>
|
||||
<tr *ngFor="let rows of report.detailsTable.datasets" style="text-align: center;">
|
||||
<td *ngFor="let row of rows">{{row | translate }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div *ngSwitchCase="'masterDetailTable'" >
|
||||
<div *ngIf="isCurrent(idx)">
|
||||
<h4>{{report.title}}</h4>
|
||||
<div *ngIf="!report.hasDatasets()">{{'ANALYTICS.MESSAGES.NO-DATA-FOUND' | translate}}</div>
|
||||
<div [attr.id]="'chart-master-detail-table-' + report.id" *ngIf="report.hasDatasets()">
|
||||
<table class="table table-responsive table-condensed" style="width: 100%">
|
||||
<tr>
|
||||
<th *ngFor="let label of report.labels">{{label | translate}}</th>
|
||||
</tr>
|
||||
<tr *ngFor="let rows of report.datasets" class="analytics-row__entry">
|
||||
<td *ngFor="let row of rows" (click)="toggleDetailsTable()">{{row | translate }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div [attr.id]="'chart-master-detail-' + report.id" *ngIf="isShowDetails()">
|
||||
<table class="table table-responsive table-condensed" style="width: 100%">
|
||||
<tr>
|
||||
<th *ngFor="let label of report.detailsTable.labels">{{label | translate}}</th>
|
||||
</tr>
|
||||
<tr *ngFor="let rows of report.detailsTable.datasets">
|
||||
<td *ngFor="let row of rows">{{row | translate }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngSwitchCase="'bar'">
|
||||
<div class="col-md-6">
|
||||
<div class="col-md-6" *ngIf="isCurrent(idx)">
|
||||
<h4>{{report.title}}</h4>
|
||||
<div *ngIf="!report.hasDatasets()">{{'ANALYTICS.MESSAGES.NO-DATA-FOUND' | translate}}</div>
|
||||
<base-chart *ngIf="report.hasDatasets()" class="chart"
|
||||
[datasets]="report.datasets"
|
||||
@@ -61,7 +77,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<div *ngSwitchCase="'multiBar'">
|
||||
<div class="col-md-6">
|
||||
<div class="col-md-6" *ngIf="isCurrent(idx)">
|
||||
<h4>{{report.title}}</h4>
|
||||
<div *ngIf="!report.hasDatasets()">{{'ANALYTICS.MESSAGES.NO-DATA-FOUND' | translate}}</div>
|
||||
<div *ngIf="report.hasDatasets()">
|
||||
<label class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect" [attr.for]="'stacked-id'">
|
||||
@@ -80,7 +97,10 @@
|
||||
</div>
|
||||
</div>
|
||||
<div *ngSwitchCase="'HeatMap'">
|
||||
<analytics-report-heat-map [report]="report"></analytics-report-heat-map>
|
||||
<div *ngIf="isCurrent(idx)">
|
||||
<h4>{{report.title}}</h4>
|
||||
<analytics-report-heat-map [report]="report"></analytics-report-heat-map>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngSwitchDefault>
|
||||
<span>{{'ANALYTICS.MESSAGES.UNKNOWN-WIDGET-TYPE' | translate}}: {{report.type}}</span>
|
||||
|
@@ -135,6 +135,44 @@ describe('AnalyticsGeneratorComponent', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('Should render the Process definition overview report when onchanges is called ', (done) => {
|
||||
component.onSuccess.subscribe((res) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(res.length).toEqual(3);
|
||||
|
||||
expect(res[0]).toBeDefined();
|
||||
expect(res[0].type).toEqual('table');
|
||||
expect(res[0].datasets).toBeDefined();
|
||||
expect(res[0].datasets.length).toEqual(4);
|
||||
expect(res[0].datasets[0][0]).toEqual('__KEY_REPORTING.DEFAULT-REPORTS.PROCESS-DEFINITION-OVERVIEW.GENERAL-TABLE-TOTAL-PROCESS-DEFINITIONS');
|
||||
expect(res[0].datasets[0][1]).toEqual('9');
|
||||
expect(res[0].datasets[1][0]).toEqual('__KEY_REPORTING.DEFAULT-REPORTS.PROCESS-DEFINITION-OVERVIEW.GENERAL-TABLE-TOTAL-PROCESS-INSTANCES');
|
||||
expect(res[0].datasets[1][1]).toEqual('41');
|
||||
expect(res[0].datasets[2][0]).toEqual('__KEY_REPORTING.DEFAULT-REPORTS.PROCESS-DEFINITION-OVERVIEW.GENERAL-TABLE-ACTIVE-PROCESS-INSTANCES');
|
||||
expect(res[0].datasets[2][1]).toEqual('3');
|
||||
expect(res[0].datasets[3][0]).toEqual('__KEY_REPORTING.DEFAULT-REPORTS.PROCESS-DEFINITION-OVERVIEW.GENERAL-TABLE-COMPLETED-PROCESS-INSTANCES');
|
||||
expect(res[0].datasets[3][1]).toEqual('38');
|
||||
|
||||
expect(res[1]).toBeDefined();
|
||||
expect(res[1].type).toEqual('pie');
|
||||
|
||||
expect(res[2]).toBeDefined();
|
||||
expect(res[2].type).toEqual('table');
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
component.reportId = 1001;
|
||||
component.reportParamQuery = new ReportQuery({status: 'All'});
|
||||
component.ngOnChanges();
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
status: 200,
|
||||
contentType: 'json',
|
||||
responseText: analyticMock.chartProcessDefOverview
|
||||
});
|
||||
});
|
||||
|
||||
it('Should render the Task overview report ', (done) => {
|
||||
component.onSuccess.subscribe((res) => {
|
||||
expect(res).toBeDefined();
|
||||
|
@@ -44,6 +44,7 @@ export class AnalyticsGeneratorComponent implements OnChanges {
|
||||
reports: Chart[];
|
||||
|
||||
showDetails: boolean = false;
|
||||
currentChartPosition: number;
|
||||
|
||||
public barChartOptions: any = {
|
||||
responsive: true,
|
||||
@@ -80,9 +81,15 @@ export class AnalyticsGeneratorComponent implements OnChanges {
|
||||
}
|
||||
|
||||
public generateReport(reportId, reportParamQuery) {
|
||||
if (reportParamQuery === undefined || reportParamQuery === null) {
|
||||
reportParamQuery = {};
|
||||
}
|
||||
this.analyticsService.getReportsByParams(reportId, reportParamQuery).subscribe(
|
||||
(res: Chart[]) => {
|
||||
this.reports = res;
|
||||
if (this.reports) {
|
||||
this.selectFirstReport();
|
||||
}
|
||||
this.onSuccess.emit(res);
|
||||
},
|
||||
(err: any) => {
|
||||
@@ -116,4 +123,16 @@ export class AnalyticsGeneratorComponent implements OnChanges {
|
||||
isShowDetails(): boolean {
|
||||
return this.showDetails;
|
||||
}
|
||||
|
||||
isCurrent(position: number) {
|
||||
return position === this.currentChartPosition ? true : false;
|
||||
}
|
||||
|
||||
selectCurrent(position: number) {
|
||||
this.currentChartPosition = position;
|
||||
}
|
||||
|
||||
selectFirstReport() {
|
||||
this.selectCurrent(0);
|
||||
}
|
||||
}
|
||||
|
@@ -16,4 +16,37 @@
|
||||
|
||||
.activiti-filters__entry.active .activiti-filters__entry-icon {
|
||||
color: rgb(68,138,255);
|
||||
}
|
||||
}
|
||||
|
||||
.application-title {
|
||||
color: white;
|
||||
z-index: 7;
|
||||
}
|
||||
|
||||
.logo {
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
top: 35px;
|
||||
z-index: 6;
|
||||
}
|
||||
.logo i{
|
||||
font-size: 70px;
|
||||
}
|
||||
|
||||
.theme-1 {
|
||||
background-color: #269abc;
|
||||
}
|
||||
|
||||
.theme-1 .logo i {
|
||||
color: #168aac;
|
||||
}
|
||||
.theme-1 .mdl-card__actions i {
|
||||
color: #168aac;
|
||||
}
|
||||
.theme-1 .mdl-card__actions i:hover {
|
||||
color: #b7dfea;
|
||||
}
|
||||
|
||||
.selectedIcon{
|
||||
color: #e9f1f3!important;
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<div class="menu-container">
|
||||
<ul class='mdl-list'>
|
||||
<ul class='mdl-list' *ngIf="isList()">
|
||||
<li class="mdl-list__item activiti-filters__entry" (click)="selectReport(report)" *ngFor="let report of reports; let idx = index"
|
||||
[class.active]="currentReport === report">
|
||||
<span [attr.id]="'report-list-' + idx" class="mdl-list__item-primary-content">
|
||||
@@ -8,4 +8,18 @@
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="mdl-grid" *ngIf="isGrid()">
|
||||
<div (click)="selectReport(report)" [ngClass]="['mdl-card mdl-cell', 'theme-1']" *ngFor="let report of reports;">
|
||||
<div class="logo"><i class="material-icons">equalizer</i></div>
|
||||
<div class="mdl-card__title">
|
||||
<h1 class="mdl-card__title-text application-title">{{report.name}}</h1>
|
||||
</div>
|
||||
<div class="mdl-card__supporting-text">
|
||||
<p>{{report.description}}</p>
|
||||
</div>
|
||||
<div class="mdl-card__actions mdl-card--border">
|
||||
<i class="material-icons selectedIcon" *ngIf="isSelected(report)">done</i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -21,6 +21,7 @@ import { Observable } from 'rxjs/Rx';
|
||||
import { CoreModule, AlfrescoTranslationService } from 'ng2-alfresco-core';
|
||||
import { AnalyticsReportListComponent } from '../components/analytics-report-list.component';
|
||||
import { AnalyticsService } from '../services/analytics.service';
|
||||
import { ReportParametersModel } from '../models/report.model';
|
||||
|
||||
declare let jasmine: any;
|
||||
|
||||
@@ -166,6 +167,59 @@ describe('AnalyticsReportListComponent', () => {
|
||||
component.selectReport(reportSelected);
|
||||
});
|
||||
|
||||
it('Should return true if the current report is selected', () => {
|
||||
component.selectReport(reportSelected);
|
||||
expect(component.isSelected(reportSelected)).toBe(true);
|
||||
});
|
||||
|
||||
it('Should return false if the current report is different', () => {
|
||||
component.selectReport(reportSelected);
|
||||
let anotherReport = {'id': 111, 'name': 'Another Fake Test Process definition overview'};
|
||||
expect(component.isSelected(anotherReport)).toBe(false);
|
||||
});
|
||||
|
||||
it('Should reload the report list', (done) => {
|
||||
component.initObserver();
|
||||
let report = new ReportParametersModel({'id': 2002, 'name': 'Fake Test Process definition heat map'});
|
||||
component.reports = [report];
|
||||
expect(component.reports.length).toEqual(1);
|
||||
component.reload();
|
||||
|
||||
component.onSuccess.subscribe(() => {
|
||||
expect(component.reports.length).toEqual(5);
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
status: 200,
|
||||
contentType: 'json',
|
||||
responseText: reportList
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('layout', () => {
|
||||
|
||||
it('should display a list by default', () => {
|
||||
fixture.detectChanges();
|
||||
expect(component.isGrid()).toBe(false);
|
||||
expect(component.isList()).toBe(true);
|
||||
});
|
||||
|
||||
it('should display a grid when configured to', () => {
|
||||
component.layoutType = AnalyticsReportListComponent.LAYOUT_GRID;
|
||||
fixture.detectChanges();
|
||||
expect(component.isGrid()).toBe(true);
|
||||
expect(component.isList()).toBe(false);
|
||||
});
|
||||
|
||||
it('should display a list when configured to', () => {
|
||||
component.layoutType = AnalyticsReportListComponent.LAYOUT_LIST;
|
||||
fixture.detectChanges();
|
||||
expect(component.isGrid()).toBe(false);
|
||||
expect(component.isList()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Component, EventEmitter, OnInit, Output } from '@angular/core';
|
||||
import { Component, EventEmitter, OnInit, Output, Input } from '@angular/core';
|
||||
import { Observer, Observable } from 'rxjs/Rx';
|
||||
import { LogService } from 'ng2-alfresco-core';
|
||||
import { AnalyticsService } from '../services/analytics.service';
|
||||
@@ -29,6 +29,12 @@ import { ReportParametersModel } from '../models/report.model';
|
||||
})
|
||||
export class AnalyticsReportListComponent implements OnInit {
|
||||
|
||||
public static LAYOUT_LIST: string = 'LIST';
|
||||
public static LAYOUT_GRID: string = 'GRID';
|
||||
|
||||
@Input()
|
||||
layoutType: string = AnalyticsReportListComponent.LAYOUT_LIST;
|
||||
|
||||
@Output()
|
||||
reportClick: EventEmitter<ReportParametersModel> = new EventEmitter<ReportParametersModel>();
|
||||
|
||||
@@ -51,11 +57,15 @@ export class AnalyticsReportListComponent implements OnInit {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.initObserver();
|
||||
|
||||
this.getReportList();
|
||||
}
|
||||
|
||||
initObserver() {
|
||||
this.report$.subscribe((report: ReportParametersModel) => {
|
||||
this.reports.push(report);
|
||||
});
|
||||
|
||||
this.getReportList();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -131,4 +141,16 @@ export class AnalyticsReportListComponent implements OnInit {
|
||||
this.currentReport = report;
|
||||
this.reportClick.emit(report);
|
||||
}
|
||||
|
||||
isSelected(report: any) {
|
||||
return this.currentReport === report ? true : false;
|
||||
}
|
||||
|
||||
isList() {
|
||||
return this.layoutType === AnalyticsReportListComponent.LAYOUT_LIST;
|
||||
}
|
||||
|
||||
isGrid() {
|
||||
return this.layoutType === AnalyticsReportListComponent.LAYOUT_GRID;
|
||||
}
|
||||
}
|
||||
|
@@ -56,10 +56,50 @@
|
||||
}
|
||||
|
||||
.report-container {
|
||||
border: solid 1px rgb(212, 212, 212);
|
||||
border-bottom: solid 1px rgb(212, 212, 212);
|
||||
padding: 10px 10px 10px 10px;
|
||||
}
|
||||
|
||||
.report-container-setting {
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.option_button_details{
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
.report-icons {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.report-icons button {
|
||||
min-width: 48px;
|
||||
padding: 0 0px;
|
||||
}
|
||||
|
||||
|
||||
.mdl-dialog__title.choose_name{
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.mdl-dialog.options-name-dialog {
|
||||
width: 30%;
|
||||
}
|
||||
|
||||
.export-message{
|
||||
background-color: lightgray;
|
||||
}
|
||||
|
||||
.save-export-input{
|
||||
width:100%;
|
||||
}
|
||||
|
||||
.delete-parameter {
|
||||
position: absolute;
|
||||
margin-left: 60%;
|
||||
padding-top: 5px;
|
||||
}
|
||||
|
||||
.hide {
|
||||
display: none;
|
||||
}
|
||||
|
@@ -1,83 +1,117 @@
|
||||
<div class="report-container">
|
||||
<a class="mdl-navigation__link setting-button" data-automation-id="settings">
|
||||
<button (click)="toggleParameters()" class="mdl-button mdl-js-button mdl-button--fab mdl-button--colored">
|
||||
<i class="material-icons">settings</i>
|
||||
</button>
|
||||
<span class="report-container-setting">{{'ANALYTICS.MESSAGES.SETTING-TITLE' | translate}}</span>
|
||||
</a>
|
||||
<div class="col-md-6" [class.is-hide]="isParametersHide()" >
|
||||
<div *ngIf="reportParameters">
|
||||
<form [formGroup]="reportForm" novalidate>
|
||||
<div *ngIf="isEditable">
|
||||
<input
|
||||
type="text"
|
||||
class="mdl-textfield__input large"
|
||||
id="reportName"
|
||||
autofocus
|
||||
data-automation-id="reportName"
|
||||
[value]="reportParameters.name"
|
||||
(input)="reportParameters.name=$event.target.value"
|
||||
(blur)="editTitle($event)"
|
||||
<div [class.hide]="hideComponent">
|
||||
<div class="report-container">
|
||||
<div class="col-md-6">
|
||||
<div *ngIf="reportParameters">
|
||||
<form [formGroup]="reportForm" novalidate>
|
||||
<div *ngIf="isEditable">
|
||||
<input
|
||||
type="text"
|
||||
class="mdl-textfield__input large"
|
||||
id="reportName"
|
||||
autofocus
|
||||
data-automation-id="reportName"
|
||||
[value]="reportParameters.name"
|
||||
(input)="reportParameters.name=$event.target.value"
|
||||
(blur)="editTitle($event)"
|
||||
/>
|
||||
</div>
|
||||
<div *ngIf="!isEditable">
|
||||
<div class="report-icons">
|
||||
<button mdTooltip="{{'ANALYTICS.MESSAGES.ICON-SETTING' | translate}}" (click)="toggleParameters()" class="mdl-button mdl-js-button">
|
||||
<i class="material-icons">settings</i>
|
||||
</button>
|
||||
<button id="delete-button" (click)="deleteReport(reportId)" mdTooltip="{{'ANALYTICS.MESSAGES.ICON-DELETE' | translate}}" class="mdl-button mdl-js-button">
|
||||
<i class="material-icons">delete</i>
|
||||
</button>
|
||||
<span *ngIf="isFormValid()">
|
||||
<button id="export-button" (click)="showDialog('Export')" mdTooltip="{{'ANALYTICS.MESSAGES.ICON-EXPORT-CSV' | translate}}" class="mdl-button mdl-js-button">
|
||||
<i class="material-icons">file_download</i>
|
||||
</button>
|
||||
<button id="save-button" (click)="showDialog('Save')" mdTooltip="{{'ANALYTICS.MESSAGES.ICON-SAVE' | translate}}" class="mdl-button mdl-js-button">
|
||||
<i class="material-icons">save</i>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
<div class="icon-small">
|
||||
<i class="material-icons">mode_edit</i>
|
||||
<h4 (click)="editEnable()">{{reportParameters.name}}</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngFor="let field of reportParameters.definition.parameters" [class.is-hide]="isParametersHide()">
|
||||
<div [ngSwitch]="field.type">
|
||||
<div *ngSwitchCase="'integer'">
|
||||
<br>
|
||||
<number-widget [field]="field" [group]="reportForm.controls.processInstanceGroup" [controllerName]="'slowProcessInstanceInteger'"
|
||||
[required]="true"></number-widget>
|
||||
</div>
|
||||
<div *ngSwitchCase="'duration'">
|
||||
<br>
|
||||
<duration-widget [field]="field" [group]="reportForm.controls.durationGroup"
|
||||
[controllerName]="'duration'"></duration-widget>
|
||||
</div>
|
||||
<div *ngSwitchCase="'boolean'">
|
||||
<br>
|
||||
<checkbox-widget [field]="field" [group]="reportForm.controls.typeFilteringGroup"
|
||||
[controllerName]="'typeFiltering'"></checkbox-widget>
|
||||
</div>
|
||||
<div *ngSwitchCase="'status'">
|
||||
<br>
|
||||
<dropdown-widget [field]="field" [group]="reportForm.controls.statusGroup" [controllerName]="'status'"
|
||||
[required]="true"></dropdown-widget>
|
||||
</div>
|
||||
<div *ngSwitchCase="'processDefinition'">
|
||||
<br>
|
||||
<dropdown-widget [field]="field" [group]="reportForm.controls.processDefGroup" [controllerName]="'processDefinitionId'"
|
||||
[required]="true" (fieldChanged)="onProcessDefinitionChanges(field)"></dropdown-widget>
|
||||
</div>
|
||||
<div *ngSwitchCase="'task'">
|
||||
<br>
|
||||
<dropdown-widget [field]="field" [group]="reportForm.controls.taskGroup" [controllerName]="'taskName'"
|
||||
[required]="true"></dropdown-widget>
|
||||
</div>
|
||||
<div *ngSwitchCase="'dateRange'">
|
||||
<br>
|
||||
<date-range-widget [field]="field" [group]="reportForm.controls.dateRange"></date-range-widget>
|
||||
</div>
|
||||
<div *ngSwitchCase="'dateInterval'">
|
||||
<br>
|
||||
<dropdown-widget [field]="field" [group]="reportForm.controls.dateIntervalGroup" [controllerName]="'dateRangeInterval'"
|
||||
[required]="true" [showDefaultOption]="false"></dropdown-widget>
|
||||
</div>
|
||||
<div *ngSwitchDefault>
|
||||
<span>{{'ANALYTICS.MESSAGES.UNKNOWN-WIDGET-TYPE' | translate}}: {{field.type}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<dialog id="report-dialog" class="mdl-dialog options-name-dialog" #reportNameDialog>
|
||||
<h5 id="report-dialog-title" class="mdl-dialog__title">{{action}} report</h5>
|
||||
<div class="mdl-dialog__content">
|
||||
<div *ngIf="isSaveAction()" id="save-title-submessage" class="export-message">{{'DIALOG.SAVE_MESSAGE' | translate}}</div>
|
||||
<div class="mdl-textfield mdl-js-textfield save-export-input">
|
||||
<label id="report-name-label" [attr.for]="repname">Report Name</label>
|
||||
<input class="mdl-textfield__input"
|
||||
type="text"
|
||||
id="repName"
|
||||
[attr.value]="reportName"
|
||||
[(ngModel)]="reportName"
|
||||
[ngModelOptions]="{standalone: true}"
|
||||
placeholder="report name">
|
||||
</div>
|
||||
</div>
|
||||
<div class="mdl-dialog__actions">
|
||||
<button type="button" id="close-dialog-button" (click)="closeDialog()" class="mdl-button close">Close</button>
|
||||
<button type="button" id="action-dialog-button" (click)="performAction(action, reportParamQuery)"
|
||||
class="mdl-button close">{{action}}
|
||||
</button>
|
||||
</div>
|
||||
</dialog>
|
||||
<div *ngIf="debug">
|
||||
<p>ReportForm valid : {{ reportForm.valid }}</p>
|
||||
<p>ReportForm status : {{ reportForm.errors | json }}</p>
|
||||
<p>ReportForm FormGroup valid : {{reportForm && reportForm.controls.dateRange.valid | json }}</p>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div *ngIf="!isEditable">
|
||||
<span class="icon-small">
|
||||
<i class="material-icons">mode_edit</i>
|
||||
<h4 (click)="editEnable()">{{reportParameters.name}}</h4>
|
||||
</span>
|
||||
</div><hr>
|
||||
<div *ngFor="let field of reportParameters.definition.parameters">
|
||||
<div [ngSwitch]="field.type">
|
||||
<div *ngSwitchCase="'integer'">
|
||||
<br>
|
||||
<number-widget [field]="field" [group]="reportForm.controls.processInstanceGroup" [controllerName]="'slowProcessInstanceInteger'"
|
||||
[required]="true"></number-widget>
|
||||
</div>
|
||||
<div *ngSwitchCase="'duration'">
|
||||
<br>
|
||||
<duration-widget [field]="field" [group]="reportForm.controls.durationGroup"
|
||||
[controllerName]="'duration'"></duration-widget>
|
||||
</div>
|
||||
<div *ngSwitchCase="'boolean'">
|
||||
<br>
|
||||
<checkbox-widget [field]="field" [group]="reportForm.controls.typeFilteringGroup"
|
||||
[controllerName]="'typeFiltering'"></checkbox-widget>
|
||||
</div>
|
||||
<div *ngSwitchCase="'status'">
|
||||
<br>
|
||||
<dropdown-widget [field]="field" [group]="reportForm.controls.statusGroup" [controllerName]="'status'"
|
||||
[required]="true"></dropdown-widget>
|
||||
</div>
|
||||
<div *ngSwitchCase="'processDefinition'">
|
||||
<br>
|
||||
<dropdown-widget [field]="field" [group]="reportForm.controls.processDefGroup" [controllerName]="'processDefinitionId'"
|
||||
[required]="true" (fieldChanged)="onProcessDefinitionChanges(field)"></dropdown-widget>
|
||||
</div>
|
||||
<div *ngSwitchCase="'task'">
|
||||
<br>
|
||||
<dropdown-widget [field]="field" [group]="reportForm.controls.taskGroup" [controllerName]="'taskName'"
|
||||
[required]="true"></dropdown-widget>
|
||||
</div>
|
||||
<div *ngSwitchCase="'dateRange'">
|
||||
<br>
|
||||
<date-range-widget [field]="field" [group]="reportForm.controls.dateRange"></date-range-widget>
|
||||
</div>
|
||||
<div *ngSwitchCase="'dateInterval'">
|
||||
<br>
|
||||
<dropdown-widget [field]="field" [group]="reportForm.controls.dateIntervalGroup" [controllerName]="'dateRangeInterval'"
|
||||
[required]="true" [showDefaultOption]="false"></dropdown-widget>
|
||||
</div>
|
||||
<div *ngSwitchDefault>
|
||||
<span>{{'ANALYTICS.MESSAGES.UNKNOWN-WIDGET-TYPE' | translate}}: {{field.type}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="debug">
|
||||
<p>ReportForm valid : {{ reportForm.valid }}</p>
|
||||
<p>ReportForm status : {{ reportForm.errors | json }}</p>
|
||||
<p>ReportForm FormGroup valid : {{reportForm && reportForm.controls.dateRange.valid | json }}</p>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -55,7 +55,9 @@ describe('AnalyticsReportParametersComponent', () => {
|
||||
|
||||
let translateService = TestBed.get(AlfrescoTranslationService);
|
||||
spyOn(translateService, 'addTranslationFolder').and.stub();
|
||||
spyOn(translateService, 'get').and.callFake((key) => { return Observable.of(key); });
|
||||
spyOn(translateService, 'get').and.callFake((key) => {
|
||||
return Observable.of(key);
|
||||
});
|
||||
|
||||
componentHandler = jasmine.createSpyObj('componentHandler', [
|
||||
'upgradeAllRegistered'
|
||||
@@ -80,17 +82,22 @@ describe('AnalyticsReportParametersComponent', () => {
|
||||
jasmine.Ajax.uninstall();
|
||||
});
|
||||
|
||||
it('Should initialize the Report form with a Form Group ', () => {
|
||||
expect(component.reportForm.get('dateRange')).toBeDefined();
|
||||
expect(component.reportForm.get('dateRange').get('startDate')).toBeDefined();
|
||||
expect(component.reportForm.get('dateRange').get('endDate')).toBeDefined();
|
||||
it('Should initialize the Report form with a Form Group ', (done) => {
|
||||
let fakeReportParam = new ReportParametersModel(analyticParamsMock.reportDefParamTask);
|
||||
component.onSuccessReportParams.subscribe(() => {
|
||||
fixture.detectChanges();
|
||||
expect(component.reportForm.get('taskGroup')).toBeDefined();
|
||||
expect(component.reportForm.get('taskGroup').get('taskName')).toBeDefined();
|
||||
done();
|
||||
});
|
||||
component.onSuccessReportParams.emit(fakeReportParam);
|
||||
});
|
||||
|
||||
it('Should render a dropdown with all the status when the definition parameter type is \'status\' ', (done) => {
|
||||
component.onSuccessReportParams.subscribe(() => {
|
||||
fixture.detectChanges();
|
||||
let dropDown: any = element.querySelector('#select-status');
|
||||
expect(element.querySelector('h4').innerHTML).toEqual('Fake Task overview status');
|
||||
expect(element.querySelector('h4').textContent.trim()).toEqual('Fake Task overview status');
|
||||
expect(dropDown).toBeDefined();
|
||||
expect(dropDown.length).toEqual(4);
|
||||
expect(dropDown[0].innerHTML).toEqual('Choose One');
|
||||
@@ -320,13 +327,14 @@ describe('AnalyticsReportParametersComponent', () => {
|
||||
responseText: analyticParamsMock.reportDefParamProcessDef
|
||||
});
|
||||
|
||||
jasmine.Ajax.stubRequest('http://localhost:9999/activiti-app/api/enterprise/process-definitions').andReturn({
|
||||
let appId = '1';
|
||||
|
||||
jasmine.Ajax.stubRequest('http://localhost:9999/activiti-app/api/enterprise/process-definitions?appDefinitionId=' + appId).andReturn({
|
||||
status: 200,
|
||||
contentType: 'json',
|
||||
responseText: analyticParamsMock.reportDefParamProcessDefOptionsApp
|
||||
});
|
||||
|
||||
let appId = '1';
|
||||
component.appId = appId;
|
||||
component.reportId = '1';
|
||||
let change = new SimpleChange(null, appId);
|
||||
@@ -334,6 +342,24 @@ describe('AnalyticsReportParametersComponent', () => {
|
||||
|
||||
});
|
||||
|
||||
it('Should create an empty valid form when there are no parameters definitions', () => {
|
||||
component.onSuccess.subscribe((res) => {
|
||||
expect(component.reportForm).toBeDefined();
|
||||
expect(component.reportForm.valid).toEqual(true);
|
||||
expect(component.reportForm.controls).toEqual({});
|
||||
});
|
||||
|
||||
let reportId = 1;
|
||||
let change = new SimpleChange(null, reportId);
|
||||
component.ngOnChanges({ 'reportId': change });
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
status: 200,
|
||||
contentType: 'json',
|
||||
responseText: analyticParamsMock.reportNoParameterDefinitions
|
||||
});
|
||||
});
|
||||
|
||||
it('Should load the task list when a process definition is selected', () => {
|
||||
component.onSuccessReportParams.subscribe((res) => {
|
||||
expect(res).toBeDefined();
|
||||
@@ -400,5 +426,148 @@ describe('AnalyticsReportParametersComponent', () => {
|
||||
let numberConvert = component.convertNumber('2');
|
||||
expect(numberConvert).toEqual(2);
|
||||
});
|
||||
|
||||
describe('When the form is rendered correctly', () => {
|
||||
let values: any = {
|
||||
dateRange: {
|
||||
startDate: '2016-09-01', endDate: '2016-10-05'
|
||||
},
|
||||
statusGroup: {
|
||||
status: 'All'
|
||||
},
|
||||
processDefGroup: {
|
||||
processDefinitionId: 'FakeProcess:1:22'
|
||||
},
|
||||
taskGroup: {
|
||||
taskName: 'FakeTaskName'
|
||||
},
|
||||
durationGroup: {
|
||||
duration: 22
|
||||
},
|
||||
dateIntervalGroup: {
|
||||
dateRangeInterval: 120
|
||||
},
|
||||
processInstanceGroup: {
|
||||
slowProcessInstanceInteger: 2
|
||||
},
|
||||
typeFilteringGroup: {
|
||||
typeFiltering: true
|
||||
}
|
||||
};
|
||||
|
||||
beforeEach(async(() => {
|
||||
let reportId = 1;
|
||||
let change = new SimpleChange(null, reportId);
|
||||
component.ngOnChanges({ 'reportId': change });
|
||||
fixture.detectChanges();
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
status: 200,
|
||||
contentType: 'json',
|
||||
responseText: analyticParamsMock.reportDefParamStatus
|
||||
});
|
||||
fixture.whenStable().then(() => {
|
||||
component.toggleParameters();
|
||||
component.reportId = '1';
|
||||
spyOn(component, 'isFormValid').and.returnValue(true);
|
||||
fixture.detectChanges();
|
||||
});
|
||||
}));
|
||||
|
||||
it('Should be able to change the report title', async(() => {
|
||||
let title: HTMLElement = element.querySelector('h4');
|
||||
title.click();
|
||||
fixture.detectChanges();
|
||||
let reportName: HTMLInputElement = <HTMLInputElement> element.querySelector('#reportName');
|
||||
expect(reportName).not.toBeNull();
|
||||
reportName.focus();
|
||||
component.reportParameters.name = 'FAKE_TEST_NAME';
|
||||
reportName.value = 'FAKE_TEST_NAME';
|
||||
reportName.blur();
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
status: 200,
|
||||
contentType: 'json',
|
||||
responseText: analyticParamsMock.reportDefParamStatus
|
||||
});
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
let titleChanged: HTMLElement = element.querySelector('h4');
|
||||
expect(titleChanged.textContent.trim()).toEqual('FAKE_TEST_NAME');
|
||||
});
|
||||
}));
|
||||
|
||||
it('Should show a dialog to allowing report save', async(() => {
|
||||
component.saveReportSuccess.subscribe(() => {
|
||||
let reportDialogTitle: HTMLElement = <HTMLElement>element.querySelector('#report-dialog');
|
||||
expect(reportDialogTitle.getAttribute('open')).toBeNull();
|
||||
});
|
||||
|
||||
component.submit(values);
|
||||
fixture.detectChanges();
|
||||
let saveButton: HTMLButtonElement = <HTMLButtonElement>element.querySelector('#save-button');
|
||||
expect(saveButton).toBeDefined();
|
||||
expect(saveButton).not.toBeNull();
|
||||
saveButton.click();
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
let reportDialogTitle: HTMLElement = <HTMLElement>element.querySelector('#report-dialog-title');
|
||||
let saveTitleSubMessage: HTMLElement = <HTMLElement> element.querySelector('#save-title-submessage');
|
||||
let inputSaveName: HTMLInputElement = <HTMLInputElement> element.querySelector('#repName');
|
||||
let performActionButton: HTMLButtonElement = <HTMLButtonElement>element.querySelector('#action-dialog-button');
|
||||
let todayDate = component.getTodayDate();
|
||||
expect(reportDialogTitle).not.toBeNull();
|
||||
expect(saveTitleSubMessage).not.toBeNull();
|
||||
expect(inputSaveName.value.trim()).toEqual(analyticParamsMock.reportDefParamStatus.name + ' ( ' + todayDate + ' )');
|
||||
expect(performActionButton).not.toBeNull();
|
||||
performActionButton.click();
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
status: 200,
|
||||
contentType: 'json'
|
||||
});
|
||||
});
|
||||
}));
|
||||
|
||||
it('Should show a dialog to allowing report export', async(() => {
|
||||
component.submit(values);
|
||||
spyOn(component, 'generateDownloadElement').and.stub();
|
||||
fixture.detectChanges();
|
||||
let exportButton: HTMLButtonElement = <HTMLButtonElement>element.querySelector('#export-button');
|
||||
expect(exportButton).toBeDefined();
|
||||
expect(exportButton).not.toBeNull();
|
||||
exportButton.click();
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
let reportDialogTitle: HTMLElement = <HTMLElement>element.querySelector('#report-dialog-title');
|
||||
let inputSaveName: HTMLInputElement = <HTMLInputElement> element.querySelector('#repName');
|
||||
let performActionButton: HTMLButtonElement = <HTMLButtonElement>element.querySelector('#action-dialog-button');
|
||||
let todayDate = component.getTodayDate();
|
||||
expect(reportDialogTitle).not.toBeNull();
|
||||
expect(inputSaveName.value.trim()).toEqual(analyticParamsMock.reportDefParamStatus.name + ' ( ' + todayDate + ' )');
|
||||
expect(performActionButton).not.toBeNull();
|
||||
performActionButton.click();
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
status: 200,
|
||||
contentType: 'json'
|
||||
});
|
||||
});
|
||||
}));
|
||||
|
||||
it('Should raise an event for report deleted', async(() => {
|
||||
let deleteButton: HTMLButtonElement = <HTMLButtonElement>element.querySelector('#delete-button');
|
||||
expect(deleteButton).toBeDefined();
|
||||
expect(deleteButton).not.toBeNull();
|
||||
|
||||
component.deleteReportSuccess.subscribe((reportId) => {
|
||||
expect(reportId).not.toBeNull();
|
||||
});
|
||||
deleteButton.click();
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
status: 200,
|
||||
contentType: 'json'
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -24,7 +24,8 @@ import {
|
||||
Output,
|
||||
SimpleChanges,
|
||||
OnDestroy,
|
||||
AfterViewChecked
|
||||
AfterViewChecked,
|
||||
ViewChild
|
||||
} from '@angular/core';
|
||||
import { FormGroup, FormBuilder, FormControl } from '@angular/forms';
|
||||
import * as moment from 'moment';
|
||||
@@ -38,6 +39,7 @@ import {
|
||||
} from '../models/report.model';
|
||||
|
||||
declare var componentHandler;
|
||||
declare let dialogPolyfill: any;
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
@@ -47,7 +49,7 @@ declare var componentHandler;
|
||||
})
|
||||
export class AnalyticsReportParametersComponent implements OnInit, OnChanges, OnDestroy, AfterViewChecked {
|
||||
|
||||
public static FORMAT_DATE_ACTIVITI: string = 'YYYY-MM-DD';
|
||||
public static FORMAT_DATE_ACTIVITI: string = 'YYYY-MM-DD';
|
||||
|
||||
@Input()
|
||||
appId: string;
|
||||
@@ -55,6 +57,9 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On
|
||||
@Input()
|
||||
reportId: string;
|
||||
|
||||
@Input()
|
||||
hideComponent: boolean = false;
|
||||
|
||||
@Input()
|
||||
debug: boolean = false;
|
||||
|
||||
@@ -70,6 +75,15 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On
|
||||
@Output()
|
||||
onFormValueChanged = new EventEmitter();
|
||||
|
||||
@Output()
|
||||
saveReportSuccess = new EventEmitter();
|
||||
|
||||
@Output()
|
||||
deleteReportSuccess = new EventEmitter();
|
||||
|
||||
@ViewChild('reportNameDialog')
|
||||
reportNameDialog: any;
|
||||
|
||||
onDropdownChanged = new EventEmitter();
|
||||
|
||||
onSuccessReportParams = new EventEmitter();
|
||||
@@ -84,6 +98,9 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On
|
||||
private reportParamsSub;
|
||||
private paramOpts;
|
||||
private isEditable: boolean = false;
|
||||
private action: string;
|
||||
private reportParamQuery: ReportQuery;
|
||||
private reportName: string;
|
||||
private hideParameters: boolean = true;
|
||||
|
||||
constructor(private translateService: AlfrescoTranslationService,
|
||||
@@ -96,8 +113,6 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.initForm();
|
||||
|
||||
this.dropDownSub = this.onDropdownChanged.subscribe((field) => {
|
||||
let paramDependOn: ReportParameterDetailsModel = this.reportParameters.definition.parameters.find(p => p.dependsOn === field.id);
|
||||
if (paramDependOn) {
|
||||
@@ -108,10 +123,9 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On
|
||||
this.paramOpts = this.onSuccessReportParams.subscribe((report: ReportParametersModel) => {
|
||||
if (report.hasParameters()) {
|
||||
this.retrieveParameterOptions(report.definition.parameters, this.appId);
|
||||
this.generateFormGroupFromParameter(report.definition.parameters);
|
||||
}
|
||||
});
|
||||
|
||||
this.reportForm.valueChanges.subscribe(data => this.onValueChanged(data));
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
@@ -127,31 +141,54 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On
|
||||
}
|
||||
}
|
||||
|
||||
initForm() {
|
||||
this.reportForm = this.formBuilder.group({
|
||||
dateRange: new FormGroup({}),
|
||||
statusGroup: new FormGroup({
|
||||
status: new FormControl()
|
||||
}),
|
||||
processInstanceGroup: new FormGroup({
|
||||
slowProcessInstanceInteger: new FormControl()
|
||||
}),
|
||||
taskGroup: new FormGroup({
|
||||
taskName: new FormControl()
|
||||
}),
|
||||
typeFilteringGroup: new FormGroup({
|
||||
typeFiltering: new FormControl()
|
||||
}),
|
||||
dateIntervalGroup: new FormGroup({
|
||||
dateRangeInterval: new FormControl()
|
||||
}),
|
||||
durationGroup: new FormGroup({
|
||||
duration: new FormControl()
|
||||
}),
|
||||
processDefGroup: new FormGroup({
|
||||
processDefinitionId: new FormControl()
|
||||
})
|
||||
private generateFormGroupFromParameter(parameters: ReportParameterDetailsModel[]) {
|
||||
let formBuilderGroup: any = {};
|
||||
parameters.forEach((param: ReportParameterDetailsModel) => {
|
||||
switch (param.type) {
|
||||
case 'dateRange' :
|
||||
formBuilderGroup.dateRange = new FormGroup({});
|
||||
break;
|
||||
case 'processDefinition':
|
||||
formBuilderGroup.processDefGroup = new FormGroup({
|
||||
processDefinitionId: new FormControl()
|
||||
});
|
||||
break;
|
||||
case 'duration':
|
||||
formBuilderGroup.durationGroup = new FormGroup({
|
||||
duration: new FormControl()
|
||||
});
|
||||
break;
|
||||
case 'dateInterval':
|
||||
formBuilderGroup.dateIntervalGroup = new FormGroup({
|
||||
dateRangeInterval: new FormControl()
|
||||
});
|
||||
break;
|
||||
case 'boolean':
|
||||
formBuilderGroup.typeFilteringGroup = new FormGroup({
|
||||
typeFiltering: new FormControl()
|
||||
});
|
||||
break;
|
||||
case 'task':
|
||||
formBuilderGroup.taskGroup = new FormGroup({
|
||||
taskName: new FormControl()
|
||||
});
|
||||
break;
|
||||
case 'integer':
|
||||
formBuilderGroup.processInstanceGroup = new FormGroup({
|
||||
slowProcessInstanceInteger: new FormControl()
|
||||
});
|
||||
break;
|
||||
case 'status':
|
||||
formBuilderGroup.statusGroup = new FormGroup({
|
||||
status: new FormControl()
|
||||
});
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
});
|
||||
this.reportForm = this.formBuilder.group(formBuilderGroup);
|
||||
this.reportForm.valueChanges.subscribe(data => this.onValueChanged(data));
|
||||
}
|
||||
|
||||
public getReportParams(reportId: string) {
|
||||
@@ -161,6 +198,7 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On
|
||||
if (this.reportParameters.hasParameters()) {
|
||||
this.onSuccessReportParams.emit(res);
|
||||
} else {
|
||||
this.reportForm = this.formBuilder.group({});
|
||||
this.onSuccess.emit();
|
||||
}
|
||||
},
|
||||
@@ -193,8 +231,8 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On
|
||||
}
|
||||
|
||||
public submit(values: any) {
|
||||
let reportParamQuery = this.convertFormValuesToReportParamQuery(values);
|
||||
this.onSuccess.emit(reportParamQuery);
|
||||
this.reportParamQuery = this.convertFormValuesToReportParamQuery(values);
|
||||
this.onSuccess.emit(this.reportParamQuery);
|
||||
}
|
||||
|
||||
onValueChanged(values: any) {
|
||||
@@ -209,21 +247,41 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On
|
||||
.format(AnalyticsReportParametersComponent.FORMAT_DATE_ACTIVITI) + 'T00:00:00.000Z';
|
||||
}
|
||||
|
||||
public getTodayDate() {
|
||||
return moment().format(AnalyticsReportParametersComponent.FORMAT_DATE_ACTIVITI);
|
||||
}
|
||||
|
||||
public convertNumber(value: string): number {
|
||||
return value != null ? parseInt(value, 10) : 0;
|
||||
}
|
||||
|
||||
convertFormValuesToReportParamQuery(values: any): ReportQuery {
|
||||
let reportParamQuery: ReportQuery = new ReportQuery();
|
||||
reportParamQuery.dateRange.startDate = this.convertMomentDate(values.dateRange.startDate);
|
||||
reportParamQuery.dateRange.endDate = this.convertMomentDate(values.dateRange.endDate);
|
||||
reportParamQuery.status = values.statusGroup.status;
|
||||
reportParamQuery.processDefinitionId = values.processDefGroup.processDefinitionId;
|
||||
reportParamQuery.taskName = values.taskGroup.taskName;
|
||||
reportParamQuery.duration = values.durationGroup.duration;
|
||||
reportParamQuery.dateRangeInterval = values.dateIntervalGroup.dateRangeInterval;
|
||||
reportParamQuery.slowProcessInstanceInteger = this.convertNumber(values.processInstanceGroup.slowProcessInstanceInteger);
|
||||
reportParamQuery.typeFiltering = values.typeFilteringGroup.typeFiltering;
|
||||
if (values.dateRange) {
|
||||
reportParamQuery.dateRange.startDate = this.convertMomentDate(values.dateRange.startDate);
|
||||
reportParamQuery.dateRange.endDate = this.convertMomentDate(values.dateRange.endDate);
|
||||
}
|
||||
if (values.statusGroup) {
|
||||
reportParamQuery.status = values.statusGroup.status;
|
||||
}
|
||||
if (values.processDefGroup) {
|
||||
reportParamQuery.processDefinitionId = values.processDefGroup.processDefinitionId;
|
||||
}
|
||||
if (values.taskGroup) {
|
||||
reportParamQuery.taskName = values.taskGroup.taskName;
|
||||
}
|
||||
if (values.durationGroup) {
|
||||
reportParamQuery.duration = values.durationGroup.duration;
|
||||
}
|
||||
if (values.dateIntervalGroup) {
|
||||
reportParamQuery.dateRangeInterval = values.dateIntervalGroup.dateRangeInterval;
|
||||
}
|
||||
if (values.processInstanceGroup) {
|
||||
reportParamQuery.slowProcessInstanceInteger = this.convertNumber(values.processInstanceGroup.slowProcessInstanceInteger);
|
||||
}
|
||||
if (values.typeFilteringGroup) {
|
||||
reportParamQuery.typeFiltering = values.typeFilteringGroup.typeFiltering;
|
||||
}
|
||||
return reportParamQuery;
|
||||
}
|
||||
|
||||
@@ -236,7 +294,7 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On
|
||||
}
|
||||
|
||||
public editEnable() {
|
||||
this.isEditable = true;
|
||||
this.isEditable = true;
|
||||
}
|
||||
|
||||
public editDisable() {
|
||||
@@ -256,6 +314,74 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On
|
||||
);
|
||||
}
|
||||
|
||||
public showDialog(event: string) {
|
||||
if (!this.reportNameDialog.nativeElement.showModal) {
|
||||
dialogPolyfill.registerDialog(this.reportNameDialog.nativeElement);
|
||||
}
|
||||
this.reportNameDialog.nativeElement.showModal();
|
||||
this.action = event;
|
||||
this.reportName = this.reportParameters.name + ' ( ' + this.getTodayDate() + ' )';
|
||||
}
|
||||
|
||||
closeDialog() {
|
||||
if (this.reportNameDialog) {
|
||||
this.reportNameDialog.nativeElement.close();
|
||||
}
|
||||
}
|
||||
|
||||
performAction(action: string, reportParamQuery: ReportQuery) {
|
||||
reportParamQuery.reportName = this.reportName;
|
||||
this.closeDialog();
|
||||
if (action === 'Save') {
|
||||
this.doSave(reportParamQuery);
|
||||
} else if (action === 'Export') {
|
||||
this.doExport(reportParamQuery);
|
||||
}
|
||||
this.resetActions();
|
||||
}
|
||||
|
||||
resetActions() {
|
||||
this.action = '';
|
||||
this.reportName = '';
|
||||
}
|
||||
|
||||
isFormValid() {
|
||||
return this.reportForm && this.reportForm.valid && this.reportForm.dirty;
|
||||
}
|
||||
|
||||
isSaveAction() {
|
||||
return this.action === 'Save';
|
||||
}
|
||||
|
||||
doExport(paramQuery: ReportQuery) {
|
||||
this.analyticsService.exportReportToCsv(this.reportId, paramQuery).subscribe(
|
||||
(data: any) => {
|
||||
let blob: Blob = new Blob([data], { type: 'text/csv' });
|
||||
let downloadUrl = window.URL.createObjectURL(blob);
|
||||
this.generateDownloadElement(downloadUrl, paramQuery);
|
||||
});
|
||||
}
|
||||
|
||||
generateDownloadElement(downloadUrl: string, paramQuery: ReportQuery) {
|
||||
let downloadElement = window.document.createElement('a');
|
||||
downloadElement.setAttribute('id', 'export-download');
|
||||
downloadElement.setAttribute('href', downloadUrl);
|
||||
downloadElement.setAttribute('download', paramQuery.reportName);
|
||||
downloadElement.click();
|
||||
}
|
||||
|
||||
doSave(paramQuery: ReportQuery) {
|
||||
this.analyticsService.saveReport(this.reportId, paramQuery).subscribe(() => {
|
||||
this.saveReportSuccess.emit();
|
||||
});
|
||||
}
|
||||
|
||||
deleteReport(reportId: string) {
|
||||
this.analyticsService.deleteReport(reportId).subscribe(() => {
|
||||
this.deleteReportSuccess.emit(reportId);
|
||||
}, error => this.logService.error(error));
|
||||
}
|
||||
|
||||
ngAfterViewChecked() {
|
||||
// workaround for MDL issues with dynamic components
|
||||
if (componentHandler) {
|
||||
|
@@ -1,7 +1,10 @@
|
||||
<div class="col-md-6">
|
||||
<analytics-report-parameters [appId]="appId" [reportId]="reportId"
|
||||
[hideComponent]="hideParameters"
|
||||
(onFormValueChanged)="reset()"
|
||||
(onSuccess)="showReport($event)"
|
||||
(saveReportSuccess)="onSaveReportSuccess()"
|
||||
(deleteReportSuccess)="onDeleteReportSuccess()"
|
||||
(onEdit)="onEditReport($event)">
|
||||
</analytics-report-parameters>
|
||||
|
||||
|
@@ -35,12 +35,21 @@ export class AnalyticsComponent implements OnChanges {
|
||||
@Input()
|
||||
reportId: number;
|
||||
|
||||
@Input()
|
||||
hideParameters: boolean = false;
|
||||
|
||||
@Input()
|
||||
debug: boolean = false;
|
||||
|
||||
@Output()
|
||||
editReport = new EventEmitter();
|
||||
|
||||
@Output()
|
||||
reportSaved = new EventEmitter();
|
||||
|
||||
@Output()
|
||||
reportDeleted = new EventEmitter();
|
||||
|
||||
@ViewChild('analyticsgenerator')
|
||||
analyticsgenerator: AnalyticsGeneratorComponent;
|
||||
|
||||
@@ -71,4 +80,12 @@ export class AnalyticsComponent implements OnChanges {
|
||||
this.editReport.emit(name);
|
||||
}
|
||||
|
||||
public onSaveReportSuccess() {
|
||||
this.reportSaved.emit();
|
||||
}
|
||||
|
||||
public onDeleteReportSuccess() {
|
||||
this.reportDeleted.emit();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
import { Component, Input, Output, EventEmitter } from '@angular/core';
|
||||
import { FormGroup, Validators } from '@angular/forms';
|
||||
import { FormGroup, Validators, FormControl } from '@angular/forms';
|
||||
import { WidgetComponent } from './../widget.component';
|
||||
|
||||
@Component({
|
||||
@@ -54,7 +54,20 @@ export class DropdownWidget extends WidgetComponent {
|
||||
|
||||
ngOnInit() {
|
||||
if (this.required) {
|
||||
this.formGroup.get(this.controllerName).setValidators(Validators.required);
|
||||
this.formGroup.get(this.controllerName).setValidators(Validators.compose(this.buildValidatorList()));
|
||||
}
|
||||
}
|
||||
|
||||
validateDropDown(controller: FormControl) {
|
||||
return controller.value !== 'null' ? null : { controllerName: false };
|
||||
}
|
||||
|
||||
buildValidatorList() {
|
||||
let validatorList = [];
|
||||
validatorList.push(Validators.required);
|
||||
if (this.showDefaultOption) {
|
||||
validatorList.push(this.validateDropDown);
|
||||
}
|
||||
return validatorList;
|
||||
}
|
||||
}
|
||||
|
@@ -6,7 +6,10 @@
|
||||
"FILL-PARAMETER": "Fill in the parameters to generate your report",
|
||||
"NO-DATA-FOUND": "No data found",
|
||||
"ZERO-DATA-FOUND": "There are only zero values",
|
||||
"SETTING-TITLE": "Change report setting"
|
||||
"ICON-SETTING": "Settings",
|
||||
"ICON-SAVE": "Save",
|
||||
"ICON-DELETE": "Delete",
|
||||
"ICON-EXPORT-CSV": "Export to CSV"
|
||||
}
|
||||
},
|
||||
"__KEY_REPORTING": {
|
||||
@@ -43,5 +46,9 @@
|
||||
},
|
||||
"PROCESS-STATUS": "Process status",
|
||||
"TASK-STATUS": "Task status"
|
||||
},
|
||||
"DIALOG":{
|
||||
"SAVE_MESSAGE" : "The current parameter settings will be stored, and a new report will be shown in the reports list. When that particular report is clicked, the report will be generated using these saved parameter values.",
|
||||
"EXPORT_MESSAGE":""
|
||||
}
|
||||
}
|
||||
|
@@ -6,7 +6,10 @@
|
||||
"FILL-PARAMETER": "Riempi tutti i campi per generare il report",
|
||||
"NO-DATA-FOUND": "Nessun valore trovato",
|
||||
"ZERO-DATA-FOUND": "Ci sono solo valori che valgono zero",
|
||||
"SETTING-TITLE": "Modifica i parametri del report"
|
||||
"ICON-SETTING": "Modifica i parametri del report",
|
||||
"ICON-SAVE": "Salva",
|
||||
"ICON-DELETE": "Cancella",
|
||||
"ICON-EXPORT-CSV": "Esporta come CSV"
|
||||
}
|
||||
},
|
||||
"__KEY_REPORTING": {
|
||||
|
@@ -20,11 +20,13 @@ import * as moment from 'moment';
|
||||
export class Chart {
|
||||
id: string;
|
||||
type: string;
|
||||
icon: string;
|
||||
|
||||
constructor(obj?: any) {
|
||||
this.id = obj && obj.id || null;
|
||||
if (obj && obj.type) {
|
||||
this.type = this.convertType(obj.type);
|
||||
this.icon = this.getIconType(this.type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,6 +60,37 @@ export class Chart {
|
||||
}
|
||||
return chartType;
|
||||
}
|
||||
|
||||
private getIconType(type: string): string {
|
||||
let typeIcon: string = '';
|
||||
switch (type) {
|
||||
case 'pie':
|
||||
typeIcon = 'pie_chart';
|
||||
break;
|
||||
case 'table':
|
||||
typeIcon = 'web';
|
||||
break;
|
||||
case 'line':
|
||||
typeIcon = 'show_chart';
|
||||
break;
|
||||
case 'bar':
|
||||
typeIcon = 'equalizer';
|
||||
break;
|
||||
case 'multiBar':
|
||||
typeIcon = 'poll';
|
||||
break;
|
||||
case 'HeatMap':
|
||||
typeIcon = 'share';
|
||||
break;
|
||||
case 'masterDetailTable':
|
||||
typeIcon = 'subtitles';
|
||||
break;
|
||||
default:
|
||||
typeIcon = 'web';
|
||||
break;
|
||||
}
|
||||
return typeIcon;
|
||||
}
|
||||
}
|
||||
|
||||
export class LineChart extends Chart {
|
||||
|
@@ -106,6 +106,7 @@ export class ParameterValueModel {
|
||||
}
|
||||
|
||||
export class ReportQuery {
|
||||
reportName: string;
|
||||
processDefinitionId: string;
|
||||
status: string;
|
||||
taskName: string;
|
||||
@@ -116,6 +117,7 @@ export class ReportQuery {
|
||||
duration: number;
|
||||
|
||||
constructor(obj?: any) {
|
||||
this.reportName = obj && obj.reportName || null;
|
||||
this.processDefinitionId = obj && obj.processDefinitionId || null;
|
||||
this.status = obj && obj.status || null;
|
||||
this.taskName = obj && obj.taskName || null;
|
||||
@@ -125,15 +127,18 @@ export class ReportQuery {
|
||||
this.duration = obj && obj.duration || 0;
|
||||
this.dateRange = new ReportDateRange(obj);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class ReportDateRange {
|
||||
startDate: string;
|
||||
endDate: string;
|
||||
rangeId: string;
|
||||
|
||||
constructor(obj?: any) {
|
||||
this.startDate = obj && obj.startDate || null;
|
||||
this.endDate = obj && obj.endDate || null;
|
||||
this.rangeId = obj && obj.rangeId || null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -126,7 +126,8 @@ export class AnalyticsService {
|
||||
}
|
||||
|
||||
getProcessDefinitionsValues(appId: string): Observable<any> {
|
||||
return Observable.fromPromise(this.apiService.getInstance().activiti.processDefinitionsApi.getProcessDefinitions(appId))
|
||||
let options = { 'appDefinitionId': appId};
|
||||
return Observable.fromPromise(this.apiService.getInstance().activiti.processDefinitionsApi.getProcessDefinitions(options))
|
||||
.map((res: any) => {
|
||||
let paramOptions: ParameterValueModel[] = [];
|
||||
res.data.forEach((opt) => {
|
||||
@@ -184,6 +185,28 @@ export class AnalyticsService {
|
||||
}).catch(err => this.handleError(err));
|
||||
}
|
||||
|
||||
exportReportToCsv(reportId: string, paramsQuery: any): Observable<any> {
|
||||
return Observable.fromPromise(this.apiService.getInstance().activiti.reportApi.exportToCsv(reportId, paramsQuery))
|
||||
.map((res: any) => {
|
||||
this.logService.info('export');
|
||||
return res;
|
||||
}).catch(err => this.handleError(err));
|
||||
}
|
||||
|
||||
saveReport(reportId: string, paramsQuery: any): Observable<any> {
|
||||
return Observable.fromPromise(this.apiService.getInstance().activiti.reportApi.saveReport(reportId, paramsQuery))
|
||||
.map(() => {
|
||||
this.logService.info('save');
|
||||
}).catch(err => this.handleError(err));
|
||||
}
|
||||
|
||||
deleteReport(reportId: string): Observable<any> {
|
||||
return Observable.fromPromise(this.apiService.getInstance().activiti.reportApi.deleteReport(reportId))
|
||||
.map(() => {
|
||||
this.logService.info('delete');
|
||||
}).catch(err => this.handleError(err));
|
||||
}
|
||||
|
||||
private handleError(error: Response) {
|
||||
this.logService.error(error);
|
||||
return Observable.throw(error.json().error || 'Server error');
|
||||
|
@@ -96,8 +96,8 @@ Follow the 3 steps below:
|
||||
- ng2-activiti-diagrams
|
||||
- raphael
|
||||
|
||||
Please refer to the following example file: [systemjs.config.js](demo/systemjs
|
||||
.config.js) .
|
||||
Please refer to the following example file: [systemjs.config.js](demo/systemjs.config.js) .
|
||||
|
||||
|
||||
## Basic usage example Activiti Diagrams
|
||||
|
||||
|
@@ -12,6 +12,7 @@
|
||||
"server": "wsrv -o -s -l",
|
||||
"build": "npm run tslint && npm run clean-build && npm run tsc",
|
||||
"build:w": "npm run tslint && rimraf dist && npm run tsc:w",
|
||||
"travis": "npm link ng2-alfresco-core",
|
||||
"tsc": "tsc",
|
||||
"tsc:w": "tsc -w",
|
||||
"tslint": "tslint -c tslint.json *.ts && tslint -c tslint.json src/{,**/}**.ts -e '{,**/}**.d.ts'"
|
||||
@@ -42,15 +43,15 @@
|
||||
"@angular/material": "2.0.0-beta.1",
|
||||
"@angular/router": "3.2.2",
|
||||
"@angular/upgrade": "2.2.2",
|
||||
"alfresco-js-api": "~1.1.0",
|
||||
"alfresco-js-api": "~1.2.0",
|
||||
"core-js": "^2.4.1",
|
||||
"dialog-polyfill": "^0.4.3",
|
||||
"element.scrollintoviewifneeded-polyfill": "^1.0.1",
|
||||
"intl": "1.2.4",
|
||||
"material-design-icons": "2.2.3",
|
||||
"material-design-lite": "1.2.1",
|
||||
"ng2-activiti-diagrams": "^1.1.0",
|
||||
"ng2-alfresco-core": "1.1.0",
|
||||
"ng2-activiti-diagrams": "1.2.0",
|
||||
"ng2-alfresco-core": "1.2.0",
|
||||
"ng2-translate": "2.5.0",
|
||||
"raphael": "^2.2.6",
|
||||
"reflect-metadata": "^0.1.3",
|
||||
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "ng2-activiti-diagrams",
|
||||
"description": "Activiti Angular2 Diagrams Component",
|
||||
"version": "1.1.0",
|
||||
"version": "1.2.0",
|
||||
"author": "Alfresco Software, Ltd.",
|
||||
"scripts": {
|
||||
"clean": "npm install rimraf && npm run clean-build && rimraf dist node_modules typings",
|
||||
@@ -55,12 +55,12 @@
|
||||
"zone.js": "^0.6.23",
|
||||
"raphael": "^2.2.6",
|
||||
"ng2-translate": "2.5.0",
|
||||
"alfresco-js-api": "~1.1.0",
|
||||
"ng2-alfresco-core": "1.1.0"
|
||||
"alfresco-js-api": "~1.2.0",
|
||||
"ng2-alfresco-core": "1.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jasmine": "^2.2.33",
|
||||
"@types/node": "^6.0.42",
|
||||
"@types/jasmine": "2.5.35",
|
||||
"@types/node": "6.0.45",
|
||||
"autoprefixer": "^6.5.4",
|
||||
"concurrently": "^2.2.0",
|
||||
"cpx": "1.3.1",
|
||||
|
@@ -114,8 +114,8 @@ Follow the 3 steps below:
|
||||
- alfresco-js-api
|
||||
- ng2-activiti-form
|
||||
|
||||
Please refer to the following example file: [systemjs.config.js](demo/systemjs
|
||||
.config.js) .
|
||||
Please refer to the following example file: [systemjs.config.js](demo/systemjs.config.js) .
|
||||
|
||||
|
||||
## ActivitiForm Component
|
||||
|
||||
@@ -351,6 +351,32 @@ There are two additional functions that can be of a great value when controlling
|
||||
**Please note that if `event.preventDefault()` is not called then default outcome behaviour
|
||||
will also be executed after your custom code.**
|
||||
|
||||
## Activiti Content Component
|
||||
|
||||
### Basic usage
|
||||
|
||||
The component shows the content preview.
|
||||
|
||||
```html
|
||||
<activiti-content [contentId]="'1001'"></activiti-content>
|
||||
```
|
||||
|
||||
### Configuration
|
||||
|
||||
#### Properties
|
||||
|
||||
The recommended set of properties can be found in the following table:
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `contentId` | string | | The content id to show. |
|
||||
|
||||
#### Events
|
||||
|
||||
| Name | Description |
|
||||
| --- | --- |
|
||||
| `contentClick` | Invoked when the content is clicked. |
|
||||
|
||||
## FormService
|
||||
|
||||
```ts
|
||||
|
@@ -12,6 +12,7 @@
|
||||
"server": "wsrv -o -s -l",
|
||||
"build": "npm run tslint && npm run clean-build && npm run tsc",
|
||||
"build:w": "npm run tslint && rimraf dist && npm run tsc:w",
|
||||
"travis": "npm link ng2-alfresco-core",
|
||||
"tsc": "tsc",
|
||||
"tsc:w": "tsc -w",
|
||||
"tslint": "tslint -c tslint.json *.ts && tslint -c tslint.json src/{,**/}**.ts -e '{,**/}**.d.ts'"
|
||||
@@ -55,9 +56,9 @@
|
||||
"moment": "2.15.1",
|
||||
"md-date-time-picker": "^2.2.0",
|
||||
"ng2-translate": "2.5.0",
|
||||
"alfresco-js-api": "~1.1.0",
|
||||
"ng2-alfresco-core": "1.1.0",
|
||||
"ng2-activiti-form": "^1.1.0"
|
||||
"alfresco-js-api": "~1.2.0",
|
||||
"ng2-alfresco-core": "1.2.0",
|
||||
"ng2-activiti-form": "1.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jasmine": "^2.2.33",
|
||||
|
@@ -19,6 +19,7 @@ import { NgModule, ModuleWithProviders } from '@angular/core';
|
||||
import { CoreModule } from 'ng2-alfresco-core';
|
||||
|
||||
import { ActivitiForm } from './src/components/activiti-form.component';
|
||||
import { ActivitiContent } from './src/components/activiti-content.component';
|
||||
import { FormFieldComponent } from './src/components/form-field/form-field.component';
|
||||
import { ActivitiStartForm } from './src/components/activiti-start-form.component';
|
||||
import { FormService } from './src/services/form.service';
|
||||
@@ -31,6 +32,7 @@ import { HttpModule } from '@angular/http';
|
||||
import { WIDGET_DIRECTIVES } from './src/components/widgets/index';
|
||||
|
||||
export * from './src/components/activiti-form.component';
|
||||
export * from './src/components/activiti-content.component';
|
||||
export * from './src/components/activiti-start-form.component';
|
||||
export * from './src/services/form.service';
|
||||
export * from './src/components/widgets/index';
|
||||
@@ -41,6 +43,7 @@ export * from './src/events/index';
|
||||
|
||||
export const ACTIVITI_FORM_DIRECTIVES: any[] = [
|
||||
ActivitiForm,
|
||||
ActivitiContent,
|
||||
ActivitiStartForm,
|
||||
FormFieldComponent,
|
||||
...WIDGET_DIRECTIVES
|
||||
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "ng2-activiti-form",
|
||||
"description": "Alfresco Activiti Form Component for Angular 2",
|
||||
"version": "1.1.0",
|
||||
"version": "1.2.0",
|
||||
"author": "Alfresco Software, Ltd.",
|
||||
"scripts": {
|
||||
"clean": "npm install rimraf && npm run clean-build && rimraf dist node_modules typings",
|
||||
@@ -63,12 +63,12 @@
|
||||
"moment": "2.15.1",
|
||||
"md-date-time-picker": "^2.2.0",
|
||||
"ng2-translate": "2.5.0",
|
||||
"alfresco-js-api": "~1.1.0",
|
||||
"ng2-alfresco-core": "1.1.0"
|
||||
"alfresco-js-api": "~1.2.0",
|
||||
"ng2-alfresco-core": "1.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jasmine": "^2.2.33",
|
||||
"@types/node": "^6.0.42",
|
||||
"@types/jasmine": "2.5.35",
|
||||
"@types/node": "6.0.45",
|
||||
"autoprefixer": "^6.5.4",
|
||||
"concurrently": "^2.2.0",
|
||||
"cpx": "^1.3.1",
|
||||
|
@@ -0,0 +1,42 @@
|
||||
.upload-widget {
|
||||
width: 100%;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.upload-widget__icon {
|
||||
float: left;
|
||||
color: rgba(0, 0, 0, .26);
|
||||
}
|
||||
|
||||
.upload-widget__file {
|
||||
float: left;
|
||||
margin-top: 4px;
|
||||
color: rgba(0, 0, 0, .26);
|
||||
}
|
||||
|
||||
.upload-widget__label {
|
||||
color: rgba(0, 0, 0, .26);
|
||||
}
|
||||
|
||||
.img-upload-widget {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 1px solid rgba(117, 117, 117, 0.57);
|
||||
box-shadow: 1px 1px 2px #dddddd;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.nothing-to-see {
|
||||
box-shadow: 1px 1px 2px #dddddd;
|
||||
background-color: #ffffff;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 50px 0 50px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.previewTxt {
|
||||
word-wrap: break-word;
|
||||
word-break: break-all;
|
||||
text-align: center;
|
||||
}
|
@@ -0,0 +1,22 @@
|
||||
<div class="upload-widget" *ngIf="content">
|
||||
<div class="mdl-card mdl-shadow--2dp">
|
||||
<div class="mdl-card__title mdl-card--expand">
|
||||
<div *ngIf="content.isThumbnailSupported()">
|
||||
<img class="img-upload-widget" [src]="sanitizeUrl(content.thumbnailUrl)">
|
||||
</div>
|
||||
<div *ngIf="!content.isThumbnailSupported()">
|
||||
<i class="material-icons">image</i>
|
||||
<div class="previewTxt">{{ 'FORM.PREVIEW.IMAGE_NOT_AVAILABLE' | translate }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mdl-card__supporting-text">{{content.name}}</div>
|
||||
<div class="mdl-card__actions mdl-card--border">
|
||||
<button (click)="openViewer(content)" class="mdl-button mdl-js-button mdl-button--icon">
|
||||
<i class="material-icons">zoom_in</i>
|
||||
</button>
|
||||
<a (click)="download($event)" [href]="content.contentRawUrl" target="_blank" [download]='content.name' class="mdl-button mdl-js-button mdl-button--icon">
|
||||
<i class="material-icons">file_download</i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@@ -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.
|
||||
*/
|
||||
|
||||
import {
|
||||
Component,
|
||||
OnChanges,
|
||||
SimpleChanges,
|
||||
Input,
|
||||
Output,
|
||||
EventEmitter
|
||||
} from '@angular/core';
|
||||
import { AlfrescoTranslationService, LogService } from 'ng2-alfresco-core';
|
||||
import { FormService } from './../services/form.service';
|
||||
import { ContentLinkModel } from './widgets/core/content-link.model';
|
||||
import { DomSanitizer } from '@angular/platform-browser';
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: 'activiti-content',
|
||||
templateUrl: './activiti-content.component.html',
|
||||
styleUrls: ['./activiti-content.component.css']
|
||||
})
|
||||
export class ActivitiContent implements OnChanges {
|
||||
|
||||
@Input()
|
||||
id: string;
|
||||
|
||||
@Output()
|
||||
contentClick = new EventEmitter();
|
||||
|
||||
content: ContentLinkModel;
|
||||
|
||||
constructor(private translate: AlfrescoTranslationService,
|
||||
protected formService: FormService,
|
||||
private logService: LogService,
|
||||
private sanitizer: DomSanitizer ) {
|
||||
|
||||
if (this.translate) {
|
||||
this.translate.addTranslationFolder('ng2-activiti-form', 'node_modules/ng2-activiti-form/src');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
let contentId = changes['id'];
|
||||
if (contentId && contentId.currentValue) {
|
||||
this.loadContent(contentId.currentValue);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
loadContent(id: number) {
|
||||
this.formService
|
||||
.getFileContent(id)
|
||||
.subscribe(
|
||||
(response: ContentLinkModel) => {
|
||||
this.content = new ContentLinkModel(response);
|
||||
this.loadThumbnailUrl(this.content);
|
||||
},
|
||||
error => {
|
||||
this.logService.error(error);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
loadThumbnailUrl(content: ContentLinkModel) {
|
||||
if (this.content.isTypeImage()) {
|
||||
this.formService.getFileRawContent(content.id).subscribe(
|
||||
(response: Blob) => {
|
||||
this.content.thumbnailUrl = this.createUrlPreview(response);
|
||||
},
|
||||
error => {
|
||||
this.logService.error(error);
|
||||
}
|
||||
);
|
||||
} else if (this.content.isThumbnailSupported()) {
|
||||
this.content.contentRawUrl = this.formService.getFileRawContentUrl(content.id);
|
||||
this.content.thumbnailUrl = this.formService.getContentThumbnailUrl(content.id);
|
||||
}
|
||||
}
|
||||
|
||||
openViewer(content: ContentLinkModel) {
|
||||
this.contentClick.emit(content);
|
||||
this.logService.info('Content clicked' + content.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Download file opening it in a new window
|
||||
*/
|
||||
download($event) {
|
||||
$event.stopPropagation();
|
||||
}
|
||||
|
||||
private sanitizeUrl(url: string) {
|
||||
return this.sanitizer.bypassSecurityTrustUrl(url);
|
||||
}
|
||||
|
||||
private createUrlPreview(blob: Blob) {
|
||||
let imageUrl = window.URL.createObjectURL(blob);
|
||||
let sanitize: any = this.sanitizeUrl(imageUrl);
|
||||
return sanitize.changingThisBreaksApplicationSecurity;
|
||||
}
|
||||
}
|
@@ -425,7 +425,7 @@ describe('ActivitiForm', () => {
|
||||
expect(formComponent.onOutcomeClicked(outcome)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should fetch and parse form by task id', () => {
|
||||
it('should fetch and parse form by task id', (done) => {
|
||||
spyOn(formService, 'getTask').and.returnValue(Observable.of({}));
|
||||
spyOn(formService, 'getTaskForm').and.callFake((taskId) => {
|
||||
return Observable.create(observer => {
|
||||
@@ -435,19 +435,18 @@ describe('ActivitiForm', () => {
|
||||
});
|
||||
|
||||
const taskId = '456';
|
||||
let loaded = false;
|
||||
formComponent.formLoaded.subscribe(() => loaded = true);
|
||||
formComponent.formLoaded.subscribe(() => {
|
||||
expect(formService.getTaskForm).toHaveBeenCalledWith(taskId);
|
||||
expect(formComponent.form).toBeDefined();
|
||||
expect(formComponent.form.taskId).toBe(taskId);
|
||||
done();
|
||||
});
|
||||
|
||||
expect(formComponent.form).toBeUndefined();
|
||||
formComponent.getFormByTaskId(taskId);
|
||||
|
||||
expect(loaded).toBeTruthy();
|
||||
expect(formService.getTaskForm).toHaveBeenCalledWith(taskId);
|
||||
expect(formComponent.form).toBeDefined();
|
||||
expect(formComponent.form.taskId).toBe(taskId);
|
||||
});
|
||||
|
||||
it('should handle error when getting form by task id', () => {
|
||||
it('should handle error when getting form by task id', (done) => {
|
||||
const error = 'Some error';
|
||||
|
||||
spyOn(formService, 'getTask').and.returnValue(Observable.of({}));
|
||||
@@ -456,11 +455,13 @@ describe('ActivitiForm', () => {
|
||||
return Observable.throw(error);
|
||||
});
|
||||
|
||||
formComponent.getFormByTaskId('123');
|
||||
expect(formComponent.handleError).toHaveBeenCalledWith(error);
|
||||
formComponent.getFormByTaskId('123').then(_ => {
|
||||
expect(formComponent.handleError).toHaveBeenCalledWith(error);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should apply readonly state when getting form by task id', () => {
|
||||
it('should apply readonly state when getting form by task id', (done) => {
|
||||
spyOn(formService, 'getTask').and.returnValue(Observable.of({}));
|
||||
spyOn(formService, 'getTaskForm').and.callFake((taskId) => {
|
||||
return Observable.create(observer => {
|
||||
@@ -470,10 +471,11 @@ describe('ActivitiForm', () => {
|
||||
});
|
||||
|
||||
formComponent.readOnly = true;
|
||||
formComponent.getFormByTaskId('123');
|
||||
|
||||
expect(formComponent.form).toBeDefined();
|
||||
expect(formComponent.form.readOnly).toBe(true);
|
||||
formComponent.getFormByTaskId('123').then(_ => {
|
||||
expect(formComponent.form).toBeDefined();
|
||||
expect(formComponent.form.readOnly).toBe(true);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should fetch and parse form definition by id', () => {
|
||||
|
@@ -305,16 +305,24 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
|
||||
}
|
||||
}
|
||||
|
||||
loadFormPorcessVariable(taskId) {
|
||||
this.formService.getTask(taskId).subscribe(
|
||||
task => {
|
||||
if (this.isAProcessTask(task)) {
|
||||
this.visibilityService.getTaskProcessVariable(taskId).subscribe();
|
||||
loadFormProcessVariables(taskId: string): Promise<boolean> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.formService.getTask(taskId).subscribe(
|
||||
task => {
|
||||
if (this.isAProcessTask(task)) {
|
||||
this.visibilityService.getTaskProcessVariable(taskId).subscribe(_ => {
|
||||
resolve(true);
|
||||
});
|
||||
} else {
|
||||
resolve(true);
|
||||
}
|
||||
},
|
||||
error => {
|
||||
this.handleError(error);
|
||||
resolve(false);
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
this.handleError(error);
|
||||
});
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
isAProcessTask(taskRepresentation) {
|
||||
@@ -330,20 +338,25 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
|
||||
return false;
|
||||
}
|
||||
|
||||
getFormByTaskId(taskId: string) {
|
||||
this.loadFormPorcessVariable(this.taskId);
|
||||
let data = this.data;
|
||||
this.formService
|
||||
.getTaskForm(taskId)
|
||||
.subscribe(
|
||||
form => {
|
||||
this.form = new FormModel(form, data, this.readOnly, this.formService);
|
||||
this.onFormLoaded(this.form);
|
||||
},
|
||||
(error) => {
|
||||
this.handleError(error);
|
||||
}
|
||||
);
|
||||
getFormByTaskId(taskId: string): Promise<FormModel> {
|
||||
return new Promise<FormModel>((resolve, reject) => {
|
||||
this.loadFormProcessVariables(this.taskId).then(_ => {
|
||||
this.formService
|
||||
.getTaskForm(taskId)
|
||||
.subscribe(
|
||||
form => {
|
||||
this.form = new FormModel(form, this.data, this.readOnly, this.formService);
|
||||
this.onFormLoaded(this.form);
|
||||
resolve(this.form);
|
||||
},
|
||||
error => {
|
||||
this.handleError(error);
|
||||
// reject(error);
|
||||
resolve(null);
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getFormDefinitionByFormId(formId: string) {
|
||||
|
@@ -21,6 +21,7 @@ import { Observable } from 'rxjs/Rx';
|
||||
|
||||
import { ActivitiStartForm } from './activiti-start-form.component';
|
||||
import { FormFieldComponent } from './form-field/form-field.component';
|
||||
import { ActivitiContent } from './activiti-content.component';
|
||||
import { WIDGET_DIRECTIVES } from './widgets/index';
|
||||
import { FormService } from './../services/form.service';
|
||||
import { EcmModelService } from './../services/ecm-model.service';
|
||||
@@ -45,6 +46,7 @@ describe('ActivitiStartForm', () => {
|
||||
declarations: [
|
||||
ActivitiStartForm,
|
||||
FormFieldComponent,
|
||||
ActivitiContent,
|
||||
...WIDGET_DIRECTIVES
|
||||
],
|
||||
providers: [
|
||||
|
@@ -24,6 +24,7 @@ import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||
import { CoreModule } from 'ng2-alfresco-core';
|
||||
import { WIDGET_DIRECTIVES } from '../index';
|
||||
import { FormFieldComponent } from './../../form-field/form-field.component';
|
||||
import { ActivitiContent } from './../../activiti-content.component';
|
||||
import { fakeFormJson } from '../../../services/assets/widget-visibility.service.mock';
|
||||
|
||||
describe('ContainerWidget', () => {
|
||||
@@ -132,7 +133,7 @@ describe('ContainerWidget', () => {
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [CoreModule],
|
||||
declarations: [FormFieldComponent, WIDGET_DIRECTIVES]
|
||||
declarations: [FormFieldComponent, ActivitiContent, WIDGET_DIRECTIVES]
|
||||
}).compileComponents().then(() => {
|
||||
fixture = TestBed.createComponent(ContainerWidget);
|
||||
containerWidgetComponent = fixture.componentInstance;
|
||||
|
@@ -0,0 +1,71 @@
|
||||
/*!
|
||||
* @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 ContentLinkModel {
|
||||
|
||||
contentAvailable: boolean;
|
||||
created: string;
|
||||
createdBy: any;
|
||||
id: number;
|
||||
link: boolean;
|
||||
mimeType: string;
|
||||
name: string;
|
||||
previewStatus: string;
|
||||
relatedContent: boolean;
|
||||
simpleType: string;
|
||||
thumbnailUrl: string;
|
||||
contentRawUrl: string;
|
||||
thumbnailStatus: string;
|
||||
|
||||
constructor(obj?: any) {
|
||||
this.contentAvailable = obj && obj.contentAvailable;
|
||||
this.created = obj && obj.created;
|
||||
this.createdBy = obj && obj.createdBy || {};
|
||||
this.id = obj && obj.id;
|
||||
this.link = obj && obj.link;
|
||||
this.mimeType = obj && obj.mimeType;
|
||||
this.name = obj && obj.name;
|
||||
this.previewStatus = obj && obj.previewStatus;
|
||||
this.relatedContent = obj && obj.relatedContent;
|
||||
this.simpleType = obj && obj.simpleType;
|
||||
this.thumbnailStatus = obj && obj.thumbnailStatus;
|
||||
}
|
||||
|
||||
hasPreviewStatus(): boolean {
|
||||
return this.previewStatus === 'supported' ? true : false;
|
||||
}
|
||||
|
||||
isTypeImage(): boolean {
|
||||
return this.simpleType === 'image' ? true : false;
|
||||
}
|
||||
|
||||
isTypePdf(): boolean {
|
||||
return this.simpleType === 'pdf' ? true : false;
|
||||
}
|
||||
|
||||
isTypeDoc(): boolean {
|
||||
return this.simpleType === 'word' || this.simpleType === 'content' ? true : false;
|
||||
}
|
||||
|
||||
isThumbnailReady(): boolean {
|
||||
return this.thumbnailStatus === 'created';
|
||||
}
|
||||
|
||||
isThumbnailSupported(): boolean {
|
||||
return this.isTypeImage() || ((this.isTypePdf() || this.isTypeDoc()) && this.isThumbnailReady());
|
||||
}
|
||||
}
|
@@ -29,3 +29,4 @@ export * from './tab.model';
|
||||
export * from './form-outcome.model';
|
||||
export * from './form-outcome-event.model';
|
||||
export * from './form-field-validator';
|
||||
export * from './content-link.model';
|
||||
|
@@ -21,32 +21,3 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
.upload-widget {
|
||||
width: 100%;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.upload-widget__icon {
|
||||
float: left;
|
||||
color: rgba(0, 0, 0, .26);
|
||||
}
|
||||
|
||||
.upload-widget__file {
|
||||
float: left;
|
||||
margin-top: 4px;
|
||||
color: rgba(0, 0, 0, .26);
|
||||
}
|
||||
|
||||
.upload-widget__label {
|
||||
color: rgba(0, 0, 0, .26);
|
||||
}
|
||||
|
||||
.img-upload-widget {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
padding: 2px;
|
||||
border: 1px solid rgba(117, 117, 117, 0.57);
|
||||
box-shadow: 1px 1px 2px #dddddd;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@
|
||||
<label class="mdl-checkbox mdl-js-checkbox" [attr.for]="field.id" >
|
||||
<input type="checkbox"
|
||||
[attr.id]="field.id"
|
||||
[checked]="field.value"
|
||||
[checked]="value"
|
||||
[(ngModel)]="value"
|
||||
class="mdl-checkbox__input"
|
||||
disabled>
|
||||
@@ -68,16 +68,9 @@
|
||||
</div>
|
||||
</div>
|
||||
<div *ngSwitchCase="'upload'">
|
||||
<div class="upload-widget">
|
||||
<div>
|
||||
<label class="upload-widget__label" [attr.for]="field.id">{{field.name}}</label>
|
||||
</div>
|
||||
<div>
|
||||
<img *ngIf="hasFile" class="img-upload-widget" src="{{settingsService.bpmHost}}/activiti-app/app/rest/content/{{id}}/raw">
|
||||
</div>
|
||||
<div>
|
||||
<i *ngIf="hasFile" class="material-icons upload-widget__icon">attachment</i>
|
||||
<span *ngIf="hasFile" class="upload-widget__file">{{value}}</span>
|
||||
<div *ngIf="hasFile" class="mdl-grid">
|
||||
<div *ngFor="let file of field.value" class="mdl-cell mdl-cell--6-col">
|
||||
<activiti-content [id]="file.id"></activiti-content>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -20,6 +20,7 @@ import { CoreModule, LogServiceMock } from 'ng2-alfresco-core';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
import { DisplayValueWidget } from './display-value.widget';
|
||||
import { FormService } from '../../../services/form.service';
|
||||
import { ActivitiContent } from '../../activiti-content.component';
|
||||
import { EcmModelService } from '../../../services/ecm-model.service';
|
||||
import { FormFieldModel } from './../core/form-field.model';
|
||||
import { FormFieldTypes } from '../core/form-field-types';
|
||||
@@ -688,7 +689,7 @@ describe('DisplayValueWidget', () => {
|
||||
window['componentHandler'] = componentHandler;
|
||||
TestBed.configureTestingModule({
|
||||
imports: [CoreModule],
|
||||
declarations: [DisplayValueWidget],
|
||||
declarations: [DisplayValueWidget, ActivitiContent],
|
||||
providers: [
|
||||
EcmModelService,
|
||||
FormService,
|
||||
|
@@ -23,6 +23,7 @@ import { TabsWidget } from './tabs.widget';
|
||||
import { TabModel } from '../core/tab.model';
|
||||
import { WIDGET_DIRECTIVES } from '../index';
|
||||
import { FormFieldComponent } from './../../form-field/form-field.component';
|
||||
import { ActivitiContent } from './../../activiti-content.component';
|
||||
import { CoreModule } from 'ng2-alfresco-core';
|
||||
|
||||
describe('TabsWidget', () => {
|
||||
@@ -103,7 +104,7 @@ describe('TabsWidget', () => {
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [CoreModule],
|
||||
declarations: [FormFieldComponent, WIDGET_DIRECTIVES]
|
||||
declarations: [FormFieldComponent, ActivitiContent, WIDGET_DIRECTIVES]
|
||||
}).compileComponents().then(() => {
|
||||
fixture = TestBed.createComponent(TabsWidget);
|
||||
tabWidgetComponent = fixture.componentInstance;
|
||||
|
@@ -2,6 +2,9 @@
|
||||
"FORM": {
|
||||
"START_FORM": {
|
||||
"TITLE": "Start Form"
|
||||
},
|
||||
"PREVIEW": {
|
||||
"IMAGE_NOT_AVAILABLE": "The preview image is not available."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
10
ng2-components/ng2-activiti-form/src/i18n/it.json
Normal file
10
ng2-components/ng2-activiti-form/src/i18n/it.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"FORM": {
|
||||
"START_FORM": {
|
||||
"TITLE": "Inizia"
|
||||
},
|
||||
"PREVIEW": {
|
||||
"IMAGE_NOT_AVAILABLE": "Anteprima immagine non disponibile."
|
||||
}
|
||||
}
|
||||
}
|
@@ -30,6 +30,7 @@ describe('FormService', () => {
|
||||
let service: FormService;
|
||||
let apiService: AlfrescoApiService;
|
||||
let logService: LogService;
|
||||
let bpmCli: any;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
@@ -44,6 +45,7 @@ describe('FormService', () => {
|
||||
});
|
||||
service = TestBed.get(FormService);
|
||||
apiService = TestBed.get(AlfrescoApiService);
|
||||
bpmCli = apiService.getInstance().bpmAuth;
|
||||
logService = TestBed.get(LogService);
|
||||
});
|
||||
|
||||
@@ -374,6 +376,81 @@ describe('FormService', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should return the unsupported content when the file is an image', (done) => {
|
||||
let contentId: number = 999;
|
||||
responseBody = {
|
||||
id: contentId,
|
||||
name: 'fake-name.jpg',
|
||||
created: '2017-01-23T12:12:53.219+0000',
|
||||
createdBy: {id: 2, firstName: 'fake-admin', lastName: 'fake-last', 'email': 'fake-admin'},
|
||||
relatedContent: false,
|
||||
contentAvailable: true,
|
||||
link: false,
|
||||
mimeType: 'image/jpeg',
|
||||
simpleType: 'image',
|
||||
previewStatus: 'unsupported',
|
||||
thumbnailStatus: 'unsupported'
|
||||
};
|
||||
|
||||
service.getFileContent(contentId).subscribe(result => {
|
||||
expect(result.id).toEqual(contentId);
|
||||
expect(result.name).toEqual('fake-name.jpg');
|
||||
expect(result.simpleType).toEqual('image');
|
||||
expect(result.thumbnailStatus).toEqual('unsupported');
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 200,
|
||||
contentType: 'application/json',
|
||||
responseText: JSON.stringify(responseBody)
|
||||
});
|
||||
});
|
||||
|
||||
it('should return the supported content when the file is a pdf', (done) => {
|
||||
let contentId: number = 888;
|
||||
responseBody = {
|
||||
id: contentId,
|
||||
name: 'fake-name.pdf',
|
||||
created: '2017-01-23T12:12:53.219+0000',
|
||||
createdBy: {id: 2, firstName: 'fake-admin', lastName: 'fake-last', 'email': 'fake-admin'},
|
||||
relatedContent: false,
|
||||
contentAvailable: true,
|
||||
link: false,
|
||||
mimeType: 'application/pdf',
|
||||
simpleType: 'pdf',
|
||||
previewStatus: 'created',
|
||||
thumbnailStatus: 'created'
|
||||
};
|
||||
|
||||
service.getFileContent(contentId).subscribe(result => {
|
||||
expect(result.id).toEqual(contentId);
|
||||
expect(result.name).toEqual('fake-name.pdf');
|
||||
expect(result.simpleType).toEqual('pdf');
|
||||
expect(result.thumbnailStatus).toEqual('created');
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 200,
|
||||
contentType: 'application/json',
|
||||
responseText: JSON.stringify(responseBody)
|
||||
});
|
||||
});
|
||||
|
||||
it('should return the raw content URL', () => {
|
||||
let contentId: number = 999;
|
||||
let contentRawUrl = service.getFileRawContentUrl(contentId);
|
||||
expect(contentRawUrl).toEqual(`${bpmCli.basePath}/api/enterprise/content/${contentId}/raw`);
|
||||
});
|
||||
|
||||
it('should return the thumbnail URL', () => {
|
||||
let contentId: number = 999;
|
||||
|
||||
let contentRawUrl = service.getContentThumbnailUrl(contentId);
|
||||
expect(contentRawUrl).toEqual(`${bpmCli.basePath}/app/rest/content/${contentId}/rendition/thumbnail`);
|
||||
});
|
||||
|
||||
it('should create a Form form a Node', (done) => {
|
||||
|
||||
let nameForm = 'testNode';
|
||||
|
@@ -252,6 +252,26 @@ export class FormService {
|
||||
return Observable.fromPromise(this.apiService.getInstance().activiti.contentApi.createTemporaryRawRelatedContent(file));
|
||||
}
|
||||
|
||||
getFileContent(contentId: number): Observable<any> {
|
||||
let alfrescoApi = this.apiService.getInstance();
|
||||
return Observable.fromPromise(alfrescoApi.activiti.contentApi.getContent(contentId));
|
||||
}
|
||||
|
||||
getFileRawContent(contentId: number): Observable<any> {
|
||||
let alfrescoApi = this.apiService.getInstance();
|
||||
return Observable.fromPromise(alfrescoApi.activiti.contentApi.getRawContent(contentId));
|
||||
}
|
||||
|
||||
getFileRawContentUrl(contentId: number): string {
|
||||
let alfrescoApi = this.apiService.getInstance();
|
||||
return alfrescoApi.activiti.contentApi.getRawContentUrl(contentId);
|
||||
}
|
||||
|
||||
getContentThumbnailUrl(contentId: number): string {
|
||||
let alfrescoApi = this.apiService.getInstance();
|
||||
return alfrescoApi.activiti.contentApi.getContentThumbnailUrl(contentId);
|
||||
}
|
||||
|
||||
getRestFieldValues(taskId: string, field: string): Observable<any> {
|
||||
let alfrescoApi = this.apiService.getInstance();
|
||||
return Observable.fromPromise(alfrescoApi.activiti.taskApi.getRestFieldValues(taskId, field));
|
||||
|
@@ -143,7 +143,7 @@ export class WidgetVisibilityService {
|
||||
if (field.value && field.value.name) {
|
||||
value = field.value.name;
|
||||
} else if (field.options) {
|
||||
let option = field.options.find(option => option.id === field.value);
|
||||
let option = field.options.find(opt => opt.id === field.value);
|
||||
if (option) {
|
||||
value = option.name;
|
||||
} else {
|
||||
|
@@ -104,8 +104,8 @@ Follow the 3 steps below:
|
||||
- ng2-activiti-tasklist
|
||||
- ng2-activiti-processlist
|
||||
|
||||
Please refer to the following example file: [systemjs.config.js](demo/systemjs
|
||||
.config.js) .
|
||||
Please refer to the following example file: [systemjs.config.js](demo/systemjs.config.js) .
|
||||
|
||||
|
||||
## Basic usage
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ng2-activiti-processlist-demo",
|
||||
"description": "Show available processes from the Activiti BPM suite - Demo",
|
||||
"description": "Show available processes from the Activiti Process Services suite - Demo",
|
||||
"version": "0.1.0",
|
||||
"author": "Will Abson",
|
||||
"main": "index.js",
|
||||
@@ -12,6 +12,7 @@
|
||||
"server": "wsrv -o -s -l",
|
||||
"build": "npm run tslint && npm run clean-build && npm run tsc",
|
||||
"build:w": "npm run tslint && rimraf dist && npm run tsc:w",
|
||||
"travis": "npm link ng2-alfresco-core ng2-alfresco-datatable ng2-activiti-form ng2-activiti-tasklist",
|
||||
"tsc": "tsc",
|
||||
"tsc:w": "tsc -w",
|
||||
"tslint": "tslint -c tslint.json *.ts && tslint -c tslint.json src/{,**/}**.ts -e '{,**/}**.d.ts'"
|
||||
@@ -48,11 +49,11 @@
|
||||
"moment": "2.15.1",
|
||||
"md-date-time-picker": "^2.2.0",
|
||||
"ng2-translate": "2.5.0",
|
||||
"alfresco-js-api": "~1.1.0",
|
||||
"ng2-activiti-tasklist": "1.1.0",
|
||||
"ng2-alfresco-core": "1.1.0",
|
||||
"ng2-alfresco-datatable": "1.1.0",
|
||||
"ng2-activiti-processlist": "^1.1.0"
|
||||
"alfresco-js-api": "~1.2.0",
|
||||
"ng2-activiti-tasklist": "1.2.0",
|
||||
"ng2-alfresco-core": "1.2.0",
|
||||
"ng2-alfresco-datatable": "1.2.0",
|
||||
"ng2-activiti-processlist": "1.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jasmine": "^2.2.33",
|
||||
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "ng2-activiti-processlist",
|
||||
"description": "Show active processes from the Activiti BPM suite",
|
||||
"version": "1.1.0",
|
||||
"description": "Show active processes from the Activiti Process Services suite",
|
||||
"version": "1.2.0",
|
||||
"author": "Alfresco Software, Ltd.",
|
||||
"scripts": {
|
||||
"clean": "npm install rimraf && npm run clean-build && rimraf dist node_modules typings",
|
||||
@@ -62,15 +62,15 @@
|
||||
"moment": "2.15.1",
|
||||
"md-date-time-picker": "^2.2.0",
|
||||
"ng2-translate": "2.5.0",
|
||||
"alfresco-js-api": "~1.1.0",
|
||||
"ng2-activiti-form": "1.1.0",
|
||||
"ng2-activiti-tasklist": "1.1.0",
|
||||
"ng2-alfresco-core": "1.1.0",
|
||||
"ng2-alfresco-datatable": "1.1.0"
|
||||
"alfresco-js-api": "~1.2.0",
|
||||
"ng2-activiti-form": "1.2.0",
|
||||
"ng2-activiti-tasklist": "1.2.0",
|
||||
"ng2-alfresco-core": "1.2.0",
|
||||
"ng2-alfresco-datatable": "1.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jasmine": "^2.2.33",
|
||||
"@types/node": "^6.0.42",
|
||||
"@types/jasmine": "2.5.35",
|
||||
"@types/node": "6.0.45",
|
||||
"autoprefixer": "^6.5.4",
|
||||
"concurrently": "^2.2.0",
|
||||
"cpx": "^1.3.1",
|
||||
|
@@ -103,8 +103,8 @@ Follow the 3 steps below:
|
||||
- ng2-alfresco-datatable
|
||||
- ng2-activiti-tasklist
|
||||
|
||||
Please refer to the following example file: [systemjs.config.js](demo/systemjs
|
||||
.config.js) .
|
||||
Please refer to the following example file: [systemjs.config.js](demo/systemjs.config.js) .
|
||||
|
||||
|
||||
## Basic usage example Activiti Task List
|
||||
|
||||
|
@@ -12,6 +12,7 @@
|
||||
"server": "wsrv -o -s -l",
|
||||
"build": "npm run tslint && npm run clean-build && npm run tsc",
|
||||
"build:w": "npm run tslint && rimraf dist && npm run tsc:w",
|
||||
"travis": "npm link ng2-alfresco-core ng2-alfresco-datatable ng2-activiti-form",
|
||||
"tsc": "tsc",
|
||||
"tsc:w": "tsc -w",
|
||||
"tslint": "tslint -c tslint.json *.ts && tslint -c tslint.json src/{,**/}**.ts -e '{,**/}**.d.ts'"
|
||||
@@ -42,10 +43,10 @@
|
||||
"moment": "2.15.1",
|
||||
"md-date-time-picker": "^2.2.0",
|
||||
"ng2-translate": "2.5.0",
|
||||
"alfresco-js-api": "~1.1.0",
|
||||
"ng2-alfresco-core": "1.1.0",
|
||||
"ng2-alfresco-datatable": "1.1.0",
|
||||
"ng2-activiti-tasklist": "^1.1.0"
|
||||
"alfresco-js-api": "~1.2.0",
|
||||
"ng2-alfresco-core": "1.2.0",
|
||||
"ng2-alfresco-datatable": "1.2.0",
|
||||
"ng2-activiti-tasklist": "1.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jasmine": "^2.2.33",
|
||||
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "ng2-activiti-tasklist",
|
||||
"description": "Activiti Angular2 Task List Component",
|
||||
"version": "1.1.0",
|
||||
"version": "1.2.0",
|
||||
"author": "Alfresco Software, Ltd.",
|
||||
"scripts": {
|
||||
"clean": "npm install rimraf && npm run clean-build && rimraf dist node_modules typings",
|
||||
@@ -67,14 +67,14 @@
|
||||
"moment": "2.15.1",
|
||||
"md-date-time-picker": "^2.2.0",
|
||||
"ng2-translate": "2.5.0",
|
||||
"alfresco-js-api": "~1.1.0",
|
||||
"ng2-activiti-form": "1.1.0",
|
||||
"ng2-alfresco-core": "1.1.0",
|
||||
"ng2-alfresco-datatable": "1.1.0"
|
||||
"alfresco-js-api": "~1.2.0",
|
||||
"ng2-activiti-form": "1.2.0",
|
||||
"ng2-alfresco-core": "1.2.0",
|
||||
"ng2-alfresco-datatable": "1.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jasmine": "^2.2.33",
|
||||
"@types/node": "^6.0.42",
|
||||
"@types/jasmine": "2.5.35",
|
||||
"@types/node": "6.0.45",
|
||||
"autoprefixer": "^6.5.4",
|
||||
"concurrently": "^2.2.0",
|
||||
"cpx": "1.3.1",
|
||||
|
@@ -51,7 +51,7 @@ describe('ActivitiChecklist', () => {
|
||||
}).compileComponents().then(() => {
|
||||
let translateService = TestBed.get(AlfrescoTranslationService);
|
||||
spyOn(translateService, 'addTranslationFolder').and.stub();
|
||||
spyOn(translateService, 'get').and.callFake((key) => {
|
||||
spyOn(translateService.translate, 'get').and.callFake((key) => {
|
||||
return Observable.of(key);
|
||||
});
|
||||
|
||||
|
@@ -58,7 +58,7 @@ describe('ActivitiPeopleSearch', () => {
|
||||
|
||||
let translateService = TestBed.get(AlfrescoTranslationService);
|
||||
spyOn(translateService, 'addTranslationFolder').and.stub();
|
||||
spyOn(translateService, 'get').and.callFake((key) => { return Observable.of(key); });
|
||||
spyOn(translateService.translate, 'get').and.callFake((key) => { return Observable.of(key); });
|
||||
|
||||
fixture = TestBed.createComponent(ActivitiPeopleSearch);
|
||||
activitiPeopleSearchComponent = fixture.componentInstance;
|
||||
|
@@ -64,7 +64,7 @@ describe('ActivitiPeople', () => {
|
||||
|
||||
let translateService = TestBed.get(AlfrescoTranslationService);
|
||||
spyOn(translateService, 'addTranslationFolder').and.stub();
|
||||
spyOn(translateService, 'get').and.callFake((key) => { return Observable.of(key); });
|
||||
spyOn(translateService.translate, 'get').and.callFake((key) => { return Observable.of(key); });
|
||||
|
||||
fixture = TestBed.createComponent(ActivitiPeople);
|
||||
activitiPeopleComponent = fixture.componentInstance;
|
||||
|
@@ -45,7 +45,7 @@ describe('ActivitiStartTaskButton', () => {
|
||||
}).compileComponents().then(() => {
|
||||
let translateService = TestBed.get(AlfrescoTranslationService);
|
||||
spyOn(translateService, 'addTranslationFolder').and.stub();
|
||||
spyOn(translateService, 'get').and.callFake((key) => { return Observable.of(key); });
|
||||
spyOn(translateService.translate, 'get').and.callFake((key) => { return Observable.of(key); });
|
||||
|
||||
fixture = TestBed.createComponent(ActivitiStartTaskButton);
|
||||
activitiStartTaskButton = fixture.componentInstance;
|
||||
|
@@ -59,7 +59,7 @@ describe('ActivitiTaskDetails', () => {
|
||||
|
||||
let translateService = TestBed.get(AlfrescoTranslationService);
|
||||
spyOn(translateService, 'addTranslationFolder').and.stub();
|
||||
spyOn(translateService, 'get').and.callFake((key) => { return Observable.of(key); });
|
||||
spyOn(translateService.translate, 'get').and.callFake((key) => { return Observable.of(key); });
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
|
@@ -47,7 +47,7 @@ describe('ActivitiTaskHeader', () => {
|
||||
|
||||
let translateService = TestBed.get(AlfrescoTranslationService);
|
||||
spyOn(translateService, 'addTranslationFolder').and.stub();
|
||||
spyOn(translateService, 'get').and.callFake((key) => { return Observable.of(key); });
|
||||
spyOn(translateService.translate, 'get').and.callFake((key) => { return Observable.of(key); });
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
|
@@ -64,7 +64,7 @@ npm install --save ng2-alfresco-core
|
||||
- **ContextMenuService**, global context menu APIs
|
||||
|
||||
|
||||
#### Alfresco Api Service
|
||||
## Alfresco Api Service
|
||||
|
||||
Provides access to initialized **AlfrescoJSApi** instance.
|
||||
|
||||
@@ -96,7 +96,7 @@ let apiService: any = this.authService.getAlfrescoApi();
|
||||
apiService.nodes.addNode('-root-', body, {});
|
||||
```
|
||||
|
||||
#### Notification Service
|
||||
## Notification Service
|
||||
|
||||
The Notification Service is implemented on top of the Angular 2 Material Design snackbar.
|
||||
Use this service to show a notification message, and optionaly get feedback from it.
|
||||
@@ -133,7 +133,7 @@ export class MyComponent implements OnInit {
|
||||
}
|
||||
```
|
||||
|
||||
#### Context Menu directive
|
||||
## Context Menu directive
|
||||
|
||||
_See **Demo Shell** or **DocumentList** implementation for more details and use cases._
|
||||
|
||||
@@ -169,7 +169,7 @@ export class MyComponent implements OnInit {
|
||||
}
|
||||
```
|
||||
|
||||
#### Authentication Service
|
||||
## Authentication Service
|
||||
|
||||
The authentication service is used inside the [login component](../ng2-alfresco-login) and is possible to find there an example of how to use it.
|
||||
|
||||
@@ -182,27 +182,24 @@ import { CoreModule, AlfrescoSettingsService, AlfrescoAuthenticationService } fr
|
||||
@Component({
|
||||
selector: 'alfresco-app-demo',
|
||||
template: `
|
||||
<div *ngIf="!authenticated" >
|
||||
Authentication failed to ip {{ ecmHost }} with user: admin, admin
|
||||
</div>
|
||||
<div *ngIf="authenticated">
|
||||
<H5>ECM</H5>
|
||||
Authentication successfull to ip {{ ecmHost }} with user: admin, admin<br>
|
||||
your token is {{ tokenEcm }}<br>
|
||||
<H5>BPM</H5>
|
||||
Authentication successfull to ip {{ bpmHost }} with user: admin, admin<br>
|
||||
your token is {{ tokenBpm }}<br>
|
||||
</div>`
|
||||
<div *ngIf="!authenticated" >
|
||||
Authentication failed to ip {{ ecmHost }} with user: admin, admin
|
||||
</div>
|
||||
<div *ngIf="authenticated">
|
||||
<H5>ECM</H5>
|
||||
Authentication successfull to ip {{ ecmHost }} with user: admin, admin<br>
|
||||
your token is {{ tokenEcm }}<br>
|
||||
<H5>BPM</H5>
|
||||
Authentication successfull to ip {{ bpmHost }} with user: admin, admin<br>
|
||||
your token is {{ tokenBpm }}<br>
|
||||
</div>
|
||||
`
|
||||
})
|
||||
class MyDemoApp {
|
||||
authenticated: boolean = false;
|
||||
|
||||
public ecmHost: string = 'http://localhost:8080';
|
||||
|
||||
public bpmHost: string = 'http://localhost:9999';
|
||||
|
||||
ecmHost: string = 'http://localhost:8080';
|
||||
bpmHost: string = 'http://localhost:9999';
|
||||
tokenBpm: string;
|
||||
|
||||
tokenEcm: string;
|
||||
|
||||
constructor(public alfrescoAuthenticationService: AlfrescoAuthenticationService,
|
||||
@@ -246,7 +243,51 @@ export class AppModule {
|
||||
platformBrowserDynamic().bootstrapModule(AppModule);
|
||||
```
|
||||
|
||||
#### Renditions Service
|
||||
## AlfrescoTranslationService
|
||||
|
||||
In order to enable localisation support you will need creating a `/resources/i18n/en.json` file
|
||||
and registering path to it's parent `i18n` folder:
|
||||
|
||||
```ts
|
||||
class MainApplication {
|
||||
constructor(private translateService: AlfrescoTranslationService) {
|
||||
translateService.addTranslationFolder('app', 'resources');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Service also allows changing current language for entire application.
|
||||
Imagine you got a language picker that invokes `onLanguageClicked` method:
|
||||
|
||||
```ts
|
||||
class MyComponent {
|
||||
constructor(private translateService: AlfrescoTranslationService) {
|
||||
}
|
||||
|
||||
onLanguageClicked(lang: string) {
|
||||
this.translateService.use('en');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
It is also possible providing custom translations for existing components by overriding their resource paths:
|
||||
|
||||
```ts
|
||||
class MyComponent {
|
||||
constructor(private translateService: AlfrescoTranslationService) {
|
||||
translateService.addTranslationFolder(
|
||||
'ng2-alfresco-login',
|
||||
'i18n/custom-translation/alfresco-login'
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Important note**: `addTranslationFolder` method redirects **all** languages to a new folder, you may need implementing multiple languages
|
||||
or copying existing translation files to a new path.
|
||||
|
||||
|
||||
## Renditions Service
|
||||
|
||||
* getRenditionsListByNodeId(nodeId: string)
|
||||
* createRendition(nodeId: string, encoding: string)
|
||||
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "ng2-alfresco-core",
|
||||
"description": "Alfresco Angular 2 Components core",
|
||||
"version": "1.1.0",
|
||||
"version": "1.2.0",
|
||||
"author": "Alfresco Software, Ltd.",
|
||||
"scripts": {
|
||||
"clean": "npm install rimraf && npm run clean-build && rimraf dist node_modules typings",
|
||||
@@ -65,7 +65,7 @@
|
||||
"@angular/material": "2.0.0-beta.1",
|
||||
"@angular/router": "3.2.2",
|
||||
"@angular/upgrade": "2.2.2",
|
||||
"alfresco-js-api": "~1.1.0",
|
||||
"alfresco-js-api": "~1.2.0",
|
||||
"core-js": "^2.4.1",
|
||||
"dialog-polyfill": "^0.4.3",
|
||||
"element.scrollintoviewifneeded-polyfill": "^1.0.1",
|
||||
@@ -79,8 +79,8 @@
|
||||
"zone.js": "^0.6.23"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jasmine": "^2.2.33",
|
||||
"@types/node": "^6.0.42",
|
||||
"@types/jasmine": "2.5.35",
|
||||
"@types/node": "6.0.45",
|
||||
"autoprefixer": "^6.5.4",
|
||||
"concurrently": "^2.2.0",
|
||||
"cpx": "1.3.1",
|
||||
|
@@ -44,6 +44,9 @@ export class AlfrescoTranslateLoader implements TranslateLoader {
|
||||
|
||||
getComponentToFetch(lang: string) {
|
||||
let observableBatch = [];
|
||||
if (!this.queue[lang]) {
|
||||
this.queue[lang] = [];
|
||||
}
|
||||
this._componentList.forEach((component) => {
|
||||
if (!this.isComponentInQueue(lang, component.name)) {
|
||||
this.queue[lang].push(component.name);
|
||||
@@ -67,7 +70,7 @@ export class AlfrescoTranslateLoader implements TranslateLoader {
|
||||
}
|
||||
|
||||
isComponentInQueue(lang: string, name: string) {
|
||||
return this.queue[lang].find(x => x === name) ? true : false;
|
||||
return (this.queue[lang] || []).find(x => x === name) ? true : false;
|
||||
}
|
||||
|
||||
getFullTranslationJSON(lang: string) {
|
||||
|
@@ -22,24 +22,35 @@ import { AlfrescoTranslateLoader } from './alfresco-translate-loader.service';
|
||||
|
||||
@Injectable()
|
||||
export class AlfrescoTranslationService {
|
||||
defaultLang: string = 'en';
|
||||
userLang: string = 'en';
|
||||
customLoader: AlfrescoTranslateLoader;
|
||||
|
||||
constructor(public translate: TranslateService) {
|
||||
this.userLang = translate.getBrowserLang() || 'en';
|
||||
translate.setDefaultLang(this.userLang);
|
||||
this.userLang = translate.getBrowserLang() || this.defaultLang;
|
||||
translate.setDefaultLang(this.defaultLang);
|
||||
this.customLoader = <AlfrescoTranslateLoader> this.translate.currentLoader;
|
||||
this.customLoader.init(this.userLang);
|
||||
this.use(this.userLang);
|
||||
}
|
||||
|
||||
addTranslationFolder(name: string = '', path: string = '') {
|
||||
if (!this.customLoader.existComponent(name)) {
|
||||
this.customLoader.addComponentList(name, path);
|
||||
this.translate.getTranslation(this.userLang).subscribe(
|
||||
() => {
|
||||
this.translate.use(this.userLang);
|
||||
}
|
||||
);
|
||||
if (this.userLang !== this.defaultLang) {
|
||||
this.translate.getTranslation(this.defaultLang).subscribe(() => {
|
||||
this.translate.getTranslation(this.userLang).subscribe(
|
||||
() => {
|
||||
this.translate.use(this.userLang);
|
||||
}
|
||||
);
|
||||
});
|
||||
} else {
|
||||
this.translate.getTranslation(this.userLang).subscribe(
|
||||
() => {
|
||||
this.translate.use(this.userLang);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -93,8 +93,8 @@ Follow the 3 steps below:
|
||||
- ng2-alfresco-core
|
||||
- ng2-alfresco-datatable
|
||||
|
||||
Please refer to the following example file: [systemjs.config.js](demo/systemjs
|
||||
.config.js) .
|
||||
Please refer to the following example file: [systemjs.config.js](demo/systemjs.config.js) .
|
||||
|
||||
|
||||
## Basic usage example
|
||||
|
||||
@@ -177,6 +177,7 @@ platformBrowserDynamic().bootstrapModule(AppModule);
|
||||
| `data` | DataTableAdapter | instance of **ObjectDataTableAdapter** | data source |
|
||||
| `multiselect` | boolean | false | Toggles multiple row selection, renders checkboxes at the beginning of each row |
|
||||
| `actions` | boolean | false | Toggles data actions column |
|
||||
| `actionsPosition` | string (left\|right) | right | Position of the actions dropdown menu. |
|
||||
| `fallbackThumbnail` | string | | Fallback image for row ehre thubnail is missing|
|
||||
|
||||
### Events
|
||||
|
@@ -3,12 +3,6 @@
|
||||
"description": "Alfresco Angular2 DataTable Component - Demo",
|
||||
"version": "0.1.0",
|
||||
"author": "Alfresco Software, Ltd.",
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Denys Vuika",
|
||||
"email": "denis.vuyka@gmail.com"
|
||||
}
|
||||
],
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"clean": "npm install rimraf && npm run clean-build && rimraf dist node_modules typings dist",
|
||||
@@ -18,11 +12,18 @@
|
||||
"server": "wsrv -o -s -l",
|
||||
"build": "npm run tslint && npm run clean-build && npm run tsc",
|
||||
"build:w": "npm run tslint && rimraf dist && npm run tsc:w",
|
||||
"travis": "npm link ng2-alfresco-core",
|
||||
"tsc": "tsc",
|
||||
"tsc:w": "tsc -w",
|
||||
"tslint": "tslint -c tslint.json *.ts && tslint -c tslint.json src/{,**/}**.ts -e '{,**/}**.d.ts'"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Denys Vuika",
|
||||
"email": "denis.vuyka@gmail.com"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"@angular/common": "2.2.2",
|
||||
"@angular/compiler": "2.2.2",
|
||||
@@ -46,9 +47,9 @@
|
||||
"material-design-icons": "2.2.3",
|
||||
"material-design-lite": "1.2.1",
|
||||
"ng2-translate": "2.5.0",
|
||||
"alfresco-js-api": "~1.1.0",
|
||||
"ng2-alfresco-core": "1.1.0",
|
||||
"ng2-alfresco-datatable": "1.1.0"
|
||||
"alfresco-js-api": "~1.2.0",
|
||||
"ng2-alfresco-core": "1.2.0",
|
||||
"ng2-alfresco-datatable": "1.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jasmine": "^2.2.33",
|
||||
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "ng2-alfresco-datatable",
|
||||
"description": "Alfresco Angular2 DataTable Component",
|
||||
"version": "1.1.0",
|
||||
"version": "1.2.0",
|
||||
"author": "Alfresco Software, Ltd.",
|
||||
"scripts": {
|
||||
"clean": "npm install rimraf && npm run clean-build && rimraf dist node_modules typings",
|
||||
@@ -61,12 +61,12 @@
|
||||
"systemjs": "0.19.27",
|
||||
"zone.js": "^0.6.23",
|
||||
"ng2-translate": "2.5.0",
|
||||
"alfresco-js-api": "~1.1.0",
|
||||
"ng2-alfresco-core": "1.1.0"
|
||||
"alfresco-js-api": "~1.2.0",
|
||||
"ng2-alfresco-core": "1.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jasmine": "^2.2.33",
|
||||
"@types/node": "^6.0.42",
|
||||
"@types/jasmine": "2.5.35",
|
||||
"@types/node": "6.0.45",
|
||||
"autoprefixer": "^6.5.4",
|
||||
"concurrently": "^2.2.0",
|
||||
"cpx": "1.3.1",
|
||||
|
@@ -3,6 +3,10 @@
|
||||
class="mdl-data-table mdl-js-data-table full-width mdl-data-table-fix-firefox">
|
||||
<thead>
|
||||
<tr>
|
||||
<!-- Actions (left) -->
|
||||
<th *ngIf="actions && actionsPosition === 'left'" class="alfresco-datatable__actions-header">
|
||||
<span class="sr-only">Actions</span>
|
||||
</th>
|
||||
<!-- Columns -->
|
||||
<th *ngIf="multiselect">
|
||||
<label
|
||||
@@ -23,8 +27,8 @@
|
||||
<span *ngIf="col.srTitle" class="sr-only">{{col.srTitle}}</span>
|
||||
<span *ngIf="col.title">{{col.title}}</span>
|
||||
</th>
|
||||
<!-- Actions -->
|
||||
<th *ngIf="actions">
|
||||
<!-- Actions (right) -->
|
||||
<th *ngIf="actions && actionsPosition === 'right'" class="alfresco-datatable__actions-header">
|
||||
<span class="sr-only">Actions</span>
|
||||
</th>
|
||||
</tr>
|
||||
@@ -34,6 +38,23 @@
|
||||
<tr *ngFor="let row of data.getRows(); let idx = index" tabindex="0"
|
||||
class="alfresco-datatable__row"
|
||||
[class.alfresco-datatable__row--selected]="selectedRow === row">
|
||||
|
||||
<!-- Actions (right) -->
|
||||
<td *ngIf="actions && actionsPosition === 'left'" class="alfresco-datatable__actions-cell">
|
||||
<button [id]="'action_menu_' + idx" alfresco-mdl-button class="mdl-button--icon" [attr.data-automation-id]="actions_menu">
|
||||
<i class="material-icons">more_vert</i>
|
||||
</button>
|
||||
<ul alfresco-mdl-menu class="mdl-menu--bottom-left"
|
||||
[attr.for]="'action_menu_' + idx">
|
||||
<li class="mdl-menu__item"
|
||||
[attr.data-automation-id]="action.title"
|
||||
*ngFor="let action of getRowActions(row)"
|
||||
(click)="onExecuteRowAction(row, action)">
|
||||
{{action.title}}
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
|
||||
<td *ngIf="multiselect">
|
||||
<label
|
||||
class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect mdl-data-table__select"
|
||||
@@ -71,8 +92,8 @@
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td *ngIf="actions">
|
||||
<!-- action menu -->
|
||||
<!-- Actions (right) -->
|
||||
<td *ngIf="actions && actionsPosition === 'right'" class="alfresco-datatable__actions-cell">
|
||||
<button [id]="'action_menu_' + idx" alfresco-mdl-button class="mdl-button--icon" [attr.data-automation-id]="actions_menu">
|
||||
<i class="material-icons">more_vert</i>
|
||||
</button>
|
||||
|
@@ -15,6 +15,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||
import { CoreModule } from 'ng2-alfresco-core';
|
||||
import { DataTableComponent } from './datatable.component';
|
||||
import {
|
||||
DataRow,
|
||||
@@ -26,23 +28,75 @@ import {
|
||||
|
||||
describe('DataTable', () => {
|
||||
|
||||
let fixture: ComponentFixture<DataTableComponent>;
|
||||
let dataTable: DataTableComponent;
|
||||
let element: any;
|
||||
let eventMock: any;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
CoreModule.forRoot()
|
||||
],
|
||||
declarations: [DataTableComponent]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(DataTableComponent);
|
||||
dataTable = fixture.componentInstance;
|
||||
element = fixture.debugElement.nativeElement;
|
||||
|
||||
// usernameInput = element.querySelector('#username');
|
||||
// passwordInput = element.querySelector('#password');
|
||||
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
// reset MDL handler
|
||||
window['componentHandler'] = null;
|
||||
dataTable = new DataTableComponent();
|
||||
// dataTable = new DataTableComponent();
|
||||
|
||||
eventMock = {
|
||||
preventDefault: function () {}
|
||||
};
|
||||
});
|
||||
|
||||
it('should put actions menu to the right by default', () => {
|
||||
dataTable.data = new ObjectDataTableAdapter([], [
|
||||
<DataColumn> {},
|
||||
<DataColumn> {},
|
||||
<DataColumn> {}
|
||||
]);
|
||||
dataTable.actions = true;
|
||||
fixture.detectChanges();
|
||||
|
||||
let headers = element.querySelectorAll('th');
|
||||
expect(headers.length).toBe(4);
|
||||
expect(headers[headers.length - 1].classList.contains('alfresco-datatable__actions-header')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should put actions menu to the left', () => {
|
||||
dataTable.data = new ObjectDataTableAdapter([], [
|
||||
<DataColumn> {},
|
||||
<DataColumn> {},
|
||||
<DataColumn> {}
|
||||
]);
|
||||
dataTable.actions = true;
|
||||
dataTable.actionsPosition = 'left';
|
||||
fixture.detectChanges();
|
||||
|
||||
let headers = element.querySelectorAll('th');
|
||||
expect(headers.length).toBe(4);
|
||||
expect(headers[0].classList.contains('alfresco-datatable__actions-header')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should initialize default adapter', () => {
|
||||
expect(dataTable.data).toBeUndefined();
|
||||
dataTable.ngOnInit();
|
||||
expect(dataTable.data).toEqual(jasmine.any(ObjectDataTableAdapter));
|
||||
let table = new DataTableComponent();
|
||||
expect(table.data).toBeUndefined();
|
||||
table.ngOnInit();
|
||||
expect(table.data).toEqual(jasmine.any(ObjectDataTableAdapter));
|
||||
});
|
||||
|
||||
it('should initialize with custom data', () => {
|
||||
|
@@ -44,6 +44,9 @@ export class DataTableComponent implements OnInit {
|
||||
@Input()
|
||||
actions: boolean = false;
|
||||
|
||||
@Input()
|
||||
actionsPosition: string = 'right'; // left|right
|
||||
|
||||
@Input()
|
||||
fallbackThumbnail: string;
|
||||
|
||||
|
@@ -92,8 +92,8 @@ Follow the 3 steps below:
|
||||
- ng2-alfresco-datatable
|
||||
- ng2-alfresco-documentlist
|
||||
|
||||
Please refer to the following example file: [systemjs.config.js](demo/systemjs
|
||||
.config.js) .
|
||||
Please refer to the following example file: [systemjs.config.js](demo/systemjs.config.js) .
|
||||
|
||||
|
||||
## Basic usage
|
||||
|
||||
@@ -181,6 +181,7 @@ The properties currentFolderId, folderNode and node are the entry initialization
|
||||
| `fallbackThumbnail` | string | | Path to fallback image to use if the row thumbnail is missing |
|
||||
| `multiselect` | boolean | false | Toggles multiselect mode |
|
||||
| `contentActions` | boolean | false | Toggles content actions for each row |
|
||||
| `contentActionsPosition` | string (left\|right) | right | Position of the content actions dropdown menu. |
|
||||
| `contextMenuActions` | boolean | false | Toggles context menus for each row |
|
||||
| `enablePagination` | boolean | true | Shows pagination |
|
||||
| `creationMenuActions` | boolean | true | Toggles the creation menu actions|
|
||||
@@ -488,7 +489,7 @@ context.row.getValue('name')
|
||||
context.row.getValue('createdByUser.displayName')
|
||||
```
|
||||
|
||||
_You may want using **row** api to get raw value access.
|
||||
You may want using **row** api to get raw value access.
|
||||
|
||||
```html
|
||||
<content-column title="Name" key="name" sortable="true" class="full-width ellipsis-cell">
|
||||
@@ -501,7 +502,7 @@ _You may want using **row** api to get raw value access.
|
||||
|
||||
Use **data** api to get values with post-processing, like datetime/icon conversion._
|
||||
|
||||
Final example, we'll name the context as `entry`:
|
||||
In the Example below will prepend `Hi!` to each file and folder name in the list:
|
||||
|
||||
```html
|
||||
<content-column title="Name" key="name" sortable="true" class="full-width ellipsis-cell">
|
||||
@@ -511,9 +512,21 @@ Final example, we'll name the context as `entry`:
|
||||
</content-column>
|
||||
```
|
||||
|
||||
Example above will prepend `Hi!` to each file and folder name in the list.
|
||||
In the Example below will add the [ng2-alfresco-tag](https://www.npmjs.com/package/ng2-alfresco-tag) component is integrate in the document list.
|
||||
|
||||
```html
|
||||
<content-column
|
||||
title="{{'DOCUMENT_LIST.COLUMNS.TAG' | translate}}"
|
||||
key="id"
|
||||
sortable="true"
|
||||
class="full-width ellipsis-cell">
|
||||
<template let-entry="$implicit">
|
||||
<alfresco-tag-node-list [nodeId]="entry.data.getValue(entry.row, entry.col)"></alfresco-tag-node-list>
|
||||
</template>
|
||||
</content-column>
|
||||
```
|
||||
|
||||

|
||||
|
||||
### Actions
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user