release 3.0.0
@@ -17,8 +17,6 @@ before_install:
|
||||
- export CHROME_BIN=/usr/bin/google-chrome
|
||||
- export DISPLAY=:99.0
|
||||
- sh -e /etc/init.d/xvfb start
|
||||
- (cd ng2-components/ng2-alfresco-core; npm version patch; sed -i "s/0\\.0\\.0-PLACEHOLDER/^0.1.0/g" package.json; npm install; npm link)
|
||||
|
||||
env:
|
||||
matrix:
|
||||
- MODULE=ng2-alfresco-core
|
||||
@@ -28,11 +26,56 @@ env:
|
||||
- MODULE=ng2-alfresco-search
|
||||
- MODULE=ng2-alfresco-upload
|
||||
- MODULE=ng2-alfresco-viewer
|
||||
- MODULE=ng2-alfresco-webscript
|
||||
- MODULE=ng2-activiti-form
|
||||
- MODULE=ng2-activiti-tasklist
|
||||
- MODULE=ng2-activiti-processlist
|
||||
|
||||
before_script:
|
||||
- cd ng2-components/$MODULE; npm version patch; sed -i "s/0\\.0\\.0-PLACEHOLDER/^0.1.0/g" package.json; npm install; npm link ng2-alfresco-core; npm run travis
|
||||
- if ([ "$MODULE" != "ng2-alfresco-core" ]); then
|
||||
(cd ng2-components/ng2-alfresco-core; npm install; npm link);
|
||||
fi
|
||||
- if ([ "$MODULE" == "ng2-alfresco-documentlist" ] || [ "$MODULE" == "ng2-alfresco-webscript" ] || [ "$MODULE" == "ng2-activiti-processlist" ] || [ "$MODULE" == "ng2-activiti-tasklist" ]); then
|
||||
(cd ng2-components/ng2-alfresco-datatable; npm link ng2-alfresco-core; npm install; npm link);
|
||||
fi
|
||||
- if ([ "$MODULE" == "ng2-activiti-tasklist" ] || [ "$MODULE" == "ng2-activiti-processlist" ]); then
|
||||
(cd ng2-components/ng2-activiti-form; npm link ng2-alfresco-core; npm install; npm link);
|
||||
fi
|
||||
- if ([ "$MODULE" == "ng2-activiti-processlist" ]); then
|
||||
(cd ng2-components/ng2-activiti-tasklist; npm link ng2-alfresco-core; npm link ng2-alfresco-datatable; npm link ng2-activiti-form; npm install; npm link);
|
||||
fi
|
||||
- cd ng2-components/$MODULE;
|
||||
- if ([ "$MODULE" != "ng2-alfresco-core" ]); then
|
||||
npm link ng2-alfresco-core;
|
||||
fi
|
||||
- if ([ "$MODULE" == "ng2-alfresco-documentlist" ] || [ "$MODULE" == "ng2-alfresco-webscript" ] || [ "$MODULE" == "ng2-activiti-processlist" ] || [ "$MODULE" == "ng2-activiti-tasklist" ]); then
|
||||
npm link ng2-alfresco-datatable;
|
||||
fi
|
||||
- if ([ "$MODULE" == "ng2-activiti-tasklist" ]); then
|
||||
npm link ng2-activiti-form;
|
||||
fi
|
||||
- if ([ "$MODULE" == "ng2-activiti-processlist" ]); then
|
||||
npm link ng2-activiti-tasklist;
|
||||
fi
|
||||
- npm install;
|
||||
- npm run travis
|
||||
- ls -ltrh ./node_modules/
|
||||
script: npm run test
|
||||
# Send coverage data to Coveralls
|
||||
after_success:
|
||||
- "cat ./coverage/report/lcov.info | ./node_modules/coveralls/bin/coveralls.js --verbose"
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- demo-shell-ng2/node_modules
|
||||
- ng2-components/ng2-activiti-form/node_modules
|
||||
- ng2-components/ng2-activiti-processlist/node_modules
|
||||
- ng2-components/ng2-activiti-tasklist/node_modules
|
||||
- ng2-components/ng2-alfresco-core/node_modules
|
||||
- ng2-components/ng2-alfresco-datatable/node_modules
|
||||
- ng2-components/ng2-alfresco-documentlist/node_modules
|
||||
- ng2-components/ng2-alfresco-login/node_modules
|
||||
- ng2-components/ng2-alfresco-search/node_modules
|
||||
- ng2-components/ng2-alfresco-upload/node_modules
|
||||
- ng2-components/ng2-alfresco-viewer/node_modules
|
||||
- ng2-components/ng2-alfresco-webscript/node_modules
|
||||
|
||||
@@ -2,9 +2,13 @@
|
||||
|
||||
The [Angular 2](https://angular.io/) based application development framework requires the following:
|
||||
|
||||
- An Alfresco Platform Repository to talk to, which has [CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing) enabled.
|
||||
- An Alfresco Platform Repository (version [5.2.a-EA](https://wiki.alfresco.com/wiki/Community_file_list_201606-EA) or newer) to talk to, which has [CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing) enabled.
|
||||
- [Node.js](https://nodejs.org/en/) JavaScript runtime.
|
||||
- [npm](https://www.npmjs.com/) package manager for JavaScript.
|
||||
|
||||
**Verify that you are running at least node `v5.x.x` and npm `3.x.x`**
|
||||
by running `node -v` and `npm -v` in a terminal/console window.
|
||||
Older versions produce errors.
|
||||
|
||||
## Installing Alfresco
|
||||
|
||||
@@ -25,9 +29,18 @@ The web client that we are building with the application development framework w
|
||||
So we need to tell the Alfresco server that any request that comes in from this custom web client should be allowed access
|
||||
to the Content Repository. This is done by enabling CORS.
|
||||
|
||||
To enable CORS in the Alfresco Platform do the following:
|
||||
To enable CORS in the Alfresco Platform do one of the following:
|
||||
|
||||
Modify *tomcat/webapps/alfresco/WEB-INF/web.xml* and uncomment the following section and update
|
||||
**Download and install the enable CORS module**
|
||||
|
||||
This is the easiest way, add the [enablecors](https://artifacts.alfresco.com/nexus/service/local/repositories/releases/content/org/alfresco/enablecors/1.0/enablecors-1.0.jar)
|
||||
platform module JAR to the *$ALF_INSTALL_DIR/modules/platform* directory and restart the server.
|
||||
|
||||
Note. by default the CORS filter that is enabled will allow any orgin.
|
||||
|
||||
**Manually update the web.xml file**
|
||||
|
||||
Modify *$ALF_INSTALL_DIR/tomcat/webapps/alfresco/WEB-INF/web.xml* and uncomment the following section and update
|
||||
`cors.allowOrigin` to `http://localhost:3000`:
|
||||
|
||||
```
|
||||
|
||||
@@ -3,12 +3,16 @@
|
||||
[](https://gitter.im/Alfresco/alfresco-ng2-components?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
<p>
|
||||
<a title='Build Status' href="https://travis-ci.org/Alfresco/alfresco-ng2-components">
|
||||
<a title='Build Status Travis' href="https://travis-ci.org/Alfresco/alfresco-ng2-components">
|
||||
<img src='https://travis-ci.org/Alfresco/alfresco-ng2-components.svg?branch=master' alt='travis
|
||||
Status' />
|
||||
</a>
|
||||
<a href='https://coveralls.io/github/Alfresco/alfresco-ng2-components'>
|
||||
<img src='https://coveralls.io/repos/github/Alfresco/alfresco-ng2-components/badge.svg?t=NzxWxh' alt='Coverage Status' />
|
||||
<a title='Build Status AppVeyor' href="https://ci.appveyor.com/project/alfresco/alfresco-ng2-components">
|
||||
<img src='https://ci.appveyor.com/api/projects/status/github/Alfresco/alfresco-ng2-components' alt='travis
|
||||
Status' />
|
||||
</a>
|
||||
<a href='https://codecov.io/gh/Alfresco/alfresco-ng2-components'>
|
||||
<img src='https://img.shields.io/codecov/c/github/Alfresco/alfresco-ng2-components/master.svg?maxAge=2592000' alt='Coverage Status' />
|
||||
</a>
|
||||
<a href='https://github.com/Alfresco/alfresco-ng2-components/blob/master/LICENSE'>
|
||||
<img src='https://img.shields.io/hexpm/l/plug.svg' alt='license' />
|
||||
@@ -55,6 +59,7 @@ The following is a list of some of the components that you can use when building
|
||||
- [Viewer](ng2-components/ng2-alfresco-viewer/README.md)
|
||||
- [Login](ng2-components/ng2-alfresco-login/README.md)
|
||||
- [Upload](ng2-components/ng2-alfresco-upload/README.md)
|
||||
- [Webscript viewer](ng2-components/ng2-alfresco-webscript/README.md)
|
||||
|
||||
You can browse all the components at the following [page](http://devproducts.alfresco.com/).
|
||||
|
||||
@@ -81,4 +86,13 @@ To generate your Alfresco Angular 2 application you can use the following Yeoman
|
||||
|
||||
- [Yeoman Generator Angular 2 Alfresco application](https://github.com/Alfresco/generator-ng2-alfresco-app)
|
||||
|
||||
## Amazon AWS Elastic Beanstalk fast deploy
|
||||
|
||||
<p align="center">
|
||||
<img alt="AmazonWebservices Logo.svg" src="https://upload.wikimedia.org/wikipedia/commons/1/1d/AmazonWebservices_Logo.svg" width="250" height="94">
|
||||
</p>
|
||||
|
||||
To deploy directly on your AWS instance our demo shell click the button below:
|
||||
|
||||
<a title="Deploy to AWS" href="https://console.aws.amazon.com/elasticbeanstalk/home?region=us-west-2#/newApplication?applicationName=Alfresco&solutionStackName=Node.js&tierName=WebServer&sourceBundleUrl=https://s3-us-west-2.amazonaws.com/elasticbeanstalk-us-west-2-677901592050/2016210o6l-Archive-v7.zip" target="_blank"><img src="http://d0.awsstatic.com/product-marketing/Elastic%20Beanstalk/deploy-to-aws.png" height="40"></a>
|
||||
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
# Test against this version of Node.js
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
|
||||
environment:
|
||||
nodejs_version: "5"
|
||||
|
||||
matrix:
|
||||
- COMPONENT_NAME: ng2-alfresco-core
|
||||
- COMPONENT_NAME: ng2-alfresco-datatable
|
||||
- COMPONENT_NAME: ng2-alfresco-documentlist
|
||||
- COMPONENT_NAME: ng2-alfresco-login
|
||||
- COMPONENT_NAME: ng2-alfresco-search
|
||||
- COMPONENT_NAME: ng2-alfresco-upload
|
||||
- COMPONENT_NAME: ng2-alfresco-viewer
|
||||
- COMPONENT_NAME: ng2-alfresco-webscript
|
||||
- COMPONENT_NAME: ng2-activiti-form
|
||||
- COMPONENT_NAME: ng2-activiti-tasklist
|
||||
- COMPONENT_NAME: ng2-activiti-processlist
|
||||
|
||||
# Install scripts. (runs after repo cloning)
|
||||
install:
|
||||
# Get the latest stable version of Node.js or io.js
|
||||
- ps: Install-Product node $env:nodejs_version
|
||||
# install module
|
||||
- IF %COMPONENT_NAME% NEQ ng2-alfresco-core (cd ng2-components/ng2-alfresco-core && npm install && npm link && cd ../../)
|
||||
- IF %COMPONENT_NAME% EQU ng2-alfresco-documentlist (cd ng2-components/ng2-alfresco-datatable && npm link ng2-alfresco-core && npm install && npm link && cd ../../)
|
||||
- IF %COMPONENT_NAME% EQU ng2-activiti-processlist (cd ng2-components/ng2-alfresco-datatable && npm link ng2-alfresco-core && npm install && npm link && cd ../../)
|
||||
- IF %COMPONENT_NAME% EQU ng2-activiti-processlist (cd ng2-components/ng2-activiti-form && npm link ng2-alfresco-core && npm install && npm link && cd ../../)
|
||||
- IF %COMPONENT_NAME% EQU ng2-activiti-processlist (cd ng2-components/ng2-activiti-tasklist && npm link ng2-alfresco-core && npm link ng2-alfresco-datatable && npm link ng2-activiti-form && npm install && npm link && cd ../../)
|
||||
- IF %COMPONENT_NAME% EQU ng2-activiti-tasklist (cd ng2-components/ng2-alfresco-datatable && npm link ng2-alfresco-core && npm install && npm link && cd ../../)
|
||||
- IF %COMPONENT_NAME% EQU ng2-activiti-tasklist (cd ng2-components/ng2-activiti-form && npm link ng2-alfresco-core && npm install && npm link && cd ../../)
|
||||
- IF %COMPONENT_NAME% EQU ng2-alfresco-webscript (cd ng2-components/ng2-alfresco-datatable && npm link ng2-alfresco-core && npm install && npm link && cd ../../)
|
||||
- cd ng2-components/%COMPONENT_NAME%
|
||||
- IF %COMPONENT_NAME% NEQ ng2-alfresco-core (npm link ng2-alfresco-core)
|
||||
- IF %COMPONENT_NAME% EQU ng2-alfresco-documentlist (npm link ng2-alfresco-datatable)
|
||||
- IF %COMPONENT_NAME% EQU ng2-activiti-processlist (npm link ng2-alfresco-datatable)
|
||||
- IF %COMPONENT_NAME% EQU ng2-activiti-processlist (npm link ng2-activiti-tasklist)
|
||||
- IF %COMPONENT_NAME% EQU ng2-activiti-tasklist (npm link ng2-alfresco-datatable && npm link ng2-activiti-form)
|
||||
- IF %COMPONENT_NAME% EQU ng2-alfresco-webscript (npm link ng2-alfresco-datatable)
|
||||
- npm install
|
||||
|
||||
# Post-install test scripts.
|
||||
test_script:
|
||||
# Output useful info for debugging.
|
||||
- node --version
|
||||
- npm --version
|
||||
# run tests
|
||||
- npm test
|
||||
|
||||
# Don't actually build.
|
||||
build: off
|
||||
@@ -0,0 +1,18 @@
|
||||
files:
|
||||
"/opt/elasticbeanstalk/hooks/appdeploy/pre/50npm.sh" :
|
||||
mode: "000775"
|
||||
owner: root
|
||||
group: root
|
||||
content: |
|
||||
#!/bin/bash
|
||||
function error_exit
|
||||
{
|
||||
eventHelper.py --msg "$1" --severity ERROR
|
||||
exit $2
|
||||
}
|
||||
|
||||
export HOME=/home/ec2-user
|
||||
echo "export home"
|
||||
|
||||
sudo curl -sL https://rpm.nodesource.com/setup_6.x | sudo -E bash -
|
||||
sudo yum install -y nodejs
|
||||
@@ -4,4 +4,8 @@ bower_components/
|
||||
app/**/*.js
|
||||
app/**/*.js.map
|
||||
.idea
|
||||
dist/
|
||||
dist/
|
||||
|
||||
# docker files
|
||||
docker-compose.yml
|
||||
Dockerfile
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
var port = process.env.PORT || 3000,
|
||||
http = require('http'),
|
||||
fs = require('fs'),
|
||||
url = require('url'),
|
||||
mime = require('mime'),
|
||||
html = fs.readFileSync('index.html');
|
||||
|
||||
var log = function(entry) {
|
||||
fs.appendFileSync('/tmp/sample-app.log', new Date().toISOString() + ' - ' + entry + '\n');
|
||||
};
|
||||
|
||||
var server = http.createServer(function (req, res) {
|
||||
|
||||
// Parse the request containing file name
|
||||
var pathname = url.parse(req.url).pathname;
|
||||
|
||||
// Print the name of the file for which request is made.
|
||||
console.log("Request for " + pathname + " received.");
|
||||
|
||||
if (req.method === 'POST') {
|
||||
var body = '';
|
||||
|
||||
req.on('data', function(chunk) {
|
||||
body += chunk;
|
||||
});
|
||||
|
||||
req.on('end', function() {
|
||||
if (req.url === '/') {
|
||||
log('Received message: ' + body);
|
||||
} else if (req.url = '/scheduled') {
|
||||
log('Received task ' + req.headers['x-aws-sqsd-taskname'] + ' scheduled at ' + req.headers['x-aws-sqsd-scheduled-at']);
|
||||
}
|
||||
|
||||
res.writeHead(200, 'OK', {'Content-Type': 'text/plain'});
|
||||
res.end();
|
||||
});
|
||||
} else {
|
||||
var filename = pathname.substr(1);
|
||||
if(filename === '' || filename.indexOf('.') === -1){
|
||||
filename = 'index.html';
|
||||
}
|
||||
// Read the requested file content from file system
|
||||
fs.readFile(filename, function (err, data) {
|
||||
if (err) {
|
||||
console.log(err, filename);
|
||||
// HTTP Status: 404 : NOT FOUND
|
||||
// Content Type: text/plain
|
||||
res.writeHead(404, {'Content-Type': 'text/html'});
|
||||
}else{
|
||||
//Page found
|
||||
// HTTP Status: 200 : OK
|
||||
// Content Type: text/plain
|
||||
var type = mime.lookup(filename);
|
||||
console.log('type',type);
|
||||
if (!res.getHeader('content-type')) {
|
||||
var charset = mime.charsets.lookup(type);
|
||||
res.setHeader('Content-Type', type + (charset ? '; charset=' + charset : ''));
|
||||
}
|
||||
if(type.indexOf('image') > -1 || type.indexOf('font') > -1){
|
||||
var img = fs.readFileSync(pathname.substr(1));
|
||||
res.end(img, 'binary');
|
||||
}else{
|
||||
res.write(data.toString());
|
||||
}
|
||||
// Write the content of the file to response body
|
||||
}
|
||||
// Send the response body
|
||||
res.end();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Listen on port 3000, IP defaults to 127.0.0.1
|
||||
server.listen(port);
|
||||
|
||||
// Put a friendly message on the terminal
|
||||
console.log('Server running at http://127.0.0.1:' + port + '/');
|
||||
@@ -12,11 +12,13 @@
|
||||
|
||||
<!-- Navigation. We hide it in small screens. -->
|
||||
<nav class="mdl-navigation mdl-layout--large-screen-only">
|
||||
<a class="mdl-navigation__link" data-automation-id="files" href="" [routerLink]="['Files']">DocumentList</a>
|
||||
<a class="mdl-navigation__link" data-automation-id="datatable" href="" [routerLink]="['DataTable']">DataTable</a>
|
||||
<a class="mdl-navigation__link" data-automation-id="uploader" href="" [routerLink]="['Uploader']">Uploader</a>
|
||||
<a class="mdl-navigation__link" data-automation-id="tasks" href="" [routerLink]="['Tasks']">Tasks</a>
|
||||
<a class="mdl-navigation__link" data-automation-id="login" href="" [routerLink]="['Login']">Login</a>
|
||||
<a class="mdl-navigation__link" data-automation-id="files" href="" routerLink="/files">DocumentList</a>
|
||||
<a class="mdl-navigation__link" data-automation-id="datatable" href="" routerLink="/datatable">DataTable</a>
|
||||
<a class="mdl-navigation__link" data-automation-id="uploader" href="" routerLink="/uploader">Uploader</a>
|
||||
<a class="mdl-navigation__link" data-automation-id="activiti" href="" routerLink="/activiti">Activiti</a>
|
||||
<a class="mdl-navigation__link" data-automation-id="webscript" href="" routerLink="/webscript">Webscript</a>
|
||||
<a class="mdl-navigation__link" data-automation-id="login" href="" routerLink="/login">Login</a>
|
||||
<a class="mdl-navigation__link" data-automation-id="about" href="" routerLink="/about">About</a>
|
||||
</nav>
|
||||
|
||||
<!-- Right aligned menu below button -->
|
||||
@@ -30,8 +32,8 @@
|
||||
<li class="mdl-menu__item " (click)="changeLanguage('en')"><span class="flag-icon flag-icon-gb"></span> English</li>
|
||||
<li class="mdl-menu__item" (click)="changeLanguage('gr')"><span class="flag-icon flag-icon-gr"></span> Greek</li>
|
||||
<li class="mdl-menu__item" (click)="changeLanguage('it')"><span class="flag-icon flag-icon-it"></span> Italian</li>
|
||||
<li *ngIf="!isLoggedIn()" class="mdl-menu__item" >More</li>
|
||||
<li *ngIf="!isLoggedIn()" class="mdl-menu__item" [routerLink]="['Login']">Login</li>
|
||||
<li *ngIf="!isLoggedIn()" class="mdl-menu__item">More</li>
|
||||
<a *ngIf="!isLoggedIn()" class="mdl-menu__item" routerLink="/login">Login</a>
|
||||
<li *ngIf="isLoggedIn()" class="mdl-menu__item" (click)="onLogout($event)">Logout</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -39,18 +41,29 @@
|
||||
<div class="mdl-layout__drawer">
|
||||
<span class="mdl-layout-title">Components List</span>
|
||||
<nav class="mdl-navigation">
|
||||
<a class="mdl-navigation__link" href="" [routerLink]="['Files']" (click)="hideDrawer()">DocumentList</a>
|
||||
<a class="mdl-navigation__link" href="" [routerLink]="['DataTable']" (click)="hideDrawer()">DataTable</a>
|
||||
<a class="mdl-navigation__link" href="" [routerLink]="['Uploader']" (click)="hideDrawer()">Uploader</a>
|
||||
<a class="mdl-navigation__link" href="" [routerLink]="['Login']" (click)="hideDrawer()">Login</a>
|
||||
<a class="mdl-navigation__link" href="" [routerLink]="['Tasks']" (click)="hideDrawer()">Tasks</a>
|
||||
<a class="mdl-navigation__link" href="" routerLink="/files" (click)="hideDrawer()">DocumentList Demo</a>
|
||||
<a class="mdl-navigation__link" href="" routerLink="/datatable" (click)="hideDrawer()">DataTable Demo</a>
|
||||
<a class="mdl-navigation__link" href="" routerLink="/uploader" (click)="hideDrawer()">Uploader Demo</a>
|
||||
<a class="mdl-navigation__link" href="" routerLink="/login" (click)="hideDrawer()">Login Demo</a>
|
||||
<a class="mdl-navigation__link" href="" routerLink="/activiti" (click)="hideDrawer()">Activiti Components Demo</a>
|
||||
<a class="mdl-navigation__link" href="" routerLink="/webscript" (click)="hideDrawer()">Webscript</a>
|
||||
<a class="mdl-navigation__link" href="" routerLink="/about" (click)="hideDrawer()">About</a>
|
||||
</nav>
|
||||
<span class="mdl-layout-title">ECM host</span>
|
||||
<nav class="mdl-navigation">
|
||||
<input type="text" class="mdl-textfield__input" id="ecmHost" data-automation-id="ecmHost"
|
||||
tabindex="1" (change)="onChangeECMHost($event)" value="{{ecmHost}}"/>
|
||||
</nav>
|
||||
<span class="mdl-layout-title">BPM host</span>
|
||||
<nav class="mdl-navigation">
|
||||
<input type="text" class="mdl-textfield__input" id="bpmHost" data-automation-id="bpmHost"
|
||||
tabindex="1" (change)="onChangeBPMHost($event)" value="{{bpmHost}}"/>
|
||||
</nav>
|
||||
</div>
|
||||
<main class="mdl-layout__content">
|
||||
<div class="page-content">
|
||||
<alfresco-login method="{{methodName}}"></alfresco-login>
|
||||
<router-outlet></router-outlet>
|
||||
<!--<auth-router-outlet></auth-router-outlet>-->
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
@@ -16,8 +16,7 @@
|
||||
*/
|
||||
|
||||
import { Component } from '@angular/core';
|
||||
import { Router, RouteConfig, ROUTER_DIRECTIVES } from '@angular/router-deprecated';
|
||||
import { FilesComponent } from './components/files/files.component';
|
||||
import { ROUTER_DIRECTIVES, Router } from '@angular/router';
|
||||
|
||||
import {
|
||||
MDL,
|
||||
@@ -26,12 +25,8 @@ import {
|
||||
AlfrescoPipeTranslate,
|
||||
AlfrescoAuthenticationService
|
||||
} from 'ng2-alfresco-core';
|
||||
import { UploadButtonComponent } from 'ng2-alfresco-upload';
|
||||
import { DataTableDemoComponent } from './components/datatable/datatable-demo.component';
|
||||
import { SearchComponent } from './components/search/search.component';
|
||||
import { SearchBarComponent } from './components/search/search-bar.component';
|
||||
import { LoginDemoComponent } from './components/login/login-demo.component';
|
||||
import { TasksDemoComponent } from './components/tasks/tasks-demo.component';
|
||||
|
||||
import { SearchBarComponent } from './components/index';
|
||||
|
||||
declare var document: any;
|
||||
|
||||
@@ -42,32 +37,36 @@ declare var document: any;
|
||||
directives: [SearchBarComponent, ROUTER_DIRECTIVES, MDL],
|
||||
pipes: [AlfrescoPipeTranslate]
|
||||
})
|
||||
@RouteConfig([
|
||||
{path: '/home', name: 'Home', component: FilesComponent},
|
||||
{path: '/files', name: 'Files', component: FilesComponent},
|
||||
{path: '/datatable', name: 'DataTable', component: DataTableDemoComponent},
|
||||
{path: '/', name: 'Login', component: LoginDemoComponent, useAsDefault: true},
|
||||
{path: '/uploader', name: 'Uploader', component: UploadButtonComponent},
|
||||
{path: '/login', name: 'Login', component: LoginDemoComponent},
|
||||
{path: '/search', name: 'Search', component: SearchComponent},
|
||||
{path: '/tasks', name: 'Tasks', component: TasksDemoComponent}
|
||||
])
|
||||
export class AppComponent {
|
||||
translate: AlfrescoTranslationService;
|
||||
searchTerm: string = '';
|
||||
|
||||
ecmHost: string = 'http://' + window.location.hostname + ':8080';
|
||||
bpmHost: string = 'http://' + window.location.hostname + ':9999';
|
||||
|
||||
constructor(public auth: AlfrescoAuthenticationService,
|
||||
public router: Router,
|
||||
translate: AlfrescoTranslationService,
|
||||
alfrescoSettingsService: AlfrescoSettingsService) {
|
||||
alfrescoSettingsService.host = 'http://localhost:8080';
|
||||
public alfrescoSettingsService: AlfrescoSettingsService) {
|
||||
this.setEcmHost();
|
||||
this.setBpmHost();
|
||||
|
||||
this.translate = translate;
|
||||
this.translate.addTranslationFolder();
|
||||
}
|
||||
|
||||
isActive(instruction: any[]): boolean {
|
||||
return this.router.isRouteActive(this.router.generate(instruction));
|
||||
public onChangeECMHost(event: KeyboardEvent): void {
|
||||
console.log((<HTMLInputElement>event.target).value);
|
||||
this.ecmHost = (<HTMLInputElement>event.target).value;
|
||||
this.alfrescoSettingsService.ecmHost = this.ecmHost;
|
||||
localStorage.setItem(`ecmHost`, this.ecmHost);
|
||||
}
|
||||
|
||||
public onChangeBPMHost(event: KeyboardEvent): void {
|
||||
console.log((<HTMLInputElement>event.target).value);
|
||||
this.bpmHost = (<HTMLInputElement>event.target).value;
|
||||
this.alfrescoSettingsService.bpmHost = this.bpmHost;
|
||||
localStorage.setItem(`bpmHost`, this.bpmHost);
|
||||
}
|
||||
|
||||
isLoggedIn(): boolean {
|
||||
@@ -78,7 +77,7 @@ export class AppComponent {
|
||||
event.preventDefault();
|
||||
this.auth.logout()
|
||||
.subscribe(
|
||||
() => this.router.navigate(['Login'])
|
||||
() => this.router.navigate(['/login'])
|
||||
);
|
||||
}
|
||||
|
||||
@@ -100,4 +99,22 @@ export class AppComponent {
|
||||
// todo: workaround for drawer closing
|
||||
document.querySelector('.mdl-layout').MaterialLayout.toggleDrawer();
|
||||
}
|
||||
|
||||
private setEcmHost() {
|
||||
if (localStorage.getItem(`ecmHost`)) {
|
||||
this.alfrescoSettingsService.ecmHost = localStorage.getItem(`ecmHost`);
|
||||
this.ecmHost = localStorage.getItem(`ecmHost`);
|
||||
} else {
|
||||
this.alfrescoSettingsService.ecmHost = this.ecmHost;
|
||||
}
|
||||
}
|
||||
|
||||
private setBpmHost() {
|
||||
if (localStorage.getItem(`bpmHost`)) {
|
||||
this.alfrescoSettingsService.bpmHost = localStorage.getItem(`bpmHost`);
|
||||
this.bpmHost = localStorage.getItem(`bpmHost`);
|
||||
} else {
|
||||
this.alfrescoSettingsService.bpmHost = this.bpmHost;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*!
|
||||
* @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 { provideRouter, RouterConfig } from '@angular/router';
|
||||
|
||||
import {
|
||||
FilesComponent,
|
||||
UploadButtonComponent,
|
||||
DataTableDemoComponent,
|
||||
SearchComponent,
|
||||
LoginDemoComponent,
|
||||
ActivitiDemoComponent,
|
||||
WebscriptComponent,
|
||||
AboutComponent,
|
||||
FormViewer
|
||||
} from './components/index';
|
||||
import { FormNodeViewer } from './components/activiti/form-node-viewer.component';
|
||||
|
||||
export const routes: RouterConfig = [
|
||||
{ path: 'home', component: FilesComponent },
|
||||
{ path: 'files', component: FilesComponent },
|
||||
{ path: 'datatable', component: DataTableDemoComponent },
|
||||
{ path: '', component: LoginDemoComponent },
|
||||
{ path: 'uploader', component: UploadButtonComponent },
|
||||
{ path: 'login', component: LoginDemoComponent },
|
||||
{ path: 'search', component: SearchComponent },
|
||||
{ path: 'activiti', component: ActivitiDemoComponent },
|
||||
{ path: 'activiti/tasks/:id', component: FormViewer },
|
||||
{ path: 'activiti/tasksnode/:id', component: FormNodeViewer },
|
||||
{ path: 'webscript', component: WebscriptComponent },
|
||||
{ path: 'about', component: AboutComponent }
|
||||
];
|
||||
|
||||
export const appRouterProviders = [
|
||||
provideRouter(routes)
|
||||
];
|
||||
@@ -0,0 +1,4 @@
|
||||
<div style="padding: 10px">
|
||||
<h3>Packages</h3>
|
||||
<alfresco-datatable [data]="data"></alfresco-datatable>
|
||||
</div>
|
||||
@@ -0,0 +1,55 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Http } from '@angular/http';
|
||||
import {
|
||||
ALFRESCO_DATATABLE_DIRECTIVES,
|
||||
ObjectDataTableAdapter /*,
|
||||
DataSorting,
|
||||
ObjectDataRow,
|
||||
ObjectDataColumn*/
|
||||
} from 'ng2-alfresco-datatable';
|
||||
|
||||
declare let __moduleName: string;
|
||||
|
||||
@Component({
|
||||
moduleId: __moduleName,
|
||||
selector: 'about-page',
|
||||
templateUrl: './about.component.html',
|
||||
directives: [ALFRESCO_DATATABLE_DIRECTIVES]
|
||||
})
|
||||
export class AboutComponent implements OnInit {
|
||||
|
||||
data: ObjectDataTableAdapter;
|
||||
|
||||
constructor(private http: Http) {}
|
||||
|
||||
ngOnInit() {
|
||||
// this.data = new ObjectDataTableAdapter();
|
||||
this.http.get('/versions').subscribe(response => {
|
||||
let data = response.json() || {};
|
||||
let packages = data.packages || [];
|
||||
|
||||
this.data = new ObjectDataTableAdapter(packages, [
|
||||
{ type: 'text', key: 'name', title: 'Name', sortable: true },
|
||||
{ type: 'text', key: 'version', title: 'Version', sortable: true }
|
||||
]);
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
.activiti-task-list__item:hover {
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.activiti {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.task-column {
|
||||
background-color: #f5f5f5;
|
||||
padding: 10px 10px 10px 10px;
|
||||
border: solid 2px rgb(31,188,210);
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
<div class="mdl-layout mdl-js-layout mdl-layout--fixed-header">
|
||||
<header class="mdl-layout__header">
|
||||
<!-- Tabs -->
|
||||
<div class="mdl-layout__tab-bar mdl-js-ripple-effect">
|
||||
<a href="#scroll-tab-1" class="mdl-layout__tab is-active">TASK LIST</a>
|
||||
<a href="#scroll-tab-2" class="mdl-layout__tab">PROCESS LIST</a>
|
||||
<a href="#scroll-tab-3" class="mdl-layout__tab">REPORT</a>
|
||||
</div>
|
||||
</header>
|
||||
<main class="mdl-layout__content activiti">
|
||||
<section class="mdl-layout__tab-panel is-active" id="scroll-tab-1">
|
||||
<div class="page-content">
|
||||
<div class="mdl-grid">
|
||||
<div class="mdl-cell mdl-cell--2-col task-column mdl-shadow--2dp">
|
||||
<span>Task Filters</span>
|
||||
<activiti-filters (filterClick)="onTaskFilterClick($event)"></activiti-filters>
|
||||
</div>
|
||||
<div class="mdl-cell mdl-cell--3-col task-column mdl-shadow--2dp">
|
||||
<span>Task List</span>
|
||||
<activiti-tasklist *ngIf="isTaskListSelected()" [taskFilter]="taskFilter" [schemaColumn]="taskSchemaColumns"
|
||||
(rowClick)="onTaskRowClick($event)" #activititasklist></activiti-tasklist>
|
||||
</div>
|
||||
<div class="mdl-cell mdl-cell--7-col task-column mdl-shadow--2dp">
|
||||
<span>Task Details</span>
|
||||
<activiti-task-details [taskId]="currentTaskId" #activitidetails></activiti-task-details>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="mdl-layout__tab-panel" id="scroll-tab-2">
|
||||
<div class="page-content">
|
||||
<div class="page-content">
|
||||
<div class="mdl-grid">
|
||||
<div class="mdl-cell mdl-cell--2-col task-column">
|
||||
<span>Process Filters</span>
|
||||
<activiti-start-process [appId]="appId"></activiti-start-process>
|
||||
<activiti-process-filters (filterClick)="onProcessFilterClick($event)"></activiti-process-filters>
|
||||
</div>
|
||||
<div class="mdl-cell mdl-cell--3-col task-column">
|
||||
<span>Process List</span>
|
||||
<activiti-process-instance-list [filter]="processFilter" [schemaColumn]="processSchemaColumns"
|
||||
(rowClick)="onProcessRowClick($event)" #activitiprocesslist></activiti-process-instance-list>
|
||||
</div>
|
||||
<div class="mdl-cell mdl-cell--7-col task-column">
|
||||
<span>Process Details</span>
|
||||
<activiti-process-instance-details [processInstanceId]="currentProcessInstanceId" (taskFormCompleted)="taskFormCompleted()" (processCancelled)="processCancelled()" #activitiprocessdetails></activiti-process-instance-details>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="mdl-layout__tab-panel" id="scroll-tab-3">
|
||||
<div class="page-content"><!-- Your content goes here --></div>
|
||||
</section>
|
||||
<section class="mdl-layout__tab-panel" id="scroll-tab-4">
|
||||
<div class="page-content"><!-- Your content goes here --></div>
|
||||
</section>
|
||||
<section class="mdl-layout__tab-panel" id="scroll-tab-5">
|
||||
<div class="page-content"><!-- Your content goes here --></div>
|
||||
</section>
|
||||
<section class="mdl-layout__tab-panel" id="scroll-tab-6">
|
||||
<div class="page-content"><!-- Your content goes here --></div>
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
@@ -0,0 +1,119 @@
|
||||
/*!
|
||||
* @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, AfterViewChecked, ViewChild, Input } from '@angular/core';
|
||||
import { ALFRESCO_TASKLIST_DIRECTIVES } from 'ng2-activiti-tasklist';
|
||||
import { ACTIVITI_PROCESSLIST_DIRECTIVES } from 'ng2-activiti-processlist';
|
||||
import { ActivitiForm } from 'ng2-activiti-form';
|
||||
|
||||
declare let __moduleName: string;
|
||||
declare var componentHandler;
|
||||
|
||||
@Component({
|
||||
moduleId: __moduleName,
|
||||
selector: 'activiti-demo',
|
||||
templateUrl: './activiti-demo.component.html',
|
||||
styleUrls: ['./activiti-demo.component.css'],
|
||||
directives: [ALFRESCO_TASKLIST_DIRECTIVES, ACTIVITI_PROCESSLIST_DIRECTIVES, ActivitiForm]
|
||||
})
|
||||
export class ActivitiDemoComponent implements AfterViewChecked {
|
||||
|
||||
currentChoice: string = 'task-list';
|
||||
|
||||
@ViewChild('activitidetails')
|
||||
activitidetails: any;
|
||||
|
||||
@ViewChild('activititasklist')
|
||||
activititasklist: any;
|
||||
|
||||
@ViewChild('activitiprocesslist')
|
||||
activitiprocesslist: any;
|
||||
|
||||
@ViewChild('activitiprocessdetails')
|
||||
activitiprocessdetails: any;
|
||||
|
||||
currentTaskId: string;
|
||||
currentProcessInstanceId: string;
|
||||
|
||||
taskSchemaColumns: any [] = [];
|
||||
processSchemaColumns: any [] = [];
|
||||
|
||||
taskFilter: any;
|
||||
processFilter: any;
|
||||
|
||||
@Input()
|
||||
appId: string;
|
||||
|
||||
setChoice($event) {
|
||||
this.currentChoice = $event.target.value;
|
||||
}
|
||||
|
||||
isProcessListSelected() {
|
||||
return this.currentChoice === 'process-list';
|
||||
}
|
||||
|
||||
isTaskListSelected() {
|
||||
return this.currentChoice === 'task-list';
|
||||
}
|
||||
|
||||
constructor() {
|
||||
this.taskSchemaColumns = [
|
||||
{type: 'text', key: 'name', title: 'Name', cssClass: 'full-width name-column', sortable: true}
|
||||
// {type: 'text', key: 'created', title: 'Created', sortable: true}
|
||||
];
|
||||
this.processSchemaColumns = [
|
||||
{type: 'text', key: 'name', title: 'Name', cssClass: 'full-width name-column', sortable: true}
|
||||
];
|
||||
}
|
||||
|
||||
onTaskFilterClick(event: any) {
|
||||
this.taskFilter = event;
|
||||
this.activititasklist.load(this.taskFilter);
|
||||
}
|
||||
|
||||
onProcessFilterClick(event: any) {
|
||||
this.processFilter = event.filter;
|
||||
this.activitiprocesslist.load(this.processFilter);
|
||||
}
|
||||
|
||||
onTaskRowClick(taskId) {
|
||||
this.currentTaskId = taskId;
|
||||
this.activitidetails.loadDetails(this.currentTaskId);
|
||||
}
|
||||
|
||||
onProcessRowClick(processInstanceId) {
|
||||
this.currentProcessInstanceId = processInstanceId;
|
||||
this.activitiprocessdetails.load(this.currentProcessInstanceId);
|
||||
}
|
||||
|
||||
processCancelled(data: any) {
|
||||
this.currentProcessInstanceId = null;
|
||||
this.activitiprocesslist.reload();
|
||||
}
|
||||
|
||||
taskFormCompleted(data: any) {
|
||||
this.activitiprocesslist.reload();
|
||||
}
|
||||
|
||||
ngAfterViewChecked() {
|
||||
// workaround for MDL issues with dynamic components
|
||||
if (componentHandler) {
|
||||
componentHandler.upgradeAllRegistered();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
.activiti-form-viewer {
|
||||
margin: 10px;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
<div class="activiti-form-viewer" *ngIf="nodeId">
|
||||
<activiti-form [nodeId]="nodeId"
|
||||
[saveMetadata]="true"
|
||||
[path]="'/Sites/swsdp/documentLibrary'">
|
||||
</activiti-form>
|
||||
</div>
|
||||
@@ -0,0 +1,62 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Component, OnInit, OnDestroy, AfterViewChecked } from '@angular/core';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { ActivitiForm, FormService, EcmModelService, NodeService } from 'ng2-activiti-form';
|
||||
import { Subscription } from 'rxjs/Rx';
|
||||
|
||||
declare let __moduleName: string;
|
||||
declare var componentHandler;
|
||||
|
||||
@Component({
|
||||
moduleId: __moduleName,
|
||||
selector: 'form-node-viewer',
|
||||
templateUrl: './form-node-viewer.component.html',
|
||||
styleUrls: ['./form-node-viewer.component.css'],
|
||||
directives: [ActivitiForm],
|
||||
providers: [FormService, EcmModelService, NodeService]
|
||||
})
|
||||
export class FormNodeViewer implements OnInit, OnDestroy, AfterViewChecked {
|
||||
|
||||
nodeId: string;
|
||||
|
||||
private sub: Subscription;
|
||||
|
||||
constructor(private formService: FormService,
|
||||
private route: ActivatedRoute,
|
||||
private router: Router) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.sub = this.route.params.subscribe(params => {
|
||||
this.nodeId = params['id'];
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.sub.unsubscribe();
|
||||
}
|
||||
|
||||
ngAfterViewChecked() {
|
||||
// workaround for MDL issues with dynamic components
|
||||
if (componentHandler) {
|
||||
componentHandler.upgradeAllRegistered();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
.activiti-form-viewer {
|
||||
margin: 10px;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<div class="activiti-form-viewer" *ngIf="taskId">
|
||||
<activiti-form [taskId]="taskId"></activiti-form>
|
||||
<!--<activiti-form [formName]="'activitiForms:patientFolder'"-->
|
||||
<!--[saveMetadata]="true"-->
|
||||
<!--[path]="'/Sites/swsdp/documentLibrary'"-->
|
||||
<!--[nameNode]="'test'"></activiti-form>-->
|
||||
<!--<activiti-form [nodeId]="'e280be3a-6584-45a1-8bb5-89bfe070262e'"-->
|
||||
<!--[saveMetadata]="true"-->
|
||||
<!--[path]="'/Sites/swsdp/documentLibrary'">-->
|
||||
<!--</activiti-form>-->
|
||||
</div>
|
||||
@@ -0,0 +1,62 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Component, OnInit, OnDestroy, AfterViewChecked } from '@angular/core';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { ActivitiForm, FormService, EcmModelService, NodeService } from 'ng2-activiti-form';
|
||||
import { Subscription } from 'rxjs/Rx';
|
||||
|
||||
declare let __moduleName: string;
|
||||
declare var componentHandler;
|
||||
|
||||
@Component({
|
||||
moduleId: __moduleName,
|
||||
selector: 'form-viewer',
|
||||
templateUrl: './form-viewer.component.html',
|
||||
styleUrls: ['./form-viewer.component.css'],
|
||||
directives: [ActivitiForm],
|
||||
providers: [FormService, EcmModelService, NodeService]
|
||||
})
|
||||
export class FormViewer implements OnInit, OnDestroy, AfterViewChecked {
|
||||
|
||||
taskId: string;
|
||||
|
||||
private sub: Subscription;
|
||||
|
||||
constructor(private formService: FormService,
|
||||
private route: ActivatedRoute,
|
||||
private router: Router) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.sub = this.route.params.subscribe(params => {
|
||||
this.taskId = params['id'];
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.sub.unsubscribe();
|
||||
}
|
||||
|
||||
ngAfterViewChecked() {
|
||||
// workaround for MDL issues with dynamic components
|
||||
if (componentHandler) {
|
||||
componentHandler.upgradeAllRegistered();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
.container {
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 640px) {
|
||||
.container {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,118 +1,109 @@
|
||||
<alfresco-upload-drag-area
|
||||
[showUploadDialog]="true"
|
||||
[currentFolderPath]="currentPath"
|
||||
[uploaddirectory]=""
|
||||
(onSuccess)="documentList.reload()">
|
||||
<alfresco-document-list-breadcrumb
|
||||
[currentFolderPath]="currentPath"
|
||||
[target]="documentList">
|
||||
</alfresco-document-list-breadcrumb>
|
||||
<alfresco-document-list
|
||||
#documentList
|
||||
<div class="container">
|
||||
<alfresco-upload-drag-area
|
||||
[showUploadDialog]="true"
|
||||
[currentFolderPath]="currentPath"
|
||||
(preview)="showFile($event)"
|
||||
(folderChange)="onFolderChanged($event)">
|
||||
<!--
|
||||
<empty-folder-content>
|
||||
<template>
|
||||
<h1>Sorry, no content here</h1>
|
||||
</template>
|
||||
</empty-folder-content>
|
||||
-->
|
||||
<content-columns>
|
||||
<content-column source="$thumbnail" type="image"></content-column>
|
||||
<content-column
|
||||
title="{{'DOCUMENT_LIST.COLUMNS.DISPLAY_NAME' | translate}}"
|
||||
source="name"
|
||||
class="full-width ellipsis-cell">
|
||||
</content-column>
|
||||
[uploaddirectory]=""
|
||||
[versioning] = "versioning"
|
||||
(onSuccess)="documentList.reload()">
|
||||
<alfresco-document-list-breadcrumb
|
||||
[currentFolderPath]="currentPath"
|
||||
[target]="documentList">
|
||||
</alfresco-document-list-breadcrumb>
|
||||
<alfresco-document-list
|
||||
#documentList
|
||||
[currentFolderPath]="currentPath"
|
||||
[contextMenuActions]="true"
|
||||
[contentActions]="true"
|
||||
(preview)="showFile($event)"
|
||||
(folderChange)="onFolderChanged($event)">
|
||||
<!--
|
||||
<content-column
|
||||
title="Type"
|
||||
source="content.mimeType">
|
||||
</content-column>
|
||||
<empty-folder-content>
|
||||
<template>
|
||||
<h1>Sorry, no content here</h1>
|
||||
</template>
|
||||
</empty-folder-content>
|
||||
-->
|
||||
<content-column
|
||||
title="{{'DOCUMENT_LIST.COLUMNS.CREATED_BY' | translate}}"
|
||||
source="createdByUser.displayName"
|
||||
class="desktop-only">
|
||||
</content-column>
|
||||
<content-column
|
||||
title="{{'DOCUMENT_LIST.COLUMNS.CREATED_ON' | translate}}"
|
||||
source="createdAt"
|
||||
type="date"
|
||||
format="medium"
|
||||
class="desktop-only">
|
||||
</content-column>
|
||||
</content-columns>
|
||||
<content-columns>
|
||||
<content-column key="$thumbnail" type="image"></content-column>
|
||||
<content-column
|
||||
title="{{'DOCUMENT_LIST.COLUMNS.DISPLAY_NAME' | translate}}"
|
||||
key="name"
|
||||
sortable="true"
|
||||
class="full-width ellipsis-cell">
|
||||
</content-column>
|
||||
<!--
|
||||
<content-column
|
||||
title="Type"
|
||||
source="content.mimeType">
|
||||
</content-column>
|
||||
-->
|
||||
<content-column
|
||||
title="{{'DOCUMENT_LIST.COLUMNS.CREATED_BY' | translate}}"
|
||||
key="createdByUser.displayName"
|
||||
sortable="true"
|
||||
class="desktop-only">
|
||||
</content-column>
|
||||
<content-column
|
||||
title="{{'DOCUMENT_LIST.COLUMNS.CREATED_ON' | translate}}"
|
||||
key="createdAt"
|
||||
type="date"
|
||||
format="medium"
|
||||
sortable="true"
|
||||
class="desktop-only">
|
||||
</content-column>
|
||||
</content-columns>
|
||||
|
||||
<content-actions>
|
||||
<!-- folder actions -->
|
||||
<content-action
|
||||
target="folder"
|
||||
type="button"
|
||||
icon="delete"
|
||||
handler="system1">
|
||||
</content-action>
|
||||
<content-action
|
||||
target="folder"
|
||||
type="menu"
|
||||
title="{{'DOCUMENT_LIST.ACTIONS.FOLDER.SYSTEM_1' | translate}}"
|
||||
handler="system1">
|
||||
</content-action>
|
||||
<content-action
|
||||
target="folder"
|
||||
type="menu"
|
||||
title="{{'DOCUMENT_LIST.ACTIONS.FOLDER.CUSTOM' | translate}}"
|
||||
(execute)="myFolderAction1($event)">
|
||||
</content-action>
|
||||
<content-action
|
||||
target="folder"
|
||||
type="menu"
|
||||
title="{{'DOCUMENT_LIST.ACTIONS.FOLDER.DELETE' | translate}}"
|
||||
handler="delete">
|
||||
</content-action>
|
||||
|
||||
<!-- document actions -->
|
||||
<content-action
|
||||
target="document"
|
||||
type="button"
|
||||
icon="account_circle"
|
||||
handler="my-handler">
|
||||
</content-action>
|
||||
<content-action
|
||||
target="document"
|
||||
type="button"
|
||||
icon="cloud_download"
|
||||
handler="download">
|
||||
</content-action>
|
||||
<content-action
|
||||
target="document"
|
||||
type="menu"
|
||||
title="{{'DOCUMENT_LIST.ACTIONS.DOCUMENT.DOWNLOAD' | translate}}"
|
||||
handler="download">
|
||||
</content-action>
|
||||
<content-action
|
||||
target="document"
|
||||
type="menu"
|
||||
title="{{'DOCUMENT_LIST.ACTIONS.DOCUMENT.SYSTEM_2' | translate}}"
|
||||
handler="system2">
|
||||
</content-action>
|
||||
<content-action
|
||||
target="document"
|
||||
type="menu"
|
||||
title="{{'DOCUMENT_LIST.ACTIONS.DOCUMENT.CUSTOM' | translate}}"
|
||||
(execute)="myCustomAction1($event)">
|
||||
</content-action>
|
||||
<content-action
|
||||
target="document"
|
||||
type="menu"
|
||||
title="{{'DOCUMENT_LIST.ACTIONS.DOCUMENT.DELETE' | translate}}"
|
||||
handler="delete">
|
||||
</content-action>
|
||||
</content-actions>
|
||||
</alfresco-document-list>
|
||||
</alfresco-upload-drag-area>
|
||||
<content-actions>
|
||||
<!-- folder actions -->
|
||||
<content-action
|
||||
target="folder"
|
||||
title="{{'DOCUMENT_LIST.ACTIONS.FOLDER.SYSTEM_1' | translate}}"
|
||||
handler="system1">
|
||||
</content-action>
|
||||
<content-action
|
||||
target="folder"
|
||||
title="{{'DOCUMENT_LIST.ACTIONS.FOLDER.CUSTOM' | translate}}"
|
||||
(execute)="myFolderAction1($event)">
|
||||
</content-action>
|
||||
<content-action
|
||||
target="folder"
|
||||
title="{{'DOCUMENT_LIST.ACTIONS.FOLDER.DELETE' | translate}}"
|
||||
handler="delete">
|
||||
</content-action>
|
||||
<!-- document actions -->
|
||||
<content-action
|
||||
target="document"
|
||||
title="{{'DOCUMENT_LIST.ACTIONS.DOCUMENT.DOWNLOAD' | translate}}"
|
||||
handler="download">
|
||||
</content-action>
|
||||
<content-action
|
||||
target="document"
|
||||
title="{{'DOCUMENT_LIST.ACTIONS.DOCUMENT.SYSTEM_2' | translate}}"
|
||||
handler="system2">
|
||||
</content-action>
|
||||
<content-action
|
||||
target="document"
|
||||
title="{{'DOCUMENT_LIST.ACTIONS.DOCUMENT.CUSTOM' | translate}}"
|
||||
(execute)="myCustomAction1($event)">
|
||||
</content-action>
|
||||
<content-action
|
||||
target="document"
|
||||
title="{{'DOCUMENT_LIST.ACTIONS.DOCUMENT.DELETE' | translate}}"
|
||||
handler="delete">
|
||||
</content-action>
|
||||
<content-action
|
||||
target="folder"
|
||||
title="Activiti: View Form"
|
||||
(execute)="viewActivitiForm($event)">
|
||||
</content-action>
|
||||
</content-actions>
|
||||
</alfresco-document-list>
|
||||
<alfresco-pagination
|
||||
[provider]="documentList.data"
|
||||
[supportedPageSizes]="[5, 10, 15, 20]">
|
||||
</alfresco-pagination>
|
||||
</alfresco-upload-drag-area>
|
||||
</div>
|
||||
|
||||
<context-menu-holder></context-menu-holder>
|
||||
|
||||
@@ -135,37 +126,70 @@
|
||||
</div>
|
||||
|
||||
|
||||
<p style="width:250px;margin: 20px;">
|
||||
<label for="switch-multiple-file" class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
|
||||
<input type="checkbox" id="switch-multiple-file" class="mdl-switch__input" (change)="toggleMultipleFileUpload()" >
|
||||
<span class="mdl-switch__label">Multiple File Upload</span>
|
||||
</label>
|
||||
</p>
|
||||
|
||||
<h5>Single file upload</h5>
|
||||
<alfresco-upload-button data-automation-id="single-file-upload"
|
||||
[uploaddirectory]="currentPath"
|
||||
[currentFolderPath]="currentPath"
|
||||
(onSuccess)="documentList.reload()">
|
||||
</alfresco-upload-button>
|
||||
|
||||
<h5>Folder upload</h5>
|
||||
<alfresco-upload-button data-automation-id="folder-upload"
|
||||
[uploaddirectory]="currentPath"
|
||||
[currentFolderPath]="currentPath"
|
||||
[uploadFolders]="true"
|
||||
(onSuccess)="documentList.reload()">
|
||||
</alfresco-upload-button>
|
||||
<p style="width:250px;margin: 20px;">
|
||||
<label for="switch-folder-upload" class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
|
||||
<input type="checkbox" id="switch-folder-upload" class="mdl-switch__input" (change)="toggleFolder()">
|
||||
<span class="mdl-switch__label">Folder Upload</span>
|
||||
</label>
|
||||
</p>
|
||||
|
||||
<h5>Multiple file upload</h5>
|
||||
<input type="text" data-automation-id="accepted-files-type" [(ngModel)]="acceptedFilesType">
|
||||
<alfresco-upload-button data-automation-id="multiple-file-upload"
|
||||
[uploaddirectory]="currentPath"
|
||||
[currentFolderPath]="currentPath"
|
||||
acceptedFilesType="{{acceptedFilesType}}"
|
||||
[multipleFiles]="true"
|
||||
(onSuccess)="documentList.reload()">
|
||||
</alfresco-upload-button>
|
||||
<p style="width:250px;margin: 20px;">
|
||||
<label for="switch-accepted-file-type" class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
|
||||
<input type="checkbox" id="switch-accepted-file-type" class="mdl-switch__input" (change)="toggleAcceptedFilesType()">
|
||||
<span class="mdl-switch__label">Filter extension</span>
|
||||
</label>
|
||||
</p>
|
||||
|
||||
<p style="width:250px;margin: 20px;">
|
||||
<label for="switch-versioning" class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
|
||||
<input type="checkbox" id="switch-versioning" class="mdl-switch__input" (change)="toggleVersioning()">
|
||||
<span class="mdl-switch__label">Versioning</span>
|
||||
</label>
|
||||
</p>
|
||||
|
||||
<h5>Upload</h5>
|
||||
<br>
|
||||
<div *ngIf="acceptedFilesTypeShow">
|
||||
<span class="mdl-input__label">Extension accepted</span>
|
||||
<input type="text" data-automation-id="accepted-files-type" [(ngModel)]="acceptedFilesType">
|
||||
<br/>
|
||||
</div>
|
||||
<div *ngIf="!acceptedFilesTypeShow">
|
||||
<alfresco-upload-button data-automation-id="multiple-file-upload"
|
||||
[uploaddirectory]="currentPath"
|
||||
[currentFolderPath]="currentPath"
|
||||
[multipleFiles]="multipleFileUpload"
|
||||
[uploadFolders]="folderUpload"
|
||||
[versioning] = "versioning"
|
||||
(onSuccess)="documentList.reload()">
|
||||
<div class="mdl-spinner mdl-js-spinner is-active"></div>
|
||||
</alfresco-upload-button>
|
||||
</div>
|
||||
<div *ngIf="acceptedFilesTypeShow">
|
||||
<alfresco-upload-button data-automation-id="multiple-file-upload"
|
||||
[uploaddirectory]="currentPath"
|
||||
[currentFolderPath]="currentPath"
|
||||
acceptedFilesType="{{acceptedFilesType}}"
|
||||
[multipleFiles]="multipleFileUpload"
|
||||
[uploadFolders]="folderUpload"
|
||||
[versioning] = "versioning"
|
||||
(onSuccess)="documentList.reload()">
|
||||
<div class="mdl-spinner mdl-js-spinner is-active"></div>
|
||||
</alfresco-upload-button>
|
||||
</div>
|
||||
|
||||
<alfresco-viewer [(showViewer)]="fileShowed"
|
||||
[urlFile]="urlFile"
|
||||
[fileName]="fileName"
|
||||
[mimeType]="mimeType"
|
||||
[fileNodeId]="fileNodeId"
|
||||
[overlayMode]="true">
|
||||
<div class="mdl-spinner mdl-js-spinner is-active"></div>
|
||||
</alfresco-viewer>
|
||||
|
||||
<file-uploading-dialog #fileDialog></file-uploading-dialog>
|
||||
|
||||
@@ -15,11 +15,16 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Component } from '@angular/core';
|
||||
import { Component, OnInit, ViewChild } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import {
|
||||
DOCUMENT_LIST_DIRECTIVES,
|
||||
DOCUMENT_LIST_PROVIDERS,
|
||||
DocumentActionsService
|
||||
DocumentActionsService,
|
||||
DocumentList,
|
||||
ContentActionHandler,
|
||||
DocumentActionModel,
|
||||
FolderActionModel
|
||||
} from 'ng2-alfresco-documentlist';
|
||||
import {
|
||||
MDL,
|
||||
@@ -27,8 +32,10 @@ import {
|
||||
CONTEXT_MENU_DIRECTIVES,
|
||||
AlfrescoPipeTranslate
|
||||
} from 'ng2-alfresco-core';
|
||||
import { PaginationComponent } from 'ng2-alfresco-datatable';
|
||||
import { ALFRESCO_ULPOAD_COMPONENTS } from 'ng2-alfresco-upload';
|
||||
import { VIEWERCOMPONENT } from 'ng2-alfresco-viewer';
|
||||
import { FormService } from 'ng2-activiti-form';
|
||||
|
||||
declare let __moduleName: string;
|
||||
|
||||
@@ -42,24 +49,31 @@ declare let __moduleName: string;
|
||||
MDL,
|
||||
ALFRESCO_ULPOAD_COMPONENTS,
|
||||
VIEWERCOMPONENT,
|
||||
CONTEXT_MENU_DIRECTIVES
|
||||
CONTEXT_MENU_DIRECTIVES,
|
||||
PaginationComponent
|
||||
],
|
||||
providers: [DOCUMENT_LIST_PROVIDERS],
|
||||
providers: [DOCUMENT_LIST_PROVIDERS, FormService],
|
||||
pipes: [AlfrescoPipeTranslate]
|
||||
})
|
||||
export class FilesComponent {
|
||||
export class FilesComponent implements OnInit {
|
||||
currentPath: string = '/Sites/swsdp/documentLibrary';
|
||||
|
||||
urlFile: string;
|
||||
fileName: string;
|
||||
mimeType: string;
|
||||
fileNodeId: any;
|
||||
fileShowed: boolean = false;
|
||||
multipleFileUpload: boolean = false;
|
||||
folderUpload: boolean = false;
|
||||
acceptedFilesTypeShow: boolean = false;
|
||||
versioning: boolean = false;
|
||||
|
||||
acceptedFilesType: string = '.jpg,.pdf,.js';
|
||||
|
||||
constructor(
|
||||
private contentService: AlfrescoContentService,
|
||||
documentActions: DocumentActionsService) {
|
||||
@ViewChild(DocumentList)
|
||||
documentList: DocumentList;
|
||||
|
||||
constructor(private contentService: AlfrescoContentService,
|
||||
private documentActions: DocumentActionsService,
|
||||
private formService: FormService,
|
||||
private router: Router) {
|
||||
documentActions.setHandler('my-handler', this.myDocumentActionHandler.bind(this));
|
||||
}
|
||||
|
||||
@@ -77,9 +91,7 @@ export class FilesComponent {
|
||||
|
||||
showFile(event) {
|
||||
if (event.value.entry.isFile) {
|
||||
this.fileName = event.value.entry.name;
|
||||
this.mimeType = event.value.entry.content.mimeType;
|
||||
this.urlFile = this.contentService.getContentUrl(event.value);
|
||||
this.fileNodeId = event.value.entry.id;
|
||||
this.fileShowed = true;
|
||||
} else {
|
||||
this.fileShowed = false;
|
||||
@@ -91,4 +103,56 @@ export class FilesComponent {
|
||||
this.currentPath = event.path;
|
||||
}
|
||||
}
|
||||
|
||||
toggleMultipleFileUpload() {
|
||||
this.multipleFileUpload = !this.multipleFileUpload;
|
||||
return this.multipleFileUpload;
|
||||
}
|
||||
|
||||
toggleFolder() {
|
||||
this.multipleFileUpload = false;
|
||||
this.folderUpload = !this.folderUpload;
|
||||
return this.folderUpload;
|
||||
}
|
||||
|
||||
toggleAcceptedFilesType() {
|
||||
this.acceptedFilesTypeShow = !this.acceptedFilesTypeShow;
|
||||
return this.acceptedFilesTypeShow;
|
||||
}
|
||||
|
||||
toggleVersioning() {
|
||||
this.versioning = !this.versioning;
|
||||
return this.versioning;
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.formService.getProcessDefinitions().subscribe(
|
||||
defs => this.setupBpmActions(defs || []),
|
||||
err => console.log(err)
|
||||
);
|
||||
}
|
||||
|
||||
viewActivitiForm(event?: any) {
|
||||
this.router.navigate(['/activiti/tasksnode', event.value.entry.id]);
|
||||
}
|
||||
|
||||
private setupBpmActions(actions: any[]) {
|
||||
actions.map(def => {
|
||||
let documentAction = new DocumentActionModel();
|
||||
documentAction.title = 'Activiti: ' + (def.name || 'Unknown process');
|
||||
documentAction.handler = this.getBpmActionHandler(def);
|
||||
this.documentList.actions.push(documentAction);
|
||||
|
||||
let folderAction = new FolderActionModel();
|
||||
folderAction.title = 'Activiti: ' + (def.name || 'Unknown process');
|
||||
folderAction.handler = this.getBpmActionHandler(def);
|
||||
this.documentList.actions.push(folderAction);
|
||||
});
|
||||
}
|
||||
|
||||
private getBpmActionHandler(processDefinition: any): ContentActionHandler {
|
||||
return function (obj: any, target?: any) {
|
||||
window.alert(`Starting BPM process: ${processDefinition.id}`);
|
||||
}.bind(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*!
|
||||
* @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 { UploadButtonComponent } from 'ng2-alfresco-upload';
|
||||
export { DataTableDemoComponent } from './datatable/datatable-demo.component';
|
||||
export { SearchComponent } from './search/search.component';
|
||||
export { SearchBarComponent } from './search/search-bar.component';
|
||||
export { LoginDemoComponent } from './login/login-demo.component';
|
||||
export { ActivitiDemoComponent } from './activiti/activiti-demo.component';
|
||||
export { FormViewer } from './activiti/form-viewer.component';
|
||||
export { WebscriptComponent } from './webscript/webscript.component';
|
||||
export { AboutComponent } from './about/about.component';
|
||||
export { FilesComponent } from './files/files.component';
|
||||
@@ -1 +1,15 @@
|
||||
<alfresco-login (onSuccess)="onLogin($event)" (onError)="onError($event)"></alfresco-login>
|
||||
<div style="border-radius: 8px; position: absolute; background-color: papayawhip; color: cadetblue; left: 10px; top: 10px; z-index: 1;">
|
||||
<p style="width:120px;margin: 20px;">
|
||||
<label for="switch1" class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
|
||||
<input type="checkbox" id="switch1" class="mdl-switch__input" checked (click)="toggleECM(ecm.checked)" #ecm>
|
||||
<span class="mdl-switch__label">ECM</span>
|
||||
</label>
|
||||
</p>
|
||||
<p style="width:120px;margin: 20px;">
|
||||
<label for="switch2" class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
|
||||
<input type="checkbox" id="switch2" class="mdl-switch__input" (click)="toggleBPM(bpm.checked)" #bpm>
|
||||
<span class="mdl-switch__label">BPM</span>
|
||||
</label>
|
||||
</p>
|
||||
</div>
|
||||
<alfresco-login [providers]="providers" (onSuccess)="onLogin($event)" (onError)="onError($event)"></alfresco-login>
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Component } from '@angular/core';
|
||||
import { AlfrescoLoginComponent } from 'ng2-alfresco-login';
|
||||
import { Router, ROUTER_DIRECTIVES } from '@angular/router-deprecated';
|
||||
import {Component} from '@angular/core';
|
||||
import {AlfrescoLoginComponent} from 'ng2-alfresco-login';
|
||||
import {ROUTER_DIRECTIVES, Router} from '@angular/router';
|
||||
|
||||
declare let __moduleName: string;
|
||||
|
||||
@@ -30,16 +30,37 @@ declare let __moduleName: string;
|
||||
})
|
||||
export class LoginDemoComponent {
|
||||
|
||||
providers: string = 'ECM';
|
||||
|
||||
constructor(public router: Router) {
|
||||
}
|
||||
|
||||
onLogin($event) {
|
||||
console.log($event);
|
||||
this.router.navigate(['Home']);
|
||||
this.router.navigate(['/home']);
|
||||
}
|
||||
|
||||
onError($event) {
|
||||
console.log($event);
|
||||
}
|
||||
|
||||
toggleECM(checked) {
|
||||
if (checked && this.providers === 'BPM') {
|
||||
this.providers = 'ALL';
|
||||
} else if (checked) {
|
||||
this.providers = 'ECM';
|
||||
} else {
|
||||
this.providers = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
toggleBPM(checked) {
|
||||
if (checked && this.providers === 'ECM') {
|
||||
this.providers = 'ALL';
|
||||
} else if (checked) {
|
||||
this.providers = 'BPM';
|
||||
} else {
|
||||
this.providers = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<alfresco-search-control *ngIf="isLoggedIn()" [searchTerm]="searchTerm" [autocomplete]="false"
|
||||
(searchChange)="searchTermChange($event);" (expand)="onExpandToggle($event);" (preview)="onFileClicked($event)"></alfresco-search-control>
|
||||
|
||||
<alfresco-viewer [(showViewer)]="fileShowed" [urlFile]="urlFile" [fileName]="fileName" [mimeType]="mimeType" [overlayMode]="true">
|
||||
<alfresco-viewer [(showViewer)]="fileShowed"
|
||||
[fileNodeId]="fileNodeId"
|
||||
[overlayMode]="true">
|
||||
<div class="mdl-spinner mdl-js-spinner is-active"></div>
|
||||
</alfresco-viewer>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
import { Component, EventEmitter, Output } from '@angular/core';
|
||||
import { Router } from '@angular/router-deprecated';
|
||||
import { Router } from '@angular/router';
|
||||
import { ALFRESCO_SEARCH_DIRECTIVES } from 'ng2-alfresco-search';
|
||||
import { VIEWERCOMPONENT } from 'ng2-alfresco-viewer';
|
||||
import {
|
||||
|
||||
@@ -56,15 +56,14 @@ export class SearchComponent {
|
||||
previewName: string;
|
||||
previewMimeType: string;
|
||||
previewActive: boolean = false;
|
||||
fileNodeId: string;
|
||||
|
||||
constructor(public contentService: AlfrescoContentService) {
|
||||
}
|
||||
|
||||
onFileClicked(event) {
|
||||
if (event.value.entry.isFile) {
|
||||
this.previewName = event.value.entry.name;
|
||||
this.previewMimeType = event.value.entry.content.mimeType;
|
||||
this.previewContentUrl = this.contentService.getContentUrl(event.value);
|
||||
this.fileNodeId = event.value.entry.id;
|
||||
this.previewActive = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Http, Headers, RequestOptions, Response } from '@angular/http';
|
||||
// import { Observable } from 'rxjs/Rx';
|
||||
|
||||
@Injectable()
|
||||
export class ActivitiService {
|
||||
|
||||
constructor(private http: Http) {}
|
||||
|
||||
login(username: string, password: string) {
|
||||
let url = 'http://localhost:9999/activiti-app/app/authentication';
|
||||
let headers = new Headers({
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
'Cache-Control': 'no-cache'
|
||||
});
|
||||
let options = new RequestOptions({ headers: headers });
|
||||
let data = 'j_username='
|
||||
+ encodeURIComponent(username)
|
||||
+ '&j_password='
|
||||
+ encodeURIComponent(password)
|
||||
+ '&_spring_security_remember_me=true&submit=Login';
|
||||
|
||||
return this.http
|
||||
.post(url, data, options)
|
||||
.toPromise()
|
||||
// .then(res => console.log(res))
|
||||
.catch(this.handleError);
|
||||
}
|
||||
|
||||
getTasks() {
|
||||
// emulate filter value
|
||||
let data = JSON.stringify({
|
||||
'page': 0,
|
||||
'filterId': 3,
|
||||
'filter': {
|
||||
'sort': 'created-desc',
|
||||
'name': '',
|
||||
'state': 'open',
|
||||
'assignment': 'involved'
|
||||
},
|
||||
'appDefinitionId': null
|
||||
});
|
||||
|
||||
let url = 'http://localhost:9999/activiti-app/app/rest/filter/tasks';
|
||||
let headers = new Headers({
|
||||
'Content-Type': 'application/json',
|
||||
'Cache-Control': 'no-cache'
|
||||
});
|
||||
let options = new RequestOptions({ headers: headers });
|
||||
|
||||
return this.http
|
||||
.post(url, data, options)
|
||||
.toPromise()
|
||||
.then(this.parseJSON)
|
||||
.catch(this.handleError);
|
||||
}
|
||||
|
||||
private parseJSON(res: Response) {
|
||||
let body = res.json();
|
||||
return body.data || { };
|
||||
}
|
||||
|
||||
private handleError(error: any) {
|
||||
console.error('An error occurred', error);
|
||||
return Promise.reject(error.message || error);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { ActivitiService } from './activiti.service';
|
||||
import {
|
||||
ALFRESCO_DATATABLE_DIRECTIVES,
|
||||
ObjectDataTableAdapter
|
||||
} from 'ng2-alfresco-datatable';
|
||||
|
||||
@Component({
|
||||
selector: 'tasks-demo',
|
||||
template: `
|
||||
<div class="container">
|
||||
<alfresco-datatable [data]="tasks"></alfresco-datatable>
|
||||
</div>
|
||||
`,
|
||||
directives: [ALFRESCO_DATATABLE_DIRECTIVES],
|
||||
providers: [ActivitiService],
|
||||
styles: [':host > .container { padding: 10px; }']
|
||||
})
|
||||
export class TasksDemoComponent implements OnInit {
|
||||
|
||||
tasks: ObjectDataTableAdapter;
|
||||
|
||||
constructor(
|
||||
private activitiService: ActivitiService) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.activitiService
|
||||
.login('denys.vuika@alfresco.com', 'test')
|
||||
.then(() => {
|
||||
this.activitiService
|
||||
.getTasks()
|
||||
.then((data) => {
|
||||
let tasks = data || [];
|
||||
console.log(tasks);
|
||||
this.loadTasks(tasks);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private loadTasks(tasks: any[]) {
|
||||
tasks = tasks.map(t => {
|
||||
t.name = t.name || 'Nameless task';
|
||||
if (t.name.length > 50) {
|
||||
t.name = t.name.substring(0, 50) + '...';
|
||||
}
|
||||
return t;
|
||||
});
|
||||
|
||||
this.tasks = new ObjectDataTableAdapter(tasks, [
|
||||
{ type: 'text', key: 'id', title: 'Id'},
|
||||
{ type: 'text', key: 'name', title: 'Name', cssClass: 'full-width name-column', sortable: true },
|
||||
{ type: 'text', key: 'formKey', title: 'Form Key', sortable: true },
|
||||
{ type: 'text', key: 'created', title: 'Created', sortable: true }
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Component } from '@angular/core';
|
||||
import {
|
||||
CONTEXT_MENU_DIRECTIVES
|
||||
} from 'ng2-alfresco-core';
|
||||
|
||||
import { WEBSCRIPTCOMPONENT } from 'ng2-alfresco-webscript';
|
||||
|
||||
@Component({
|
||||
selector: 'alfresco-webscript-demo',
|
||||
template: `
|
||||
<label for="token"><b>Insert a scriptPath</b></label><br>
|
||||
<input id="token" type="text" size="48" [(ngModel)]="scriptPath"><br>
|
||||
<label for="token"><b>Insert a contextRoot</b></label><br>
|
||||
<input id="token" type="text" size="48" [(ngModel)]="contextRoot"><br>
|
||||
<label for="token"><b>Insert a servicePath</b></label><br>
|
||||
<input id="token" type="text" size="48" [(ngModel)]="servicePath"><br>
|
||||
<alfresco-webscript-get [scriptPath]="scriptPath"
|
||||
[scriptArgs]="scriptArgs"
|
||||
[contextRoot]="contextRoot"
|
||||
[servicePath]="servicePath"
|
||||
[contentType]="'HTML'"
|
||||
(onSuccess)= "logData($event)"></alfresco-webscript-get>
|
||||
`,
|
||||
directives: [WEBSCRIPTCOMPONENT, CONTEXT_MENU_DIRECTIVES]
|
||||
})
|
||||
export class WebscriptComponent {
|
||||
|
||||
currentPath: string = '/';
|
||||
|
||||
authenticated: boolean;
|
||||
|
||||
host: string = 'http://127.0.0.1:8080';
|
||||
|
||||
scriptPath: string = 'sample/folder/Company%20Home';
|
||||
|
||||
contextRoot: string = 'alfresco';
|
||||
|
||||
servicePath: string = 'service';
|
||||
|
||||
scriptArgs: string = '';
|
||||
|
||||
logData(data) {
|
||||
console.log(data);
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 345 KiB |
@@ -0,0 +1,782 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="110px"
|
||||
height="110px" viewBox="0 0 110 110" style="enable-background:new 0 0 110 110;" xml:space="preserve">
|
||||
<g id="Artboard" style="display:none;">
|
||||
<rect x="-443" y="-79" style="display:inline;fill:#8C8C8C;" width="1412" height="743"/>
|
||||
</g>
|
||||
<g id="R-Multicolor" style="display:none;">
|
||||
<circle style="display:inline;fill:#E04F5F;" cx="55" cy="55" r="55"/>
|
||||
<g style="display:inline;">
|
||||
<path style="fill:#FFFFFF;" d="M23,26.84c0-2.121,1.719-3.84,3.84-3.84H55l16,13.44v46.72c0,2.121-1.719,3.84-3.84,3.84H26.84
|
||||
C24.719,87,23,85.281,23,83.16V26.84z"/>
|
||||
<path style="fill:#F0F1F1;" d="M55,23v9.6c0,2.121,1.719,3.84,3.84,3.84H71L55,23z"/>
|
||||
<polygon style="fill:#F4D0A1;" points="77,41.5 82,31 87,41.5 87,80 77,80 "/>
|
||||
<polygon style="fill:#EDBC7C;" points="87,47 87,41.5 82,31 82,47 "/>
|
||||
<path style="fill:#F79392;" d="M87,84c0,1.657-1.343,3-3,3h-4c-1.657,0-3-1.343-3-3v-2h10V84z"/>
|
||||
<path style="fill:#E2E4E5;" d="M62,45c0,0.55-0.45,1-1,1H46c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h15C61.55,44,62,44.45,62,45
|
||||
L62,45z"/>
|
||||
<path style="fill:#E2E4E5;" d="M56,50c0,0.55-0.45,1-1,1h-9c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h9C55.55,49,56,49.45,56,50
|
||||
L56,50z"/>
|
||||
<path style="fill:#E2E4E5;" d="M62,58c0,0.55-0.45,1-1,1H46c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h15C61.55,57,62,57.45,62,58
|
||||
L62,58z"/>
|
||||
<path style="fill:#E2E4E5;" d="M56,63c0,0.55-0.45,1-1,1h-9c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h9C55.55,62,56,62.45,56,63
|
||||
L56,63z"/>
|
||||
<path style="fill:#E2E4E5;" d="M62,71c0,0.55-0.45,1-1,1H46c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h15C61.55,70,62,70.45,62,71
|
||||
L62,71z"/>
|
||||
<path style="fill:#E2E4E5;" d="M56,76c0,0.55-0.45,1-1,1h-9c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h9C55.55,75,56,75.45,56,76
|
||||
L56,76z"/>
|
||||
<g>
|
||||
<path style="fill:#17B198;" d="M35.067,52l-3.774-3.774c-0.391-0.39-0.391-1.024,0-1.414c0.391-0.391,1.024-0.391,1.414,0
|
||||
l2.226,2.226l4.299-5.159c0.354-0.425,0.984-0.482,1.408-0.128c0.424,0.354,0.482,0.984,0.128,1.408L35.067,52z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#17B198;" d="M35.067,65l-3.774-3.774c-0.391-0.39-0.391-1.024,0-1.414c0.391-0.391,1.024-0.391,1.414,0
|
||||
l2.226,2.226l4.299-5.159c0.354-0.425,0.984-0.482,1.408-0.128c0.424,0.354,0.482,0.984,0.128,1.408L35.067,65z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#17B198;" d="M35.067,78l-3.774-3.774c-0.391-0.39-0.391-1.024,0-1.414c0.391-0.391,1.024-0.391,1.414,0
|
||||
l2.226,2.226l4.299-5.159c0.354-0.425,0.984-0.482,1.408-0.128c0.424,0.354,0.482,0.984,0.128,1.408L35.067,78z"/>
|
||||
</g>
|
||||
<rect x="77" y="79" style="fill:#FACB1B;" width="10" height="3"/>
|
||||
<rect x="77" y="80" style="fill:#FBE158;" width="5" height="2"/>
|
||||
<path style="fill:#3E3E3F;" d="M82.013,30.984l-1.857,3.899c0.512,0.678,1.152,1.101,1.857,1.101s1.345-0.422,1.857-1.101
|
||||
L82.013,30.984z"/>
|
||||
<path style="fill:#0484AB;" d="M84.5,43c-1.154,0-2.126-0.782-2.413-1.845c-0.026-0.097-0.147-0.097-0.173,0
|
||||
C81.626,42.218,80.654,43,79.5,43c-1.052,0-1.953-0.65-2.322-1.571C77.139,41.332,77,41.359,77,41.464V80h10V41.464
|
||||
c0-0.105-0.139-0.131-0.178-0.034C86.453,42.35,85.552,43,84.5,43z"/>
|
||||
<path style="fill:#21B2D1;" d="M77,80V41.493c0-0.111,0.147-0.139,0.19-0.036C77.565,42.363,78.458,43,79.5,43
|
||||
c1.159,0,2.134-0.789,2.417-1.859C81.931,41.089,82,41.096,82,41.15V80H77z"/>
|
||||
<path style="fill:#F7B4B4;" d="M77,82v2c0,1.657,1.343,3,3,3h2v-5H77z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="Multicolor">
|
||||
<g>
|
||||
<path style="fill:#FFFFFF;" d="M23,26.84c0-2.121,1.719-3.84,3.84-3.84H55l16,13.44v46.72c0,2.121-1.719,3.84-3.84,3.84H26.84
|
||||
C24.719,87,23,85.281,23,83.16V26.84z"/>
|
||||
<path style="fill:#F0F1F1;" d="M55,23v9.6c0,2.121,1.719,3.84,3.84,3.84H71L55,23z"/>
|
||||
<polygon style="fill:#F4D0A1;" points="77,41.5 82,31 87,41.5 87,80 77,80 "/>
|
||||
<polygon style="fill:#EDBC7C;" points="87,47 87,41.5 82,31 82,47 "/>
|
||||
<path style="fill:#F79392;" d="M87,84c0,1.657-1.343,3-3,3h-4c-1.657,0-3-1.343-3-3v-2h10V84z"/>
|
||||
<path style="fill:#E2E4E5;" d="M62,45c0,0.55-0.45,1-1,1H46c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h15C61.55,44,62,44.45,62,45
|
||||
L62,45z"/>
|
||||
<path style="fill:#E2E4E5;" d="M56,50c0,0.55-0.45,1-1,1h-9c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h9C55.55,49,56,49.45,56,50
|
||||
L56,50z"/>
|
||||
<path style="fill:#E2E4E5;" d="M62,58c0,0.55-0.45,1-1,1H46c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h15C61.55,57,62,57.45,62,58
|
||||
L62,58z"/>
|
||||
<path style="fill:#E2E4E5;" d="M56,63c0,0.55-0.45,1-1,1h-9c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h9C55.55,62,56,62.45,56,63
|
||||
L56,63z"/>
|
||||
<path style="fill:#E2E4E5;" d="M62,71c0,0.55-0.45,1-1,1H46c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h15C61.55,70,62,70.45,62,71
|
||||
L62,71z"/>
|
||||
<path style="fill:#E2E4E5;" d="M56,76c0,0.55-0.45,1-1,1h-9c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h9C55.55,75,56,75.45,56,76
|
||||
L56,76z"/>
|
||||
<g>
|
||||
<path style="fill:#17B198;" d="M35.067,52l-3.774-3.774c-0.391-0.39-0.391-1.024,0-1.414c0.391-0.391,1.024-0.391,1.414,0
|
||||
l2.226,2.226l4.299-5.159c0.354-0.425,0.984-0.482,1.408-0.128c0.424,0.354,0.482,0.984,0.128,1.408L35.067,52z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#17B198;" d="M35.067,65l-3.774-3.774c-0.391-0.39-0.391-1.024,0-1.414c0.391-0.391,1.024-0.391,1.414,0
|
||||
l2.226,2.226l4.299-5.159c0.354-0.425,0.984-0.482,1.408-0.128c0.424,0.354,0.482,0.984,0.128,1.408L35.067,65z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#17B198;" d="M35.067,78l-3.774-3.774c-0.391-0.39-0.391-1.024,0-1.414c0.391-0.391,1.024-0.391,1.414,0
|
||||
l2.226,2.226l4.299-5.159c0.354-0.425,0.984-0.482,1.408-0.128c0.424,0.354,0.482,0.984,0.128,1.408L35.067,78z"/>
|
||||
</g>
|
||||
<rect x="77" y="79" style="fill:#FACB1B;" width="10" height="3"/>
|
||||
<rect x="77" y="80" style="fill:#FBE158;" width="5" height="2"/>
|
||||
<path style="fill:#3E3E3F;" d="M82.013,30.984l-1.857,3.899c0.512,0.678,1.152,1.101,1.857,1.101s1.345-0.422,1.857-1.101
|
||||
L82.013,30.984z"/>
|
||||
<path style="fill:#0484AB;" d="M84.5,43c-1.154,0-2.126-0.782-2.413-1.845c-0.026-0.097-0.147-0.097-0.173,0
|
||||
C81.626,42.218,80.654,43,79.5,43c-1.052,0-1.953-0.65-2.322-1.571C77.139,41.332,77,41.359,77,41.464V80h10V41.464
|
||||
c0-0.105-0.139-0.131-0.178-0.034C86.453,42.35,85.552,43,84.5,43z"/>
|
||||
<path style="fill:#21B2D1;" d="M77,80V41.493c0-0.111,0.147-0.139,0.19-0.036C77.565,42.363,78.458,43,79.5,43
|
||||
c1.159,0,2.134-0.789,2.417-1.859C81.931,41.089,82,41.096,82,41.15V80H77z"/>
|
||||
<path style="fill:#F7B4B4;" d="M77,82v2c0,1.657,1.343,3,3,3h2v-5H77z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="Blue" style="display:none;">
|
||||
<g style="display:inline;">
|
||||
<g>
|
||||
<path style="fill:#FFFFFF;" d="M23,26.84c0-2.121,1.719-3.84,3.84-3.84H55l16,13.44v46.72c0,2.121-1.719,3.84-3.84,3.84H26.84
|
||||
C24.719,87,23,85.281,23,83.16V26.84z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#BBE7F2;" d="M55,23v9.6c0,2.121,1.719,3.84,3.84,3.84H71L55,23z"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon style="fill:#FFFFFF;" points="77,41.5 82,31 87,41.5 87,80 77,80 "/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon style="fill:#E1F5FA;" points="87,47 87,41.5 82,31 82,47 "/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#E1F5FA;" d="M87,84c0,1.657-1.343,3-3,3h-4c-1.657,0-3-1.343-3-3v-2h10V84z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#BBE7F2;" d="M62,45c0,0.55-0.45,1-1,1H46c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h15
|
||||
C61.55,44,62,44.45,62,45L62,45z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#BBE7F2;" d="M56,50c0,0.55-0.45,1-1,1h-9c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h9C55.55,49,56,49.45,56,50
|
||||
L56,50z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#BBE7F2;" d="M62,58c0,0.55-0.45,1-1,1H46c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h15
|
||||
C61.55,57,62,57.45,62,58L62,58z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#BBE7F2;" d="M56,63c0,0.55-0.45,1-1,1h-9c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h9C55.55,62,56,62.45,56,63
|
||||
L56,63z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#BBE7F2;" d="M62,71c0,0.55-0.45,1-1,1H46c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h15
|
||||
C61.55,70,62,70.45,62,71L62,71z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#BBE7F2;" d="M56,76c0,0.55-0.45,1-1,1h-9c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h9C55.55,75,56,75.45,56,76
|
||||
L56,76z"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path style="fill:#009FC7;" d="M35.067,52l-3.774-3.774c-0.391-0.39-0.391-1.024,0-1.414c0.391-0.391,1.023-0.391,1.414,0
|
||||
l2.226,2.226l4.299-5.159c0.354-0.424,0.984-0.481,1.408-0.128c0.424,0.353,0.482,0.984,0.128,1.408L35.067,52z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path style="fill:#009FC7;" d="M35.067,65l-3.774-3.774c-0.391-0.39-0.391-1.024,0-1.414c0.391-0.391,1.023-0.391,1.414,0
|
||||
l2.226,2.226l4.299-5.159c0.354-0.424,0.984-0.481,1.408-0.128c0.424,0.353,0.482,0.984,0.128,1.408L35.067,65z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path style="fill:#009FC7;" d="M35.067,78l-3.774-3.774c-0.391-0.39-0.391-1.023,0-1.414c0.391-0.391,1.023-0.391,1.414,0
|
||||
l2.226,2.226l4.299-5.159c0.354-0.424,0.984-0.481,1.408-0.128c0.424,0.353,0.482,0.984,0.128,1.408L35.067,78z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="77" y="79" style="fill:#0F6175;" width="10" height="3"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="77" y="80" style="fill:#33899E;" width="5" height="2"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#0C333D;" d="M82.013,30.984l-1.857,3.899c0.512,0.678,1.152,1.101,1.857,1.101s1.345-0.423,1.857-1.101
|
||||
L82.013,30.984z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#0081A1;" d="M84.5,43c-1.154,0-2.126-0.782-2.414-1.845c-0.026-0.097-0.147-0.097-0.173,0
|
||||
C81.626,42.218,80.654,43,79.5,43c-1.052,0-1.953-0.65-2.322-1.57C77.139,41.332,77,41.359,77,41.464V80h10V41.464
|
||||
c0-0.105-0.139-0.132-0.178-0.034C86.453,42.35,85.552,43,84.5,43z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#009FC7;" d="M77,80V41.494c0-0.112,0.146-0.14,0.19-0.037C77.565,42.363,78.458,43,79.5,43
|
||||
c1.159,0,2.134-0.789,2.416-1.858C81.931,41.089,82,41.096,82,41.149V80H77z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFFFFF;" d="M77,82v2c0,1.657,1.343,3,3,3h2v-5H77z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="R-Blue" style="display:none;">
|
||||
<g style="display:inline;">
|
||||
<circle style="fill:#81D2EB;" cx="55" cy="55" r="55"/>
|
||||
</g>
|
||||
<g style="display:inline;">
|
||||
<g>
|
||||
<path style="fill:#FFFFFF;" d="M23,26.84c0-2.121,1.719-3.84,3.84-3.84H55l16,13.44v46.72c0,2.121-1.719,3.84-3.84,3.84H26.84
|
||||
C24.719,87,23,85.281,23,83.16V26.84z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#BBE7F2;" d="M55,23v9.6c0,2.121,1.719,3.84,3.84,3.84H71L55,23z"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon style="fill:#FFFFFF;" points="77,41.5 82,31 87,41.5 87,80 77,80 "/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon style="fill:#E1F5FA;" points="87,47 87,41.5 82,31 82,47 "/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#E1F5FA;" d="M87,84c0,1.657-1.343,3-3,3h-4c-1.657,0-3-1.343-3-3v-2h10V84z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#BBE7F2;" d="M62,45c0,0.55-0.45,1-1,1H46c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h15
|
||||
C61.55,44,62,44.45,62,45L62,45z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#BBE7F2;" d="M56,50c0,0.55-0.45,1-1,1h-9c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h9C55.55,49,56,49.45,56,50
|
||||
L56,50z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#BBE7F2;" d="M62,58c0,0.55-0.45,1-1,1H46c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h15
|
||||
C61.55,57,62,57.45,62,58L62,58z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#BBE7F2;" d="M56,63c0,0.55-0.45,1-1,1h-9c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h9C55.55,62,56,62.45,56,63
|
||||
L56,63z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#BBE7F2;" d="M62,71c0,0.55-0.45,1-1,1H46c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h15
|
||||
C61.55,70,62,70.45,62,71L62,71z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#BBE7F2;" d="M56,76c0,0.55-0.45,1-1,1h-9c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h9C55.55,75,56,75.45,56,76
|
||||
L56,76z"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path style="fill:#009FC7;" d="M35.067,52l-3.774-3.774c-0.391-0.39-0.391-1.024,0-1.414c0.391-0.391,1.023-0.391,1.414,0
|
||||
l2.226,2.226l4.299-5.159c0.354-0.424,0.984-0.481,1.408-0.128c0.424,0.353,0.482,0.984,0.128,1.408L35.067,52z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path style="fill:#009FC7;" d="M35.067,65l-3.774-3.774c-0.391-0.39-0.391-1.024,0-1.414c0.391-0.391,1.023-0.391,1.414,0
|
||||
l2.226,2.226l4.299-5.159c0.354-0.424,0.984-0.481,1.408-0.128c0.424,0.353,0.482,0.984,0.128,1.408L35.067,65z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path style="fill:#009FC7;" d="M35.067,78l-3.774-3.774c-0.391-0.39-0.391-1.023,0-1.414c0.391-0.391,1.023-0.391,1.414,0
|
||||
l2.226,2.226l4.299-5.159c0.354-0.424,0.984-0.481,1.408-0.128c0.424,0.353,0.482,0.984,0.128,1.408L35.067,78z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="77" y="79" style="fill:#0F6175;" width="10" height="3"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="77" y="80" style="fill:#33899E;" width="5" height="2"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#0C333D;" d="M82.013,30.984l-1.857,3.899c0.512,0.678,1.152,1.101,1.857,1.101s1.345-0.423,1.857-1.101
|
||||
L82.013,30.984z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#0081A1;" d="M84.5,43c-1.154,0-2.126-0.782-2.414-1.845c-0.026-0.097-0.147-0.097-0.173,0
|
||||
C81.626,42.218,80.654,43,79.5,43c-1.052,0-1.953-0.65-2.322-1.57C77.139,41.332,77,41.359,77,41.464V80h10V41.464
|
||||
c0-0.105-0.139-0.132-0.178-0.034C86.453,42.35,85.552,43,84.5,43z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#009FC7;" d="M77,80V41.494c0-0.112,0.146-0.14,0.19-0.037C77.565,42.363,78.458,43,79.5,43
|
||||
c1.159,0,2.134-0.789,2.416-1.858C81.931,41.089,82,41.096,82,41.149V80H77z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFFFFF;" d="M77,82v2c0,1.657,1.343,3,3,3h2v-5H77z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="Green" style="display:none;">
|
||||
<g style="display:inline;">
|
||||
<g>
|
||||
<path style="fill:#FFFFFF;" d="M23,26.84c0-2.121,1.719-3.84,3.84-3.84H55l16,13.44v46.72c0,2.121-1.719,3.84-3.84,3.84H26.84
|
||||
C24.719,87,23,85.281,23,83.16V26.84z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#AAF0E9;" d="M55,23v9.6c0,2.121,1.719,3.84,3.84,3.84H71L55,23z"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon style="fill:#FFFFFF;" points="77,41.5 82,31 87,41.5 87,80 77,80 "/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon style="fill:#D7FCF9;" points="87,47 87,41.5 82,31 82,47 "/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#D7FCF9;" d="M87,84c0,1.657-1.343,3-3,3h-4c-1.657,0-3-1.343-3-3v-2h10V84z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#AAF0E9;" d="M62,45c0,0.55-0.45,1-1,1H46c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h15
|
||||
C61.55,44,62,44.45,62,45L62,45z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#AAF0E9;" d="M56,50c0,0.55-0.45,1-1,1h-9c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h9C55.55,49,56,49.45,56,50
|
||||
L56,50z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#AAF0E9;" d="M62,58c0,0.55-0.45,1-1,1H46c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h15
|
||||
C61.55,57,62,57.45,62,58L62,58z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#AAF0E9;" d="M56,63c0,0.55-0.45,1-1,1h-9c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h9C55.55,62,56,62.45,56,63
|
||||
L56,63z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#AAF0E9;" d="M62,71c0,0.55-0.45,1-1,1H46c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h15
|
||||
C61.55,70,62,70.45,62,71L62,71z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#AAF0E9;" d="M56,76c0,0.55-0.45,1-1,1h-9c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h9C55.55,75,56,75.45,56,76
|
||||
L56,76z"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path style="fill:#00B8A5;" d="M35.067,52l-3.774-3.774c-0.391-0.39-0.391-1.024,0-1.414c0.391-0.391,1.023-0.391,1.414,0
|
||||
l2.226,2.226l4.299-5.159c0.354-0.424,0.984-0.481,1.408-0.128c0.424,0.353,0.481,0.984,0.128,1.408L35.067,52z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path style="fill:#00B8A5;" d="M35.067,65l-3.774-3.774c-0.391-0.39-0.391-1.024,0-1.414c0.391-0.391,1.023-0.391,1.414,0
|
||||
l2.226,2.226l4.299-5.159c0.354-0.424,0.984-0.481,1.408-0.128c0.424,0.353,0.481,0.984,0.128,1.408L35.067,65z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path style="fill:#00B8A5;" d="M35.067,78l-3.774-3.774c-0.391-0.39-0.391-1.023,0-1.414c0.391-0.391,1.023-0.391,1.414,0
|
||||
l2.226,2.226l4.299-5.159c0.354-0.424,0.984-0.481,1.408-0.128c0.424,0.353,0.481,0.984,0.128,1.408L35.067,78z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="77" y="79" style="fill:#14635B;" width="10" height="3"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="77" y="80" style="fill:#3E948B;" width="5" height="2"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#0A3631;" d="M82.013,30.984l-1.857,3.899c0.512,0.678,1.152,1.101,1.857,1.101s1.345-0.423,1.857-1.101
|
||||
L82.013,30.984z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#009687;" d="M84.5,43c-1.154,0-2.126-0.782-2.414-1.845c-0.026-0.097-0.147-0.097-0.173,0
|
||||
C81.625,42.218,80.654,43,79.5,43c-1.052,0-1.953-0.65-2.322-1.57C77.139,41.332,77,41.359,77,41.464V80h10V41.464
|
||||
c0-0.105-0.139-0.132-0.178-0.034C86.453,42.35,85.552,43,84.5,43z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#00B8A5;" d="M77,80V41.494c0-0.112,0.146-0.14,0.19-0.037C77.565,42.363,78.458,43,79.5,43
|
||||
c1.159,0,2.134-0.789,2.416-1.858C81.931,41.089,82,41.096,82,41.149V80H77z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFFFFF;" d="M77,82v2c0,1.657,1.343,3,3,3h2v-5H77z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="R-Green" style="display:none;">
|
||||
<g style="display:inline;">
|
||||
<circle style="fill:#87E0C8;" cx="55" cy="55" r="55"/>
|
||||
</g>
|
||||
<g style="display:inline;">
|
||||
<g>
|
||||
<path style="fill:#FFFFFF;" d="M23,26.84c0-2.121,1.719-3.84,3.84-3.84H55l16,13.44v46.72C71,85.281,69.28,87,67.16,87H26.84
|
||||
C24.719,87,23,85.281,23,83.16V26.84z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#AAF0E9;" d="M55,23v9.6c0,2.121,1.719,3.84,3.84,3.84H71L55,23z"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon style="fill:#FFFFFF;" points="77,41.5 82,31 87,41.5 87,80 77,80 "/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon style="fill:#D7FCF9;" points="87,47 87,41.5 82,31 82,47 "/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#D7FCF9;" d="M87,84c0,1.657-1.343,3-3,3h-4c-1.657,0-3-1.343-3-3v-2h10V84z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#AAF0E9;" d="M62,45c0,0.55-0.45,1-1,1H46c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h15
|
||||
C61.55,44,62,44.45,62,45L62,45z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#AAF0E9;" d="M56,50c0,0.55-0.45,1-1,1h-9c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h9C55.55,49,56,49.45,56,50
|
||||
L56,50z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#AAF0E9;" d="M62,58c0,0.55-0.45,1-1,1H46c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h15
|
||||
C61.55,57,62,57.45,62,58L62,58z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#AAF0E9;" d="M56,63c0,0.55-0.45,1-1,1h-9c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h9C55.55,62,56,62.45,56,63
|
||||
L56,63z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#AAF0E9;" d="M62,71c0,0.55-0.45,1-1,1H46c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h15
|
||||
C61.55,70,62,70.45,62,71L62,71z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#AAF0E9;" d="M56,76c0,0.55-0.45,1-1,1h-9c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h9C55.55,75,56,75.45,56,76
|
||||
L56,76z"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path style="fill:#00B8A5;" d="M35.067,52l-3.774-3.774c-0.391-0.39-0.391-1.024,0-1.414c0.391-0.391,1.023-0.391,1.414,0
|
||||
l2.226,2.226l4.299-5.159c0.354-0.424,0.984-0.481,1.408-0.128c0.424,0.353,0.481,0.984,0.128,1.408L35.067,52z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path style="fill:#00B8A5;" d="M35.067,65l-3.774-3.774c-0.391-0.39-0.391-1.024,0-1.414c0.391-0.391,1.023-0.391,1.414,0
|
||||
l2.226,2.226l4.299-5.159c0.354-0.424,0.984-0.481,1.408-0.128c0.424,0.353,0.481,0.984,0.128,1.408L35.067,65z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path style="fill:#00B8A5;" d="M35.067,78l-3.774-3.774c-0.391-0.39-0.391-1.023,0-1.414c0.391-0.391,1.023-0.391,1.414,0
|
||||
l2.226,2.226l4.299-5.159c0.354-0.424,0.984-0.481,1.408-0.128c0.424,0.353,0.481,0.984,0.128,1.408L35.067,78z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="77" y="79" style="fill:#14635B;" width="10" height="3"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="77" y="80" style="fill:#3E948B;" width="5" height="2"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#0A3631;" d="M82.013,30.984l-1.857,3.899c0.512,0.678,1.152,1.101,1.857,1.101
|
||||
c0.705,0,1.345-0.423,1.857-1.101L82.013,30.984z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#009687;" d="M84.5,43c-1.154,0-2.125-0.782-2.414-1.845c-0.026-0.097-0.147-0.097-0.173,0
|
||||
C81.625,42.218,80.654,43,79.5,43c-1.052,0-1.953-0.65-2.322-1.57C77.139,41.332,77,41.359,77,41.464V80h10V41.464
|
||||
c0-0.105-0.139-0.132-0.178-0.034C86.452,42.35,85.552,43,84.5,43z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#00B8A5;" d="M77,80V41.494c0-0.112,0.146-0.14,0.19-0.037C77.565,42.363,78.458,43,79.5,43
|
||||
c1.159,0,2.134-0.789,2.417-1.858C81.93,41.089,82,41.096,82,41.149V80H77z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFFFFF;" d="M77,82v2c0,1.657,1.343,3,3,3h2v-5H77z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="Red" style="display:none;">
|
||||
<g style="display:inline;">
|
||||
<g>
|
||||
<path style="fill:#FFFFFF;" d="M22.896,26.84c0-2.121,1.719-3.84,3.84-3.84h28.16l16,13.44v46.72c0,2.121-1.719,3.84-3.84,3.84
|
||||
h-40.32c-2.121,0-3.84-1.719-3.84-3.84V26.84z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFD7D4;" d="M54.896,23v9.6c0,2.121,1.719,3.84,3.84,3.84h12.16L54.896,23z"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon style="fill:#FFFFFF;" points="76.896,41.5 81.896,31 86.896,41.5 86.896,80 76.896,80 "/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon style="fill:#FFEFED;" points="86.896,47 86.896,41.5 81.896,31 81.896,47 "/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFEFED;" d="M86.896,84c0,1.657-1.343,3-3,3h-4c-1.657,0-3-1.343-3-3v-2h10V84z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFD7D4;" d="M61.896,45c0,0.55-0.45,1-1,1h-15c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h15
|
||||
C61.446,44,61.896,44.45,61.896,45L61.896,45z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFD7D4;" d="M55.896,50c0,0.55-0.45,1-1,1h-9c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h9
|
||||
C55.446,49,55.896,49.45,55.896,50L55.896,50z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFD7D4;" d="M61.896,58c0,0.55-0.45,1-1,1h-15c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h15
|
||||
C61.446,57,61.896,57.45,61.896,58L61.896,58z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFD7D4;" d="M55.896,63c0,0.55-0.45,1-1,1h-9c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h9
|
||||
C55.446,62,55.896,62.45,55.896,63L55.896,63z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFD7D4;" d="M61.896,71c0,0.55-0.45,1-1,1h-15c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h15
|
||||
C61.446,70,61.896,70.45,61.896,71L61.896,71z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFD7D4;" d="M55.896,76c0,0.55-0.45,1-1,1h-9c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h9
|
||||
C55.446,75,55.896,75.45,55.896,76L55.896,76z"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path style="fill:#E54B44;" d="M34.963,52l-3.774-3.774c-0.391-0.39-0.391-1.024,0-1.414c0.391-0.391,1.023-0.391,1.414,0
|
||||
l2.226,2.226l4.299-5.159c0.354-0.424,0.984-0.481,1.408-0.128c0.424,0.353,0.482,0.984,0.128,1.408L34.963,52z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path style="fill:#E54B44;" d="M34.963,65l-3.774-3.774c-0.391-0.39-0.391-1.024,0-1.414c0.391-0.391,1.023-0.391,1.414,0
|
||||
l2.226,2.226l4.299-5.159c0.354-0.424,0.984-0.481,1.408-0.128c0.424,0.353,0.482,0.984,0.128,1.408L34.963,65z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path style="fill:#E54B44;" d="M34.963,78l-3.774-3.774c-0.391-0.39-0.391-1.023,0-1.414c0.391-0.391,1.023-0.391,1.414,0
|
||||
l2.226,2.226l4.299-5.159c0.354-0.424,0.984-0.481,1.408-0.128c0.424,0.353,0.482,0.984,0.128,1.408L34.963,78z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="76.896" y="79" style="fill:#7D261E;" width="10" height="3"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="76.896" y="80" style="fill:#B84E44;" width="5" height="2"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#4A1410;" d="M81.909,30.984l-1.857,3.899c0.512,0.678,1.152,1.101,1.857,1.101s1.345-0.423,1.857-1.101
|
||||
L81.909,30.984z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#C23023;" d="M84.396,43c-1.154,0-2.126-0.782-2.414-1.845c-0.026-0.097-0.147-0.097-0.173,0
|
||||
C81.521,42.218,80.55,43,79.396,43c-1.052,0-1.953-0.65-2.322-1.57c-0.039-0.098-0.178-0.071-0.178,0.034V80h10V41.464
|
||||
c0-0.105-0.139-0.132-0.178-0.034C86.349,42.35,85.448,43,84.396,43z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#E54B44;" d="M76.896,80V41.494c0-0.112,0.146-0.14,0.19-0.037C77.461,42.363,78.354,43,79.396,43
|
||||
c1.159,0,2.134-0.789,2.416-1.858c0.014-0.052,0.084-0.046,0.084,0.008V80H76.896z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFFFFF;" d="M76.896,82v2c0,1.657,1.343,3,3,3h2v-5H76.896z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="R-Red" style="display:none;">
|
||||
<g style="display:inline;">
|
||||
<circle style="fill:#FABBAF;" cx="55" cy="55" r="55"/>
|
||||
</g>
|
||||
<g style="display:inline;">
|
||||
<g>
|
||||
<path style="fill:#FFFFFF;" d="M23,26.84c0-2.121,1.719-3.84,3.84-3.84H55l16,13.44v46.72c0,2.121-1.719,3.84-3.84,3.84H26.84
|
||||
C24.719,87,23,85.281,23,83.16V26.84z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFD7D4;" d="M55,23v9.6c0,2.121,1.719,3.84,3.84,3.84H71L55,23z"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon style="fill:#FFFFFF;" points="77,41.5 82,31 87,41.5 87,80 77,80 "/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon style="fill:#FFEFED;" points="87,47 87,41.5 82,31 82,47 "/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFEFED;" d="M87,84c0,1.657-1.343,3-3,3h-4c-1.657,0-3-1.343-3-3v-2h10V84z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFD7D4;" d="M62,45c0,0.55-0.45,1-1,1H46c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h15
|
||||
C61.55,44,62,44.45,62,45L62,45z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFD7D4;" d="M56,50c0,0.55-0.45,1-1,1h-9c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h9C55.55,49,56,49.45,56,50
|
||||
L56,50z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFD7D4;" d="M62,58c0,0.55-0.45,1-1,1H46c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h15
|
||||
C61.55,57,62,57.45,62,58L62,58z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFD7D4;" d="M56,63c0,0.55-0.45,1-1,1h-9c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h9C55.55,62,56,62.45,56,63
|
||||
L56,63z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFD7D4;" d="M62,71c0,0.55-0.45,1-1,1H46c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h15
|
||||
C61.55,70,62,70.45,62,71L62,71z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFD7D4;" d="M56,76c0,0.55-0.45,1-1,1h-9c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h9C55.55,75,56,75.45,56,76
|
||||
L56,76z"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path style="fill:#E54B44;" d="M35.067,52l-3.774-3.774c-0.391-0.39-0.391-1.024,0-1.414c0.391-0.391,1.023-0.391,1.414,0
|
||||
l2.226,2.226l4.299-5.159c0.354-0.424,0.984-0.481,1.408-0.128c0.424,0.353,0.482,0.984,0.128,1.408L35.067,52z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path style="fill:#E54B44;" d="M35.067,65l-3.774-3.774c-0.391-0.39-0.391-1.024,0-1.414c0.391-0.391,1.023-0.391,1.414,0
|
||||
l2.226,2.226l4.299-5.159c0.354-0.424,0.984-0.481,1.408-0.128c0.424,0.353,0.482,0.984,0.128,1.408L35.067,65z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path style="fill:#E54B44;" d="M35.067,78l-3.774-3.774c-0.391-0.39-0.391-1.023,0-1.414c0.391-0.391,1.023-0.391,1.414,0
|
||||
l2.226,2.226l4.299-5.159c0.354-0.424,0.984-0.481,1.408-0.128c0.424,0.353,0.482,0.984,0.128,1.408L35.067,78z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="77" y="79" style="fill:#7D261E;" width="10" height="3"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="77" y="80" style="fill:#B84E44;" width="5" height="2"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#4A1410;" d="M82.013,30.984l-1.857,3.899c0.512,0.678,1.152,1.101,1.857,1.101s1.345-0.423,1.857-1.101
|
||||
L82.013,30.984z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#C23023;" d="M84.5,43c-1.154,0-2.126-0.782-2.414-1.845c-0.026-0.097-0.147-0.097-0.173,0
|
||||
C81.626,42.218,80.654,43,79.5,43c-1.052,0-1.953-0.65-2.322-1.57C77.139,41.332,77,41.359,77,41.464V80h10V41.464
|
||||
c0-0.105-0.139-0.132-0.178-0.034C86.453,42.35,85.552,43,84.5,43z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#E54B44;" d="M77,80V41.494c0-0.112,0.146-0.14,0.19-0.037C77.565,42.363,78.458,43,79.5,43
|
||||
c1.159,0,2.134-0.789,2.416-1.858C81.931,41.089,82,41.096,82,41.149V80H77z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFFFFF;" d="M77,82v2c0,1.657,1.343,3,3,3h2v-5H77z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="Yellow" style="display:none;">
|
||||
<g style="display:inline;">
|
||||
<g>
|
||||
<path style="fill:#FFFFFF;" d="M22.896,26.84c0-2.121,1.719-3.84,3.84-3.84h28.16l16,13.44v46.72c0,2.121-1.719,3.84-3.84,3.84
|
||||
h-40.32c-2.121,0-3.84-1.719-3.84-3.84V26.84z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFE9A1;" d="M54.896,23v9.6c0,2.121,1.719,3.84,3.84,3.84h12.16L54.896,23z"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon style="fill:#FFFFFF;" points="76.896,41.5 81.896,31 86.896,41.5 86.896,80 76.896,80 "/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon style="fill:#FFF5D9;" points="86.896,47 86.896,41.5 81.896,31 81.896,47 "/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFF5D9;" d="M86.896,84c0,1.657-1.343,3-3,3h-4c-1.657,0-3-1.343-3-3v-2h10V84z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFE9A1;" d="M61.896,45c0,0.55-0.45,1-1,1h-15c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h15
|
||||
C61.446,44,61.896,44.45,61.896,45L61.896,45z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFE9A1;" d="M55.896,50c0,0.55-0.45,1-1,1h-9c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h9
|
||||
C55.446,49,55.896,49.45,55.896,50L55.896,50z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFE9A1;" d="M61.896,58c0,0.55-0.45,1-1,1h-15c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h15
|
||||
C61.446,57,61.896,57.45,61.896,58L61.896,58z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFE9A1;" d="M55.896,63c0,0.55-0.45,1-1,1h-9c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h9
|
||||
C55.446,62,55.896,62.45,55.896,63L55.896,63z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFE9A1;" d="M61.896,71c0,0.55-0.45,1-1,1h-15c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h15
|
||||
C61.446,70,61.896,70.45,61.896,71L61.896,71z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFE9A1;" d="M55.896,76c0,0.55-0.45,1-1,1h-9c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h9
|
||||
C55.446,75,55.896,75.45,55.896,76L55.896,76z"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path style="fill:#FA9200;" d="M34.963,52l-3.774-3.774c-0.391-0.39-0.391-1.024,0-1.414c0.391-0.391,1.023-0.391,1.414,0
|
||||
l2.226,2.226l4.299-5.159c0.354-0.424,0.984-0.481,1.408-0.128c0.424,0.353,0.481,0.984,0.128,1.408L34.963,52z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path style="fill:#FA9200;" d="M34.963,65l-3.774-3.774c-0.391-0.39-0.391-1.024,0-1.414c0.391-0.391,1.023-0.391,1.414,0
|
||||
l2.226,2.226l4.299-5.159c0.354-0.424,0.984-0.481,1.408-0.128c0.424,0.353,0.481,0.984,0.128,1.408L34.963,65z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path style="fill:#FA9200;" d="M34.963,78l-3.774-3.774c-0.391-0.39-0.391-1.023,0-1.414c0.391-0.391,1.023-0.391,1.414,0
|
||||
l2.226,2.226l4.299-5.159c0.354-0.424,0.984-0.481,1.408-0.128c0.424,0.353,0.481,0.984,0.128,1.408L34.963,78z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="76.896" y="79" style="fill:#66510D;" width="10" height="3"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="76.896" y="80" style="fill:#947615;" width="5" height="2"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#3D320C;" d="M81.909,30.984l-1.857,3.899c0.512,0.678,1.152,1.101,1.857,1.101s1.345-0.423,1.857-1.101
|
||||
L81.909,30.984z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#E07000;" d="M84.396,43c-1.154,0-2.126-0.782-2.414-1.845c-0.026-0.097-0.147-0.097-0.173,0
|
||||
C81.521,42.218,80.55,43,79.396,43c-1.052,0-1.953-0.65-2.322-1.57c-0.039-0.098-0.178-0.071-0.178,0.034V80h10V41.464
|
||||
c0-0.105-0.139-0.132-0.178-0.034C86.349,42.35,85.448,43,84.396,43z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FA9200;" d="M76.896,80V41.494c0-0.112,0.146-0.14,0.19-0.037C77.461,42.363,78.354,43,79.396,43
|
||||
c1.159,0,2.134-0.789,2.416-1.858c0.014-0.052,0.084-0.046,0.084,0.008V80H76.896z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFFFFF;" d="M76.896,82v2c0,1.657,1.343,3,3,3h2v-5H76.896z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="R-Yellow" style="display:none;">
|
||||
<g style="display:inline;">
|
||||
<circle style="fill:#FFD75E;" cx="55" cy="55" r="55"/>
|
||||
</g>
|
||||
<g style="display:inline;">
|
||||
<g>
|
||||
<path style="fill:#FFFFFF;" d="M23,26.84c0-2.121,1.719-3.84,3.84-3.84H55l16,13.44v46.72c0,2.121-1.719,3.84-3.84,3.84H26.84
|
||||
C24.719,87,23,85.281,23,83.16V26.84z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFE9A1;" d="M55,23v9.6c0,2.121,1.719,3.84,3.84,3.84H71L55,23z"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon style="fill:#FFFFFF;" points="77,41.5 82,31 87,41.5 87,80 77,80 "/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon style="fill:#FFF5D9;" points="87,47 87,41.5 82,31 82,47 "/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFF5D9;" d="M87,84c0,1.657-1.343,3-3,3h-4c-1.657,0-3-1.343-3-3v-2h10V84z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFE9A1;" d="M62,45c0,0.55-0.45,1-1,1H46c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h15
|
||||
C61.55,44,62,44.45,62,45L62,45z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFE9A1;" d="M56,50c0,0.55-0.45,1-1,1h-9c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h9C55.55,49,56,49.45,56,50
|
||||
L56,50z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFE9A1;" d="M62,58c0,0.55-0.45,1-1,1H46c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h15
|
||||
C61.55,57,62,57.45,62,58L62,58z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFE9A1;" d="M56,63c0,0.55-0.45,1-1,1h-9c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h9C55.55,62,56,62.45,56,63
|
||||
L56,63z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFE9A1;" d="M62,71c0,0.55-0.45,1-1,1H46c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h15
|
||||
C61.55,70,62,70.45,62,71L62,71z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFE9A1;" d="M56,76c0,0.55-0.45,1-1,1h-9c-0.55,0-1-0.45-1-1l0,0c0-0.55,0.45-1,1-1h9C55.55,75,56,75.45,56,76
|
||||
L56,76z"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path style="fill:#FA9200;" d="M35.067,52l-3.774-3.774c-0.391-0.39-0.391-1.024,0-1.414c0.391-0.391,1.023-0.391,1.414,0
|
||||
l2.226,2.226l4.299-5.159c0.354-0.424,0.984-0.481,1.408-0.128c0.424,0.353,0.482,0.984,0.128,1.408L35.067,52z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path style="fill:#FA9200;" d="M35.067,65l-3.774-3.774c-0.391-0.39-0.391-1.024,0-1.414c0.391-0.391,1.023-0.391,1.414,0
|
||||
l2.226,2.226l4.299-5.159c0.354-0.424,0.984-0.481,1.408-0.128c0.424,0.353,0.482,0.984,0.128,1.408L35.067,65z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path style="fill:#FA9200;" d="M35.067,78l-3.774-3.774c-0.391-0.39-0.391-1.023,0-1.414c0.391-0.391,1.023-0.391,1.414,0
|
||||
l2.226,2.226l4.299-5.159c0.354-0.424,0.984-0.481,1.408-0.128c0.424,0.353,0.482,0.984,0.128,1.408L35.067,78z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="77" y="79" style="fill:#66510D;" width="10" height="3"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="77" y="80" style="fill:#947615;" width="5" height="2"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#3D320C;" d="M82.013,30.984l-1.857,3.899c0.512,0.678,1.152,1.101,1.857,1.101s1.345-0.423,1.857-1.101
|
||||
L82.013,30.984z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#E07000;" d="M84.5,43c-1.154,0-2.126-0.782-2.414-1.845c-0.026-0.097-0.147-0.097-0.173,0
|
||||
C81.626,42.218,80.654,43,79.5,43c-1.052,0-1.953-0.65-2.322-1.57C77.139,41.332,77,41.359,77,41.464V80h10V41.464
|
||||
c0-0.105-0.139-0.132-0.178-0.034C86.453,42.35,85.552,43,84.5,43z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FA9200;" d="M77,80V41.494c0-0.112,0.146-0.14,0.19-0.037C77.565,42.363,78.458,43,79.5,43
|
||||
c1.159,0,2.134-0.789,2.416-1.858C81.931,41.089,82,41.096,82,41.149V80H77z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFFFFF;" d="M77,82v2c0,1.657,1.343,3,3,3h2v-5H77z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 34 KiB |
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 80 80" style="enable-background:new 0 0 80 80;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#4B4B4B;}
|
||||
</style>
|
||||
<g id="XMLID_52_">
|
||||
<path id="XMLID_1171_" class="st0" d="M46.5,78.9c-7.7,0-15.5,0-23.2,0c-5.5,0-9.2-3.7-9.2-9.2c0-15.5,0-31,0-46.5
|
||||
c0-5.5,3.7-9.2,9.1-9.2c15.6,0,31.2,0,46.7,0c5.2,0,9,3.8,9,9c0,15.5,0,31.1,0,46.6c0,5.5-3.7,9.2-9.2,9.2
|
||||
C62,78.9,54.2,78.9,46.5,78.9z M20.5,46.5c0,7.4,0,14.9,0,22.3c0,2.4,1.3,3.7,3.7,3.7c14.8,0,29.7,0,44.5,0c2.5,0,3.7-1.3,3.7-3.7
|
||||
c0-14.8,0-29.7,0-44.5c0-2.5-1.3-3.7-3.8-3.7c-14.8,0-29.7,0-44.5,0c-2.4,0-3.7,1.3-3.7,3.7C20.5,31.6,20.5,39.1,20.5,46.5z"/>
|
||||
<path id="XMLID_1170_" class="st0" d="M10.8,65.9c-5.6,0.4-9.7-3.5-9.7-8.9c0-15.6,0-31.3,0-46.9c0-5.2,3.8-8.9,9-8.9
|
||||
c15.7,0,31.4,0,47,0c5.3,0,9.2,4.2,8.8,9.7c-0.4,0-0.8,0-1.2,0c-15.1,0-30.3,0-45.4,0c-5.1,0-8.5,3.5-8.5,8.5c0,15.1,0,30.2,0,45.3
|
||||
C10.8,65,10.8,65.4,10.8,65.9z"/>
|
||||
<path id="XMLID_899_" class="st0" d="M37.9,50.5c4.7-4.7,9.3-9.3,13.8-13.9c1.8-1.8,3.5-3.5,5.3-5.3c2.1-2.1,4.8-2,6.9,0.1
|
||||
c2.3,2.3,2.5,5,0.4,7.1c-7.7,7.7-15.3,15.3-23,23c-2.1,2.1-4.8,2.1-6.8,0c-2.2-2.2-4.5-4.5-6.7-6.8c-1.9-2-1.9-4.6,0-6.6
|
||||
c1.4-1.5,2.9-2.5,5-1.9c0.8,0.2,1.6,0.7,2.2,1.3C36.1,48.5,36.9,49.5,37.9,50.5z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 7.9 KiB |
|
After Width: | Height: | Size: 112 KiB |
|
After Width: | Height: | Size: 144 KiB |
|
After Width: | Height: | Size: 41 KiB |
@@ -16,17 +16,20 @@
|
||||
*/
|
||||
|
||||
import { bootstrap } from '@angular/platform-browser-dynamic';
|
||||
import { ROUTER_PROVIDERS } from '@angular/router-deprecated';
|
||||
import { HTTP_PROVIDERS } from '@angular/http';
|
||||
import { ALFRESCO_SEARCH_PROVIDERS } from 'ng2-alfresco-search';
|
||||
import { ALFRESCO_CORE_PROVIDERS } from 'ng2-alfresco-core';
|
||||
import { ATIVITI_FORM_PROVIDERS } from 'ng2-activiti-form';
|
||||
import { UploadService } from 'ng2-alfresco-upload';
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
import { appRouterProviders } from './app.routes';
|
||||
|
||||
bootstrap(AppComponent, [
|
||||
ROUTER_PROVIDERS,
|
||||
appRouterProviders,
|
||||
HTTP_PROVIDERS,
|
||||
ALFRESCO_CORE_PROVIDERS,
|
||||
ALFRESCO_SEARCH_PROVIDERS,
|
||||
UploadService
|
||||
]);
|
||||
UploadService,
|
||||
ATIVITI_FORM_PROVIDERS
|
||||
]).catch(err => console.error(err));
|
||||
|
||||
@@ -16,23 +16,16 @@
|
||||
*/
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Subject } from 'rxjs/Subject';
|
||||
|
||||
@Injectable()
|
||||
export class AlfrescoSettingsServiceMock {
|
||||
export class NotificationService {
|
||||
|
||||
static DEFAULT_HOST_ADDRESS: string = 'fakehost';
|
||||
static DEFAULT_CONTEXT_PATH: string = '/fake-path-alfresco';
|
||||
static DEFAULT_BASE_API_PATH: string = '/fake-api/fake-public/fake-alfresco/fake-versions/1';
|
||||
notificationsdSource = new Subject<string>();
|
||||
|
||||
private _host: string = AlfrescoSettingsServiceMock.DEFAULT_HOST_ADDRESS;
|
||||
private _contextPath = AlfrescoSettingsServiceMock.DEFAULT_CONTEXT_PATH;
|
||||
private _apiBasePath: string = AlfrescoSettingsServiceMock.DEFAULT_BASE_API_PATH;
|
||||
notifications = this.notificationsdSource.asObservable();
|
||||
|
||||
public get host(): string {
|
||||
return this._host;
|
||||
}
|
||||
|
||||
getApiBaseUrl(): string {
|
||||
return this._host + this._contextPath + this._apiBasePath;
|
||||
sendNotification(message: string) {
|
||||
this.notificationsdSource.next(message);
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
var browserSync = require("browser-sync").create();
|
||||
var historyApiFallback = require('connect-history-api-fallback');
|
||||
|
||||
browserSync.init({
|
||||
|
||||
server: {
|
||||
baseDir: './',
|
||||
middleware: [ historyApiFallback() ]
|
||||
},
|
||||
|
||||
files: [
|
||||
'index.html',
|
||||
'app/**/*.{html,htm,css,js}',
|
||||
'dist/**/*.{html,htm,css,js}',
|
||||
'node_modules/ng2-alfresco-core/dist/**/*.{html,htm,css,js}',
|
||||
'node_modules/ng2-alfresco-datatable/dist/**/*.{html,htm,css,js}',
|
||||
'node_modules/ng2-alfresco-documentlist/dist/**/*.{html,htm,css,js}',
|
||||
'node_modules/ng2-alfresco-login/dist/**/*.{html,htm,css,js}',
|
||||
'node_modules/ng2-alfresco-search/dist/**/*.{html,htm,css,js}',
|
||||
'node_modules/ng2-alfresco-upload/dist/**/*.{html,htm,css,js}',
|
||||
'node_modules/ng2-alfresco-viewer/dist/**/*.{html,htm,css,js}'],
|
||||
|
||||
reloadDelay: 1000
|
||||
});
|
||||
@@ -4,7 +4,7 @@
|
||||
"DOCUMENT_LIST": {
|
||||
"COLUMNS": {
|
||||
"DISPLAY_NAME": "Display name",
|
||||
"CREATED_BY": "Created by",
|
||||
"CREATED_BY": "mario",
|
||||
"CREATED_ON": "Created on"
|
||||
},
|
||||
"ACTIONS": {
|
||||
@@ -39,5 +39,29 @@
|
||||
"CUSTOM": "Custom action"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"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 4 characters.",
|
||||
"PASSWORD-REQUIRED": "Enter your password to sign in",
|
||||
"LOGIN-ERROR": "You have entered an invalid username or password",
|
||||
"LOGIN-SUCCESS": "Login successful"
|
||||
},
|
||||
"BUTTON": {
|
||||
"LOGIN": "MARIO"
|
||||
},
|
||||
"ACTION": {
|
||||
"HELP": "NEED HELP?",
|
||||
"REGISTER": "REGISTER"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
||||
|
||||
<script src="/app/js/xml2json.js"></script>
|
||||
<script src="node_modules/alfresco-js-api/bundle.js"></script>
|
||||
<script src="node_modules/alfresco-js-api/dist/alfresco-js-api.js"></script>
|
||||
|
||||
<script src="node_modules/pdfjs-dist/build/pdf.js"></script>
|
||||
<script src="node_modules/pdfjs-dist/build/pdf.worker.js"></script>
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
{
|
||||
"name": "Alfresco-Angular2-Demo",
|
||||
"description": "Demo shell for Alfresco Angular2 components",
|
||||
"version": "0.2.0",
|
||||
"version": "0.3.0",
|
||||
"author": "Alfresco Software, Ltd.",
|
||||
"scripts": {
|
||||
"postinstall": "typings install",
|
||||
"clean": "rimraf node_modules typings",
|
||||
"start": "npm run tslint && typings install && concurrently \"npm run tsc:w\" \"license-check\" \"npm run serve\" ",
|
||||
"build": "npm run tslint && npm run tsc && npm run licensecheck",
|
||||
"start": "npm run build && concurrently \"npm run tsc:w\" \"npm run serve\" ",
|
||||
"aws": "node app.js",
|
||||
"tsc": "tsc",
|
||||
"tsc:w": "tsc -w",
|
||||
"serve": "node browser-sync-config.js",
|
||||
"serve": "wsrv -o -s -l -p 3000 -a 0.0.0.0 -x ./server/versions.js",
|
||||
"typings": "typings install",
|
||||
"tslint": "npm run tslint-src && npm run tslint-root",
|
||||
"tslint-src": "tslint -c tslint.json app/{,**/}**.ts",
|
||||
"tslint-root": "tslint -c tslint.json *.ts",
|
||||
"tslint": "tslint -c tslint.json *.ts && tslint -c tslint.json 'app/{,**/}**.ts'",
|
||||
"licensecheck": "license-check"
|
||||
},
|
||||
"repository": {
|
||||
@@ -62,47 +63,43 @@
|
||||
"@angular/router": "3.0.0-alpha.7",
|
||||
"@angular/router-deprecated": "2.0.0-rc.2",
|
||||
"@angular/upgrade": "2.0.0-rc.3",
|
||||
"alfresco-js-api": "^0.3.0",
|
||||
"systemjs": "0.19.27",
|
||||
"core-js": "2.4.0",
|
||||
"reflect-metadata": "0.1.3",
|
||||
"rxjs": "5.0.0-beta.6",
|
||||
"zone.js": "0.6.12",
|
||||
|
||||
"rimraf": "2.5.2",
|
||||
"material-design-icons": "2.2.3",
|
||||
"material-design-lite": "1.1.3",
|
||||
"ng2-translate": "2.2.0",
|
||||
"pdfjs-dist": "1.5.258",
|
||||
"flag-icon-css": "2.3.0",
|
||||
|
||||
"alfresco-js-api": "0.1.0",
|
||||
"ng2-alfresco-core": "0.2.0",
|
||||
"ng2-alfresco-datatable": "0.2.0",
|
||||
"ng2-alfresco-documentlist": "0.2.0",
|
||||
"ng2-alfresco-login": "0.2.0",
|
||||
"ng2-alfresco-search": "0.2.0",
|
||||
"ng2-alfresco-upload": "0.2.0",
|
||||
"ng2-alfresco-viewer": "0.2.0"
|
||||
"ng2-alfresco-core": "0.3.0",
|
||||
"ng2-alfresco-datatable": "0.3.0",
|
||||
"ng2-alfresco-documentlist": "0.3.0",
|
||||
"ng2-alfresco-login": "0.3.0",
|
||||
"ng2-alfresco-search": "0.3.0",
|
||||
"ng2-alfresco-upload": "0.3.0",
|
||||
"ng2-alfresco-viewer": "0.3.0",
|
||||
"ng2-activiti-form": "0.3.0",
|
||||
"ng2-activiti-tasklist": "0.3.0",
|
||||
"ng2-activiti-processlist": "0.3.0",
|
||||
"ng2-alfresco-webscript": "0.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"browser-sync": "2.10.0",
|
||||
"concurrently": "2.0.0",
|
||||
"connect-history-api-fallback": "1.2.0",
|
||||
"license-check": "1.1.5",
|
||||
"mime": "^1.3.4",
|
||||
"tslint": "3.8.1",
|
||||
"typescript": "1.8.10",
|
||||
"typings": "1.0.4"
|
||||
"typings": "1.0.4",
|
||||
"wsrv": "0.1.4"
|
||||
},
|
||||
"license-check-config": {
|
||||
"src": [
|
||||
"**/*.js",
|
||||
"**/*.ts",
|
||||
"!/**/coverage/**/*",
|
||||
"!/**/demo/**/*",
|
||||
"!/**/node_modules/**/*",
|
||||
"!/**/typings/**/*",
|
||||
"!*.js",
|
||||
"!app/js/xml2json.js"
|
||||
"./app/**/*.js",
|
||||
"!./app/js/xml2json.js"
|
||||
],
|
||||
"path": "assets/license_header.txt",
|
||||
"blocking": true,
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
'use strict';
|
||||
|
||||
// wsrv extension that provides dynamic '/versions' route
|
||||
|
||||
exports.register = function (server, options, next) {
|
||||
|
||||
var packages = [
|
||||
'ng2-activiti-form',
|
||||
'ng2-alfresco-core',
|
||||
'ng2-alfresco-datatable',
|
||||
'ng2-alfresco-documentlist',
|
||||
'ng2-alfresco-login',
|
||||
'ng2-alfresco-search',
|
||||
'ng2-alfresco-upload',
|
||||
'ng2-alfresco-viewer',
|
||||
'ng2-alfresco-webscript'
|
||||
];
|
||||
|
||||
server.route({
|
||||
method: 'GET',
|
||||
path: '/versions',
|
||||
handler: function (request, reply) {
|
||||
var result = {
|
||||
packages: packages.map(function (packageName) {
|
||||
return {
|
||||
name: packageName,
|
||||
version: require('./../node_modules/' + packageName + '/package.json').version
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
return reply(result).type('application/json');
|
||||
}
|
||||
});
|
||||
|
||||
next();
|
||||
};
|
||||
|
||||
exports.register.attributes = {
|
||||
name: 'ng2-module-versions',
|
||||
version: '1.0.0'
|
||||
};
|
||||
@@ -17,7 +17,11 @@
|
||||
'ng2-alfresco-login': 'node_modules/ng2-alfresco-login/dist',
|
||||
'ng2-alfresco-search': 'node_modules/ng2-alfresco-search/dist',
|
||||
'ng2-alfresco-upload': 'node_modules/ng2-alfresco-upload/dist',
|
||||
'ng2-alfresco-viewer': 'node_modules/ng2-alfresco-viewer/dist'
|
||||
'ng2-activiti-form': 'node_modules/ng2-activiti-form/dist',
|
||||
'ng2-alfresco-viewer': 'node_modules/ng2-alfresco-viewer/dist',
|
||||
'ng2-alfresco-webscript': 'node_modules/ng2-alfresco-webscript/dist',
|
||||
'ng2-activiti-processlist': 'node_modules/ng2-activiti-processlist/dist',
|
||||
'ng2-activiti-tasklist': 'node_modules/ng2-activiti-tasklist/dist'
|
||||
};
|
||||
// packages tells the System loader how to load when no filename and/or no extension
|
||||
var packages = {
|
||||
@@ -33,7 +37,11 @@
|
||||
'ng2-alfresco-login': { main: 'index.js', defaultExtension: 'js'},
|
||||
'ng2-alfresco-search': { main: 'index.js', defaultExtension: 'js'},
|
||||
'ng2-alfresco-upload': { main: 'index.js', defaultExtension: 'js'},
|
||||
'ng2-alfresco-viewer': { main: 'index.js', defaultExtension: 'js'}
|
||||
'ng2-alfresco-viewer': { main: 'index.js', defaultExtension: 'js'},
|
||||
'ng2-activiti-form': { main: 'index.js', defaultExtension: 'js'},
|
||||
'ng2-activiti-processlist': { main: 'index.js', defaultExtension: 'js'},
|
||||
'ng2-activiti-tasklist': { main: 'index.js', defaultExtension: 'js'},
|
||||
'ng2-alfresco-webscript': { main: 'index.js', defaultExtension: 'js'}
|
||||
};
|
||||
var ngPackageNames = [
|
||||
'common',
|
||||
@@ -56,8 +64,13 @@
|
||||
}
|
||||
// Most environments should use UMD; some (Karma) need the individual index files
|
||||
var setPackageConfig = System.packageWithIndex ? packIndex : packUmd;
|
||||
|
||||
// Add package entries for angular packages
|
||||
ngPackageNames.forEach(setPackageConfig);
|
||||
|
||||
// No umd for router yet
|
||||
packages['@angular/router'] = { main: 'index.js', defaultExtension: 'js' };
|
||||
|
||||
var config = {
|
||||
map: map,
|
||||
packages: packages
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
"label-undefined": true,
|
||||
"max-line-length": [
|
||||
true,
|
||||
140
|
||||
180
|
||||
],
|
||||
"member-ordering": [
|
||||
true,
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"watch": [
|
||||
"node_modules/ng2-alfresco-core/dist/**/*.{html,css,js}",
|
||||
"node_modules/ng2-alfresco-datatable/dist/**/*.{html,css,js}",
|
||||
"node_modules/ng2-alfresco-documentlist/dist/**/*.{html,css,js}",
|
||||
"node_modules/ng2-alfresco-login/dist/**/*.{html,css,js}",
|
||||
"node_modules/ng2-alfresco-search/dist/**/*.{html,css,js}",
|
||||
"node_modules/ng2-alfresco-upload/dist/**/*.{html,css,js}",
|
||||
"node_modules/ng2-alfresco-viewer/dist/**/*.{html,css,js}",
|
||||
"node_modules/ng2-alfresco-webscript/dist/**/*.{html,css,js}",
|
||||
"node_modules/ng2-activiti-form/dist/**/*.{html,css,js}"
|
||||
]
|
||||
}
|
||||
@@ -1,12 +1,16 @@
|
||||
# Alfresco Angular 2 Components
|
||||
|
||||
<p>
|
||||
<a title='Build Status' href="https://travis-ci.org/Alfresco/alfresco-ng2-components">
|
||||
<a title='Build Status Travis' href="https://travis-ci.org/Alfresco/alfresco-ng2-components">
|
||||
<img src='https://travis-ci.org/Alfresco/alfresco-ng2-components.svg?branch=master' alt='travis
|
||||
Status' />
|
||||
</a>
|
||||
<a href='https://coveralls.io/github/Alfresco/alfresco-ng2-components'>
|
||||
<img src='https://coveralls.io/repos/github/Alfresco/alfresco-ng2-components/badge.svg?t=NzxWxh' alt='Coverage Status' />
|
||||
<a title='Build Status AppVeyor' href="https://ci.appveyor.com/project/alfresco/alfresco-ng2-components">
|
||||
<img src='https://ci.appveyor.com/api/projects/status/github/Alfresco/alfresco-ng2-components' alt='travis
|
||||
Status' />
|
||||
</a>
|
||||
<a href='https://codecov.io/gh/Alfresco/alfresco-ng2-components'>
|
||||
<img src='https://img.shields.io/codecov/c/github/Alfresco/alfresco-ng2-components/master.svg?maxAge=2592000' alt='Coverage Status' />
|
||||
</a>
|
||||
<a href='https://github.com/Alfresco/alfresco-ng2-components/blob/master/LICENSE'>
|
||||
<img src='https://img.shields.io/hexpm/l/plug.svg' alt='license' />
|
||||
@@ -25,12 +29,25 @@
|
||||
</a>
|
||||
</p>
|
||||
|
||||
## Base components
|
||||
|
||||
- [Core library](ng2-alfresco-core/README.md)
|
||||
* Material Design elements
|
||||
* Context Menu component
|
||||
|
||||
## ECM components
|
||||
|
||||
- [DataTable](ng2-alfresco-datatable/README.md)
|
||||
- [Document List](ng2-alfresco-documentlist/README.md)
|
||||
- [DocumentList](ng2-alfresco-documentlist/README.md)
|
||||
- [Viewer](ng2-alfresco-viewer/README.md)
|
||||
- [Login](ng2-alfresco-login/README.md)
|
||||
- [Upload](ng2-alfresco-upload/README.md)
|
||||
- [Webscript Viewer](ng2-components/ng2-alfresco-webscript/README.md)
|
||||
|
||||
## BPM components
|
||||
|
||||
- [ProcessList](ng2-activiti-processlist/README.md)
|
||||
- [Form](ng2-activiti-form/README.md)
|
||||
|
||||
You can browse all the components at the following address:
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
# http://editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[package.json]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[karma.conf.js]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.md]
|
||||
insert_final_newline = false
|
||||
trim_trailing_whitespace = false
|
||||
@@ -0,0 +1,11 @@
|
||||
npm-debug.log
|
||||
node_modules/
|
||||
.idea/
|
||||
typings
|
||||
coverage/
|
||||
dist/
|
||||
src/**/*.js
|
||||
src/**/*.js.map
|
||||
index.js
|
||||
index.js.map
|
||||
!systemjs.config.js
|
||||
@@ -0,0 +1,16 @@
|
||||
npm-debug.log
|
||||
.idea
|
||||
|
||||
assets/
|
||||
coverage/
|
||||
node_modules
|
||||
typings/
|
||||
fonts/
|
||||
|
||||
/.editorconfig
|
||||
/.travis.yml
|
||||
/*.js
|
||||
/*.json
|
||||
/*.ts
|
||||
/*.js.map
|
||||
/.npmignore
|
||||
@@ -0,0 +1,177 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
@@ -0,0 +1,283 @@
|
||||
# Alfresco Bpm Form component for Angular 2
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before you start using this development framework, make sure you have installed all required software and done all the
|
||||
necessary configuration, see this [page](https://github.com/Alfresco/alfresco-ng2-components/blob/master/PREREQUISITES.md).
|
||||
|
||||
## Install
|
||||
|
||||
```sh
|
||||
npm install --save ng2-activiti-form
|
||||
```
|
||||
|
||||
### Dependencies
|
||||
|
||||
Add the following dependency to your index.html:
|
||||
|
||||
```html
|
||||
<script src="node_modules/alfresco-js-api/dist/alfresco-js-api.js"></script>
|
||||
```
|
||||
|
||||
You must separately install the following libraries for your application:
|
||||
|
||||
- [ng2-translate](https://github.com/ocombe/ng2-translate)
|
||||
- [ng2-alfresco-core](https://www.npmjs.com/package/ng2-alfresco-core)
|
||||
|
||||
```sh
|
||||
npm install --save ng2-translate ng2-alfresco-core
|
||||
```
|
||||
|
||||
#### Material Design Lite
|
||||
|
||||
The style of this component is based on [material design](https://getmdl.io/), so if you want to visualize it correctly you have to add the material
|
||||
design dependency to your project:
|
||||
|
||||
```sh
|
||||
npm install --save material-design-icons material-design-lite
|
||||
```
|
||||
|
||||
Also make sure you include these dependencies in your `index.html` file:
|
||||
|
||||
```html
|
||||
<!-- Google Material Design Lite -->
|
||||
<link rel="stylesheet" href="node_modules/material-design-lite/material.min.css">
|
||||
<script src="node_modules/material-design-lite/material.min.js"></script>
|
||||
<link rel="stylesheet" href="node_modules/material-design-icons/iconfont/material-icons.css">
|
||||
```
|
||||
|
||||
## Basic usage examples
|
||||
|
||||
### Display form instance by task id
|
||||
|
||||
```html
|
||||
<activiti-form
|
||||
[taskId]="selectedTask?.id">
|
||||
</activiti-form>
|
||||
```
|
||||
|
||||
For an existing Task both form and values will be fetched and displayed.
|
||||
|
||||
### Display form definition by form id
|
||||
|
||||
```html
|
||||
<activiti-form
|
||||
[formId]="selectedFormDefinition?.id"
|
||||
[data]="customData">
|
||||
</activiti-form>
|
||||
```
|
||||
|
||||
Only form definition will be fetched
|
||||
|
||||
### Display form definition by form name
|
||||
|
||||
```html
|
||||
<activiti-form
|
||||
[formName]="selectedFormDefinition?.name"
|
||||
[data]="customData">
|
||||
</activiti-form>
|
||||
```
|
||||
|
||||
### Display form definition by ECM nodeId, in this case the metadata of the node are showed in an activiti Form. If there are no form
|
||||
definied in activiti for the type of the node, a new form will be automaticaly created in activiti.
|
||||
|
||||
```html
|
||||
<activiti-form
|
||||
[nodeId]="'e280be3a-6584-45a1-8bb5-89bfe070262e'">
|
||||
</activiti-form>
|
||||
```
|
||||
|
||||
### Display form definition by form name, and store the form field as metadata. The param nameNode is optional.
|
||||
|
||||
```html
|
||||
<activiti-form
|
||||
[formName]="'activitiForms:patientFolder'"
|
||||
[saveMetadata]="true"
|
||||
[path]="'/Sites/swsdp/documentLibrary'"
|
||||
[nameNode]="'test'">
|
||||
</activiti-form>
|
||||
```
|
||||
|
||||
### Display form definition by ECM nodeId, in this case the metadata of the node are showed in an activiti Form, and store the form field
|
||||
as metadata. The param nameNode is optional.
|
||||
|
||||
```html
|
||||
<activiti-form
|
||||
[nodeId]="'e280be3a-6584-45a1-8bb5-89bfe070262e'"
|
||||
[saveMetadata]="true"
|
||||
[path]="'/Sites/swsdp/documentLibrary'"
|
||||
[nameNode]="'test'">
|
||||
</activiti-form>
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### Properties
|
||||
|
||||
The recommended set of properties can be found in the following table:
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| taskId | string | | Task id to fetch corresponding form and values. |
|
||||
| formId | string | | The id of the form definition to load and display with custom values. |
|
||||
| formName | string | | Name of hte form definition to load and display with custom values. |
|
||||
| data | `FormValues` | | Custom form values map to be used with the rendered form. |
|
||||
| showTitle | boolean | true | Toggle rendering of the form title. |
|
||||
| showCompleteButton | boolean | true | Toggle rendering of the `Complete` outcome button. |
|
||||
| showSaveButton | boolean | true | Toggle rendering of the `Save` outcome button. |
|
||||
| readOnly | boolean | false | Toggle readonly state of the form. Enforces all form widgets render readonly if enabled. |
|
||||
| showRefreshButton | boolean | true | Toggle rendering of the `Refresh` button. |
|
||||
| saveMetadata | boolean | false | Store the value of the form as metadata. |
|
||||
| path | string | | Path of the folder where to store the metadata. |
|
||||
| nameNode (optional) | string | true | Name to assign to the new node where the metadata are stored. |
|
||||
|
||||
|
||||
* {path} string - path of the folder where the to store the metadata
|
||||
*
|
||||
* {nameNode} string (optional) - name of the node stored, if not defined the node will be sotred with an uuid as name
|
||||
#### Advanced properties
|
||||
|
||||
The following properties are for complex customisation purposes:
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| form | `FormModel` | | Underlying form model instance. |
|
||||
| debugMode | boolean | false | Toggle debug mode, allows displaying additional data for development and debugging purposes. |
|
||||
|
||||
### Events
|
||||
|
||||
| Name | Description |
|
||||
| --- | --- |
|
||||
| formLoaded | Invoked when form is loaded or reloaded. |
|
||||
| formSaved | Invoked when form is submitted with `Save` or custom outcomes. |
|
||||
| formCompleted | Invoked when form is submitted with `Complete` outcome. |
|
||||
| executeOutcome | Invoked when any outcome is executed, default behaviour can be prevented via `event.preventDefault()` |
|
||||
|
||||
All `form*` events receive an instance of the `FormModel` as event argument for ease of development:
|
||||
|
||||
**MyView.component.html**
|
||||
```html
|
||||
<activiti-form
|
||||
[taskId]="selectedTask?.id"
|
||||
(formSaved)="onFormSaved($event)">
|
||||
</activiti-form>
|
||||
```
|
||||
|
||||
**MyView.component.ts**
|
||||
```ts
|
||||
onFormSaved(form: FormModel) {
|
||||
console.log(form);
|
||||
}
|
||||
```
|
||||
|
||||
#### Controlling outcome execution behaviour
|
||||
|
||||
If absolutely needed it is possible taking full control over form outcome execution by means of `executeOutcome` event.
|
||||
This event is fired upon each outcome execution, both system and custom ones.
|
||||
|
||||
You can prevent default behaviour by calling `event.preventDefault()`.
|
||||
This allows for example having custom form validation scenarios and/or additional validation summary presentation.
|
||||
|
||||
Alternatively you may want just running additional code on outcome execution without suppressing default one.
|
||||
|
||||
**MyView.component.html**
|
||||
```html
|
||||
<activiti-form
|
||||
[taskId]="selectedTask?.id"
|
||||
executeOutcome="validateForm($event)">
|
||||
</activiti-form>
|
||||
```
|
||||
|
||||
**MyView.component.ts**
|
||||
```ts
|
||||
import { FormOutcomeEvent } from 'ng2-activiti-form';
|
||||
|
||||
export class MyView {
|
||||
|
||||
validateForm(event: FormOutcomeEvent) {
|
||||
let outcome = event.outcome;
|
||||
|
||||
// you can also get additional properties of outcomes
|
||||
// if you defined them within outcome definition
|
||||
|
||||
if (outcome) {
|
||||
let form = outcome.form;
|
||||
if (form) {
|
||||
// check/update the form here
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
There are two additional functions that can be of a great value when controlling outcomes:
|
||||
|
||||
- `saveTaskForm()` - saves current form
|
||||
- `completeTaskForm(outcome?: string)` - save and complete form with a given outcome name
|
||||
|
||||
**Please note that if `event.preventDefault()` is not called then default outcome behaviour
|
||||
will also be executed after your custom code.**
|
||||
|
||||
## Supported form widgets
|
||||
|
||||
- [x] Tabs
|
||||
- [x] Text
|
||||
- [x] Multiline Text
|
||||
- [x] Number
|
||||
- [x] Checkbox
|
||||
- [ ] Date
|
||||
- Dropdown
|
||||
* [x] Manual
|
||||
* [x] REST service
|
||||
* [ ] Data source
|
||||
- [ ] Typeahead
|
||||
- [ ] Amount
|
||||
- [x] Radio buttons
|
||||
- [ ] People
|
||||
- [ ] Group of People
|
||||
- [ ] Dynamic Table
|
||||
- [x] Hyperlink
|
||||
- Header
|
||||
* [x] Plain header
|
||||
* [x] Collapsible header
|
||||
- [ ] Attach
|
||||
- [x] Display value
|
||||
- [x] Display text
|
||||
|
||||
## Build from sources
|
||||
|
||||
Alternatively you can build component from sources with the following commands:
|
||||
|
||||
```sh
|
||||
npm install
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Build the files and keep watching for changes
|
||||
|
||||
```sh
|
||||
$ npm run build:w
|
||||
```
|
||||
|
||||
### Running unit tests
|
||||
|
||||
```sh
|
||||
npm test
|
||||
```
|
||||
|
||||
### Running unit tests in browser
|
||||
|
||||
```sh
|
||||
npm test-browser
|
||||
```
|
||||
|
||||
This task rebuilds all the code, runs tslint, license checks and other quality check tools
|
||||
before performing unit testing.
|
||||
|
||||
### Code coverage
|
||||
|
||||
```sh
|
||||
npm run coverage
|
||||
```
|
||||
@@ -0,0 +1,16 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
@@ -0,0 +1,33 @@
|
||||
/*!
|
||||
* @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 { FormService } from './src/services/form.service';
|
||||
import { EcmModelService } from './src/services/ecm-model.service';
|
||||
import { NodeService } from './src/services/node.service';
|
||||
|
||||
export * from './src/components/activiti-form.component';
|
||||
export * from './src/services/form.service';
|
||||
export * from './src/components/widgets/index';
|
||||
export * from './src/services/ecm-model.service';
|
||||
export * from './src/services/node.service';
|
||||
|
||||
|
||||
export const ATIVITI_FORM_PROVIDERS: [any] = [
|
||||
FormService,
|
||||
EcmModelService,
|
||||
NodeService
|
||||
];
|
||||
@@ -0,0 +1,107 @@
|
||||
// Tun on full stack traces in errors to help debugging
|
||||
Error.stackTraceLimit = Infinity;
|
||||
|
||||
jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000;
|
||||
|
||||
__karma__.loaded = function() {};
|
||||
|
||||
var map = {
|
||||
'app': 'base/dist',
|
||||
'rxjs': 'base/node_modules/rxjs',
|
||||
'@angular': 'base/node_modules/@angular',
|
||||
'ng2-alfresco-core': '/base/node_modules/ng2-alfresco-core/dist',
|
||||
'ng2-translate' : '/base/node_modules/ng2-translate'
|
||||
};
|
||||
|
||||
var packages = {
|
||||
'app': { main: 'main.js', defaultExtension: 'js' },
|
||||
'rxjs': { defaultExtension: 'js' },
|
||||
'ng2-alfresco-core': { main: 'index.js', defaultExtension: 'js' },
|
||||
'ng2-translate': { defaultExtension: 'js' }
|
||||
};
|
||||
|
||||
var packageNames = [
|
||||
'@angular/common',
|
||||
'@angular/compiler',
|
||||
'@angular/core',
|
||||
'@angular/http',
|
||||
'@angular/platform-browser',
|
||||
'@angular/platform-browser-dynamic',
|
||||
'@angular/router',
|
||||
'@angular/router-deprecated',
|
||||
'@angular/testing',
|
||||
'@angular/upgrade'
|
||||
];
|
||||
|
||||
packageNames.forEach(function(pkgName) {
|
||||
packages[pkgName] = { main: 'index.js', defaultExtension: 'js' };
|
||||
});
|
||||
|
||||
packages['base/dist'] = {
|
||||
defaultExtension: 'js',
|
||||
format: 'register',
|
||||
map: Object.keys(window.__karma__.files).filter(onlyAppFiles).reduce(createPathRecords, {})
|
||||
};
|
||||
|
||||
var config = {
|
||||
map: map,
|
||||
packages: packages
|
||||
};
|
||||
|
||||
System.config(config);
|
||||
|
||||
System.import('@angular/platform-browser/src/browser/browser_adapter')
|
||||
.then(function(browser_adapter) { browser_adapter.BrowserDomAdapter.makeCurrent(); })
|
||||
.then(function () {
|
||||
return Promise.all([
|
||||
System.import('@angular/core/testing'),
|
||||
System.import('@angular/platform-browser-dynamic/testing')
|
||||
])
|
||||
})
|
||||
.then(function (providers) {
|
||||
var testing = providers[0];
|
||||
var testingBrowser = providers[1];
|
||||
|
||||
testing.setBaseTestProviders(
|
||||
testingBrowser.TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
|
||||
testingBrowser.TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS);
|
||||
|
||||
})
|
||||
.then(function() { return Promise.all(resolveTestFiles()); })
|
||||
.then(
|
||||
function() {
|
||||
__karma__.start();
|
||||
},
|
||||
function(error) {
|
||||
if(typeof __karma__.error == 'function') {
|
||||
__karma__.error(error.stack || error);
|
||||
}else{
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
);
|
||||
function createPathRecords(pathsMapping, appPath) {
|
||||
var pathParts = appPath.split('/');
|
||||
var moduleName = './' + pathParts.slice(Math.max(pathParts.length - 2, 1)).join('/');
|
||||
moduleName = moduleName.replace(/\.js$/, '');
|
||||
pathsMapping[moduleName] = appPath + '?' + window.__karma__.files[appPath];
|
||||
return pathsMapping;
|
||||
}
|
||||
|
||||
function onlyAppFiles(filePath) {
|
||||
return /\/base\/dist\/(?!.*\.spec\.js$).*\.js$/.test(filePath);
|
||||
}
|
||||
|
||||
function onlySpecFiles(path) {
|
||||
return /\.spec\.js$/.test(path);
|
||||
}
|
||||
|
||||
function resolveTestFiles() {
|
||||
return Object.keys(window.__karma__.files) // All files served by Karma.
|
||||
.filter(onlySpecFiles)
|
||||
.map(function(moduleName) {
|
||||
// loads all spec files via their global module names (e.g.
|
||||
// 'base/dist/vg-player/vg-player.spec')
|
||||
return System.import(moduleName);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = function (config) {
|
||||
var configuration = {
|
||||
basePath: '.',
|
||||
|
||||
frameworks: ['jasmine-ajax', 'jasmine'],
|
||||
|
||||
files: [
|
||||
// paths loaded by Karma
|
||||
{pattern: 'node_modules/reflect-metadata/Reflect.js', included: true, watched: true},
|
||||
{pattern: 'node_modules/systemjs/dist/system.src.js', included: true, watched: false},
|
||||
{pattern: 'node_modules/zone.js/dist/zone.js', included: true, watched: true},
|
||||
{pattern: 'node_modules/rxjs/**/*.js', included: false, watched: false},
|
||||
{pattern: 'node_modules/rxjs/**/*.map', included: false, watched: false},
|
||||
{pattern: 'node_modules/@angular/**/*.js', included: false, watched: false},
|
||||
{pattern: 'node_modules/@angular/**/*.map', included: false, watched: false},
|
||||
{pattern: 'node_modules/ng2-alfresco-core/dist/**/*.js', included: false, served: true, watched: false},
|
||||
{pattern: 'node_modules/ng2-translate/**/*.js', included: false, served: true, watched: false},
|
||||
{pattern: 'node_modules/alfresco-js-api/dist/alfresco-js-api.js', included: true, watched: false},
|
||||
|
||||
{pattern: 'karma-test-shim.js', included: true, watched: true},
|
||||
|
||||
// paths loaded via module imports
|
||||
{pattern: 'dist/**/*.js', included: false, watched: true},
|
||||
{pattern: 'dist/**/*.html', included: true, served: true, watched: true},
|
||||
{pattern: 'dist/**/*.css', included: true, served: true, watched: true},
|
||||
|
||||
// paths to support debugging with source maps in dev tools
|
||||
{pattern: 'src/**/*.ts', included: false, watched: false},
|
||||
{pattern: 'dist/**/*.js.map', included: false, watched: false}
|
||||
],
|
||||
|
||||
exclude: [
|
||||
'node_modules/**/*spec.js'
|
||||
],
|
||||
|
||||
// proxied base paths
|
||||
proxies: {
|
||||
// required for component assets fetched by Angular's compiler
|
||||
'/src/': '/base/src/'
|
||||
},
|
||||
|
||||
port: 9876,
|
||||
|
||||
// level of logging
|
||||
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
|
||||
logLevel: config.LOG_INFO,
|
||||
|
||||
colors: true,
|
||||
|
||||
autoWatch: true,
|
||||
|
||||
browsers: ['Chrome'],
|
||||
|
||||
customLaunchers: {
|
||||
Chrome_travis_ci: {
|
||||
base: 'Chrome',
|
||||
flags: ['--no-sandbox']
|
||||
}
|
||||
},
|
||||
|
||||
// Karma plugins loaded
|
||||
plugins: [
|
||||
'karma-jasmine',
|
||||
'karma-coverage',
|
||||
'karma-jasmine-ajax',
|
||||
'karma-chrome-launcher',
|
||||
'karma-mocha-reporter',
|
||||
'karma-jasmine-html-reporter'
|
||||
],
|
||||
|
||||
// Coverage reporter generates the coverage
|
||||
reporters: ['mocha', 'coverage', 'kjhtml'],
|
||||
|
||||
// Source files that you wanna generate coverage for.
|
||||
// Do not include tests or libraries (these files will be instrumented by Istanbul)
|
||||
preprocessors: {
|
||||
'dist/**/!(*spec).js': ['coverage']
|
||||
},
|
||||
|
||||
coverageReporter: {
|
||||
dir: 'coverage/',
|
||||
subdir: 'report',
|
||||
reporters: [
|
||||
{type: 'text'},
|
||||
{type: 'json', file: 'coverage-final.json'},
|
||||
{type: 'html'},
|
||||
{type: 'lcov'}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
if (process.env.TRAVIS) {
|
||||
configuration.browsers = ['Chrome_travis_ci'];
|
||||
}
|
||||
|
||||
config.set(configuration)
|
||||
};
|
||||
@@ -0,0 +1,106 @@
|
||||
{
|
||||
"name": "ng2-activiti-form",
|
||||
"description": "Alfresco Activiti Form Component for Angular 2",
|
||||
"version": "0.3.0",
|
||||
"author": "Alfresco Software, Ltd.",
|
||||
"scripts": {
|
||||
"postinstall": "typings install",
|
||||
"clean": "rimraf dist node_modules typings",
|
||||
"typings": "typings install",
|
||||
"server": "wsrv -o -p 9875",
|
||||
"build": "npm run tslint && rimraf dist && tsc && npm run copy-dist && license-check",
|
||||
"build:w": "npm run tslint && rimraf dist && npm run watch-task",
|
||||
"watch-task": "concurrently \"npm run tsc:w\" \"npm run copy-dist:w\" \"license-check\"",
|
||||
"tslint": "tslint -c tslint.json *.ts && tslint -c tslint.json 'src/{,**/}**.ts'",
|
||||
"copy-dist": "cpx \"./src/**/*.{html,css,json,png,jpg,gif,svg}\" ./dist/src",
|
||||
"copy-dist:w": "cpx \"./src/**/*.{html,css,json,png,jpg,gif,svg}\" ./dist/src -w",
|
||||
"tsc": "tsc",
|
||||
"tsc:w": "tsc -w",
|
||||
"pretest": "npm run build",
|
||||
"test": "karma start karma.conf.js --reporters mocha,coverage --single-run",
|
||||
"test-browser": "concurrently \"karma start karma.conf.js --reporters kjhtml\" \"npm run watch-task\"",
|
||||
"posttest": "remap-istanbul -i coverage/report/coverage-final.json -o coverage/report -t html && remap-istanbul -i coverage/report/coverage-final.json -o coverage/report/coverage-final.json",
|
||||
"coverage": "npm run test && wsrv -o -p 9875 ./coverage/report",
|
||||
"prepublish": "npm run build",
|
||||
"travis": "npm link ng2-alfresco-core"
|
||||
},
|
||||
"main": "./dist/index.js",
|
||||
"typings": "./dist/index.d.ts",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Alfresco/alfresco-ng2-components.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/Alfresco/alfresco-ng2-components/issues"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Denys Vuika",
|
||||
"email": "denys.vuika@gmail.com"
|
||||
}
|
||||
],
|
||||
"keywords": [
|
||||
"ng2",
|
||||
"angular",
|
||||
"angular2",
|
||||
"alfresco",
|
||||
"activiti"
|
||||
],
|
||||
"dependencies": {
|
||||
"@angular/common": "2.0.0-rc.3",
|
||||
"@angular/compiler": "2.0.0-rc.3",
|
||||
"@angular/core": "2.0.0-rc.3",
|
||||
"@angular/forms": "0.1.1",
|
||||
"@angular/http": "2.0.0-rc.3",
|
||||
"@angular/platform-browser": "2.0.0-rc.3",
|
||||
"@angular/platform-browser-dynamic": "2.0.0-rc.3",
|
||||
"@angular/router": "3.0.0-alpha.7",
|
||||
"@angular/router-deprecated": "2.0.0-rc.2",
|
||||
"@angular/upgrade": "2.0.0-rc.3",
|
||||
"alfresco-js-api": "^0.3.0",
|
||||
"systemjs": "0.19.27",
|
||||
"core-js": "2.4.0",
|
||||
"reflect-metadata": "0.1.3",
|
||||
"rxjs": "5.0.0-beta.6",
|
||||
"zone.js": "0.6.12",
|
||||
"ng2-translate": "2.2.2",
|
||||
"ng2-alfresco-core": "0.3.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"material-design-icons": "^2.2.3",
|
||||
"material-design-lite": "^1.1.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"concurrently": "2.1.0",
|
||||
"coveralls": "2.11.9",
|
||||
"cpx": "1.3.1",
|
||||
"jasmine-core": "2.4.1",
|
||||
"karma": "0.13.22",
|
||||
"karma-chrome-launcher": "1.0.1",
|
||||
"karma-coverage": "1.0.0",
|
||||
"karma-coveralls": "1.1.2",
|
||||
"karma-jasmine": "1.0.2",
|
||||
"karma-jasmine-ajax": "0.1.13",
|
||||
"karma-jasmine-html-reporter": "0.2.0",
|
||||
"karma-jasmine-ajax": "0.1.13",
|
||||
"karma-mocha-reporter": "2.0.3",
|
||||
"license-check": "1.1.5",
|
||||
"remap-istanbul": "0.6.3",
|
||||
"rimraf": "2.5.2",
|
||||
"traceur": "0.0.91",
|
||||
"tslint": "3.8.1",
|
||||
"typescript": "1.8.10",
|
||||
"typings": "1.0.4",
|
||||
"wsrv": "0.1.3"
|
||||
},
|
||||
"license-check-config": {
|
||||
"src": [
|
||||
"./dist/**/*.js"
|
||||
],
|
||||
"path": "assets/license_header.txt",
|
||||
"blocking": true,
|
||||
"logInfo": false,
|
||||
"logError": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
.activiti-form-container {
|
||||
width: 100%;
|
||||
min-height: 100px;
|
||||
}
|
||||
|
||||
.activiti-form-container > .mdl-card__media {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.activiti-form-debug-container {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.activiti-form-debug-container .debug-toggle-text {
|
||||
padding-left: 15px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.activiti-form-debug-container .debug-toggle-text:hover {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.activiti-form-hide-button {
|
||||
display: none;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
<div>
|
||||
<div *ngIf="!hasForm()">
|
||||
<h3 style="text-align: center">Please select a Task</h3>
|
||||
</div>
|
||||
<div *ngIf="hasForm()">
|
||||
<div class="mdl-card mdl-shadow--2dp activiti-form-container">
|
||||
<div *ngIf="isTitleEnabled()" class="mdl-card__title">
|
||||
<h2 class="mdl-card__title-text">{{form.taskName}}</h2>
|
||||
</div>
|
||||
<div class="mdl-card__media">
|
||||
<div *ngIf="form.hasTabs()">
|
||||
<tabs-widget [tabs]="form.tabs"></tabs-widget>
|
||||
</div>
|
||||
|
||||
<div *ngIf="!form.hasTabs() && form.hasFields()">
|
||||
<container-widget *ngFor="let field of form.fields" [content]="field" (formValueChanged)="checkVisibility($event);"></container-widget>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="form.hasOutcomes()" class="mdl-card__actions mdl-card--border">
|
||||
<button *ngFor="let outcome of form.outcomes"
|
||||
alfresco-mdl-button
|
||||
[class.mdl-button--colored]="!outcome.isSystem"
|
||||
[class.activiti-form-hide-button]="!isOutcomeButtonEnabled(outcome)"
|
||||
(click)="onOutcomeClicked(outcome, $event)">
|
||||
{{outcome.name}}
|
||||
</button>
|
||||
</div>
|
||||
<div *ngIf="showRefreshButton" class="mdl-card__menu" >
|
||||
<button (click)="onRefreshClicked()"
|
||||
class="mdl-button mdl-button--icon mdl-js-button mdl-js-ripple-effect">
|
||||
<i class="material-icons">refresh</i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--
|
||||
For debugging and data visualisation purposes,
|
||||
will be removed during future revisions
|
||||
-->
|
||||
<div class="activiti-form-debug-container">
|
||||
|
||||
<label class="mdl-switch mdl-js-switch mdl-js-ripple-effect" for="switch-1" [class.is-checked]="debugMode">
|
||||
<input type="checkbox" id="switch-1" class="mdl-switch__input" [(ngModel)]="debugMode">
|
||||
<span class="mdl-switch__label"></span>
|
||||
<span class="debug-toggle-text">Debug mode</span>
|
||||
</label>
|
||||
|
||||
<div *ngIf="debugMode && hasForm()">
|
||||
<h4>Values</h4>
|
||||
<pre>{{form.values | json}}</pre>
|
||||
|
||||
<h4>Form</h4>
|
||||
<pre>{{form.json | json}}</pre>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,637 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { it, describe, expect } from '@angular/core/testing';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
import { SimpleChange } from '@angular/core';
|
||||
import { ActivitiForm } from './activiti-form.component';
|
||||
import { FormModel, FormOutcomeModel, FormFieldModel, FormOutcomeEvent } from './widgets/index';
|
||||
import { FormService } from './../services/form.service';
|
||||
import { WidgetVisibilityService } from './../services/widget-visibility.service';
|
||||
import { ContainerWidget } from './widgets/container/container.widget';
|
||||
|
||||
describe('ActivitiForm', () => {
|
||||
|
||||
let componentHandler: any;
|
||||
let formService: FormService;
|
||||
let formComponent: ActivitiForm;
|
||||
let visibilityService: WidgetVisibilityService;
|
||||
|
||||
beforeEach(() => {
|
||||
componentHandler = jasmine.createSpyObj('componentHandler', [
|
||||
'upgradeAllRegistered'
|
||||
]);
|
||||
visibilityService = jasmine.createSpyObj('WidgetVisibilityService', [
|
||||
'updateVisibilityForForm', 'getTaskProcessVariableModelsForTask'
|
||||
]);
|
||||
window['componentHandler'] = componentHandler;
|
||||
|
||||
formService = new FormService(null, null);
|
||||
formComponent = new ActivitiForm(formService, visibilityService, null, null, null);
|
||||
});
|
||||
|
||||
it('should upgrade MDL content on view checked', () => {
|
||||
formComponent.ngAfterViewChecked();
|
||||
expect(componentHandler.upgradeAllRegistered).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should setup MDL content only if component handler available', () => {
|
||||
expect(formComponent.setupMaterialComponents()).toBeTruthy();
|
||||
|
||||
window['componentHandler'] = null;
|
||||
expect(formComponent.setupMaterialComponents()).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should start loading form on init', () => {
|
||||
spyOn(formComponent, 'loadForm').and.stub();
|
||||
formComponent.ngOnInit();
|
||||
expect(formComponent.loadForm).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should check form', () => {
|
||||
expect(formComponent.hasForm()).toBeFalsy();
|
||||
formComponent.form = new FormModel();
|
||||
expect(formComponent.hasForm()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should allow title if task name available', () => {
|
||||
let formModel = new FormModel();
|
||||
formComponent.form = formModel;
|
||||
|
||||
expect(formComponent.showTitle).toBeTruthy();
|
||||
expect(formModel.taskName).toBe(FormModel.UNSET_TASK_NAME);
|
||||
expect(formComponent.isTitleEnabled()).toBeTruthy();
|
||||
|
||||
// override property as it's the readonly one
|
||||
Object.defineProperty(formModel, 'taskName', {
|
||||
enumerable: false,
|
||||
configurable: false,
|
||||
writable: false,
|
||||
value: null
|
||||
});
|
||||
|
||||
expect(formComponent.isTitleEnabled()).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should not allow title', () => {
|
||||
let formModel = new FormModel();
|
||||
|
||||
formComponent.form = formModel;
|
||||
formComponent.showTitle = false;
|
||||
|
||||
expect(formModel.taskName).toBe(FormModel.UNSET_TASK_NAME);
|
||||
expect(formComponent.isTitleEnabled()).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should not enable outcome button when model missing', () => {
|
||||
expect(formComponent.isOutcomeButtonEnabled(null)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should enable custom outcome buttons', () => {
|
||||
let formModel = new FormModel();
|
||||
let outcome = new FormOutcomeModel(formModel, { id: 'action1', name: 'Action 1' });
|
||||
expect(formComponent.isOutcomeButtonEnabled(outcome)).toBeTruthy();
|
||||
});
|
||||
|
||||
|
||||
it('should allow controlling [complete] button visibility', () => {
|
||||
let formModel = new FormModel();
|
||||
let outcome = new FormOutcomeModel(formModel, { id: '$save', name: FormOutcomeModel.SAVE_ACTION });
|
||||
|
||||
formComponent.showSaveButton = true;
|
||||
expect(formComponent.isOutcomeButtonEnabled(outcome)).toBeTruthy();
|
||||
|
||||
formComponent.showSaveButton = false;
|
||||
expect(formComponent.isOutcomeButtonEnabled(outcome)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should allow controlling [save] button visibility', () => {
|
||||
let formModel = new FormModel();
|
||||
let outcome = new FormOutcomeModel(formModel, { id: '$save', name: FormOutcomeModel.COMPLETE_ACTION });
|
||||
|
||||
formComponent.showCompleteButton = true;
|
||||
expect(formComponent.isOutcomeButtonEnabled(outcome)).toBeTruthy();
|
||||
|
||||
formComponent.showCompleteButton = false;
|
||||
expect(formComponent.isOutcomeButtonEnabled(outcome)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should load form on refresh', () => {
|
||||
spyOn(formComponent, 'loadForm').and.stub();
|
||||
|
||||
formComponent.onRefreshClicked();
|
||||
expect(formComponent.loadForm).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should get form by task id on load', () => {
|
||||
spyOn(formComponent, 'getFormByTaskId').and.stub();
|
||||
const taskId = '123';
|
||||
|
||||
formComponent.taskId = taskId;
|
||||
formComponent.loadForm();
|
||||
|
||||
expect(formComponent.getFormByTaskId).toHaveBeenCalledWith(taskId);
|
||||
expect(visibilityService.getTaskProcessVariableModelsForTask).toHaveBeenCalledWith(taskId);
|
||||
});
|
||||
|
||||
it('should get form definition by form id on load', () => {
|
||||
spyOn(formComponent, 'getFormDefinitionByFormId').and.stub();
|
||||
const formId = '123';
|
||||
|
||||
formComponent.formId = formId;
|
||||
formComponent.loadForm();
|
||||
|
||||
expect(formComponent.getFormDefinitionByFormId).toHaveBeenCalledWith(formId);
|
||||
});
|
||||
|
||||
it('should get form definition by form name on load', () => {
|
||||
spyOn(formComponent, 'getFormDefinitionByFormName').and.stub();
|
||||
const formName = '<form>';
|
||||
|
||||
formComponent.formName = formName;
|
||||
formComponent.loadForm();
|
||||
|
||||
expect(formComponent.getFormDefinitionByFormName).toHaveBeenCalledWith(formName);
|
||||
});
|
||||
|
||||
it('should reload form by task id on binding changes', () => {
|
||||
spyOn(formComponent, 'getFormByTaskId').and.stub();
|
||||
const taskId = '<task id>';
|
||||
|
||||
let change = new SimpleChange(null, taskId);
|
||||
formComponent.ngOnChanges({ 'taskId': change });
|
||||
|
||||
expect(formComponent.getFormByTaskId).toHaveBeenCalledWith(taskId);
|
||||
});
|
||||
|
||||
it('should reload form definition by form id on binding changes', () => {
|
||||
spyOn(formComponent, 'getFormDefinitionByFormId').and.stub();
|
||||
const formId = '123';
|
||||
|
||||
let change = new SimpleChange(null, formId);
|
||||
formComponent.ngOnChanges({ 'formId': change });
|
||||
|
||||
expect(formComponent.getFormDefinitionByFormId).toHaveBeenCalledWith(formId);
|
||||
});
|
||||
|
||||
it('should reload form definition by name on binding changes', () => {
|
||||
spyOn(formComponent, 'getFormDefinitionByFormName').and.stub();
|
||||
const formName = '<form>';
|
||||
|
||||
let change = new SimpleChange(null, formName);
|
||||
formComponent.ngOnChanges({ 'formName': change });
|
||||
|
||||
expect(formComponent.getFormDefinitionByFormName).toHaveBeenCalledWith(formName);
|
||||
});
|
||||
|
||||
it('should not get form on load', () => {
|
||||
spyOn(formComponent, 'getFormByTaskId').and.stub();
|
||||
spyOn(formComponent, 'getFormDefinitionByFormId').and.stub();
|
||||
spyOn(formComponent, 'getFormDefinitionByFormName').and.stub();
|
||||
|
||||
formComponent.taskId = null;
|
||||
formComponent.formId = null;
|
||||
formComponent.formName = null;
|
||||
formComponent.loadForm();
|
||||
|
||||
expect(formComponent.getFormByTaskId).not.toHaveBeenCalled();
|
||||
expect(formComponent.getFormDefinitionByFormId).not.toHaveBeenCalled();
|
||||
expect(formComponent.getFormDefinitionByFormName).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not reload form on binding changes', () => {
|
||||
spyOn(formComponent, 'getFormByTaskId').and.stub();
|
||||
spyOn(formComponent, 'getFormDefinitionByFormId').and.stub();
|
||||
spyOn(formComponent, 'getFormDefinitionByFormName').and.stub();
|
||||
|
||||
formComponent.ngOnChanges({ 'tag': new SimpleChange(null, 'hello world')});
|
||||
|
||||
expect(formComponent.getFormByTaskId).not.toHaveBeenCalled();
|
||||
expect(formComponent.getFormDefinitionByFormId).not.toHaveBeenCalled();
|
||||
expect(formComponent.getFormDefinitionByFormName).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should complete form on custom outcome click', () => {
|
||||
let formModel = new FormModel();
|
||||
let outcomeName = 'Custom Action';
|
||||
let outcome = new FormOutcomeModel(formModel, { id: 'custom1', name: outcomeName });
|
||||
|
||||
let saved = false;
|
||||
formComponent.form = formModel;
|
||||
formComponent.formSaved.subscribe(v => saved = true);
|
||||
spyOn(formComponent, 'completeTaskForm').and.stub();
|
||||
|
||||
let result = formComponent.onOutcomeClicked(outcome);
|
||||
expect(result).toBeTruthy();
|
||||
expect(saved).toBeTruthy();
|
||||
expect(formComponent.completeTaskForm).toHaveBeenCalledWith(outcomeName);
|
||||
});
|
||||
|
||||
it('should save form on [save] outcome click', () => {
|
||||
let formModel = new FormModel();
|
||||
let outcome = new FormOutcomeModel(formModel, {
|
||||
id: ActivitiForm.SAVE_OUTCOME_ID,
|
||||
name: 'Save',
|
||||
isSystem: true
|
||||
});
|
||||
|
||||
formComponent.form = formModel;
|
||||
spyOn(formComponent, 'saveTaskForm').and.stub();
|
||||
|
||||
let result = formComponent.onOutcomeClicked(outcome);
|
||||
expect(result).toBeTruthy();
|
||||
expect(formComponent.saveTaskForm).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should complete form on [complete] outcome click', () => {
|
||||
let formModel = new FormModel();
|
||||
let outcome = new FormOutcomeModel(formModel, {
|
||||
id: ActivitiForm.COMPLETE_OUTCOME_ID,
|
||||
name: 'Complete',
|
||||
isSystem: true
|
||||
});
|
||||
|
||||
formComponent.form = formModel;
|
||||
spyOn(formComponent, 'completeTaskForm').and.stub();
|
||||
|
||||
let result = formComponent.onOutcomeClicked(outcome);
|
||||
expect(result).toBeTruthy();
|
||||
expect(formComponent.completeTaskForm).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should emit form saved event on custom outcome click', () => {
|
||||
let formModel = new FormModel();
|
||||
let outcome = new FormOutcomeModel(formModel, {
|
||||
id: ActivitiForm.CUSTOM_OUTCOME_ID,
|
||||
name: 'Custom',
|
||||
isSystem: true
|
||||
});
|
||||
|
||||
let saved = false;
|
||||
formComponent.form = formModel;
|
||||
formComponent.formSaved.subscribe(v => saved = true);
|
||||
|
||||
let result = formComponent.onOutcomeClicked(outcome);
|
||||
expect(result).toBeTruthy();
|
||||
expect(saved).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should do nothing when clicking outcome for readonly form', () => {
|
||||
let formModel = new FormModel();
|
||||
const outcomeName = 'Custom Action';
|
||||
let outcome = new FormOutcomeModel(formModel, { id: 'custom1', name: outcomeName });
|
||||
|
||||
formComponent.form = formModel;
|
||||
spyOn(formComponent, 'completeTaskForm').and.stub();
|
||||
|
||||
expect(formComponent.onOutcomeClicked(outcome)).toBeTruthy();
|
||||
formComponent.readOnly = true;
|
||||
expect(formComponent.onOutcomeClicked(outcome)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should require outcome model when clicking outcome', () => {
|
||||
formComponent.form = new FormModel();
|
||||
formComponent.readOnly = false;
|
||||
expect(formComponent.onOutcomeClicked(null)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should require loaded form when clicking outcome', () => {
|
||||
let formModel = new FormModel();
|
||||
const outcomeName = 'Custom Action';
|
||||
let outcome = new FormOutcomeModel(formModel, { id: 'custom1', name: outcomeName });
|
||||
|
||||
formComponent.readOnly = false;
|
||||
formComponent.form = null;
|
||||
expect(formComponent.onOutcomeClicked(outcome)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should not execute unknown system outcome', () => {
|
||||
let formModel = new FormModel();
|
||||
let outcome = new FormOutcomeModel(formModel, { id: 'unknown', name: 'Unknown', isSystem: true });
|
||||
|
||||
formComponent.form = formModel;
|
||||
expect(formComponent.onOutcomeClicked(outcome)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should require custom action name to complete form', () => {
|
||||
let formModel = new FormModel();
|
||||
let outcome = new FormOutcomeModel(formModel, { id: 'custom' });
|
||||
|
||||
formComponent.form = formModel;
|
||||
expect(formComponent.onOutcomeClicked(outcome)).toBeFalsy();
|
||||
|
||||
outcome = new FormOutcomeModel(formModel, { id: 'custom', name: 'Custom' });
|
||||
spyOn(formComponent, 'completeTaskForm').and.stub();
|
||||
expect(formComponent.onOutcomeClicked(outcome)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should fetch and parse form by task id', () => {
|
||||
spyOn(formService, 'getTaskForm').and.callFake((taskId) => {
|
||||
return Observable.create(observer => {
|
||||
observer.next({ taskId: taskId });
|
||||
observer.complete();
|
||||
});
|
||||
});
|
||||
|
||||
const taskId = '456';
|
||||
let loaded = false;
|
||||
formComponent.formLoaded.subscribe(() => loaded = true);
|
||||
|
||||
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', () => {
|
||||
const error = 'Some error';
|
||||
|
||||
spyOn(formComponent, 'handleError').and.stub();
|
||||
spyOn(formService, 'getTaskForm').and.callFake((taskId) => {
|
||||
return Observable.throw(error);
|
||||
});
|
||||
|
||||
formComponent.getFormByTaskId('123');
|
||||
expect(formComponent.handleError).toHaveBeenCalledWith(error);
|
||||
});
|
||||
|
||||
it('should apply readonly state when getting form by task id', () => {
|
||||
spyOn(formService, 'getTaskForm').and.callFake((taskId) => {
|
||||
return Observable.create(observer => {
|
||||
observer.next({ taskId: taskId });
|
||||
observer.complete();
|
||||
});
|
||||
});
|
||||
|
||||
formComponent.readOnly = true;
|
||||
formComponent.getFormByTaskId('123');
|
||||
|
||||
expect(formComponent.form).toBeDefined();
|
||||
expect(formComponent.form.readOnly).toBe(true);
|
||||
});
|
||||
|
||||
it('should fetch and parse form definition by id', () => {
|
||||
spyOn(formService, 'getFormDefinitionById').and.callFake((formId) => {
|
||||
return Observable.create(observer => {
|
||||
observer.next({ id: formId });
|
||||
observer.complete();
|
||||
});
|
||||
});
|
||||
|
||||
const formId = '456';
|
||||
let loaded = false;
|
||||
formComponent.formLoaded.subscribe(() => loaded = true);
|
||||
|
||||
expect(formComponent.form).toBeUndefined();
|
||||
formComponent.getFormDefinitionByFormId(formId);
|
||||
|
||||
expect(loaded).toBeTruthy();
|
||||
expect(formService.getFormDefinitionById).toHaveBeenCalledWith(formId);
|
||||
expect(formComponent.form).toBeDefined();
|
||||
expect(formComponent.form.id).toBe(formId);
|
||||
});
|
||||
|
||||
it('should handle error when getting form by definition id', () => {
|
||||
const error = 'Some error';
|
||||
|
||||
spyOn(formComponent, 'handleError').and.stub();
|
||||
spyOn(formService, 'getFormDefinitionById').and.callFake(() => Observable.throw(error));
|
||||
|
||||
formComponent.getFormDefinitionByFormId('123');
|
||||
expect(formService.getFormDefinitionById).toHaveBeenCalledWith('123');
|
||||
expect(formComponent.handleError).toHaveBeenCalledWith(error);
|
||||
});
|
||||
|
||||
it('should fetch and parse form definition by form name', () => {
|
||||
spyOn(formService, 'getFormDefinitionByName').and.callFake((formName) => {
|
||||
return Observable.create(observer => {
|
||||
observer.next(formName);
|
||||
observer.complete();
|
||||
});
|
||||
});
|
||||
|
||||
spyOn(formService, 'getFormDefinitionById').and.callFake((formName) => {
|
||||
return Observable.create(observer => {
|
||||
observer.next({ name: formName });
|
||||
observer.complete();
|
||||
});
|
||||
});
|
||||
|
||||
const formName = '<form>';
|
||||
let loaded = false;
|
||||
formComponent.formLoaded.subscribe(() => loaded = true);
|
||||
|
||||
expect(formComponent.form).toBeUndefined();
|
||||
formComponent.getFormDefinitionByFormName(formName);
|
||||
|
||||
expect(loaded).toBeTruthy();
|
||||
expect(formService.getFormDefinitionByName).toHaveBeenCalledWith(formName);
|
||||
expect(formComponent.form).toBeDefined();
|
||||
expect(formComponent.form.name).toBe(formName);
|
||||
});
|
||||
|
||||
it('should save task form and raise corresponding event', () => {
|
||||
spyOn(formService, 'saveTaskForm').and.callFake(() => {
|
||||
return Observable.create(observer => {
|
||||
observer.next();
|
||||
observer.complete();
|
||||
});
|
||||
});
|
||||
|
||||
let saved = false;
|
||||
let savedForm = null;
|
||||
formComponent.formSaved.subscribe(form => {
|
||||
saved = true;
|
||||
savedForm = form;
|
||||
});
|
||||
|
||||
let formModel = new FormModel({
|
||||
taskId: '123',
|
||||
fields: [
|
||||
{ id: 'field1' },
|
||||
{ id: 'field2' }
|
||||
]
|
||||
});
|
||||
formComponent.form = formModel;
|
||||
formComponent.saveTaskForm();
|
||||
|
||||
expect(formService.saveTaskForm).toHaveBeenCalledWith(formModel.taskId, formModel.values);
|
||||
expect(saved).toBeTruthy();
|
||||
expect(savedForm).toEqual(formModel);
|
||||
});
|
||||
|
||||
it('should handle error during form save', () => {
|
||||
const error = 'Error';
|
||||
spyOn(formService, 'saveTaskForm').and.callFake(() => Observable.throw(error));
|
||||
spyOn(formComponent, 'handleError').and.stub();
|
||||
|
||||
formComponent.form = new FormModel({ taskId: '123' });
|
||||
formComponent.saveTaskForm();
|
||||
|
||||
expect(formComponent.handleError).toHaveBeenCalledWith(error);
|
||||
});
|
||||
|
||||
it('should require form with task id to save', () => {
|
||||
spyOn(formService, 'saveTaskForm').and.stub();
|
||||
|
||||
formComponent.form = null;
|
||||
formComponent.saveTaskForm();
|
||||
|
||||
formComponent.form = new FormModel();
|
||||
formComponent.saveTaskForm();
|
||||
|
||||
expect(formService.saveTaskForm).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should require form with task id to complete', () => {
|
||||
spyOn(formService, 'completeTaskForm').and.stub();
|
||||
|
||||
formComponent.form = null;
|
||||
formComponent.completeTaskForm('save');
|
||||
|
||||
formComponent.form = new FormModel();
|
||||
formComponent.completeTaskForm('complete');
|
||||
|
||||
expect(formService.completeTaskForm).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should log error to console by default', () => {
|
||||
const error = 'Error';
|
||||
spyOn(console, 'log').and.stub();
|
||||
formComponent.handleError(error);
|
||||
expect(console.log).toHaveBeenCalledWith(error);
|
||||
});
|
||||
|
||||
it('should complete form form and raise corresponding event', () => {
|
||||
spyOn(formService, 'completeTaskForm').and.callFake(() => {
|
||||
return Observable.create(observer => {
|
||||
observer.next();
|
||||
observer.complete();
|
||||
});
|
||||
});
|
||||
|
||||
const outcome = 'complete';
|
||||
let completed = false;
|
||||
formComponent.formCompleted.subscribe(() => completed = true);
|
||||
|
||||
let formModel = new FormModel({
|
||||
taskId: '123',
|
||||
fields: [
|
||||
{ id: 'field1' },
|
||||
{ id: 'field2' }
|
||||
]
|
||||
});
|
||||
|
||||
formComponent.form = formModel;
|
||||
formComponent.completeTaskForm(outcome);
|
||||
|
||||
expect(formService.completeTaskForm).toHaveBeenCalledWith(formModel.taskId, formModel.values, outcome);
|
||||
expect(completed).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should require json to parse form', () => {
|
||||
expect(formComponent.parseForm(null)).toBeNull();
|
||||
});
|
||||
|
||||
it('should parse form from json', () => {
|
||||
let form = formComponent.parseForm({
|
||||
id: '<id>',
|
||||
fields: [
|
||||
{ id: 'field1' }
|
||||
]
|
||||
});
|
||||
|
||||
expect(form).toBeDefined();
|
||||
expect(form.id).toBe('<id>');
|
||||
expect(form.fields.length).toBe(1);
|
||||
expect(form.fields[0].id).toBe('field1');
|
||||
});
|
||||
|
||||
it('should provide outcomes for form definition', () => {
|
||||
spyOn(formComponent, 'getFormDefinitionOutcomes').and.callThrough();
|
||||
|
||||
let form = formComponent.parseForm({ id: '<id>' });
|
||||
expect(formComponent.getFormDefinitionOutcomes).toHaveBeenCalledWith(form);
|
||||
});
|
||||
|
||||
it('should update the visibility when the container raise the change event', (valueChanged) => {
|
||||
spyOn(formComponent, 'checkVisibility').and.callThrough();
|
||||
let widget = new ContainerWidget();
|
||||
let fakeForm = new FormModel();
|
||||
let fakeField = new FormFieldModel(fakeForm, {id: 'fakeField', value: 'fakeValue'});
|
||||
widget.formValueChanged.subscribe(field => { valueChanged(); });
|
||||
widget.fieldChanged(fakeField);
|
||||
|
||||
expect(formComponent.checkVisibility).toHaveBeenCalledWith(fakeField);
|
||||
});
|
||||
|
||||
it('should prevent default outcome execution', () => {
|
||||
|
||||
let outcome = new FormOutcomeModel(new FormModel(), {
|
||||
id: ActivitiForm.CUSTOM_OUTCOME_ID,
|
||||
name: 'Custom'
|
||||
});
|
||||
|
||||
formComponent.form = new FormModel();
|
||||
formComponent.executeOutcome.subscribe((event: FormOutcomeEvent) => {
|
||||
expect(event.outcome).toBe(outcome);
|
||||
event.preventDefault();
|
||||
expect(event.defaultPrevented).toBeTruthy();
|
||||
});
|
||||
|
||||
let result = formComponent.onOutcomeClicked(outcome);
|
||||
expect(result).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should not prevent default outcome execution', () => {
|
||||
let outcome = new FormOutcomeModel(new FormModel(), {
|
||||
id: ActivitiForm.CUSTOM_OUTCOME_ID,
|
||||
name: 'Custom'
|
||||
});
|
||||
|
||||
formComponent.form = new FormModel();
|
||||
formComponent.executeOutcome.subscribe((event: FormOutcomeEvent) => {
|
||||
expect(event.outcome).toBe(outcome);
|
||||
expect(event.defaultPrevented).toBeFalsy();
|
||||
});
|
||||
|
||||
spyOn(formComponent, 'completeTaskForm').and.callThrough();
|
||||
|
||||
let result = formComponent.onOutcomeClicked(outcome);
|
||||
expect(result).toBeTruthy();
|
||||
|
||||
expect(formComponent.completeTaskForm).toHaveBeenCalledWith(outcome.name);
|
||||
});
|
||||
|
||||
it('should check visibility only if field with form provided', () => {
|
||||
|
||||
formComponent.checkVisibility(null);
|
||||
expect(visibilityService.updateVisibilityForForm).not.toHaveBeenCalled();
|
||||
|
||||
let field = new FormFieldModel(null);
|
||||
formComponent.checkVisibility(field);
|
||||
expect(visibilityService.updateVisibilityForForm).not.toHaveBeenCalled();
|
||||
|
||||
field = new FormFieldModel(new FormModel());
|
||||
formComponent.checkVisibility(field);
|
||||
expect(visibilityService.updateVisibilityForForm).toHaveBeenCalledWith(field.form);
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,431 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
Component,
|
||||
OnInit, AfterViewChecked, OnChanges,
|
||||
SimpleChanges,
|
||||
Input,
|
||||
Output,
|
||||
EventEmitter
|
||||
} from '@angular/core';
|
||||
import { MATERIAL_DESIGN_DIRECTIVES, AlfrescoAuthenticationService } from 'ng2-alfresco-core';
|
||||
import { EcmModelService } from './../services/ecm-model.service';
|
||||
import { FormService } from './../services/form.service';
|
||||
import { NodeService } from './../services/node.service';
|
||||
import { FormModel, FormOutcomeModel, FormValues, FormFieldModel, FormOutcomeEvent } from './widgets/core/index';
|
||||
|
||||
import { TabsWidget } from './widgets/tabs/tabs.widget';
|
||||
import { ContainerWidget } from './widgets/container/container.widget';
|
||||
|
||||
declare let __moduleName: string;
|
||||
declare var componentHandler;
|
||||
|
||||
import { WidgetVisibilityService } from './../services/widget-visibility.service';
|
||||
|
||||
/**
|
||||
* @Input
|
||||
* ActivitiForm can show 4 types of forms searching by 4 type of params:
|
||||
* 1) Form attached to a task passing the {taskId}.
|
||||
*
|
||||
* 2) Form that are only defined with the {formId} (in this case you receive only the form definition and the form will not be
|
||||
* attached to any process, useful in case you want to use ActivitiForm as form designer), in this case you can pass also other 2
|
||||
* parameters:
|
||||
* - {saveOption} as parameter to tell what is the function to call on the save action.
|
||||
* - {data} to fill the form field with some data, the id of the form must to match the name of the field of the provided data object.
|
||||
*
|
||||
* 3) Form that are only defined with the {formName} (in this case you receive only the form definition and the form will not be
|
||||
* attached to any process, useful in case you want to use ActivitiForm as form designer),
|
||||
* in this case you can pass also other 2 parameters:
|
||||
* - {saveOption} as parameter to tell what is the function to call on the save action.
|
||||
* - {data} to fill the form field with some data, the id of the form must to match the name of the field of the provided data object.
|
||||
*
|
||||
* 4) Form that show the metadata of a {nodeId}
|
||||
*
|
||||
* {showTitle} boolean - to hide the title of the form pass false, default true;
|
||||
*
|
||||
* {showRefreshButton} boolean - to hide the refresh button of the form pass false, default true;
|
||||
*
|
||||
* {showCompleteButton} boolean - to hide the complete button of the form pass false, default true;
|
||||
*
|
||||
* {showSaveButton} boolean - to hide the save button of the form pass false, default true;
|
||||
*
|
||||
* {saveMetadata} boolean - store the value of the form as metadata, default false;
|
||||
*
|
||||
* {path} string - path of the folder where to store the metadata;
|
||||
*
|
||||
* {nameNode} string (optional) - Name to assign to the new node where the metadata are stored;
|
||||
*
|
||||
* @Output
|
||||
* {formLoaded} EventEmitter - This event is fired when the form is loaded, it pass all the value in the form.
|
||||
* {formSaved} EventEmitter - This event is fired when the form is saved, it pass all the value in the form.
|
||||
* {formCompleted} EventEmitter - This event is fired when the form is completed, it pass all the value in the form.
|
||||
*
|
||||
* @returns {ActivitiForm} .
|
||||
*/
|
||||
@Component({
|
||||
moduleId: __moduleName,
|
||||
selector: 'activiti-form',
|
||||
templateUrl: './activiti-form.component.html',
|
||||
styleUrls: ['./activiti-form.component.css'],
|
||||
directives: [MATERIAL_DESIGN_DIRECTIVES, ContainerWidget, TabsWidget],
|
||||
providers: [EcmModelService, FormService, WidgetVisibilityService, NodeService]
|
||||
})
|
||||
export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
|
||||
|
||||
static SAVE_OUTCOME_ID: string = '$save';
|
||||
static COMPLETE_OUTCOME_ID: string = '$complete';
|
||||
static CUSTOM_OUTCOME_ID: string = '$custom';
|
||||
|
||||
@Input()
|
||||
taskId: string;
|
||||
|
||||
@Input()
|
||||
nodeId: string;
|
||||
|
||||
@Input()
|
||||
formId: string;
|
||||
|
||||
@Input()
|
||||
formName: string;
|
||||
|
||||
@Input()
|
||||
saveMetadata: boolean = false;
|
||||
|
||||
@Input()
|
||||
data: FormValues;
|
||||
|
||||
@Input()
|
||||
path: string;
|
||||
|
||||
@Input()
|
||||
nameNode: string;
|
||||
|
||||
@Input()
|
||||
showTitle: boolean = true;
|
||||
|
||||
@Input()
|
||||
showCompleteButton: boolean = true;
|
||||
|
||||
@Input()
|
||||
showSaveButton: boolean = true;
|
||||
|
||||
@Input()
|
||||
readOnly: boolean = false;
|
||||
|
||||
@Input()
|
||||
showRefreshButton: boolean = true;
|
||||
|
||||
@Output()
|
||||
formSaved: EventEmitter<FormModel> = new EventEmitter<FormModel>();
|
||||
|
||||
@Output()
|
||||
formCompleted: EventEmitter<FormModel> = new EventEmitter<FormModel>();
|
||||
|
||||
@Output()
|
||||
formLoaded: EventEmitter<FormModel> = new EventEmitter<FormModel>();
|
||||
|
||||
@Output()
|
||||
executeOutcome: EventEmitter<FormOutcomeEvent> = new EventEmitter<FormOutcomeEvent>();
|
||||
|
||||
form: FormModel;
|
||||
|
||||
debugMode: boolean = false;
|
||||
|
||||
constructor(private formService: FormService,
|
||||
private visibilityService: WidgetVisibilityService,
|
||||
private authService: AlfrescoAuthenticationService,
|
||||
private ecmModelService: EcmModelService,
|
||||
private nodeService: NodeService) {
|
||||
}
|
||||
|
||||
hasForm(): boolean {
|
||||
return this.form ? true : false;
|
||||
}
|
||||
|
||||
isTitleEnabled(): boolean {
|
||||
if (this.showTitle) {
|
||||
if (this.form && this.form.taskName) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
isOutcomeButtonEnabled(outcome: FormOutcomeModel): boolean {
|
||||
if (outcome && outcome.name) {
|
||||
if (outcome.name === FormOutcomeModel.COMPLETE_ACTION) {
|
||||
return this.showCompleteButton;
|
||||
}
|
||||
if (outcome.name === FormOutcomeModel.SAVE_ACTION) {
|
||||
return this.showSaveButton;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
if (this.nodeId) {
|
||||
this.loadActivitiFormForEcmNode();
|
||||
} else {
|
||||
this.loadForm();
|
||||
}
|
||||
}
|
||||
|
||||
ngAfterViewChecked() {
|
||||
this.setupMaterialComponents();
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
let taskId = changes['taskId'];
|
||||
if (taskId && taskId.currentValue) {
|
||||
this.getFormByTaskId(taskId.currentValue);
|
||||
return;
|
||||
}
|
||||
|
||||
let formId = changes['formId'];
|
||||
if (formId && formId.currentValue) {
|
||||
this.getFormDefinitionByFormId(formId.currentValue);
|
||||
return;
|
||||
}
|
||||
|
||||
let formName = changes['formName'];
|
||||
if (formName && formName.currentValue) {
|
||||
this.getFormDefinitionByFormName(formName.currentValue);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when user clicks outcome button.
|
||||
* @param outcome Form outcome model
|
||||
* @returns {boolean} True if outcome action was executed, otherwise false.
|
||||
*/
|
||||
onOutcomeClicked(outcome: FormOutcomeModel): boolean {
|
||||
if (!this.readOnly && outcome && this.form) {
|
||||
|
||||
let args = new FormOutcomeEvent(outcome);
|
||||
this.executeOutcome.emit(args);
|
||||
if (args.defaultPrevented) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (outcome.isSystem) {
|
||||
if (outcome.id === ActivitiForm.SAVE_OUTCOME_ID) {
|
||||
this.saveTaskForm();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (outcome.id === ActivitiForm.COMPLETE_OUTCOME_ID) {
|
||||
this.completeTaskForm();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (outcome.id === ActivitiForm.CUSTOM_OUTCOME_ID) {
|
||||
this.formSaved.emit(this.form);
|
||||
this.storeFormAsMetadata();
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// Note: Activiti is using NAME field rather than ID for outcomes
|
||||
if (outcome.name) {
|
||||
this.formSaved.emit(this.form);
|
||||
this.completeTaskForm(outcome.name);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when user clicks form refresh button.
|
||||
*/
|
||||
onRefreshClicked() {
|
||||
this.loadForm();
|
||||
}
|
||||
|
||||
loadForm() {
|
||||
if (this.taskId) {
|
||||
this.getFormByTaskId(this.taskId);
|
||||
this.visibilityService.getTaskProcessVariableModelsForTask(this.taskId);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.formId) {
|
||||
this.getFormDefinitionByFormId(this.formId);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.formName) {
|
||||
this.getFormDefinitionByFormName(this.formName);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
setupMaterialComponents(): boolean {
|
||||
// workaround for MDL issues with dynamic components
|
||||
if (componentHandler) {
|
||||
componentHandler.upgradeAllRegistered();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
getFormByTaskId(taskId: string) {
|
||||
let data = this.data;
|
||||
this.formService
|
||||
.getTaskForm(taskId)
|
||||
.subscribe(
|
||||
form => {
|
||||
this.form = new FormModel(form, data, this.readOnly);
|
||||
this.formLoaded.emit(this.form);
|
||||
},
|
||||
this.handleError
|
||||
);
|
||||
}
|
||||
|
||||
getFormDefinitionByFormId(formId: string) {
|
||||
this.formService
|
||||
.getFormDefinitionById(formId)
|
||||
.subscribe(
|
||||
form => {
|
||||
this.formName = form.name;
|
||||
this.form = this.parseForm(form);
|
||||
this.formLoaded.emit(this.form);
|
||||
},
|
||||
this.handleError
|
||||
);
|
||||
}
|
||||
|
||||
getFormDefinitionByFormName(formName: string) {
|
||||
this.formService
|
||||
.getFormDefinitionByName(formName)
|
||||
.subscribe(
|
||||
id => {
|
||||
this.formService.getFormDefinitionById(id).subscribe(
|
||||
form => {
|
||||
// console.log('Get Form By Form definition Name', form);
|
||||
this.form = this.parseForm(form);
|
||||
this.formLoaded.emit(this.form);
|
||||
},
|
||||
this.handleError
|
||||
);
|
||||
},
|
||||
this.handleError
|
||||
);
|
||||
}
|
||||
|
||||
saveTaskForm() {
|
||||
if (this.form && this.form.taskId) {
|
||||
this.formService
|
||||
.saveTaskForm(this.form.taskId, this.form.values)
|
||||
.subscribe(
|
||||
() => {
|
||||
this.formSaved.emit(this.form);
|
||||
this.storeFormAsMetadata();
|
||||
},
|
||||
this.handleError
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
completeTaskForm(outcome?: string) {
|
||||
if (this.form && this.form.taskId) {
|
||||
this.formService
|
||||
.completeTaskForm(this.form.taskId, this.form.values, outcome)
|
||||
.subscribe(
|
||||
() => {
|
||||
this.formCompleted.emit(this.form);
|
||||
this.storeFormAsMetadata();
|
||||
},
|
||||
this.handleError
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
handleError(err: any): any {
|
||||
console.log(err);
|
||||
}
|
||||
|
||||
parseForm(json: any): FormModel {
|
||||
if (json) {
|
||||
let form = new FormModel(json, this.data, this.readOnly);
|
||||
if (!json.fields) {
|
||||
form.outcomes = this.getFormDefinitionOutcomes(form);
|
||||
}
|
||||
return form;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get custom set of outcomes for a Form Definition.
|
||||
* @param form Form definition model.
|
||||
* @returns {FormOutcomeModel[]} Outcomes for a given form definition.
|
||||
*/
|
||||
getFormDefinitionOutcomes(form: FormModel): FormOutcomeModel[] {
|
||||
return [
|
||||
new FormOutcomeModel(form, {id: '$custom', name: FormOutcomeModel.SAVE_ACTION, isSystem: true})
|
||||
];
|
||||
}
|
||||
|
||||
checkVisibility(field: FormFieldModel) {
|
||||
if (field && field.form) {
|
||||
this.visibilityService.updateVisibilityForForm(field.form);
|
||||
}
|
||||
}
|
||||
|
||||
private loadActivitiFormForEcmNode(): void {
|
||||
this.nodeService.getNodeMetadata(this.nodeId).subscribe(data => {
|
||||
this.data = data.metadata;
|
||||
this.loadFormFromActiviti(data.nodeType);
|
||||
},
|
||||
this.handleError);
|
||||
}
|
||||
|
||||
public loadFormFromActiviti(nodeType: string): any {
|
||||
this.formService.searchFrom(nodeType).subscribe(
|
||||
form => {
|
||||
if (!form) {
|
||||
this.formService.createFormFromNodeType(nodeType).subscribe(formMetadata => {
|
||||
this.loadFormFromFormId(formMetadata.id);
|
||||
});
|
||||
} else {
|
||||
this.loadFormFromFormId(form.id);
|
||||
}
|
||||
},
|
||||
this.handleError
|
||||
);
|
||||
}
|
||||
|
||||
private loadFormFromFormId(formId: string) {
|
||||
this.formId = formId;
|
||||
this.loadForm();
|
||||
}
|
||||
|
||||
private storeFormAsMetadata() {
|
||||
if (this.saveMetadata) {
|
||||
this.ecmModelService.createEcmTypeForActivitiForm(this.formName, this.form).subscribe(type => {
|
||||
this.nodeService.createNodeMetadata(type.nodeType || type.entry.prefixedName, EcmModelService.MODEL_NAMESPACE, this.form.values, this.path, this.nameNode);
|
||||
}, this.handleError
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
/widget.model.ts
|
||||
@@ -0,0 +1,9 @@
|
||||
<label class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect" [attr.for]="field.id">
|
||||
<input type="checkbox"
|
||||
[attr.id]="field.id"
|
||||
class="mdl-checkbox__input"
|
||||
[(ngModel)]="field.value"
|
||||
(ngModelChange)="checkVisibility(field)"
|
||||
[disabled]="field.readOnly">
|
||||
<span class="mdl-checkbox__label">{{field.name}}</span>
|
||||
</label>
|
||||
@@ -0,0 +1,31 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Component } from '@angular/core';
|
||||
import { WidgetComponent } from './../widget.component';
|
||||
|
||||
declare let __moduleName: string;
|
||||
declare var componentHandler;
|
||||
|
||||
@Component({
|
||||
moduleId: __moduleName,
|
||||
selector: 'checkbox-widget',
|
||||
templateUrl: './checkbox.widget.html'
|
||||
})
|
||||
export class CheckboxWidget extends WidgetComponent {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
.container-widget {}
|
||||
|
||||
.container-widget__header {}
|
||||
|
||||
.container-widget__header-text {
|
||||
border-bottom: 1px solid rgba(0,0,0,.87);
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
cursor: default;
|
||||
|
||||
user-select: none;
|
||||
-webkit-user-select: none; /* Chrome/Safari/Opera */
|
||||
-moz-user-select: none; /* Firefox */
|
||||
-ms-user-select: none; /* IE/Edge */
|
||||
-webkit-touch-callout: none; /* iOS Safari */
|
||||
}
|
||||
|
||||
.container-widget__header-text.collapsible {
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<div class="container-widget">
|
||||
<div *ngIf="content?.isGroup()" class="container-widget__header">
|
||||
<h4 class="container-widget__header-text"
|
||||
[class.collapsible]="content?.isCollapsible()">
|
||||
<button *ngIf="content?.isCollapsible()"
|
||||
alfresco-mdl-button
|
||||
class="mdl-button--icon"
|
||||
(click)="onExpanderClicked()">
|
||||
<i class="material-icons">{{ content?.isExpanded ? 'expand_less' : 'expand_more' }}</i>
|
||||
</button>
|
||||
<span (click)="onExpanderClicked()">{{content.name}}</span>
|
||||
</h4>
|
||||
</div>
|
||||
<div class="mdl-grid" *ngIf="content?.isExpanded">
|
||||
<div *ngFor="let col of content.columns" class="mdl-cell mdl-cell--{{col.size}}-col">
|
||||
<div class="mdl-grid" *ngIf="col.hasFields()">
|
||||
<div *ngFor="let field of col.fields" class="mdl-cell mdl-cell--12-col">
|
||||
<div [ngSwitch]="field.type" [hidden]="!field.isVisible">
|
||||
<div *ngSwitchCase="'integer'">
|
||||
<number-widget [field]="field" (fieldChanged)="fieldChanged($event);"></number-widget>
|
||||
</div>
|
||||
<div *ngSwitchCase="'text'">
|
||||
<text-widget [field]="field" (fieldChanged)="fieldChanged($event);"></text-widget>
|
||||
</div>
|
||||
<div *ngSwitchCase="'multi-line-text'">
|
||||
<multiline-text-widget [field]="field" (fieldChanged)="fieldChanged($event);"></multiline-text-widget>
|
||||
</div>
|
||||
<div *ngSwitchCase="'boolean'">
|
||||
<checkbox-widget [field]="field" (fieldChanged)="fieldChanged($event);"></checkbox-widget>
|
||||
</div>
|
||||
<div *ngSwitchCase="'dropdown'">
|
||||
<dropdown-widget [field]="field" (fieldChanged)="fieldChanged($event);"></dropdown-widget>
|
||||
</div>
|
||||
<div *ngSwitchCase="'hyperlink'">
|
||||
<hyperlink-widget [field]="field" (fieldChanged)="fieldChanged($event);"></hyperlink-widget>
|
||||
</div>
|
||||
<div *ngSwitchCase="'radio-buttons'">
|
||||
<radio-buttons-widget [field]="field" (fieldChanged)="fieldChanged($event);"></radio-buttons-widget>
|
||||
</div>
|
||||
<div *ngSwitchCase="'readonly'">
|
||||
<display-value-widget [field]="field" (fieldChanged)="fieldChanged($event);"></display-value-widget>
|
||||
</div>
|
||||
<div *ngSwitchCase="'readonly-text'">
|
||||
<display-text-widget [field]="field" (fieldChanged)="fieldChanged($event);"></display-text-widget>
|
||||
</div>
|
||||
<div *ngSwitchCase="'upload'">
|
||||
<upload-widget [field]="field" (fieldChanged)="fieldChanged($event);"></upload-widget>
|
||||
</div>
|
||||
<div *ngSwitchDefault>
|
||||
<span>UNKNOWN WIDGET TYPE: {{field.type}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,112 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { it, describe, expect, beforeEach } from '@angular/core/testing';
|
||||
import { ContainerWidget } from './container.widget';
|
||||
import { FormModel } from './../core/form.model';
|
||||
import { ContainerModel } from './../core/container.model';
|
||||
import { FormFieldTypes } from './../core/form-field-types';
|
||||
import { FormFieldModel } from './../core/form-field.model';
|
||||
|
||||
describe('ContainerWidget', () => {
|
||||
|
||||
let componentHandler;
|
||||
|
||||
beforeEach(() => {
|
||||
componentHandler = jasmine.createSpyObj('componentHandler', [
|
||||
'upgradeAllRegistered'
|
||||
]);
|
||||
|
||||
window['componentHandler'] = componentHandler;
|
||||
});
|
||||
|
||||
it('should upgrade MDL content on view init', () => {
|
||||
let container = new ContainerWidget();
|
||||
container.ngAfterViewInit();
|
||||
expect(componentHandler.upgradeAllRegistered).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should setup MDL content only if component handler available', () => {
|
||||
let container = new ContainerWidget();
|
||||
expect(container.setupMaterialComponents()).toBeTruthy();
|
||||
|
||||
window['componentHandler'] = null;
|
||||
expect(container.setupMaterialComponents()).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should toggle underlying group container', () => {
|
||||
let container = new ContainerModel(new FormModel(), {
|
||||
type: FormFieldTypes.GROUP,
|
||||
params: {
|
||||
allowCollapse: true
|
||||
}
|
||||
});
|
||||
|
||||
let widget = new ContainerWidget();
|
||||
widget.content = container;
|
||||
|
||||
expect(container.isExpanded).toBeTruthy();
|
||||
widget.onExpanderClicked();
|
||||
expect(container.isExpanded).toBeFalsy();
|
||||
widget.onExpanderClicked();
|
||||
expect(container.isExpanded).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should toggle only collapsible container', () => {
|
||||
let container = new ContainerModel(new FormModel(), {
|
||||
type: FormFieldTypes.GROUP
|
||||
});
|
||||
|
||||
let widget = new ContainerWidget();
|
||||
widget.content = container;
|
||||
|
||||
expect(container.isExpanded).toBeTruthy();
|
||||
widget.onExpanderClicked();
|
||||
expect(container.isExpanded).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should toggle only group container', () => {
|
||||
let container = new ContainerModel(new FormModel(), {
|
||||
type: FormFieldTypes.CONTAINER,
|
||||
params: {
|
||||
allowCollapse: true
|
||||
}
|
||||
});
|
||||
|
||||
let widget = new ContainerWidget();
|
||||
widget.content = container;
|
||||
|
||||
expect(container.isExpanded).toBeTruthy();
|
||||
widget.onExpanderClicked();
|
||||
expect(container.isExpanded).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should send an event when a value is changed in the form', (done) => {
|
||||
let widget = new ContainerWidget();
|
||||
let fakeForm = new FormModel();
|
||||
let fakeField = new FormFieldModel(fakeForm, {id: 'fakeField', value: 'fakeValue'});
|
||||
widget.formValueChanged.subscribe(field => {
|
||||
expect(field).not.toBe(null);
|
||||
expect(field.id).toBe('fakeField');
|
||||
expect(field.value).toBe('fakeValue');
|
||||
done();
|
||||
});
|
||||
|
||||
widget.fieldChanged(fakeField);
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,69 @@
|
||||
/*!
|
||||
* @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, Input, AfterViewInit, Output, EventEmitter } from '@angular/core';
|
||||
import { ContainerModel } from './../core/index';
|
||||
|
||||
import { MATERIAL_DESIGN_DIRECTIVES } from 'ng2-alfresco-core';
|
||||
import { PRIMITIVE_WIDGET_DIRECTIVES } from './../index';
|
||||
import { FormFieldModel } from '../core/index';
|
||||
|
||||
declare let __moduleName: string;
|
||||
declare var componentHandler;
|
||||
|
||||
@Component({
|
||||
moduleId: __moduleName,
|
||||
selector: 'container-widget',
|
||||
templateUrl: './container.widget.html',
|
||||
styleUrls: ['./container.widget.css'],
|
||||
directives: [
|
||||
MATERIAL_DESIGN_DIRECTIVES,
|
||||
PRIMITIVE_WIDGET_DIRECTIVES
|
||||
]
|
||||
})
|
||||
export class ContainerWidget implements AfterViewInit {
|
||||
|
||||
@Input()
|
||||
content: ContainerModel;
|
||||
|
||||
@Output()
|
||||
formValueChanged: EventEmitter<FormFieldModel> = new EventEmitter<FormFieldModel>();
|
||||
|
||||
onExpanderClicked() {
|
||||
if (this.content && this.content.isCollapsible()) {
|
||||
this.content.isExpanded = !this.content.isExpanded;
|
||||
}
|
||||
}
|
||||
|
||||
ngAfterViewInit() {
|
||||
this.setupMaterialComponents();
|
||||
}
|
||||
|
||||
setupMaterialComponents(): boolean {
|
||||
// workaround for MDL issues with dynamic components
|
||||
if (componentHandler) {
|
||||
componentHandler.upgradeAllRegistered();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
fieldChanged(field: FormFieldModel) {
|
||||
this.formValueChanged.emit(field);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { it, describe, expect } from '@angular/core/testing';
|
||||
import { ContainerColumnModel } from './container-column.model';
|
||||
import { FormFieldModel } from './form-field.model';
|
||||
|
||||
describe('ContainerColumnModel', () => {
|
||||
|
||||
it('should have max size by default', () => {
|
||||
let column = new ContainerColumnModel();
|
||||
expect(column.size).toBe(12);
|
||||
});
|
||||
|
||||
it('should check fields', () => {
|
||||
let column = new ContainerColumnModel();
|
||||
|
||||
column.fields = null;
|
||||
expect(column.hasFields()).toBeFalsy();
|
||||
|
||||
column.fields = [];
|
||||
expect(column.hasFields()).toBeFalsy();
|
||||
|
||||
column.fields = [new FormFieldModel(null, null)];
|
||||
expect(column.hasFields()).toBeTruthy();
|
||||
});
|
||||
|
||||
});
|
||||
@@ -15,17 +15,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export class ColumnSortingModel {
|
||||
import { FormFieldModel } from './form-field.model';
|
||||
|
||||
static DEFAULT_DIRECTION: string = 'asc';
|
||||
export class ContainerColumnModel {
|
||||
|
||||
key: string;
|
||||
direction: string = ColumnSortingModel.DEFAULT_DIRECTION;
|
||||
size: number = 12;
|
||||
fields: FormFieldModel[] = [];
|
||||
|
||||
constructor(opts?: any) {
|
||||
if (opts) {
|
||||
this.key = opts.key;
|
||||
this.direction = opts.direction || ColumnSortingModel.DEFAULT_DIRECTION;
|
||||
}
|
||||
hasFields(): boolean {
|
||||
return this.fields && this.fields.length > 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { it, describe, expect } from '@angular/core/testing';
|
||||
import { ContainerModel } from './container.model';
|
||||
import { FormModel } from './form.model';
|
||||
import { FormFieldTypes } from './form-field-types';
|
||||
|
||||
describe('ContainerModel', () => {
|
||||
|
||||
it('should store the form reference', () => {
|
||||
let form = new FormModel();
|
||||
let model = new ContainerModel(form);
|
||||
expect(model.form).toBe(form);
|
||||
});
|
||||
|
||||
it('should store original json', () => {
|
||||
let json = {};
|
||||
let model = new ContainerModel(null, json);
|
||||
expect(model.json).toBe(json);
|
||||
});
|
||||
|
||||
it('should have 1 column layout by default', () => {
|
||||
let container = new ContainerModel(null, null);
|
||||
expect(container.numberOfColumns).toBe(1);
|
||||
});
|
||||
|
||||
it('should be expanded by default', () => {
|
||||
let container = new ContainerModel(null, null);
|
||||
expect(container.isExpanded).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should setup with json config', () => {
|
||||
let json = {
|
||||
fieldType: '<type>',
|
||||
id: '<id>',
|
||||
name: '<name>',
|
||||
type: '<type>',
|
||||
tab: '<tab>',
|
||||
numberOfColumns: 2,
|
||||
params: {}
|
||||
};
|
||||
let container = new ContainerModel(null, json);
|
||||
Object.keys(json).forEach(key => {
|
||||
expect(container[key]).toEqual(json[key]);
|
||||
});
|
||||
});
|
||||
|
||||
it('should wrap fields into columns on setup', () => {
|
||||
let form = new FormModel();
|
||||
let json = {
|
||||
fieldType: '<type>',
|
||||
id: '<id>',
|
||||
name: '<name>',
|
||||
type: '<type>',
|
||||
tab: '<tab>',
|
||||
numberOfColumns: 3,
|
||||
params: {},
|
||||
fields: {
|
||||
'1': [
|
||||
{ id: 'field-1' },
|
||||
{ id: 'field-3' }
|
||||
],
|
||||
'2': [
|
||||
{ id: 'field-2' }
|
||||
],
|
||||
'3': null
|
||||
}
|
||||
};
|
||||
let container = new ContainerModel(form, json);
|
||||
expect(container.columns.length).toBe(3);
|
||||
|
||||
let col1 = container.columns[0];
|
||||
expect(col1.fields.length).toBe(2);
|
||||
expect(col1.fields[0].id).toBe('field-1');
|
||||
expect(col1.fields[1].id).toBe('field-3');
|
||||
|
||||
let col2 = container.columns[1];
|
||||
expect(col2.fields.length).toBe(1);
|
||||
expect(col2.fields[0].id).toBe('field-2');
|
||||
|
||||
let col3 = container.columns[2];
|
||||
expect(col3.fields.length).toBe(0);
|
||||
});
|
||||
|
||||
it('should allow collapsing only when of a group type', () => {
|
||||
let container = new ContainerModel(new FormModel(), {
|
||||
type: FormFieldTypes.CONTAINER,
|
||||
params: {
|
||||
allowCollapse: true
|
||||
}
|
||||
});
|
||||
|
||||
expect(container.isCollapsible()).toBeFalsy();
|
||||
container.type = FormFieldTypes.GROUP;
|
||||
expect(container.isCollapsible()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should allow collapsing only when explicitly defined in params', () => {
|
||||
let container = new ContainerModel(new FormModel(), {
|
||||
type: FormFieldTypes.GROUP,
|
||||
params: {}
|
||||
});
|
||||
expect(container.isCollapsible()).toBeFalsy();
|
||||
|
||||
container = new ContainerModel(new FormModel(), {
|
||||
type: FormFieldTypes.GROUP,
|
||||
params: {
|
||||
allowCollapse: true
|
||||
}
|
||||
});
|
||||
expect(container.isCollapsible()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should be collapsed by default', () => {
|
||||
let container = new ContainerModel(new FormModel(), {
|
||||
type: FormFieldTypes.GROUP,
|
||||
params: {
|
||||
allowCollapse: true,
|
||||
collapseByDefault: true
|
||||
}
|
||||
});
|
||||
expect(container.isCollapsedByDefault()).toBeTruthy();
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,97 @@
|
||||
/*!
|
||||
* @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 { FormWidgetModel } from './form-widget.model';
|
||||
import { FormFieldMetadata } from './form-field-metadata';
|
||||
import { ContainerColumnModel } from './container-column.model';
|
||||
import { FormFieldTypes } from './form-field-types';
|
||||
import { FormModel } from './form.model';
|
||||
import { FormFieldModel } from './form-field.model';
|
||||
|
||||
// TODO: inherit FormFieldModel
|
||||
export class ContainerModel extends FormWidgetModel {
|
||||
|
||||
fieldType: string;
|
||||
id: string;
|
||||
name: string;
|
||||
type: string;
|
||||
tab: string;
|
||||
numberOfColumns: number = 1;
|
||||
params: FormFieldMetadata = {};
|
||||
|
||||
columns: ContainerColumnModel[] = [];
|
||||
isExpanded: boolean = true;
|
||||
|
||||
isGroup(): boolean {
|
||||
return this.type === FormFieldTypes.GROUP;
|
||||
}
|
||||
|
||||
isCollapsible(): boolean {
|
||||
let allowCollapse = false;
|
||||
|
||||
if (this.isGroup() && this.params['allowCollapse']) {
|
||||
allowCollapse = <boolean> this.params['allowCollapse'];
|
||||
}
|
||||
|
||||
return allowCollapse;
|
||||
}
|
||||
|
||||
isCollapsedByDefault(): boolean {
|
||||
let collapseByDefault = false;
|
||||
|
||||
if (this.isCollapsible() && this.params['collapseByDefault']) {
|
||||
collapseByDefault = <boolean> this.params['collapseByDefault'];
|
||||
}
|
||||
|
||||
return collapseByDefault;
|
||||
}
|
||||
|
||||
constructor(form: FormModel, json?: any) {
|
||||
super(form, json);
|
||||
|
||||
if (json) {
|
||||
this.fieldType = json.fieldType;
|
||||
this.id = json.id;
|
||||
this.name = json.name;
|
||||
this.type = json.type;
|
||||
this.tab = json.tab;
|
||||
this.numberOfColumns = <number> json.numberOfColumns;
|
||||
this.params = <FormFieldMetadata> json.params || {};
|
||||
|
||||
let columnSize: number = 12;
|
||||
if (this.numberOfColumns > 1) {
|
||||
columnSize = 12 / this.numberOfColumns;
|
||||
}
|
||||
|
||||
for (let i = 0; i < this.numberOfColumns; i++) {
|
||||
let col = new ContainerColumnModel();
|
||||
col.size = columnSize;
|
||||
this.columns.push(col);
|
||||
}
|
||||
|
||||
if (json.fields) {
|
||||
Object.keys(json.fields).map(key => {
|
||||
let fields = (json.fields[key] || []).map(f => new FormFieldModel(form, f));
|
||||
let col = this.columns[parseInt(key, 10) - 1];
|
||||
col.fields = fields;
|
||||
});
|
||||
}
|
||||
|
||||
this.isExpanded = !this.isCollapsedByDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*!
|
||||
* @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 interface FormFieldMetadata {
|
||||
[key: string]: any;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export interface FormFieldOption {
|
||||
id: string;
|
||||
name: string;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*!
|
||||
* @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 FormFieldTypes {
|
||||
static CONTAINER: string = 'container';
|
||||
static GROUP: string = 'group';
|
||||
static DROPDOWN: string = 'dropdown';
|
||||
static HYPERLINK: string = 'hyperlink';
|
||||
static RADIO_BUTTONS: string = 'radio-buttons';
|
||||
static DISPLAY_VALUE: string = 'readonly';
|
||||
static READONLY_TEXT: string = 'readonly-text';
|
||||
static UPLOAD: string = 'upload';
|
||||
|
||||
static READONLY_TYPES: string[] = [
|
||||
FormFieldTypes.HYPERLINK,
|
||||
FormFieldTypes.DISPLAY_VALUE,
|
||||
FormFieldTypes.READONLY_TEXT
|
||||
];
|
||||
|
||||
static isReadOnlyType(type: string) {
|
||||
return FormFieldTypes.READONLY_TYPES.indexOf(type) > -1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,243 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { it, describe, expect } from '@angular/core/testing';
|
||||
import { FormFieldModel } from './form-field.model';
|
||||
import { FormFieldTypes } from './form-field-types';
|
||||
import { FormModel } from './form.model';
|
||||
|
||||
|
||||
describe('FormFieldModel', () => {
|
||||
|
||||
it('should store the form reference', () => {
|
||||
let form = new FormModel();
|
||||
let model = new FormFieldModel(form);
|
||||
expect(model.form).toBe(form);
|
||||
});
|
||||
|
||||
it('should store original json', () => {
|
||||
let json = {};
|
||||
let model = new FormFieldModel(new FormModel(), json);
|
||||
expect(model.json).toBe(json);
|
||||
});
|
||||
|
||||
it('should setup with json config', () => {
|
||||
let json = {
|
||||
fieldType: '<fieldType>',
|
||||
id: '<id>',
|
||||
name: '<name>',
|
||||
type: '<type>',
|
||||
required: true,
|
||||
readOnly: true,
|
||||
overrideId: true,
|
||||
tab: '<tab>',
|
||||
restUrl: '<rest-url>',
|
||||
restResponsePath: '<rest-path>',
|
||||
restIdProperty: '<rest-id>',
|
||||
restLabelProperty: '<rest-label>',
|
||||
colspan: 1,
|
||||
options: [],
|
||||
hasEmptyValue: true,
|
||||
className: '<class>',
|
||||
optionType: '<type>',
|
||||
params: {},
|
||||
hyperlinkUrl: '<url>',
|
||||
displayText: '<text>',
|
||||
value: '<value>'
|
||||
};
|
||||
let field = new FormFieldModel(new FormModel(), json);
|
||||
Object.keys(json).forEach(key => {
|
||||
expect(field[key]).toBe(json[key]);
|
||||
});
|
||||
});
|
||||
|
||||
it('should setup empty options collection', () => {
|
||||
let field = new FormFieldModel(new FormModel(), null);
|
||||
expect(field.options).toBeDefined();
|
||||
expect(field.options.length).toBe(0);
|
||||
|
||||
field = new FormFieldModel(new FormModel(), { options: null });
|
||||
expect(field.options).toBeDefined();
|
||||
expect(field.options.length).toBe(0);
|
||||
});
|
||||
|
||||
it('should setup empty params', () => {
|
||||
let field = new FormFieldModel(new FormModel(), null);
|
||||
expect(field.params).toEqual({});
|
||||
|
||||
field = new FormFieldModel(new FormModel(), { params: null });
|
||||
expect(field.params).toEqual({});
|
||||
});
|
||||
|
||||
it('should update form on every value change', () => {
|
||||
let form = new FormModel();
|
||||
let field = new FormFieldModel(form, { id: 'field1' });
|
||||
let value = 10;
|
||||
|
||||
spyOn(field, 'updateForm').and.callThrough();
|
||||
field.value = value;
|
||||
|
||||
expect(field.value).toBe(value);
|
||||
expect(field.updateForm).toHaveBeenCalled();
|
||||
expect(form.values['field1']).toBe(value);
|
||||
});
|
||||
|
||||
it('should get form readonly state', () => {
|
||||
let form = new FormModel();
|
||||
let field = new FormFieldModel(form, null);
|
||||
|
||||
expect(field.readOnly).toBeFalsy();
|
||||
form.readOnly = true;
|
||||
expect(field.readOnly).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should take own readonly state if form is writable', () => {
|
||||
let form = new FormModel();
|
||||
let field = new FormFieldModel(form, { readOnly: true });
|
||||
|
||||
expect(form.readOnly).toBeFalsy();
|
||||
expect(field.readOnly).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should parse and convert empty dropdown value', () => {
|
||||
let field = new FormFieldModel(new FormModel(), {
|
||||
type: FormFieldTypes.DROPDOWN,
|
||||
value: ''
|
||||
});
|
||||
|
||||
expect(field.value).toBe('empty');
|
||||
});
|
||||
|
||||
it('should parse and leave dropdown value as is', () => {
|
||||
let field = new FormFieldModel(new FormModel(), {
|
||||
type: FormFieldTypes.DROPDOWN,
|
||||
options: [],
|
||||
value: 'deferred'
|
||||
});
|
||||
|
||||
expect(field.value).toBe('deferred');
|
||||
});
|
||||
|
||||
it('should parse and resolve radio button value', () => {
|
||||
let field = new FormFieldModel(new FormModel(), {
|
||||
type: FormFieldTypes.RADIO_BUTTONS,
|
||||
options: [
|
||||
{ id: 'opt1', value: 'Option 1' },
|
||||
{ id: 'opt2', value: 'Option 2' }
|
||||
],
|
||||
value: 'opt2'
|
||||
});
|
||||
|
||||
expect(field.value).toBe('opt2');
|
||||
});
|
||||
|
||||
it('should parse and fall back to first radio button value', () => {
|
||||
let field = new FormFieldModel(new FormModel(), {
|
||||
type: FormFieldTypes.RADIO_BUTTONS,
|
||||
options: [
|
||||
{ id: 'opt1', value: 'Option 1' },
|
||||
{ id: 'opt2', value: 'Option 2' }
|
||||
],
|
||||
value: 'opt3'
|
||||
});
|
||||
|
||||
expect(field.value).toBe('opt1');
|
||||
});
|
||||
|
||||
it('should parse and leave radio button value as is', () => {
|
||||
let field = new FormFieldModel(new FormModel(), {
|
||||
type: FormFieldTypes.RADIO_BUTTONS,
|
||||
options: [],
|
||||
value: 'deferred-radio'
|
||||
});
|
||||
expect(field.value).toBe('deferred-radio');
|
||||
});
|
||||
|
||||
it('should update form with empty dropdown value', () => {
|
||||
let form = new FormModel();
|
||||
let field = new FormFieldModel(form, {
|
||||
id: 'dropdown-1',
|
||||
type: FormFieldTypes.DROPDOWN
|
||||
});
|
||||
|
||||
field.value = 'empty';
|
||||
expect(form.values['dropdown-1']).toEqual({});
|
||||
|
||||
field.value = '';
|
||||
expect(form.values['dropdown-1']).toEqual({});
|
||||
});
|
||||
|
||||
it('should update form with dropdown value', () => {
|
||||
let form = new FormModel();
|
||||
let field = new FormFieldModel(form, {
|
||||
id: 'dropdown-2',
|
||||
type: FormFieldTypes.DROPDOWN,
|
||||
options: [
|
||||
{ id: 'opt1', value: 'Option 1' },
|
||||
{ id: 'opt2', value: 'Option 2' }
|
||||
]
|
||||
});
|
||||
|
||||
field.value = 'opt2';
|
||||
expect(form.values['dropdown-2']).toEqual(field.options[1]);
|
||||
});
|
||||
|
||||
it('should update form with radio button value', () => {
|
||||
let form = new FormModel();
|
||||
let field = new FormFieldModel(form, {
|
||||
id: 'radio-1',
|
||||
type: FormFieldTypes.RADIO_BUTTONS,
|
||||
options: [
|
||||
{ id: 'opt1', value: 'Option 1' },
|
||||
{ id: 'opt2', value: 'Option 2' }
|
||||
]
|
||||
});
|
||||
|
||||
field.value = 'opt2';
|
||||
expect(form.values['radio-1']).toEqual(field.options[1]);
|
||||
});
|
||||
|
||||
it('should update form with the first radio button value', () => {
|
||||
let form = new FormModel();
|
||||
let field = new FormFieldModel(form, {
|
||||
id: 'radio-2',
|
||||
type: FormFieldTypes.RADIO_BUTTONS,
|
||||
options: [
|
||||
{ id: 'opt1', value: 'Option 1' },
|
||||
{ id: 'opt2', value: 'Option 2' }
|
||||
]
|
||||
});
|
||||
|
||||
field.value = 'missing';
|
||||
expect(form.values['radio-2']).toEqual(field.options[0]);
|
||||
});
|
||||
|
||||
it('should not update form with display-only field value', () => {
|
||||
let form = new FormModel();
|
||||
|
||||
FormFieldTypes.READONLY_TYPES.forEach(typeName => {
|
||||
let field = new FormFieldModel(form, {
|
||||
id: typeName,
|
||||
type: typeName
|
||||
});
|
||||
|
||||
field.value = '<some value>';
|
||||
expect(form.values[field.id]).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,173 @@
|
||||
/*!
|
||||
* @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 { FormWidgetModel } from './form-widget.model';
|
||||
import { FormFieldOption } from './form-field-option';
|
||||
import { FormFieldTypes } from './form-field-types';
|
||||
import { FormFieldMetadata } from './form-field-metadata';
|
||||
import { FormModel } from './form.model';
|
||||
import { WidgetVisibilityModel } from '../../../models/widget-visibility.model';
|
||||
|
||||
export class FormFieldModel extends FormWidgetModel {
|
||||
|
||||
private _value: string;
|
||||
private _readOnly: boolean = false;
|
||||
|
||||
fieldType: string;
|
||||
id: string;
|
||||
name: string;
|
||||
type: string;
|
||||
required: boolean;
|
||||
overrideId: boolean;
|
||||
tab: string;
|
||||
colspan: number = 1;
|
||||
options: FormFieldOption[] = [];
|
||||
restUrl: string;
|
||||
restResponsePath: string;
|
||||
restIdProperty: string;
|
||||
restLabelProperty: string;
|
||||
hasEmptyValue: boolean;
|
||||
className: string;
|
||||
optionType: string;
|
||||
params: FormFieldMetadata = {};
|
||||
hyperlinkUrl: string;
|
||||
displayText: string;
|
||||
isVisible: boolean = true;
|
||||
visibilityCondition: WidgetVisibilityModel = null;
|
||||
|
||||
get value(): any {
|
||||
return this._value;
|
||||
}
|
||||
|
||||
set value(v: any) {
|
||||
this._value = v;
|
||||
this.updateForm();
|
||||
}
|
||||
|
||||
get readOnly(): boolean {
|
||||
if (this.form && this.form.readOnly) {
|
||||
return true;
|
||||
}
|
||||
return this._readOnly;
|
||||
}
|
||||
|
||||
constructor(form: FormModel, json?: any) {
|
||||
super(form, json);
|
||||
|
||||
if (json) {
|
||||
this.fieldType = json.fieldType;
|
||||
this.id = json.id;
|
||||
this.name = json.name;
|
||||
this.type = json.type;
|
||||
this.required = <boolean> json.required;
|
||||
this._readOnly = <boolean> json.readOnly;
|
||||
this.overrideId = <boolean> json.overrideId;
|
||||
this.tab = json.tab;
|
||||
this.restUrl = json.restUrl;
|
||||
this.restResponsePath = json.restResponsePath;
|
||||
this.restIdProperty = json.restIdProperty;
|
||||
this.restLabelProperty = json.restLabelProperty;
|
||||
this.colspan = <number> json.colspan;
|
||||
this.options = <FormFieldOption[]> json.options || [];
|
||||
this.hasEmptyValue = <boolean> json.hasEmptyValue;
|
||||
this.className = json.className;
|
||||
this.optionType = json.optionType;
|
||||
this.params = <FormFieldMetadata> json.params || {};
|
||||
this.hyperlinkUrl = json.hyperlinkUrl;
|
||||
this.displayText = json.displayText;
|
||||
this.visibilityCondition = <WidgetVisibilityModel> json.visibilityCondition;
|
||||
|
||||
this._value = this.parseValue(json);
|
||||
this.updateForm();
|
||||
}
|
||||
}
|
||||
|
||||
parseValue(json: any): any {
|
||||
let value = json.value;
|
||||
|
||||
/*
|
||||
This is needed due to Activiti issue related to reading dropdown values as value string
|
||||
but saving back as object: { id: <id>, name: <name> }
|
||||
*/
|
||||
// TODO: needs review
|
||||
if (json.type === FormFieldTypes.DROPDOWN) {
|
||||
if (value === '') {
|
||||
value = 'empty';
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
This is needed due to Activiti issue related to reading radio button values as value string
|
||||
but saving back as object: { id: <id>, name: <name> }
|
||||
*/
|
||||
if (json.type === FormFieldTypes.RADIO_BUTTONS) {
|
||||
// Activiti has a bug with default radio button value,
|
||||
// so try resolving current one with a fallback to first entry
|
||||
let entry: FormFieldOption[] = this.options.filter(opt => opt.id === value);
|
||||
if (entry.length > 0) {
|
||||
value = entry[0].id;
|
||||
} else if (this.options.length > 0) {
|
||||
value = this.options[0].id;
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
updateForm() {
|
||||
|
||||
switch (this.type) {
|
||||
case FormFieldTypes.DROPDOWN:
|
||||
/*
|
||||
This is needed due to Activiti reading dropdown values as string
|
||||
but saving back as object: { id: <id>, name: <name> }
|
||||
*/
|
||||
if (this.value === 'empty' || this.value === '') {
|
||||
this.form.values[this.id] = {};
|
||||
} else {
|
||||
let entry: FormFieldOption[] = this.options.filter(opt => opt.id === this.value);
|
||||
if (entry.length > 0) {
|
||||
this.form.values[this.id] = entry[0];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case FormFieldTypes.RADIO_BUTTONS:
|
||||
/*
|
||||
This is needed due to Activiti issue related to reading radio button values as value string
|
||||
but saving back as object: { id: <id>, name: <name> }
|
||||
*/
|
||||
let entry: FormFieldOption[] = this.options.filter(opt => opt.id === this.value);
|
||||
if (entry.length > 0) {
|
||||
this.form.values[this.id] = entry[0];
|
||||
} else if (this.options.length > 0) {
|
||||
this.form.values[this.id] = this.options[0];
|
||||
}
|
||||
break;
|
||||
case FormFieldTypes.UPLOAD:
|
||||
if (this.value && this.value.length > 0) {
|
||||
this.form.values[this.id] = `${this.value[0].id}`;
|
||||
} else {
|
||||
this.form.values[this.id] = null;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (!FormFieldTypes.isReadOnlyType(this.type)) {
|
||||
this.form.values[this.id] = this.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { FormOutcomeModel } from './form-outcome.model';
|
||||
|
||||
export class FormOutcomeEvent {
|
||||
|
||||
private _outcome: FormOutcomeModel;
|
||||
private _defaultPrevented: boolean = false;
|
||||
|
||||
get outcome(): FormOutcomeModel {
|
||||
return this._outcome;
|
||||
}
|
||||
|
||||
get defaultPrevented() {
|
||||
return this._defaultPrevented;
|
||||
}
|
||||
|
||||
constructor(outcome: FormOutcomeModel) {
|
||||
this._outcome = outcome;
|
||||
}
|
||||
|
||||
preventDefault() {
|
||||
this._defaultPrevented = true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { it, describe, expect } from '@angular/core/testing';
|
||||
import { FormModel } from './form.model';
|
||||
import { FormOutcomeModel } from './form-outcome.model';
|
||||
|
||||
describe('FormOutcomeModel', () => {
|
||||
|
||||
it('should setup with json config', () => {
|
||||
let json = {
|
||||
id: '<id>',
|
||||
name: '<name>'
|
||||
};
|
||||
let model = new FormOutcomeModel(null, json);
|
||||
expect(model.id).toBe(json.id);
|
||||
expect(model.name).toBe(json.name);
|
||||
});
|
||||
|
||||
it('should store the form reference', () => {
|
||||
let form = new FormModel();
|
||||
let model = new FormOutcomeModel(form);
|
||||
expect(model.form).toBe(form);
|
||||
});
|
||||
|
||||
it('should store original json', () => {
|
||||
let json = {};
|
||||
let model = new FormOutcomeModel(null, json);
|
||||
expect(model.json).toBe(json);
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,48 @@
|
||||
/*!
|
||||
* @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 { FormWidgetModel } from './form-widget.model';
|
||||
import { FormModel } from './form.model';
|
||||
|
||||
export class FormOutcomeModel extends FormWidgetModel {
|
||||
|
||||
static SAVE_ACTION: string = 'Save'; // Activiti 'Save' action name
|
||||
static COMPLETE_ACTION: string = 'Complete'; // Activiti 'Complete' action name
|
||||
|
||||
private _id: string;
|
||||
private _name: string;
|
||||
|
||||
isSystem: boolean = false;
|
||||
|
||||
get id() {
|
||||
return this._id;
|
||||
}
|
||||
|
||||
get name() {
|
||||
return this._name;
|
||||
}
|
||||
|
||||
constructor(form: FormModel, json?: any) {
|
||||
super(form, json);
|
||||
|
||||
if (json) {
|
||||
this._id = json.id;
|
||||
this._name = json.name;
|
||||
this.isSystem = json.isSystem ? true : false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { FormFieldMetadata } from './form-field-metadata';
|
||||
|
||||
export interface FormValues extends FormFieldMetadata {
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { it, describe, expect } from '@angular/core/testing';
|
||||
import { FormModel } from './form.model';
|
||||
import { FormWidgetModel } from './form-widget.model';
|
||||
|
||||
describe('FormWidgetModel', () => {
|
||||
|
||||
it('should store the form reference', () => {
|
||||
let form = new FormModel();
|
||||
let model = new FormWidgetModel(form, null);
|
||||
expect(model.form).toBe(form);
|
||||
});
|
||||
|
||||
it('should store original json', () => {
|
||||
let json = {};
|
||||
let model = new FormWidgetModel(null, json);
|
||||
expect(model.json).toBe(json);
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,41 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { FormModel } from './form.model';
|
||||
|
||||
export class FormWidgetModel {
|
||||
|
||||
private _form: FormModel;
|
||||
private _json: any;
|
||||
|
||||
get form(): FormModel {
|
||||
return this._form;
|
||||
}
|
||||
|
||||
get json(): any {
|
||||
return this._json;
|
||||
}
|
||||
|
||||
constructor(form: FormModel, json: any) {
|
||||
this._form = form;
|
||||
this._json = json;
|
||||
}
|
||||
}
|
||||
|
||||
export interface FormWidgetModelCache<T extends FormWidgetModel> {
|
||||
[key: string]: T;
|
||||
}
|
||||
@@ -0,0 +1,295 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { it, describe, expect } from '@angular/core/testing';
|
||||
import { FormModel } from './form.model';
|
||||
import { TabModel } from './tab.model';
|
||||
import { ContainerModel } from './container.model';
|
||||
import { FormOutcomeModel } from './form-outcome.model';
|
||||
import { FormValues } from './form-values';
|
||||
|
||||
describe('FormModel', () => {
|
||||
|
||||
it('should store original json', () => {
|
||||
let json = {};
|
||||
let form = new FormModel(json);
|
||||
expect(form.json).toBe(json);
|
||||
});
|
||||
|
||||
it('should setup properties with json', () => {
|
||||
let json = {
|
||||
id: '<id>',
|
||||
name: '<name>',
|
||||
taskId: '<task-id>',
|
||||
taskName: '<task-name>'
|
||||
};
|
||||
let form = new FormModel(json);
|
||||
|
||||
Object.keys(json).forEach(key => {
|
||||
expect(form[key]).toEqual(form[key]);
|
||||
});
|
||||
});
|
||||
|
||||
it('should take form name when task name is missing', () => {
|
||||
let json = {
|
||||
id: '<id>',
|
||||
name: '<name>'
|
||||
};
|
||||
let form = new FormModel(json);
|
||||
expect(form.taskName).toBe(json.name);
|
||||
});
|
||||
|
||||
it('should use fallback value for task name', () => {
|
||||
let form = new FormModel({});
|
||||
expect(form.taskName).toBe(FormModel.UNSET_TASK_NAME);
|
||||
});
|
||||
|
||||
it('should set readonly state from params', () => {
|
||||
let form = new FormModel({}, null, true);
|
||||
expect(form.readOnly).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should check tabs', () => {
|
||||
let form = new FormModel();
|
||||
|
||||
form.tabs = null;
|
||||
expect(form.hasTabs()).toBeFalsy();
|
||||
|
||||
form.tabs = [];
|
||||
expect(form.hasTabs()).toBeFalsy();
|
||||
|
||||
form.tabs = [new TabModel(null)];
|
||||
expect(form.hasTabs()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should check fields', () => {
|
||||
let form = new FormModel();
|
||||
|
||||
form.fields = null;
|
||||
expect(form.hasFields()).toBeFalsy();
|
||||
|
||||
form.fields = [];
|
||||
expect(form.hasFields()).toBeFalsy();
|
||||
|
||||
form.fields = [new ContainerModel(null)];
|
||||
expect(form.hasFields()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should check outcomes', () => {
|
||||
let form = new FormModel();
|
||||
|
||||
form.outcomes = null;
|
||||
expect(form.hasOutcomes()).toBeFalsy();
|
||||
|
||||
form.outcomes = [];
|
||||
expect(form.hasOutcomes()).toBeFalsy();
|
||||
|
||||
form.outcomes = [new FormOutcomeModel(null)];
|
||||
expect(form.hasOutcomes()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should parse tabs', () => {
|
||||
let json = {
|
||||
tabs: [
|
||||
{ id: 'tab1' },
|
||||
{ id: 'tab2' }
|
||||
]
|
||||
};
|
||||
|
||||
let form = new FormModel(json);
|
||||
expect(form.tabs.length).toBe(2);
|
||||
expect(form.tabs[0].id).toBe('tab1');
|
||||
expect(form.tabs[1].id).toBe('tab2');
|
||||
});
|
||||
|
||||
it('should parse fields', () => {
|
||||
let json = {
|
||||
fields: [
|
||||
{ id: 'field1' },
|
||||
{ id: 'field2' }
|
||||
]
|
||||
};
|
||||
|
||||
let form = new FormModel(json);
|
||||
expect(form.fields.length).toBe(2);
|
||||
expect(form.fields[0].id).toBe('field1');
|
||||
expect(form.fields[1].id).toBe('field2');
|
||||
});
|
||||
|
||||
it('should parse fields from the definition', () => {
|
||||
let json = {
|
||||
fields: null,
|
||||
formDefinition: {
|
||||
fields: [
|
||||
{ id: 'field1' },
|
||||
{ id: 'field2' }
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
let form = new FormModel(json);
|
||||
expect(form.fields.length).toBe(2);
|
||||
expect(form.fields[0].id).toBe('field1');
|
||||
expect(form.fields[1].id).toBe('field2');
|
||||
});
|
||||
|
||||
it('should convert missing fields to empty collection', () => {
|
||||
let json = {
|
||||
fields: null
|
||||
};
|
||||
|
||||
let form = new FormModel(json);
|
||||
expect(form.fields).toBeDefined();
|
||||
expect(form.fields.length).toBe(0);
|
||||
});
|
||||
|
||||
it('should put fields into corresponding tabs', () => {
|
||||
let json = {
|
||||
tabs: [
|
||||
{ id: 'tab1' },
|
||||
{ id: 'tab2' }
|
||||
],
|
||||
fields: [
|
||||
{ id: 'field1', tab: 'tab1' },
|
||||
{ id: 'field2', tab: 'tab2' },
|
||||
{ id: 'field3', tab: 'tab1' },
|
||||
{ id: 'field4', tab: 'missing-tab' }
|
||||
]
|
||||
};
|
||||
|
||||
let form = new FormModel(json);
|
||||
expect(form.tabs.length).toBe(2);
|
||||
expect(form.fields.length).toBe(4);
|
||||
|
||||
let tab1 = form.tabs[0];
|
||||
expect(tab1.fields.length).toBe(2);
|
||||
expect(tab1.fields[0].id).toBe('field1');
|
||||
expect(tab1.fields[1].id).toBe('field3');
|
||||
|
||||
let tab2 = form.tabs[1];
|
||||
expect(tab2.fields.length).toBe(1);
|
||||
expect(tab2.fields[0].id).toBe('field2');
|
||||
});
|
||||
|
||||
it('should apply external data', () => {
|
||||
let data: FormValues = {
|
||||
field1: 'one',
|
||||
field2: 'two'
|
||||
};
|
||||
|
||||
let json = {
|
||||
fields: [
|
||||
{
|
||||
fieldType: 'ContainerRepresentation',
|
||||
id: 'container1',
|
||||
type: 'container',
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
'1': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
type: 'text',
|
||||
id: 'field1'
|
||||
}
|
||||
],
|
||||
'2': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
type: 'text',
|
||||
id: 'field2'
|
||||
},
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
type: 'text',
|
||||
id: 'field3',
|
||||
value: 'original-value'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
let form = new FormModel(json, data);
|
||||
expect(form.fields.length).toBe(1);
|
||||
|
||||
let container = form.fields[0];
|
||||
expect(container.columns.length).toBe(2);
|
||||
|
||||
let column1 = container.columns[0];
|
||||
let column2 = container.columns[1];
|
||||
expect(column1.fields.length).toBe(1);
|
||||
expect(column2.fields.length).toBe(2);
|
||||
|
||||
let field1 = column1.fields[0];
|
||||
expect(field1.id).toBe('field1');
|
||||
expect(field1.value).toBe('one');
|
||||
|
||||
let field2 = column2.fields[0];
|
||||
expect(field2.id).toBe('field2');
|
||||
expect(field2.value).toBe('two');
|
||||
|
||||
let field3 = column2.fields[1];
|
||||
expect(field3.id).toBe('field3');
|
||||
expect(field3.value).toBe('original-value');
|
||||
});
|
||||
|
||||
it('should create standard form outcomes', () => {
|
||||
let json = {
|
||||
fields: [
|
||||
{ id: 'container1' }
|
||||
]
|
||||
};
|
||||
|
||||
let form = new FormModel(json);
|
||||
expect(form.outcomes.length).toBe(2);
|
||||
|
||||
expect(form.outcomes[0].id).toBe(FormModel.SAVE_OUTCOME);
|
||||
expect(form.outcomes[0].isSystem).toBeTruthy();
|
||||
|
||||
expect(form.outcomes[1].id).toBe(FormModel.COMPLETE_OUTCOME);
|
||||
expect(form.outcomes[1].isSystem).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should create outcomes only when fields available', () => {
|
||||
let json = {
|
||||
fields: null
|
||||
};
|
||||
let form = new FormModel(json);
|
||||
expect(form.outcomes.length).toBe(0);
|
||||
});
|
||||
|
||||
it('should use custom form outcomes', () => {
|
||||
let json = {
|
||||
fields: [
|
||||
{ id: 'container1' }
|
||||
],
|
||||
outcomes: [
|
||||
{ id: 'custom-1', name: 'custom 1' }
|
||||
]
|
||||
};
|
||||
|
||||
let form = new FormModel(json);
|
||||
expect(form.outcomes.length).toBe(2);
|
||||
|
||||
expect(form.outcomes[0].id).toBe(FormModel.SAVE_OUTCOME);
|
||||
expect(form.outcomes[0].isSystem).toBeTruthy();
|
||||
|
||||
expect(form.outcomes[1].id).toBe('custom-1');
|
||||
expect(form.outcomes[1].isSystem).toBeFalsy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,151 @@
|
||||
/*!
|
||||
* @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 { FormWidgetModelCache } from './form-widget.model';
|
||||
import { FormValues } from './form-values';
|
||||
import { ContainerModel } from './container.model';
|
||||
import { TabModel } from './tab.model';
|
||||
import { FormOutcomeModel } from './form-outcome.model';
|
||||
|
||||
export class FormModel {
|
||||
|
||||
static UNSET_TASK_NAME: string = 'Nameless task';
|
||||
static SAVE_OUTCOME: string = '$save';
|
||||
static COMPLETE_OUTCOME: string = '$complete';
|
||||
|
||||
private _id: string;
|
||||
private _name: string;
|
||||
private _taskId: string;
|
||||
private _taskName: string = FormModel.UNSET_TASK_NAME;
|
||||
|
||||
get id(): string {
|
||||
return this._id;
|
||||
}
|
||||
|
||||
get name(): string {
|
||||
return this._name;
|
||||
}
|
||||
|
||||
get taskId(): string {
|
||||
return this._taskId;
|
||||
}
|
||||
|
||||
get taskName(): string {
|
||||
return this._taskName;
|
||||
}
|
||||
|
||||
readOnly: boolean = false;
|
||||
tabs: TabModel[] = [];
|
||||
fields: ContainerModel[] = [];
|
||||
outcomes: FormOutcomeModel[] = [];
|
||||
|
||||
values: FormValues = {};
|
||||
|
||||
private _json: any;
|
||||
|
||||
get json() {
|
||||
return this._json;
|
||||
}
|
||||
|
||||
hasTabs(): boolean {
|
||||
return this.tabs && this.tabs.length > 0;
|
||||
}
|
||||
|
||||
hasFields(): boolean {
|
||||
return this.fields && this.fields.length > 0;
|
||||
}
|
||||
|
||||
hasOutcomes(): boolean {
|
||||
return this.outcomes && this.outcomes.length > 0;
|
||||
}
|
||||
|
||||
constructor(json?: any, data?: FormValues, readOnly: boolean = false) {
|
||||
this.readOnly = readOnly;
|
||||
if (json) {
|
||||
this._json = json;
|
||||
|
||||
this._id = json.id;
|
||||
this._name = json.name;
|
||||
this._taskId = json.taskId;
|
||||
this._taskName = json.taskName || json.name || FormModel.UNSET_TASK_NAME;
|
||||
|
||||
let tabCache: FormWidgetModelCache<TabModel> = {};
|
||||
|
||||
this.tabs = (json.tabs || []).map(t => {
|
||||
let model = new TabModel(this, t);
|
||||
tabCache[model.id] = model;
|
||||
return model;
|
||||
});
|
||||
|
||||
this.fields = this.parseContainerFields(json);
|
||||
|
||||
if (data) {
|
||||
this.loadData(data);
|
||||
}
|
||||
|
||||
for (let i = 0; i < this.fields.length; i++) {
|
||||
let field = this.fields[i];
|
||||
if (field.tab) {
|
||||
let tab = tabCache[field.tab];
|
||||
if (tab) {
|
||||
tab.fields.push(new ContainerModel(this, field.json));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (json.fields) {
|
||||
let saveOutcome = new FormOutcomeModel(this, { id: FormModel.SAVE_OUTCOME, name: 'Save', isSystem: true });
|
||||
let completeOutcome = new FormOutcomeModel(this, {id: FormModel.COMPLETE_OUTCOME, name: 'Complete', isSystem: true });
|
||||
|
||||
let customOutcomes = (json.outcomes || []).map(obj => new FormOutcomeModel(this, obj));
|
||||
|
||||
this.outcomes = [saveOutcome].concat(
|
||||
customOutcomes.length > 0 ? customOutcomes : [completeOutcome]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private parseContainerFields(json: any): ContainerModel[] {
|
||||
let fields = [];
|
||||
|
||||
if (json.fields) {
|
||||
fields = json.fields;
|
||||
} else if (json.formDefinition && json.formDefinition.fields) {
|
||||
fields = json.formDefinition.fields;
|
||||
}
|
||||
|
||||
return fields.map(obj => new ContainerModel(this, obj));
|
||||
}
|
||||
|
||||
// Loads external data and overrides field values
|
||||
// Typically used when form definition and form data coming from different sources
|
||||
private loadData(data: FormValues) {
|
||||
for (let i = 0; i < this.fields.length; i++) {
|
||||
let container = this.fields[i];
|
||||
for (let i = 0; i < container.columns.length; i++) {
|
||||
let column = container.columns[i];
|
||||
for (let i = 0; i < column.fields.length; i++) {
|
||||
let field = column.fields[i];
|
||||
if (data[field.id]) {
|
||||
field.json.value = data[field.id];
|
||||
field.value = data[field.id];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export * from './form-field-metadata';
|
||||
export * from './form-values';
|
||||
export * from './form-field-types';
|
||||
export * from './form-field-option';
|
||||
export * from './form-widget.model';
|
||||
export * from './form-field.model';
|
||||
export * from './form.model';
|
||||
export * from './container-column.model';
|
||||
export * from './container.model';
|
||||
export * from './tab.model';
|
||||
export * from './form-outcome.model';
|
||||
export * from './form-outcome-event.model';
|
||||
@@ -0,0 +1,70 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { it, describe, expect } from '@angular/core/testing';
|
||||
import { FormModel } from './form.model';
|
||||
import { TabModel } from './tab.model';
|
||||
import { ContainerModel } from './container.model';
|
||||
|
||||
describe('TabModel', () => {
|
||||
|
||||
it('should setup with json config', () => {
|
||||
let json = {
|
||||
id: '<id>',
|
||||
title: '<title>',
|
||||
visibilityCondition: '<condition>'
|
||||
};
|
||||
|
||||
let model = new TabModel(null, json);
|
||||
expect(model.id).toBe(json.id);
|
||||
expect(model.title).toBe(json.title);
|
||||
expect(model.visibilityCondition).toBe(json.visibilityCondition);
|
||||
});
|
||||
|
||||
it('should not setup with json config', () => {
|
||||
let model = new TabModel(null, null);
|
||||
expect(model.id).toBeUndefined();
|
||||
expect(model.title).toBeUndefined();
|
||||
expect(model.visibilityCondition).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should evaluate content based on fields', () => {
|
||||
let model = new TabModel(null, null);
|
||||
|
||||
model.fields = null;
|
||||
expect(model.hasContent()).toBeFalsy();
|
||||
|
||||
model.fields = [];
|
||||
expect(model.hasContent()).toBeFalsy();
|
||||
|
||||
model.fields = [new ContainerModel(null, null)];
|
||||
expect(model.hasContent()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should store the form reference', () => {
|
||||
let form = new FormModel();
|
||||
let model = new TabModel(form);
|
||||
expect(model.form).toBe(form);
|
||||
});
|
||||
|
||||
it('should store original json', () => {
|
||||
let json = {};
|
||||
let model = new TabModel(null, json);
|
||||
expect(model.json).toBe(json);
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,43 @@
|
||||
/*!
|
||||
* @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 { FormWidgetModel } from './form-widget.model';
|
||||
import { ContainerModel } from './container.model';
|
||||
import { FormModel } from './form.model';
|
||||
|
||||
export class TabModel extends FormWidgetModel {
|
||||
|
||||
id: string;
|
||||
title: string;
|
||||
visibilityCondition: any;
|
||||
|
||||
fields: ContainerModel[] = [];
|
||||
|
||||
hasContent(): boolean {
|
||||
return this.fields && this.fields.length > 0;
|
||||
}
|
||||
|
||||
constructor(form: FormModel, json?: any) {
|
||||
super(form, json);
|
||||
|
||||
if (json) {
|
||||
this.id = json.id;
|
||||
this.title = json.title;
|
||||
this.visibilityCondition = json.visibilityCondition;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
.display-text-widget {}
|
||||
@@ -0,0 +1,3 @@
|
||||
<div class="display-text-widget">
|
||||
<span>{{field.value}}</span>
|
||||
</div>
|
||||
@@ -0,0 +1,32 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Component } from '@angular/core';
|
||||
import { WidgetComponent } from './../widget.component';
|
||||
|
||||
declare let __moduleName: string;
|
||||
declare var componentHandler;
|
||||
|
||||
@Component({
|
||||
moduleId: __moduleName,
|
||||
selector: 'display-text-widget',
|
||||
templateUrl: './display-text.widget.html',
|
||||
styleUrls: ['./display-text.widget.css']
|
||||
})
|
||||
export class DisplayTextWidget extends WidgetComponent {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
.display-value-widget {
|
||||
width: 100%;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label display-value-widget">
|
||||
<input class="mdl-textfield__input"
|
||||
type="text"
|
||||
[attr.id]="field.id"
|
||||
[(ngModel)]="field.value"
|
||||
(ngModelChange)="checkVisibility(field)"
|
||||
disabled>
|
||||
<label class="mdl-textfield__label" [attr.for]="field.id">{{field.name}}</label>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Component } from '@angular/core';
|
||||
import { WidgetComponent } from './../widget.component';
|
||||
|
||||
declare let __moduleName: string;
|
||||
declare var componentHandler;
|
||||
|
||||
@Component({
|
||||
moduleId: __moduleName,
|
||||
selector: 'display-value-widget',
|
||||
templateUrl: './display-value.widget.html',
|
||||
styleUrls: ['./display-value.widget.css']
|
||||
})
|
||||
export class DisplayValueWidget extends WidgetComponent {
|
||||
|
||||
}
|
||||