Merge pull request #1341 from Alfresco/development

1.0.0
This commit is contained in:
Eugenio Romano
2016-12-20 17:05:27 +00:00
committed by GitHub
587 changed files with 16991 additions and 6205 deletions
+6 -5
View File
@@ -1,8 +1,9 @@
**Please check if the PR fulfills these requirements**
- [ ] The commit message follows our [guidelines](https://github.com/Alfresco/alfresco-ng2-components/wiki/Commit-format)
- [ ] Tests for the changes have been added (for bug fixes / features)
- [ ] Docs have been added / updated (for bug fixes / features)
```
[ ] The commit message follows our [guidelines](https://github.com/Alfresco/alfresco-ng2-components/wiki/Commit-format)
[ ] Tests for the changes have been added (for bug fixes / features)
[ ] Docs have been added / updated (for bug fixes / features)
```
<!--
Before submitting your PR, please check that your code follows our contribution guidelines:
https://github.com/Alfresco/alfresco-ng2-components/wiki/Code-contribution-acceptance-criteria
@@ -35,4 +36,4 @@
If this PR contains a breaking change, please describe the impact and migration path for existing applications: ...
**Other information**:
**Other information**:
+2
View File
@@ -8,3 +8,5 @@ demo-shell-ng2/app/components/router/
ng2-components/ng2-alfresco-userinfo-old/demo/src/app/
ng2-components/ng2-alfresco-userinfo-old/src/services/bpm-user.service.spec.ts
ng2-components/ng2-alfresco-userinfo-old/src/services/ecm-user.service.spec.ts
src/environments/
/ng2-components/ng2-example-webpack/
+67
View File
@@ -0,0 +1,67 @@
### Enable CORS in Alfresco
The web client that we are building with the application development framework will be loaded from a different web server than the Alfresco Platform is running on.
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 **one of the following**:
##Recommended - 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.
##Or - 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`:
```
<filter>
<filter-name>CORS</filter-name>
<filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
<init-param>
<param-name>cors.allowGenericHttpRequests</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>cors.allowOrigin</param-name>
<param-value>http://localhost:3000</param-value>
</init-param>
<init-param>
<param-name>cors.allowSubdomains</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>cors.supportedMethods</param-name>
<param-value>GET, HEAD, POST, PUT, DELETE, OPTIONS</param-value>
</init-param>
<init-param>
<param-name>cors.supportedHeaders</param-name>
<param-value>origin, authorization, x-file-size, x-file-name, content-type, accept, x-file-type</param-value>
</init-param>
<init-param>
<param-name>cors.supportsCredentials</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>cors.maxAge</param-name>
<param-value>3600</param-value>
</init-param>
</filter>
```
When specifying the `cors.allowOrigin` URL make sure to use the URL that will be used by the web client.
Then uncomment filter mappings:
```
<filter-mapping>
<filter-name>CORS</filter-name>
<url-pattern>/api/*</url-pattern>
<url-pattern>/service/*</url-pattern>
<url-pattern>/s/*</url-pattern>
<url-pattern>/cmisbrowser/*</url-pattern>
</filter-mapping>
```
+2 -1
View File
@@ -2,7 +2,8 @@
The [Angular 2](https://angular.io/) based application development framework requires the following:
- An Alfresco Platform Repository (version [201609 Early Access](https://community.alfresco.com/docs/DOC-6372-alfresco-community-edition-file-list-201609-ea) or newer) to talk to, which has [CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing) enabled.
- An Alfresco Platform Repository (version [201609 Early Access](https://community.alfresco.com/docs/DOC-6372-alfresco-community-edition-file-list-201609-ea) or newer)
- [Enable cors on Alfresco One](/ALFRESCOCORS.md)
- [Download and install Activiti](https://www.alfresco.com/products/bpm/alfresco-activiti/trial)
- [Node.js](https://nodejs.org/en/) JavaScript runtime.
- [npm](https://www.npmjs.com/) package manager for JavaScript.
+2
View File
@@ -5,7 +5,9 @@ app/**/*.js
app/**/*.js.map
!app/js/Polyline.js
.idea
versions.json
dist/
coverage/
# docker files
docker-compose.yml
+25 -11
View File
@@ -10,28 +10,42 @@
</a>
</p>
### Node
To correctly use this demo check that on your machine is running Node version 5.0.0 or higher.
## Installing
#### Local build
1 Install dependencies
To correctly use this demo check that on your machine is running Node version 6.9.2 LTS or higher.
```sh
npm install
```
2 Fast build and watch for dev purposes
## Development build
```sh
npm start
```
>`start` script also includes live reload and watchers for all the `.ts` files.
TypeScript watchers are also configured for `node_modules` folder within demo shell
and provide live reload for all the component libraries as well.
This command compiles and starts the project in watch mode.
Browser will automatically reload upon changes.
Upon start you can navigate to `http://localhost:3000` with your preferred browser.
#### Development branch build
## Production build
```sh
npm run build
```
This command builds broject in `production` mode.
All output is placed to `dist` folder and can be served your preferred web server.
You should need no additional files outside the `dist` folder.
In order to quickly test the output you can use the [wsrv](https://www.npmjs.com/package/wsrv) tool (lightweight web server):
```sh
npm install -g wsrv
wsrv -s -o dist/
```
## Development branch build
If you want to run the demo shell with the latest change from the development branch, use the following command from the /script folder:
@@ -40,7 +54,7 @@ If you want to run the demo shell with the latest change from the development br
./start-linked.sh -install
```
###Multi-language
## Multi-language
To support a new language you need to create your language file (.json) and add it to `i18n/` folder.
```json
+21 -3
View File
@@ -1,6 +1,12 @@
@media only screen and (max-width: 640px) {
.mdl-layout__header.header-search-expanded .mdl-layout-title {
display: none;
@media screen and (max-width: 1024px) {
.mdl-layout__header {
display: block;
}
}
@media screen and (max-width: 1024px) {
.mdl-layout__header {
display: block;
}
}
@@ -15,3 +21,15 @@
.mdl-button-padding {
padding-left: 20px;
}
.hide {
display: none !important;
}
.mdl-navigation__link {
cursor: pointer;
}
.mdl-navigation__link label {
cursor: pointer;
}
+55 -71
View File
@@ -1,82 +1,66 @@
<!-- Always shows a header, even in smaller screens. -->
<div mdl class="mdl-layout mdl-js-layout mdl-layout--fixed-header">
<div *ngIf="!isLoginPage()">
<header class="mdl-layout__header">
<div class="mdl-button-padding mdl-layout__header-row">
<header class="mdl-layout__header main_header_adf" [ngClass]="{hide: isLoginPage()}">
<div class="mdl-button-padding mdl-layout__header-row">
<!-- User Info -->
<ng2-alfresco-userinfo class="user-profile" [menuOpenType]="left">
</ng2-alfresco-userinfo>
<ng2-alfresco-userinfo class="user-profile" [menuOpenType]="left">
</ng2-alfresco-userinfo>
<!-- Title -->
<span class="mdl-layout-title">Demo Application</span>
<!-- Add spacer, to align navigation to the right -->
<div class="mdl-layout-spacer"></div>
<!-- Search bar -->
<search-bar (expand)="onToggleSearch($event)"></search-bar>
<!-- Title -->
<span class="mdl-layout-title">Demo Application</span>
<!-- Add spacer, to align navigation to the right -->
<div class="mdl-layout-spacer"></div>
<!-- Search bar -->
<search-bar (expand)="onToggleSearch($event)"></search-bar>
<!-- 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="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="tag" href="" routerLink="/tag">Tag</a>
<a class="mdl-navigation__link" data-automation-id="login" href="" routerLink="/login">Login</a>
<a class="mdl-navigation__link" data-automation-id="settings" href="" routerLink="/settings">Settings</a>
</nav>
<!-- Right aligned menu below button -->
<button id="demo-menu-lower-right" data-automation-id="right-action-menu"
class="mdl-button mdl-js-button mdl-button--icon">
<i class="material-icons">more_vert</i>
</button>
<ul class="mdl-menu mdl-menu--bottom-right mdl-js-menu mdl-js-ripple-effect"
for="demo-menu-lower-right">
<li class="mdl-menu__item" (click)="changeLanguage('en')">
<span class="flag-icon flag-icon-gb"></span>
<label tabindex="0"> English</label>
</li>
<li class="mdl-menu__item" (click)="changeLanguage('gr')">
<span class="flag-icon flag-icon-gr"></span>
<label tabindex="0"> Greek</label>
</li>
<li class="mdl-menu__item" (click)="changeLanguage('it')">
<span class="flag-icon flag-icon-it"></span>
<label tabindex="0"> Italian</label>
</li>
<a class="mdl-menu__item" routerLink="/about">
<label tabindex="0">About</label>
</a>
<a *ngIf="!isLoggedIn()" class="mdl-menu__item" routerLink="/login">
<label tabindex="0">Login</label>
</a>
<li *ngIf="isLoggedIn()" class="mdl-menu__item" (click)="onLogout($event)">
<label tabindex="0">Logout</label>
</li>
</ul>
</div>
</header>
<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 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="/tag" (click)="hideDrawer()">Tag</a>
<a class="mdl-navigation__link" href="" routerLink="/settings" (click)="hideDrawer()">Settings</a>
<!-- Navigation. We hide it in small screens. -->
<nav class="mdl-navigation mdl-layout--large-screen-only">
<a class="mdl-navigation__link" data-automation-id="home" href="" routerLink="/">Home</a>
<a class="mdl-navigation__link" data-automation-id="files" href="" routerLink="/files">DocumentList</a>
<a class="mdl-navigation__link" data-automation-id="activiti" href="" routerLink="/activiti">Activiti</a>
<a class="mdl-navigation__link" data-automation-id="login" href="" routerLink="/login">Login</a>
<a class="mdl-navigation__link" data-automation-id="settings" href="" routerLink="/settings">Settings</a>
</nav>
</div>
</header>
<div class="mdl-layout__drawer">
<nav class="mdl-navigation">
<a class="mdl-navigation__link" (click)="onLogout($event)">
<label tabindex="0">Logout</label>
</a>
</nav>
<span class="mdl-layout-title">Languages</span>
<nav class="mdl-navigation">
<a class="mdl-navigation__link" (click)="changeLanguage('en')">
<span class="flag-icon flag-icon-gb"></span>
<label tabindex="0"> English</label>
</a>
<a class="mdl-navigation__link" (click)="changeLanguage('gr')">
<span class="flag-icon flag-icon-gr"></span>
<label tabindex="0"> Greek</label>
</a>
<a class="mdl-navigation__link" (click)="changeLanguage('it')">
<span class="flag-icon flag-icon-it"></span>
<label tabindex="0"> Italian</label>
</a>
</nav>
<span class="mdl-layout-title">Components</span>
<nav class="mdl-navigation">
<a class="mdl-navigation__link" href="" routerLink="/" (click)="hideDrawer()">Home</a>
<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="/activiti" (click)="hideDrawer()">Activiti</a>
<a class="mdl-navigation__link" href="" routerLink="/webscript" (click)="hideDrawer()">Webscript</a>
<a class="mdl-navigation__link" href="" routerLink="/tag" (click)="hideDrawer()">Tag</a>
<a class="mdl-navigation__link" href="" routerLink="/about" (click)="hideDrawer()">About</a>
<a class="mdl-navigation__link" href="" routerLink="/settings" (click)="hideDrawer()">Settings</a>
</nav>
</div>
<main class="mdl-layout__content">
<div class="page-content">
+34 -20
View File
@@ -21,15 +21,16 @@ import { Router } from '@angular/router';
import {
AlfrescoTranslationService,
AlfrescoAuthenticationService,
AlfrescoSettingsService
AlfrescoSettingsService,
StorageService
} from 'ng2-alfresco-core';
declare var document: any;
@Component({
selector: 'alfresco-app',
templateUrl: 'app/app.component.html',
styleUrls: ['app/app.component.css']
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
searchTerm: string = '';
@@ -40,14 +41,20 @@ export class AppComponent {
constructor(public auth: AlfrescoAuthenticationService,
public router: Router,
public alfrescoSettingsService: AlfrescoSettingsService,
private translate: AlfrescoTranslationService) {
private translate: AlfrescoTranslationService,
private storage: StorageService) {
this.setEcmHost();
this.setBpmHost();
this.setProvider();
if (translate) {
translate.addTranslationFolder('custom', 'custom-translation/');
translate.addTranslationFolder('ng2-alfresco-login', 'custom-translation/alfresco-login');
if (process.env.ENV === 'production') {
translate.addTranslationFolder('custom', 'i18n/custom-translation');
translate.addTranslationFolder('ng2-alfresco-login', 'i18n/custom-translation/alfresco-login');
} else {
translate.addTranslationFolder('custom', 'custom-translation');
translate.addTranslationFolder('ng2-alfresco-login', 'custom-translation/alfresco-login');
}
}
}
@@ -63,7 +70,7 @@ export class AppComponent {
}
isLoginPage(): boolean {
return location.pathname === '/login' || location.pathname === '/' || location.pathname === '/settings';
return location.pathname === '/login' || location.pathname === '/settings';
}
onLogout(event) {
@@ -71,18 +78,24 @@ export class AppComponent {
this.auth.logout()
.subscribe(
() => {
this.router.navigate(['/login']);
this.navigateToLogin();
},
($event: any) => {
if ($event && $event.response && $event.response.status === 401) {
this.router.navigate(['/login']);
(error: any) => {
if (error && error.response && error.response.status === 401) {
this.navigateToLogin();
} else {
console.error('An unknown error occurred while logging out', $event);
console.error('An unknown error occurred while logging out', error);
this.navigateToLogin();
}
}
);
}
navigateToLogin(){
this.router.navigate(['/login']);
this.hideDrawer();
}
onToggleSearch(event) {
let expandedHeaderClass = 'header-search-expanded',
header = document.querySelector('header');
@@ -95,6 +108,7 @@ export class AppComponent {
changeLanguage(lang: string) {
this.translate.use(lang);
this.hideDrawer();
}
hideDrawer() {
@@ -103,26 +117,26 @@ export class AppComponent {
}
private setEcmHost() {
if (localStorage.getItem(`ecmHost`)) {
this.alfrescoSettingsService.ecmHost = localStorage.getItem(`ecmHost`);
this.ecmHost = localStorage.getItem(`ecmHost`);
if (this.storage.hasItem(`ecmHost`)) {
this.alfrescoSettingsService.ecmHost = this.storage.getItem(`ecmHost`);
this.ecmHost = this.storage.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`);
if (this.storage.hasItem(`bpmHost`)) {
this.alfrescoSettingsService.bpmHost = this.storage.getItem(`bpmHost`);
this.bpmHost = this.storage.getItem(`bpmHost`);
} else {
this.alfrescoSettingsService.bpmHost = this.bpmHost;
}
}
private setProvider() {
if (localStorage.getItem(`providers`)) {
this.alfrescoSettingsService.setProviders(localStorage.getItem(`providers`));
if (this.storage.hasItem(`providers`)) {
this.alfrescoSettingsService.setProviders(this.storage.getItem(`providers`));
}
}
}
+4 -1
View File
@@ -38,11 +38,13 @@ import { routing } from './app.routes';
import { CustomEditorsModule } from './components/activiti/custom-editor/custom-editor.component';
import {
HomeComponent,
DataTableDemoComponent,
SearchComponent,
SearchBarComponent,
LoginDemoComponent,
ActivitiDemoComponent,
ActivitiAppsView,
FormViewer,
WebscriptComponent,
TagComponent,
@@ -74,12 +76,13 @@ import {
],
declarations: [
AppComponent,
SearchBarComponent,
HomeComponent,
DataTableDemoComponent,
SearchComponent,
SearchBarComponent,
LoginDemoComponent,
ActivitiDemoComponent,
ActivitiAppsView,
FormViewer,
WebscriptComponent,
TagComponent,
+81 -12
View File
@@ -17,13 +17,16 @@
import { ModuleWithProviders } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { AuthGuard, AuthGuardEcm, AuthGuardBpm } from 'ng2-alfresco-core';
import {
HomeComponent,
FilesComponent,
DataTableDemoComponent,
SearchComponent,
LoginDemoComponent,
ActivitiDemoComponent,
ActivitiAppsView,
WebscriptComponent,
TagComponent,
AboutComponent,
@@ -35,19 +38,85 @@ import {
import { UploadButtonComponent } from 'ng2-alfresco-upload';
export const appRoutes: Routes = [
{ 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/appId/:appId', component: ActivitiDemoComponent },
{ path: 'activiti/tasks/:id', component: FormViewer },
{ path: 'activiti/tasksnode/:id', component: FormNodeViewer },
{ path: 'webscript', component: WebscriptComponent },
{ path: 'tag', component: TagComponent },
{
path: '',
component: HomeComponent,
canActivate: [AuthGuard]
},
{
path: 'home',
component: HomeComponent,
canActivate: [AuthGuard]
},
{
path: 'files',
component: FilesComponent,
canActivate: [AuthGuardEcm]
},
{
path: 'files/:id',
component: FilesComponent,
canActivate: [AuthGuardEcm]
},
{
path: 'datatable',
component: DataTableDemoComponent,
canActivate: [AuthGuard]
},
{
path: 'uploader',
component: UploadButtonComponent,
canActivate: [AuthGuardEcm]
},
{
path: 'search',
component: SearchComponent,
canActivate: [AuthGuardEcm]
},
{
path: 'activiti',
component: ActivitiAppsView,
canActivate: [AuthGuardBpm]
},
{
path: 'activiti/apps',
component: ActivitiAppsView,
canActivate: [AuthGuardBpm]
},
{
path: 'activiti/apps/:appId/tasks',
component: ActivitiDemoComponent,
canActivate: [AuthGuardBpm]
},
// TODO: check if neeeded
{
path: 'activiti/appId/:appId',
component: ActivitiDemoComponent,
canActivate: [AuthGuardBpm]
},
// TODO: check if needed
{
path: 'activiti/tasks/:id',
component: FormViewer,
canActivate: [AuthGuardBpm]
},
// TODO: check if needed
{
path: 'activiti/tasksnode/:id',
component: FormNodeViewer,
canActivate: [AuthGuardBpm]
},
{
path: 'webscript',
component: WebscriptComponent,
canActivate: [AuthGuardEcm]
},
{
path: 'tag',
component: TagComponent,
canActivate: [AuthGuardEcm]
},
{ path: 'about', component: AboutComponent },
{ path: 'settings', component: SettingComponent }
];
@@ -19,10 +19,7 @@ import { Component, OnInit } from '@angular/core';
import { Http } from '@angular/http';
import { ObjectDataTableAdapter } from 'ng2-alfresco-datatable';
declare let __moduleName: string;
@Component({
moduleId: __moduleName,
selector: 'about-page',
templateUrl: './about.component.html'
})
@@ -30,17 +27,29 @@ export class AboutComponent implements OnInit {
data: ObjectDataTableAdapter;
constructor(private http: Http) {}
constructor(private http: Http) {
}
ngOnInit() {
// this.data = new ObjectDataTableAdapter();
this.http.get('/versions').subscribe(response => {
let data = response.json() || {};
let packages = data.packages || [];
this.http.get('/versions.json').subscribe(response => {
var regexp = new RegExp("^(ng2-activiti|ng2-alfresco|alfresco-)", 'g');
this.data = new ObjectDataTableAdapter(packages, [
{ type: 'text', key: 'name', title: 'Name', sortable: true },
{ type: 'text', key: 'version', title: 'Version', sortable: true }
var alfrescoPackages = Object.keys(response.json().dependencies).filter(function (val) {
console.log(val);
return regexp.test(val);
});
let alfrescoPackagesTableRappresentation = [];
alfrescoPackages.forEach((val)=> {
console.log(response.json().dependencies[val]);
alfrescoPackagesTableRappresentation.push({name:val,version:response.json().dependencies[val].version});
});
console.log(alfrescoPackagesTableRappresentation);
this.data = new ObjectDataTableAdapter(alfrescoPackagesTableRappresentation, [
{type: 'text', key: 'name', title: 'Name', sortable: true},
{type: 'text', key: 'version', title: 'Version', sortable: true}
]);
});
@@ -10,9 +10,13 @@
.task-column {
background-color: #f5f5f5;
padding: 10px 10px 10px 10px;
border: solid 2px rgb(31,188,210);
border-right: solid 2px rgb(144, 143, 143);
}
.list-column {
width: 320px;
}
.mdl-layout__header {
z-index: 1;
}
}
@@ -4,38 +4,31 @@
<!-- TABS -->
<div class="mdl-layout__tab-bar mdl-js-ripple-effect" #tabheader>
<a id="apps-header" href="#apps" class="mdl-layout__tab is-active">APPS</a>
<a id="tasks-header" href="#tasks" class="mdl-layout__tab">TASK LIST</a>
<a id="processes-header" href="#processes" class="mdl-layout__tab">PROCESS LIST</a>
<a id="report-header" href="#report" class="mdl-layout__tab">ANALYTICS</a>
<div class="mdl-layout__tab-bar mdl-js-ripple-effect">
<a id="tasks-header" href="#tasks" class="mdl-layout__tab is-active">TASKS</a>
<a id="processes-header" href="#processes" class="mdl-layout__tab" (click)="activeProcess()">PROCESSES</a>
<a id="report-header" href="#report" class="mdl-layout__tab" (click)="activeReports()">REPORTS</a>
</div>
</header>
<main class="mdl-layout__content activiti" #tabmain>
<!-- APPPS COMPONENT -->
<section class="mdl-layout__tab-panel is-active" id="apps">
<div class="page-content">
<activiti-apps [layoutType]="layoutType" (appClick)="onAppClick($event)" #activitiapps></activiti-apps>
</div>
</section>
<main class="mdl-layout__content activiti">
<!-- TASKS COMPONENT -->
<section class="mdl-layout__tab-panel" id="tasks">
<section class="mdl-layout__tab-panel is-active" id="tasks">
<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>
<span><h5>Task Filters</h5></span>
<hr>
<activiti-start-task [appId]="appId" (onSuccess)="onStartTaskSuccess($event)"></activiti-start-task>
<activiti-filters [appId]="appId" (filterClick)="onTaskFilterClick($event)" (onSuccess)="onSuccessTaskFilterList($event)"
<activiti-filters [appId]="appId" (filterClick)="onTaskFilterClick($event)"
(onSuccess)="onSuccessTaskFilterList($event)"
#activitifilter></activiti-filters>
</div>
<div class="mdl-cell mdl-cell--3-col task-column mdl-shadow--2dp">
<span>Task List</span>
<div class="mdl-cell mdl-cell--3-col task-column mdl-shadow--2dp list-column">
<span><h5>Task List</h5></span>
<hr>
<activiti-tasklist *ngIf="taskFilter?.hasFilter()" [appId]="taskFilter.appId"
[processDefinitionKey]="taskFilter.filter.processDefinitionKey"
[name]="taskFilter.filter.name"
@@ -47,7 +40,8 @@
#activititasklist></activiti-tasklist>
</div>
<div class="mdl-cell mdl-cell--7-col task-column mdl-shadow--2dp">
<span>Task Details</span>
<span><h5>Task Details</h5></span>
<hr>
<activiti-task-details [taskId]="currentTaskId" (formCompleted)="onFormCompleted($event)"
#activitidetails></activiti-task-details>
</div>
@@ -59,33 +53,41 @@
<!-- PROCESS COMPONENT -->
<section class="mdl-layout__tab-panel" id="processes">
<div class="page-content">
<div class="page-content" *ngIf="processTabActivie">
<div class="page-content">
<div class="mdl-grid">
<div class="mdl-cell mdl-cell--2-col task-column">
<span>Process Filters</span>
<button type="button" (click)="navigateStartProcess()" class="mdl-button" data-automation-id="btn-start-process">Start Process</button>
<div class="mdl-cell mdl-cell--2-col task-column mdl-shadow--2dp">
<span><h5>Process Filters</h5></span>
<hr>
<button type="button" (click)="navigateStartProcess()" class="mdl-button"
data-automation-id="btn-start-process">Start Process
</button>
<activiti-process-instance-filters [appId]="appId"
(filterClick)="onProcessFilterClick($event)" (onSuccess)="onSuccessProcessFilterList($event)"
#activitiprocessfilter></activiti-process-instance-filters>
(filterClick)="onProcessFilterClick($event)"
(onSuccess)="onSuccessProcessFilterList($event)"></activiti-process-instance-filters>
</div>
<div class="mdl-cell mdl-cell--3-col task-column">
<span>Process List</span>
<div class="mdl-cell mdl-cell--3-col task-column list-column mdl-shadow--2dp">
<span><h5>Process List</h5></span>
<hr>
<activiti-process-instance-list *ngIf="processFilter?.hasFilter()" [appId]="processFilter.appId"
[processDefinitionKey]="processFilter.filter.processDefinitionKey"
[name]="processFilter.filter.name"
[state]="processFilter.filter.state"
[sort]="processFilter.filter.sort"
[data]="dataProcesses"
(rowClick)="onProcessRowClick($event)" (onSuccess)="onSuccessProcessList($event)"
#activitiprocesslist></activiti-process-instance-list>
[processDefinitionKey]="processFilter.filter.processDefinitionKey"
[name]="processFilter.filter.name"
[state]="processFilter.filter.state"
[sort]="processFilter.filter.sort"
[data]="dataProcesses"
(rowClick)="onProcessRowClick($event)"
(onSuccess)="onSuccessProcessList($event)"></activiti-process-instance-list>
</div>
<div class="mdl-cell mdl-cell--7-col task-column" *ngIf="!isStartProcessMode()">
<span>Process Details</span>
<activiti-process-instance-details [processInstanceId]="currentProcessInstanceId" (activitiprocesslist)="taskFormCompleted()" (processCancelled)="processCancelled()" #activitiprocessdetails></activiti-process-instance-details>
<div class="mdl-cell mdl-cell--7-col task-column mdl-shadow--2dp" *ngIf="!isStartProcessMode()">
<span><h5>Process Details</h5></span>
<hr>
<activiti-process-instance-details [processInstanceId]="currentProcessInstanceId"
(activitiprocesslist)="taskFormCompleted()"
(processCancelled)="processCancelled()"></activiti-process-instance-details>
</div>
<div class="mdl-cell mdl-cell--7-col task-column" *ngIf="isStartProcessMode()">
<span>Start Process</span>
<hr>
<activiti-start-process [appId]="appId" (start)="onStartProcessInstance($event)"></activiti-start-process>
</div>
</div>
@@ -97,13 +99,22 @@
<!-- ANALYTICS COMPONENT -->
<section class="mdl-layout__tab-panel" id="report">
<div class="page-content">
<div class="page-content" *ngIf="reportsTabActivie">
<div class="mdl-grid">
<div class="mdl-cell mdl-cell--4-col task-column mdl-shadow--2dp">
<analytics-report-list (reportClick)="onReportClick($event)"></analytics-report-list>
<span><h5>Report List</h5></span>
<hr>
<analytics-report-list
(reportClick)="onReportClick($event)"
#analyticsreportlist>
</analytics-report-list>
</div>
<div class="mdl-cell mdl-cell--8-col task-column mdl-shadow--2dp">
<activiti-analytics [appId]="appId" *ngIf="report" [reportId]="report.id"></activiti-analytics>
<activiti-analytics *ngIf="report"
[appId]="appId"
[reportId]="report.id"
(editReport)="onEditReport($event)">
</activiti-analytics>
</div>
</div>
</div>
@@ -15,70 +15,69 @@
* limitations under the License.
*/
import { Component, AfterViewChecked, ViewChild, Input } from '@angular/core';
import { AfterViewInit, Component, ElementRef, Input, ViewChild } from '@angular/core';
import {
AppDefinitionRepresentationModel,
FilterRepresentationModel,
ActivitiApps,
ActivitiTaskList
ActivitiFilters,
ActivitiTaskDetails,
ActivitiTaskList,
FilterRepresentationModel
} from 'ng2-activiti-tasklist';
import {
ActivitiProcessFilters,
ActivitiProcessInstanceDetails,
ActivitiProcessInstanceListComponent,
ActivitiStartProcessInstance,
ProcessInstance
} from 'ng2-activiti-processlist';
import { AnalyticsReportListComponent } from 'ng2-activiti-analytics';
import { ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs/Rx';
import {
ObjectDataTableAdapter,
DataSorting
} from 'ng2-alfresco-datatable';
import { AlfrescoApiService } from 'ng2-alfresco-core';
import { FormRenderingService } from 'ng2-activiti-form';
import { /*CustomEditorComponent*/ CustomStencil01 } from './custom-editor/custom-editor.component';
declare let __moduleName: string;
declare var componentHandler;
const currentProcessIdNew = '__NEW__';
@Component({
moduleId: __moduleName,
selector: 'activiti-demo',
templateUrl: './activiti-demo.component.html',
styleUrls: ['./activiti-demo.component.css']
})
export class ActivitiDemoComponent implements AfterViewChecked {
export class ActivitiDemoComponent implements AfterViewInit {
@ViewChild('activitiapps')
@ViewChild(ActivitiApps)
activitiapps: ActivitiApps;
@ViewChild('activitifilter')
activitifilter: any;
@ViewChild('activitidetails')
activitidetails: any;
@ViewChild(ActivitiFilters)
activitifilter: ActivitiFilters;
@ViewChild(ActivitiTaskList)
activititasklist: ActivitiTaskList;
@ViewChild('activitiprocessfilter')
activitiprocessfilter: any;
@ViewChild(ActivitiTaskDetails)
activitidetails: ActivitiTaskDetails;
@ViewChild(ActivitiProcessFilters)
activitiprocessfilter: ActivitiProcessFilters;
@ViewChild(ActivitiProcessInstanceListComponent)
activitiprocesslist: ActivitiProcessInstanceListComponent;
@ViewChild('activitiprocessdetails')
activitiprocessdetails: any;
@ViewChild(ActivitiProcessInstanceDetails)
activitiprocessdetails: ActivitiProcessInstanceDetails;
@ViewChild(ActivitiStartProcessInstance)
activitiStartProcess: ActivitiStartProcessInstance;
@ViewChild('tabmain')
tabMain: any;
@ViewChild('tabheader')
tabHeader: any;
@ViewChild(AnalyticsReportListComponent)
analyticsreportlist: AnalyticsReportListComponent;
@Input()
appId: number;
@@ -90,6 +89,10 @@ export class ActivitiDemoComponent implements AfterViewChecked {
taskSchemaColumns: any [] = [];
processSchemaColumns: any [] = [];
processTabActivie: boolean = false;
reportsTabActivie: boolean = false;
taskFilter: FilterRepresentationModel;
report: any;
processFilter: FilterRepresentationModel;
@@ -99,7 +102,10 @@ export class ActivitiDemoComponent implements AfterViewChecked {
dataTasks: ObjectDataTableAdapter;
dataProcesses: ObjectDataTableAdapter;
constructor(private route: ActivatedRoute, private formRenderingService: FormRenderingService) {
constructor(private elementRef: ElementRef,
private route: ActivatedRoute,
private apiService: AlfrescoApiService,
private formRenderingService: FormRenderingService) {
this.dataTasks = new ObjectDataTableAdapter(
[],
[
@@ -112,8 +118,8 @@ export class ActivitiDemoComponent implements AfterViewChecked {
this.dataProcesses = new ObjectDataTableAdapter(
[],
[
{type: 'text', key: 'name', title: 'Name', cssClass: 'full-width name-column'},
{type: 'text', key: 'started', title: 'Started', cssClass: 'hidden'}
{type: 'text', key: 'name', title: 'Name', cssClass: 'full-width name-column', sortable: true},
{type: 'text', key: 'started', title: 'Started', cssClass: 'hidden', sortable: true}
]
);
@@ -126,7 +132,15 @@ export class ActivitiDemoComponent implements AfterViewChecked {
ngOnInit() {
this.sub = this.route.params.subscribe(params => {
this.appId = params['appId'];
let applicationId = params['appId'];
if (applicationId && applicationId !== '0') {
this.appId = params['appId'];
}
this.taskFilter = null;
this.currentTaskId = null;
this.processFilter = null;
this.currentProcessInstanceId = null;
});
this.layoutType = ActivitiApps.LAYOUT_GRID;
}
@@ -135,25 +149,6 @@ export class ActivitiDemoComponent implements AfterViewChecked {
this.sub.unsubscribe();
}
onAppClick(app: AppDefinitionRepresentationModel) {
this.appId = app.id;
this.taskFilter = null;
this.currentTaskId = null;
this.processFilter = null;
this.currentProcessInstanceId = null;
this.changeTab('apps', 'tasks');
}
changeTab(origin: string, destination: string) {
this.tabMain.nativeElement.children[origin].classList.remove('is-active');
this.tabMain.nativeElement.children[destination].classList.add('is-active');
this.tabHeader.nativeElement.children[`${origin}-header`].classList.remove('is-active');
this.tabHeader.nativeElement.children[`${destination}-header`].classList.add('is-active');
}
onTaskFilterClick(event: FilterRepresentationModel) {
this.taskFilter = event;
}
@@ -167,6 +162,8 @@ export class ActivitiDemoComponent implements AfterViewChecked {
}
onStartTaskSuccess(event: any) {
this.activitifilter.selectFirstFilter();
this.taskFilter = this.activitifilter.getCurrentFilter();
this.activititasklist.reload();
}
@@ -194,6 +191,10 @@ export class ActivitiDemoComponent implements AfterViewChecked {
this.currentProcessInstanceId = processInstanceId;
}
onEditReport(name: string) {
this.analyticsreportlist.reload();
}
navigateStartProcess() {
this.currentProcessInstanceId = currentProcessIdNew;
}
@@ -201,6 +202,7 @@ export class ActivitiDemoComponent implements AfterViewChecked {
onStartProcessInstance(instance: ProcessInstance) {
this.currentProcessInstanceId = instance.id;
this.activitiStartProcess.reset();
this.activitiprocesslist.reload();
}
isStartProcessMode() {
@@ -225,11 +227,32 @@ export class ActivitiDemoComponent implements AfterViewChecked {
this.currentTaskId = null;
}
ngAfterViewChecked() {
ngAfterViewInit() {
// workaround for MDL issues with dynamic components
if (componentHandler) {
componentHandler.upgradeAllRegistered();
}
this.loadStencilScriptsInPageFromActiviti();
}
activeProcess() {
this.processTabActivie = true;
}
activeReports() {
this.reportsTabActivie = true;
}
loadStencilScriptsInPageFromActiviti() {
this.apiService.getInstance().activiti.scriptFileApi.getControllers().then(response => {
if (response) {
let s = document.createElement('script');
s.type = 'text/javascript';
s.text = response;
this.elementRef.nativeElement.appendChild(s);
}
});
}
}
@@ -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.
*/
import { Component } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { AppDefinitionRepresentationModel } from 'ng2-activiti-tasklist';
@Component({
selector: 'activiti-apps-view',
template: `
<activiti-apps (appClick)="onAppClicked($event)"></activiti-apps>
`
})
export class ActivitiAppsView {
constructor(private router: Router, private route: ActivatedRoute) {
}
onAppClicked(app: AppDefinitionRepresentationModel) {
this.router.navigate(['/activiti/apps', app.id || 0, 'tasks']);
}
}
@@ -1,3 +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.
*/
import { NgModule, Component } from '@angular/core';
import { WidgetComponent } from 'ng2-activiti-form';
@@ -19,11 +19,9 @@ import { Component, OnInit, OnDestroy, AfterViewChecked } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
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']
@@ -19,11 +19,9 @@ import { Component, OnInit, OnDestroy, AfterViewChecked } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
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']
@@ -23,10 +23,7 @@ import {
ObjectDataColumn
} from 'ng2-alfresco-datatable';
declare let __moduleName: string;
@Component({
moduleId: __moduleName,
selector: 'datatable-demo',
templateUrl: './datatable-demo.component.html'
})
@@ -7,3 +7,11 @@
margin: 0;
}
}
.error-message {
text-align: left;
}
.error-message--text {
color: #d50000;
}
@@ -1,191 +1,211 @@
<div *ngIf="!fileShowed">
<div class="container">
<alfresco-upload-drag-area
<div class="container">
<alfresco-upload-drag-area
[rootFolderId]="uploadRootFolderId"
[currentFolderPath]="uploadFolderPath"
[versioning] = "versioning"
(onSuccess)="documentList.reload()">
<alfresco-document-list-breadcrumb
[currentFolderPath]="currentPath"
(pathChanged)="onBreadcrumbPathChanged($event)" *ngIf="!currentFolderId">
</alfresco-document-list-breadcrumb>
<div *ngIf="errorMessage" class="error-message">
<button (click)="resetError()" class="mdl-button mdl-js-button mdl-button--icon">
<i class="material-icons">highlight_off</i>
</button>
<span class="error-message--text">{{errorMessage}}</span>
</div>
<alfresco-document-list
#documentList
[rootFolderId]="rootFolderId"
[currentFolderPath]="currentPath"
[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)">
[currentFolderId]="currentFolderId"
[contextMenuActions]="true"
[contentActions]="true"
(error)="onNavigationError($event)"
(success)="resetError()"
(preview)="showFile($event)"
(folderChange)="onFolderChanged($event)">
<!--
<empty-folder-content>
<template>
<h1>Sorry, no content here</h1>
</template>
</empty-folder-content>
-->
<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>
<!--
<empty-folder-content>
<template>
<h1>Sorry, no content here</h1>
</template>
</empty-folder-content>
<content-column
title="Type"
source="content.mimeType">
</content-column>
-->
<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-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"
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>
<div class="p-10">
<ul>
<li>Current path: {{documentList.currentFolderPath}}</li>
<li>
<button (click)="documentList.currentFolderPath = '/Sites/swsdp/documentLibrary';">Go to Document Library</button>
</li>
<li>
<button (click)="documentList.currentFolderPath = '/Sites/swsdp/documentLibrary/Agency Files/Contracts'">Go to agency contracts</button>
</li>
<li>
<button (click)="documentList.currentFolderPath = '/'">Go to root</button>
</li>
<li>
<button (click)="fileDialog.toggleShowDialog()">Show/Hide File Dialog</button>
</li>
</ul>
</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>
<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>
<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">
<label class="mdl-input__label">Extension accepted
<input type="text" data-automation-id="accepted-files-type" [(ngModel)]="acceptedFilesType">
</label>
<br/>
</div>
<div *ngIf="!acceptedFilesTypeShow">
<alfresco-upload-button data-automation-id="multiple-file-upload"
[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"
[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>
<file-uploading-dialog #fileDialog></file-uploading-dialog>
<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>
<div class="p-10">
<ul>
<li>Current path: {{currentPath}}</li>
<li>
<button (click)="currentPath = '/'">Go to root</button>
</li>
<li>
<button (click)="currentPath = '/Sites'">Go to Sites</button>
</li>
<li>
<button (click)="currentPath = '/Sites/swsdp';">Go to Web Site Design Project site</button>
</li>
<li>
<button (click)="currentPath = '/Sites/swsdp/documentLibrary';">Go to Document Library</button>
</li>
<li>
<button (click)="currentPath = '/Sites/swsdp/documentLibrary/Agency Files/Contracts'">Go to Agency Contracts</button>
</li>
<li>
<button (click)="currentPath = '!@£$%^&*()'">Go to the wrong path</button>
</li>
<li>
<button (click)="fileDialog.toggleShowDialog()">Show/Hide File Dialog</button>
</li>
</ul>
</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>
<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>
<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">
<label class="mdl-input__label">Extension accepted
<input type="text" data-automation-id="accepted-files-type" [(ngModel)]="acceptedFilesType">
</label>
<br/>
</div>
<div *ngIf="!acceptedFilesTypeShow">
<alfresco-upload-button data-automation-id="multiple-file-upload"
[rootFolderId]="uploadRootFolderId"
[currentFolderPath]="uploadFolderPath"
[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"
[rootFolderId]="uploadRootFolderId"
[currentFolderPath]="uploadFolderPath"
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>
<file-uploading-dialog #fileDialog></file-uploading-dialog>
<div *ngIf="fileShowed">
<alfresco-viewer [(showViewer)]="fileShowed"
[fileNodeId]="fileNodeId"
@@ -15,8 +15,8 @@
* limitations under the License.
*/
import { Component, OnInit, ViewChild } from '@angular/core';
import { Router } from '@angular/router';
import { Component, OnInit, Optional, ViewChild } from '@angular/core';
import { ActivatedRoute, Params, Router } from '@angular/router';
import { AlfrescoAuthenticationService } from 'ng2-alfresco-core';
import {
DocumentActionsService,
@@ -27,17 +27,17 @@ import {
} from 'ng2-alfresco-documentlist';
import { FormService } from 'ng2-activiti-form';
declare let __moduleName: string;
@Component({
moduleId: __moduleName,
selector: 'files-component',
templateUrl: './files.component.html',
styleUrls: ['./files.component.css']
})
export class FilesComponent implements OnInit {
currentPath: string = '/Sites/swsdp/documentLibrary';
rootFolderId: string = '-root-';
currentFolderId: string = null;
errorMessage: string = null;
fileNodeId: any;
fileShowed: boolean = false;
multipleFileUpload: boolean = false;
@@ -47,13 +47,22 @@ export class FilesComponent implements OnInit {
acceptedFilesType: string = '.jpg,.pdf,.js';
get uploadRootFolderId(): string {
return this.currentFolderId || this.rootFolderId;
}
get uploadFolderPath(): string {
return this.currentFolderId ? '/' : this.currentPath;
}
@ViewChild(DocumentList)
documentList: DocumentList;
constructor(private documentActions: DocumentActionsService,
public auth: AlfrescoAuthenticationService,
private formService: FormService,
private router: Router) {
private router: Router,
@Optional() private route: ActivatedRoute) {
documentActions.setHandler('my-handler', this.myDocumentActionHandler.bind(this));
}
@@ -84,6 +93,12 @@ export class FilesComponent implements OnInit {
}
}
onBreadcrumbPathChanged(event?: any) {
if (event) {
this.currentPath = event.value;
}
}
toggleMultipleFileUpload() {
this.multipleFileUpload = !this.multipleFileUpload;
return this.multipleFileUpload;
@@ -106,20 +121,35 @@ export class FilesComponent implements OnInit {
}
ngOnInit() {
if ( this.auth.isBpmLoggedIn() ) {
this.formService.getProcessDefinitions().subscribe(
defs => this.setupBpmActions(defs || []),
err => console.log(err)
);
} else {
console.log('You are not logged in');
}
if (this.route) {
this.route.params.forEach((params: Params) => {
this.currentFolderId = params.hasOwnProperty('id') ? params['id'] : null;
});
}
if (this.auth.isBpmLoggedIn()) {
this.formService.getProcessDefinitions().subscribe(
defs => this.setupBpmActions(defs || []),
err => console.log(err)
);
} else {
console.log('You are not logged in');
}
}
viewActivitiForm(event?: any) {
this.router.navigate(['/activiti/tasksnode', event.value.entry.id]);
}
onNavigationError(err: any) {
if (err) {
this.errorMessage = err.message || 'Navigation error';
}
}
resetError() {
this.errorMessage = null;
}
private setupBpmActions(actions: any[]) {
actions.map(def => {
let documentAction = new DocumentActionModel();
@@ -0,0 +1,48 @@
.home-cards {
float: left;
margin: 10px 10px 10px 10px;
}
.mdl-card__supporting-text {
display: block;
overflow-y: auto;
height: 400px;
}
.demo-card-square.mdl-card {
width: 320px;
height: 380px;
}
.demo-card-square > .mdl-card__title {
color: #fff;
background-color: rgb(158, 158, 158);
}
.mdl-card__title {
cursor: pointer;
height: 70px;
}
.home--card__icon {
padding-top: 2px;
margin-right: 4px;
}
.home--feature-list {
list-style: none;
padding-left: 0;
}
.home--feature-list__icon {
float: left;
}
.home--feature-list__text {
padding-top: 2px;
}
span.home--feature-list__text:before {
content: '';
padding-left: 4px;
}
@@ -0,0 +1,187 @@
<!-- DOCUMENT LIST-->
<div class="demo-card-square mdl-card mdl-shadow--2dp home-cards">
<div class="mdl-card__title mdl-card--expand" routerLink="/files">
<h2 class="mdl-card__title-text">
<i class="material-icons home--card__icon">dvr</i>
<span>DocumentList - ECM</span>
</h2>
</div>
<div class="mdl-card__supporting-text">
Demonstrates multiple Alfresco ECM components used together to show the files of you ECM instance :
<ul class="home--feature-list">
<li>
<i class="material-icons home--feature-list__icon">brightness_1</i>
<span class="home--feature-list__text">Comunication with the Rest Api and core services</span>
<a href="https://www.npmjs.com/package/ng2-alfresco-core" target="_blank">ng2-alfresco-core</a>
</li>
<li>
<i class="material-icons home--feature-list__icon">dvr</i>
<span class="home--feature-list__text">Document List</span>
<a href="https://www.npmjs.com/package/ng2-alfresco-documentlist" target="_blank">ng2-alfresco-documentlist</a>
</li>
<li>
<i class="material-icons home--feature-list__icon">file_upload</i>
<span class="home--feature-list__text">Upload</span>
<a href="https://www.npmjs.com/package/ng2-alfresco-upload" target="_blank">ng2-alfresco-upload</a>
</li>
<li>
<i class="material-icons home--feature-list__icon">view_module</i>
<span class="home--feature-list__text">DataTable</span>
<a href="https://www.npmjs.com/package/ng2-alfresco-datatable" target="_blank">ng2-alfresco-datatable</a>
</li>
</ul>
</div>
</div>
<!-- ACTIVITI-->
<div class="demo-card-square mdl-card mdl-shadow--2dp home-cards">
<div class="mdl-card__title mdl-card--expand" routerLink="/activiti">
<h2 class="mdl-card__title-text">
<i class="material-icons home--card__icon">apps</i>
<span>Activiti - BPM</span>
</h2>
</div>
<div class="mdl-card__supporting-text">
Demonstrates multiple Alfresco BPM components used together to show your BPM prorcess and tasks:
<ul class="home--feature-list">
<li>
<i class="material-icons home--feature-list__icon">brightness_1</i>
<span class="home--feature-list__text">Comunication with the Rest Api and core services</span>
<a href="https://www.npmjs.com/package/ng2-alfresco-core" target="_blank">ng2-alfresco-core</a>
</li>
<li>
<i class="material-icons home--feature-list__icon">view_module</i>
<span class="home--feature-list__text">App List</span>
<a href="https://www.npmjs.com/package/ng2-activiti-tasklist" target="_blank">ng2-activiti-apps</a>
</li>
<li>
<i class="material-icons home--feature-list__icon">view_headline</i>
<span class="home--feature-list__text">Task List</span>
<a href="https://www.npmjs.com/package/ng2-activiti-tasklist" target="_blank">ng2-activiti-tasklist</a>
</li>
<li>
<i class="material-icons home--feature-list__icon">view_headline</i>
<span class="home--feature-list__text">Process List</span>
<a href="https://www.npmjs.com/package/ng2-activiti-processlist" target="_blank">ng2-activiti-processlist</a>
</li>
<li>
<i class="material-icons home--feature-list__icon">view_quilt</i>
<span class="home--feature-list__text">Form</span>
<a href="https://www.npmjs.com/package/ng2-activiti-form" target="_blank">ng2-activiti-form</a>
</li>
<li>
<i class="material-icons home--feature-list__icon">pie_chart</i>
<span class="home--feature-list__text">Analytics</span>
<a href="https://www.npmjs.com/package/ng2-activiti-analytics" target="_blank">ng2-activiti-analytics</a>,
<a href="https://www.npmjs.com/package/ng2-activiti-diagrams" target="_blank">ng2-activiti-diagrams</a>
</li>
<li>
<i class="material-icons home--feature-list__icon">view_module</i>
<span class="home--feature-list__text">DataTable</span>
<a href="https://www.npmjs.com/package/ng2-alfresco-datatable" target="_blank">ng2-alfresco-datatable</a>
</li>
</ul>
</div>
</div>
<!-- DATATABLE-->
<div class="demo-card-square mdl-card mdl-shadow--2dp home-cards">
<div class="mdl-card__title mdl-card--expand" routerLink="/datatable">
<h2 class="mdl-card__title-text">
<i class="material-icons home--card__icon">view_module</i>
<span>DataTable-ECM&BPM</span>
</h2>
</div>
<div class="mdl-card__supporting-text">
Basic table component:
<ul class="home--feature-list">
<li>
<i class="material-icons home--feature-list__icon">brightness_1</i>
<span class="home--feature-list__text">Comunication with the Rest Api and core services</span>
<a href="https://www.npmjs.com/package/ng2-alfresco-core" target="_blank">ng2-alfresco-core</a>
</li>
</ul>
</div>
</div>
<!-- UPLOADER-->
<div class="demo-card-square mdl-card mdl-shadow--2dp home-cards">
<div class="mdl-card__title mdl-card--expand" routerLink="/uploader">
<h2 class="mdl-card__title-text">
<i class="material-icons home--card__icon">file_upload</i>
<span>Uploader - ECM</span>
</h2>
</div>
<div class="mdl-card__supporting-text">
Basic table uploader component for the ECM and BPM:
<ul class="home--feature-list">
<li>
<i class="material-icons home--feature-list__icon">brightness_1</i>
<span class="home--feature-list__text">Comunication with the Rest Api and core services</span>
<a href="https://www.npmjs.com/package/ng2-alfresco-core" target="_blank">ng2-alfresco-core</a>
</li>
</ul>
</div>
</div>
<!-- LOGIN-->
<div class="demo-card-square mdl-card mdl-shadow--2dp home-cards">
<div class="mdl-card__title mdl-card--expand" routerLink="/login">
<h2 class="mdl-card__title-text">
<i class="material-icons home--card__icon">account_circle</i>
<span>Login - ECM & BPM</span>
</h2>
</div>
<div class="mdl-card__supporting-text">
Login component for the ECM and BPM:
<ul class="home--feature-list">
<li>
<i class="material-icons home--feature-list__icon">brightness_1</i>
<span class="home--feature-list__text">Comunication with the Rest Api and core services</span>
<a href="https://www.npmjs.com/package/ng2-alfresco-core" target="_blank">ng2-alfresco-core</a>
</li>
</ul>
</div>
</div>
<!-- WEBSCRIPT-->
<div class="demo-card-square mdl-card mdl-shadow--2dp home-cards">
<div class="mdl-card__title mdl-card--expand" routerLink="/webscript">
<h2 class="mdl-card__title-text">
<i class="material-icons home--card__icon">extension</i>
<span>Webscript - ECM</span>
</h2>
</div>
<div class="mdl-card__supporting-text">
Shows and create webscripts in your ECM instance:
<ul class="home--feature-list">
<li>
<i class="material-icons home--feature-list__icon">brightness_1</i>
<span class="home--feature-list__text">Comunication with the Rest Api and core services</span>
<a href="https://www.npmjs.com/package/ng2-alfresco-core" target="_blank">ng2-alfresco-core</a>
</li>
</ul>
</div>
</div>
<!-- TAG-->
<div class="demo-card-square mdl-card mdl-shadow--2dp home-cards">
<div class="mdl-card__title mdl-card--expand" routerLink="/tag">
<h2 class="mdl-card__title-text">
<i class="material-icons home--card__icon">local_offer</i>
<span>Tag - ECM</span>
</h2>
</div>
<div class="mdl-card__supporting-text">
Shows and add tags to the node of your ECM instance:
<ul class="home--feature-list">
<li>
<i class="material-icons home--feature-list__icon">brightness_1</i>
<span class="home--feature-list__text">Comunication with Rest</span>
<a href="https://www.npmjs.com/package/ng2-alfresco-core" target="_blank">ng2-alfresco-core</a>
</li>
</ul>
</div>
</div>
@@ -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 { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { HomeComponent } from './home.component';
import { CoreModule } from 'ng2-alfresco-core';
describe('HomeComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [CoreModule],
declarations: [HomeComponent],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
});
});
it ('should work', () => {
let fixture = TestBed.createComponent(HomeComponent);
expect(fixture.componentInstance instanceof HomeComponent).toBe(true, 'should create HomeComponent');
});
});
@@ -15,9 +15,11 @@
* limitations under the License.
*/
declare let moment: any;
declare let mdDateTimePicker: any;
import { Component } from '@angular/core';
// MDL
declare let componentHandler: any;
declare let dialogPolyfill: any;
@Component({
selector: 'home-view',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent {}
+2
View File
@@ -15,6 +15,7 @@
* limitations under the License.
*/
export { HomeComponent } from './home/home.component';
export { DataTableDemoComponent } from './datatable/datatable-demo.component';
export { SearchComponent } from './search/search.component';
export { SearchBarComponent } from './search/search-bar.component';
@@ -27,3 +28,4 @@ export { AboutComponent } from './about/about.component';
export { FilesComponent } from './files/files.component';
export { FormNodeViewer } from './activiti/form-node-viewer.component';
export { SettingComponent } from './setting/setting.component';
export { ActivitiAppsView } from './activiti/apps.view';
@@ -1,14 +1,39 @@
.setting {
border-radius: 8px; position: absolute; background-color: papayawhip; color: cadetblue; left: 10px; top: 10px; z-index: 1;
.setting-button {
position: absolute;
right: 10px;
top: 10px;
z-index: 1;
}
.banned{
width:130px;margin: 10px;
.settings {
border-radius: 8px;
position: absolute;
background-color: papayawhip;
color: cadetblue;
left: 10px;
top: 10px;
z-index: 1;
}
.banned {
width: 130px;
margin: 10px;
}
.toggle {
width:120px;margin: 20px;
width: 120px;
margin: 20px;
}
.setting-button {
position: absolute; right: 10px; top: 10px; z-index: 1;
@media (min-width: 721px) {
.mobile-settings {
display: none;
}
}
@media (max-width: 720px) {
.settings {
display: none;
}
}
@@ -1,21 +1,23 @@
<div class="setting">
<!--BPM, ECN AND CSRF TOGGLE-->
<div class="settings">
<p class="toggle">
<label for="switch1" class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
<input type="checkbox" id="switch1" [checked]="isECM" class="mdl-switch__input"
(click)="toggleECM(ecm.checked)" #ecm>
(click)="toggleECM()">
<span class="mdl-switch__label">ECM</span>
</label>
</p>
<p class="toggle">
<label for="switch2" class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
<input type="checkbox" id="switch2" [checked]="isBPM" class="mdl-switch__input"
(click)="toggleBPM(bpm.checked)" #bpm>
(click)="toggleBPM()">
<span class="mdl-switch__label">BPM</span>
</label>
</p>
<p class="toggle">
<label for="switch3" class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
<input type="checkbox" id="switch3" class="mdl-switch__input" checked (click)="toggleCSRF()" #csrf>
<input type="checkbox" id="switch3" class="mdl-switch__input" [checked]="!disableCsrf" (click)="toggleCSRF()">
<span class="mdl-switch__label">CSRF</span>
</label>
</p>
@@ -25,12 +27,47 @@
</p>
</div>
<!--SETTING BUTTON-->
<a class="mdl-navigation__link setting-button" data-automation-id="settings" href="" routerLink="/settings">
<button class="mdl-button mdl-js-button mdl-button--fab mdl-button--colored">
<i class="material-icons">settings</i>
</button>
</a>
<alfresco-login [providers]="providers" [fieldsValidation]="customValidation" [disableCsrf]="disableCsrf"
<!--LOGIN-->
<alfresco-login #alfrescologin
[providers]="providers"
[fieldsValidation]="customValidation"
[disableCsrf]="disableCsrf"
(executeSubmit)="validateForm($event)"
(onSuccess)="onLogin($event)"
(onError)="onError($event)" #alfrescologin></alfresco-login>
(onError)="onError($event)">
<div class="mobile-settings">
<p>
<label for="switch1-mobile" class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
<input type="checkbox" id="switch1-mobile" [checked]="isECM" class="mdl-switch__input"
(click)="toggleECM()">
<span class="mdl-switch__label">ECM</span>
</label>
</p>
<p>
<label for="switch2-mobile" class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
<input type="checkbox" id="switch2-mobile" [checked]="isBPM" class="mdl-switch__input"
(click)="toggleBPM()">
<span class="mdl-switch__label">BPM</span>
</label>
</p>
<p>
<label for="switch3-mobile" class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
<input type="checkbox" id="switch3-mobile" class="mdl-switch__input" [checked]="!disableCsrf" (click)="toggleCSRF()">
<span class="mdl-switch__label">CSRF</span>
</label>
</p>
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input class="mdl-textfield__input" type="text" [(ngModel)]="blackListUsername" id="blacklistusername"/>
<label class="mdl-textfield__label" for="blacklistusername">Banned username</label>
</div>
</div>
</alfresco-login>
@@ -18,11 +18,9 @@
import { Component, ViewChild, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { Validators } from '@angular/forms';
declare let __moduleName: string;
import { StorageService } from 'ng2-alfresco-core';
@Component({
moduleId: __moduleName,
selector: 'login-demo',
templateUrl: './login-demo.component.html',
styleUrls: ['./login-demo.component.css']
@@ -33,14 +31,14 @@ export class LoginDemoComponent implements OnInit {
alfrescologin: any;
providers: string = 'ECM';
disableCsrf: boolean = false;
blackListUsername: string;
customValidation: any;
disableCsrf: boolean = false;
isECM: boolean = true;
isBPM: boolean = false;
constructor(public router: Router) {
constructor(public router: Router, private storage: StorageService) {
this.customValidation = {
username: ['', Validators.compose([Validators.required, Validators.minLength(4)])],
password: ['', Validators.required]
@@ -52,14 +50,14 @@ export class LoginDemoComponent implements OnInit {
this.alfrescologin.addCustomValidationError('username', 'minlength', 'LOGIN.MESSAGES.USERNAME-MIN');
this.alfrescologin.addCustomValidationError('password', 'required', 'LOGIN.MESSAGES.PASSWORD-REQUIRED');
if (localStorage.getItem('providers')) {
this.providers = localStorage.getItem('providers');
if (this.storage.hasItem('providers')) {
this.providers = this.storage.getItem('providers');
}
this.setProviders();
this.initProviders();
}
setProviders() {
initProviders() {
if (this.providers === 'BPM') {
this.isECM = false;
this.isBPM = true;
@@ -80,38 +78,40 @@ export class LoginDemoComponent implements OnInit {
console.log($event);
}
toggleECM(checked) {
if (checked && this.providers === 'BPM') {
this.providers = 'ALL';
} else if (checked) {
this.providers = 'ECM';
} else if (!checked && this.providers === 'ALL') {
this.providers = 'BPM';
} else if (!checked && this.providers === 'ECM') {
this.providers = '';
}
localStorage.setItem('providers', this.providers);
toggleECM() {
this.isECM = !this.isECM;
this.storage.setItem('providers', this.updateProvider());
}
toggleBPM(checked) {
if (checked && this.providers === 'ECM') {
this.providers = 'ALL';
} else if (checked) {
this.providers = 'BPM';
} else if (!checked && this.providers === 'ALL') {
this.providers = 'ECM';
} else if (!checked && this.providers === 'BPM') {
this.providers = '';
}
localStorage.setItem('providers', this.providers);
toggleBPM() {
this.isBPM = !this.isBPM;
this.storage.setItem('providers', this.updateProvider());
}
toggleCSRF() {
this.disableCsrf = !this.disableCsrf;
}
updateProvider(){
if (this.isBPM && this.isECM) {
this.providers = 'ALL';
return this.providers;
}
if (this.isECM) {
this.providers = 'ECM';
return this.providers;
}
if (this.isBPM) {
this.providers = 'BPM';
return this.providers;
}
this.providers = '';
return this.providers;
};
validateForm(event: any) {
let values = event.values;
if (values.controls['username'].value === this.blackListUsername) {
@@ -1,14 +1,13 @@
<alfresco-search-control *ngIf="isLoggedIn()"
[searchTerm]="searchTerm"
[autocomplete]="false"
[liveSearchResultType]="'cm:content'"
(searchSubmit)="onSearchSubmit($event);"
(searchChange)="onSearchTermChange($event);"
(expand)="onExpandToggle($event);"
(fileSelect)="onFileClicked($event)">
(fileSelect)="onItemClicked($event)">
</alfresco-search-control>
<alfresco-viewer [(showViewer)]="fileShowed"
<alfresco-viewer *ngIf="fileShowed" [(showViewer)]="fileShowed"
[fileNodeId]="fileNodeId"
[overlayMode]="true">
<div class="mdl-spinner mdl-js-spinner is-active"></div>
@@ -18,11 +18,9 @@
import { Component, EventEmitter, Output } from '@angular/core';
import { Router } from '@angular/router';
import { AlfrescoAuthenticationService } from 'ng2-alfresco-core';
declare let __moduleName: string;
import { MinimalNodeEntity } from 'alfresco-js-api';
@Component({
moduleId: __moduleName,
selector: 'search-bar',
templateUrl: './search-bar.component.html'
})
@@ -54,10 +52,12 @@ export class SearchBarComponent {
}]);
}
onFileClicked(event) {
if (event.value.entry.isFile) {
this.fileNodeId = event.value.entry.id;
onItemClicked(event: MinimalNodeEntity) {
if (event.entry.isFile) {
this.fileNodeId = event.entry.id;
this.fileShowed = true;
} else if (event.entry.isFolder) {
this.router.navigate(['/files', event.entry.id]);
}
}
@@ -1,8 +1,8 @@
<div class="search-results-container">
<h1>Search results</h1>
<alfresco-search [resultType]="'cm:content'" (preview)="onFileClicked($event)"></alfresco-search>
<alfresco-search (navigate)="onNavigateItem($event)"></alfresco-search>
</div>
<alfresco-viewer [(showViewer)]="fileShowed" [fileNodeId]="fileNodeId" [overlayMode]="true">
<alfresco-viewer *ngIf="fileShowed" [(showViewer)]="fileShowed" [fileNodeId]="fileNodeId" [overlayMode]="true">
<div class="mdl-spinner mdl-js-spinner is-active"></div>
</alfresco-viewer>
@@ -16,11 +16,10 @@
*/
import { Component } from '@angular/core';
declare let __moduleName: string;
import { Router } from '@angular/router';
import { MinimalNodeEntity } from 'alfresco-js-api';
@Component({
moduleId: __moduleName,
selector: 'search-component',
templateUrl: './search.component.html',
styles: [`
@@ -51,10 +50,15 @@ export class SearchComponent {
fileShowed: boolean = false;
fileNodeId: string;
onFileClicked(event) {
if (event.value.entry.isFile) {
this.fileNodeId = event.value.entry.id;
constructor(public router: Router) {
}
onNavigateItem(event: MinimalNodeEntity) {
if (event.entry.isFile) {
this.fileNodeId = event.entry.id;
this.fileShowed = true;
} else if (event.entry.isFolder) {
this.router.navigate(['/files', event.entry.id]);
}
}
}
@@ -24,6 +24,11 @@
tabindex="1" (change)="onChangeBPMHost($event)" value="{{bpmHost}}"/>
</nav>
</div>
<div class="mdl-card__actions mdl-card--border">
<a class="mdl-button mdl-button--colored mdl-js-button mdl-js-ripple-effect" onclick="window.history.back()" >
Back
</a>
</div>
</div>
<div class="setting-card-padding"></div>
</div>
@@ -16,14 +16,9 @@
*/
import { Component } from '@angular/core';
import {
AlfrescoSettingsService
} from 'ng2-alfresco-core';
declare let __moduleName: string;
import { AlfrescoSettingsService, StorageService } from 'ng2-alfresco-core';
@Component({
moduleId: __moduleName,
selector: 'alfresco-setting-demo',
templateUrl: './setting.component.html',
styleUrls: ['./setting.component.css']
@@ -33,7 +28,8 @@ export class SettingComponent {
ecmHost: string;
bpmHost: string;
constructor(public alfrescoSettingsService: AlfrescoSettingsService) {
constructor(public alfrescoSettingsService: AlfrescoSettingsService,
private storage: StorageService) {
this.ecmHost = this.alfrescoSettingsService.ecmHost;
this.bpmHost = this.alfrescoSettingsService.bpmHost;
}
@@ -42,14 +38,14 @@ export class SettingComponent {
console.log((<HTMLInputElement>event.target).value);
this.ecmHost = (<HTMLInputElement>event.target).value;
this.alfrescoSettingsService.ecmHost = this.ecmHost;
localStorage.setItem(`ecmHost`, this.ecmHost);
this.storage.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);
this.storage.setItem(`bpmHost`, this.bpmHost);
}
}
-372
View File
@@ -1,372 +0,0 @@
/**
* Class to generate polyline
*
* @author Dmitry Farafonov
*/
var ANCHOR_TYPE= {
main: "main",
middle: "middle",
first: "first",
last: "last"
};
function Anchor(uuid, type, x, y) {
this.uuid = uuid;
this.x = x;
this.y = y;
this.type = (type == ANCHOR_TYPE.middle) ? ANCHOR_TYPE.middle : ANCHOR_TYPE.main;
};
Anchor.prototype = {
uuid: null,
x: 0,
y: 0,
type: ANCHOR_TYPE.main,
isFirst: false,
isLast: false,
ndex: 0,
typeIndex: 0
};
function Polyline(uuid, points, strokeWidth, paper) {
/* Array on coordinates:
* points: [{x: 410, y: 110}, 1
* {x: 570, y: 110}, 1 2
* {x: 620, y: 240}, 2 3
* {x: 750, y: 270}, 3 4
* {x: 650, y: 370}]; 4
*/
this.points = points;
/*
* path for graph
* [["M", x1, y1], ["L", x2, y2], ["C", ax, ay, bx, by, x3, y3], ["L", x3, y3]]
*/
this.path = [];
this.anchors = [];
if (strokeWidth) this.strokeWidth = strokeWidth;
this.paper = paper;
this.closePath = false;
this.init();
};
Polyline.prototype = {
id: null,
points: [],
path: [],
anchors: [],
strokeWidth: 1,
radius: 1,
showDetails: false,
paper: null,
element: null,
isDefaultConditionAvailable: false,
closePath: false,
init: function(points){
var linesCount = this.getLinesCount();
if (linesCount < 1)
return;
this.normalizeCoordinates();
// create anchors
this.pushAnchor(ANCHOR_TYPE.first, this.getLine(0).x1, this.getLine(0).y1);
for (var i = 1; i < linesCount; i++)
{
var line1 = this.getLine(i-1);
this.pushAnchor(ANCHOR_TYPE.main, line1.x2, line1.y2);
}
this.pushAnchor(ANCHOR_TYPE.last, this.getLine(linesCount-1).x2, this.getLine(linesCount-1).y2);
this.rebuildPath();
},
normalizeCoordinates: function(){
for(var i=0; i < this.points.length; i++){
this.points[i].x = parseFloat(this.points[i].x);
this.points[i].y = parseFloat(this.points[i].y);
}
},
getLinesCount: function(){
return this.points.length-1;
},
_getLine: function(i){
if (this.points.length > i && this.points[i]) {
return {x1: this.points[i].x, y1: this.points[i].y, x2: this.points[i+1].x, y2: this.points[i+1].y};
} else {
return undefined;
}
},
getLine: function(i){
var line = this._getLine(i);
if (line != undefined) {
line.angle = this.getLineAngle(i);
}
return line;
},
getLineAngle: function(i){
var line = this._getLine(i);
return Math.atan2(line.y2 - line.y1, line.x2 - line.x1);
},
getLineLengthX: function(i){
var line = this.getLine(i);
return (line.x2 - line.x1);
},
getLineLengthY: function(i){
var line = this.getLine(i);
return (line.y2 - line.y1);
},
getLineLength: function(i){
return Math.sqrt(Math.pow(this.getLineLengthX(i), 2) + Math.pow(this.getLineLengthY(i), 2));
},
getAnchors: function(){
return this.anchors;
},
getAnchorsCount: function(type){
if (!type)
return this.anchors.length;
else {
var count = 0;
for(var i=0; i < this.getAnchorsCount(); i++){
var anchor = this.anchors[i];
if (anchor.getType() == type) {
count++;
}
}
return count;
}
},
pushAnchor: function(type, x, y, index){
if (type == ANCHOR_TYPE.first) {
index = 0;
typeIndex = 0;
} else if (type == ANCHOR_TYPE.last) {
index = this.getAnchorsCount();
typeIndex = 0;
} else if (!index) {
index = this.anchors.length;
} else {
for(var i=0; i < this.getAnchorsCount(); i++){
var anchor = this.anchors[i];
if (anchor.index > index) {
anchor.index++;
anchor.typeIndex++;
}
}
}
var anchor = new Anchor(this.id, ANCHOR_TYPE.main, x, y, index, typeIndex);
this.anchors.push(anchor);
},
getAnchor: function(position){
return this.anchors[position];
},
getAnchorByType: function(type, position){
if (type == ANCHOR_TYPE.first)
return this.anchors[0];
if (type == ANCHOR_TYPE.last)
return this.anchors[this.getAnchorsCount()-1];
for(var i=0; i < this.getAnchorsCount(); i++){
var anchor = this.anchors[i];
if (anchor.type == type) {
if( position == anchor.position)
return anchor;
}
}
return null;
},
addNewPoint: function(position, x, y){
//
for(var i = 0; i < this.getLinesCount(); i++){
var line = this.getLine(i);
if (x > line.x1 && x < line.x2 && y > line.y1 && y < line.y2) {
this.points.splice(i+1,0,{x: x, y: y});
break;
}
}
this.rebuildPath();
},
rebuildPath: function(){
var path = [];
for(var i = 0; i < this.getAnchorsCount(); i++){
var anchor = this.getAnchor(i);
var pathType = "";
if (i == 0)
pathType = "M";
else
pathType = "L";
// TODO: save previous points and calculate new path just if points are updated, and then save currents values as previous
var targetX = anchor.x, targetY = anchor.y;
if (i>0 && i < this.getAnchorsCount()-1) {
// get new x,y
var cx = anchor.x, cy = anchor.y;
// pivot point of prev line
var AO = this.getLineLength(i-1);
if (AO < this.radius) {
AO = this.radius;
}
this.isDefaultConditionAvailable = (this.isDefaultConditionAvailable || (i == 1 && AO > 10));
var ED = this.getLineLengthY(i-1) * this.radius / AO;
var OD = this.getLineLengthX(i-1) * this.radius / AO;
targetX = anchor.x - OD;
targetY = anchor.y - ED;
if (AO < 2*this.radius && i>1) {
targetX = anchor.x - this.getLineLengthX(i-1)/2;
targetY = anchor.y - this.getLineLengthY(i-1)/2;;
}
// pivot point of next line
var AO = this.getLineLength(i);
if (AO < this.radius) {
AO = this.radius;
}
var ED = this.getLineLengthY(i) * this.radius / AO;
var OD = this.getLineLengthX(i) * this.radius / AO;
var nextSrcX = anchor.x + OD;
var nextSrcY = anchor.y + ED;
if (AO < 2*this.radius && i<this.getAnchorsCount()-2) {
nextSrcX = anchor.x + this.getLineLengthX(i)/2;
nextSrcY = anchor.y + this.getLineLengthY(i)/2;;
}
var dx0 = (cx - targetX) / 3,
dy0 = (cy - targetY) / 3,
ax = cx - dx0,
ay = cy - dy0,
dx1 = (cx - nextSrcX) / 3,
dy1 = (cy - nextSrcY) / 3,
bx = cx - dx1,
by = cy - dy1,
zx=nextSrcX, zy=nextSrcY;
} else if (i==1 && this.getAnchorsCount() == 2){
var AO = this.getLineLength(i-1);
if (AO < this.radius) {
AO = this.radius;
}
this.isDefaultConditionAvailable = (this.isDefaultConditionAvailable || (i == 1 && AO > 10));
}
// anti smoothing
if (this.strokeWidth%2 == 1) {
targetX += 0.5;
targetY += 0.5;
}
path.push([pathType, targetX, targetY]);
if (i>0 && i < this.getAnchorsCount()-1) {
path.push(["C", ax, ay, bx, by, zx, zy]);
}
}
if (this.closePath)
{
path.push(["Z"]);
}
this.path = path;
},
transform: function(transformation)
{
this.element.transform(transformation);
},
attr: function(attrs)
{
// TODO: foreach and set each
this.element.attr(attrs);
}
};
function Polygone(points, strokeWidth) {
/* Array on coordinates:
* points: [{x: 410, y: 110}, 1
* {x: 570, y: 110}, 1 2
* {x: 620, y: 240}, 2 3
* {x: 750, y: 270}, 3 4
* {x: 650, y: 370}]; 4
*/
this.points = points;
/*
* path for graph
* [["M", x1, y1], ["L", x2, y2], ["C", ax, ay, bx, by, x3, y3], ["L", x3, y3]]
*/
this.path = [];
this.anchors = [];
if (strokeWidth) this.strokeWidth = strokeWidth;
this.closePath = true;
this.init();
};
/*
* Poligone is inherited from Poliline: draws closedPath of polyline
*/
var Foo = function () { };
Foo.prototype = Polyline.prototype;
Polygone.prototype = new Foo();
Polygone.prototype.rebuildPath = function(){
var path = [];
for(var i = 0; i < this.getAnchorsCount(); i++){
var anchor = this.getAnchor(i);
var pathType = "";
if (i == 0)
pathType = "M";
else
pathType = "L";
var targetX = anchor.x, targetY = anchor.y;
// anti smoothing
if (this.strokeWidth%2 == 1) {
targetX += 0.5;
targetY += 0.5;
}
path.push([pathType, targetX, targetY]);
}
if (this.closePath)
path.push(["Z"]);
this.path = path;
};
+5
View File
@@ -16,7 +16,12 @@
*/
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { AppModule } from './app.module';
if (process.env.ENV === 'production') {
enableProdMode();
}
const platform = platformBrowserDynamic();
platform.bootstrapModule(AppModule);
+16
View File
@@ -0,0 +1,16 @@
import 'core-js/es6';
import 'core-js/es7/reflect';
// IE 8-11
require('zone.js/dist/zone');
if (process.env.ENV === 'production') {
// Production
} else {
// Development
Error['stackTraceLimit'] = Infinity;
require('zone.js/dist/long-stack-trace-zone');
}
+60
View File
@@ -0,0 +1,60 @@
// Angular
import '@angular/platform-browser';
import '@angular/platform-browser-dynamic';
import '@angular/core';
import '@angular/common';
import '@angular/http';
import '@angular/router';
// RxJS
import 'rxjs';
//Alfresco
import 'ng2-alfresco-core';
import 'ng2-alfresco-datatable';
import 'ng2-activiti-diagrams';
import 'ng2-activiti-analytics';
import 'ng2-activiti-form';
import 'ng2-activiti-processlist';
import 'ng2-activiti-tasklist';
import 'ng2-alfresco-documentlist';
import 'ng2-alfresco-login';
import 'ng2-alfresco-search';
import 'ng2-alfresco-tag';
import 'ng2-alfresco-upload';
import 'ng2-alfresco-viewer';
import 'ng2-alfresco-webscript';
import 'ng2-alfresco-userinfo';
// Polyfill(s) for dialogs
require('script!dialog-polyfill/dialog-polyfill');
import 'dialog-polyfill/dialog-polyfill.css';
// Flags
import 'flag-icon-css/css/flag-icon.min.css';
import '../public/css/app.css';
import '../public/css/muli-font.css';
import 'ng2-activiti-form/stencils/runtime.ng1';
import 'ng2-activiti-form/stencils/runtime.adf';
import 'chart.js';
require('script!raphael/raphael.min.js');
require('script!moment/min/moment.min.js');
import 'md-date-time-picker/dist/css/mdDateTimePicker.css';
require('script!md-date-time-picker/dist/js/mdDateTimePicker.min.js');
require('script!md-date-time-picker/dist/js/draggabilly.pkgd.min.js');
require('pdfjs-dist/web/compatibility.js');
// Setting worker path to worker bundle.
let pdfjsLib = require('pdfjs-dist');
if (process.env.ENV === 'production') {
pdfjsLib.PDFJS.workerSrc = './pdf.worker.js';
} else {
pdfjsLib.PDFJS.workerSrc = '../../node_modules/pdfjs-dist/build/pdf.worker.js';
}
require('pdfjs-dist/web/pdf_viewer.js');
+7
View File
@@ -0,0 +1,7 @@
var path = require('path');
var _root = path.resolve(__dirname, '..');
function root(args) {
args = Array.prototype.slice.call(arguments, 0);
return path.join.apply(path, [_root].concat(args));
}
exports.root = root;
+21
View File
@@ -0,0 +1,21 @@
Error.stackTraceLimit = Infinity;
require('core-js/es6');
require('core-js/es7/reflect');
require('zone.js/dist/zone');
require('zone.js/dist/long-stack-trace-zone');
require('zone.js/dist/proxy');
require('zone.js/dist/sync-test');
require('zone.js/dist/jasmine-patch');
require('zone.js/dist/async-test');
require('zone.js/dist/fake-async-test');
var appContext = require.context('../app', true, /\.spec\.ts/);
appContext.keys().forEach(appContext);
var testing = require('@angular/core/testing');
var browser = require('@angular/platform-browser-dynamic/testing');
testing.TestBed.initTestEnvironment(browser.BrowserDynamicTestingModule, browser.platformBrowserDynamicTesting());
+37
View File
@@ -0,0 +1,37 @@
var webpackConfig = require('./webpack.test');
module.exports = function (config) {
var _config = {
basePath: '',
frameworks: ['jasmine'],
files: [
{ pattern: './config/karma-test-shim.js', watched: false }
],
preprocessors: {
'./config/karma-test-shim.js': ['webpack', 'sourcemap']
},
webpack: webpackConfig,
webpackMiddleware: {
stats: 'errors-only'
},
webpackServer: {
noInfo: true
},
reporters: ['mocha'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: false,
browsers: ['PhantomJS'],
singleRun: true
};
config.set(_config);
};
+5
View File
@@ -0,0 +1,5 @@
module.exports = function(source) {
this.cacheable();
console.log(this.resource);
return source;
}
+27
View File
@@ -0,0 +1,27 @@
const moduleIdRegex = /moduleId: module.id,/g;
const moduleNameRegex = /moduleId: __moduleName,/g;
const moduleIdPath = /module.id.replace/g;
module.exports = function(source) {
this.cacheable();
if (moduleIdRegex.test(source)) {
source = source.replace(moduleIdRegex, (match) => {
return `// ${match}`;
});
}
if (moduleNameRegex.test(source)) {
source = source.replace(moduleNameRegex, (match) => {
return `// ${match}`;
});
}
if (moduleIdPath.test(source)) {
source = source.replace(moduleIdPath, (match) => {
return `''.replace`;
});
}
return source;
}
+213
View File
@@ -0,0 +1,213 @@
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var helpers = require('./helpers');
var path = require('path');
var fs = require('fs');
var glob = require('glob');
var CopyWebpackPlugin = require('copy-webpack-plugin');
const rootPath = helpers.root('node_modules');
let pattern = '+(alfresco-js-api|ng2-alfresco|ng2-activiti)*';
let options = {
cwd: rootPath,
realpath: true
};
let alfrescoLibs = glob.sync(pattern, options);
// console.dir(alfrescoLibs);
module.exports = {
entry: {
'polyfills': './app/polyfills.ts',
'vendor': './app/vendor.ts',
'app': './app/main.ts'
},
resolve: {
extensions: ['', '.ts', '.js'],
modules: [
helpers.root('app'),
helpers.root('node_modules')
],
root: rootPath,
fallback: rootPath
},
resolveLoader: {
alias: {
'systemjs-loader': helpers.root('config', 'loaders', 'system.js'),
'debug-loader': helpers.root('config', 'loaders', 'debug.js')
},
fallback: rootPath
},
module: {
preLoaders: [
{
test: /\.js$/,
include: [
...alfrescoLibs
],
loader: 'source-map-loader'
}
],
loaders: [
{
test: /\.ts$/,
loaders: ['awesome-typescript-loader', 'angular2-template-loader', 'systemjs-loader'],
exclude: ['node_modules','public']
},
{
test: /\.js$/,
include: [
...alfrescoLibs
],
loaders: ['angular2-template-loader', 'source-map-loader', 'systemjs-loader']
},
{
test: /\.html$/,
exclude: alfrescoLibs,
loader: 'html'
},
{
test: /\.html$/,
include: alfrescoLibs,
loader: 'html',
query: {
interpolate: true
}
},
{
test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
loader: 'file?name=assets/[name].[hash].[ext]'
},
{
test: /\.css$/,
exclude: [
helpers.root('app'),
...alfrescoLibs
],
loader: ExtractTextPlugin.extract('style', 'css?sourceMap')
},
{
test: /\.css$/,
include: [
helpers.root('app'),
...alfrescoLibs
],
loader: 'raw'
}
]
},
plugins: [
new webpack.WatchIgnorePlugin([ new RegExp('^((?!(ng2-activiti|ng2-alfresco|demo-shell-ng2)).)((?!(src|app)).)*$')]),
new CopyWebpackPlugin([
{
from: 'versions.json'
},{
context: 'node_modules',
from: 'element.scrollintoviewifneeded-polyfill/index.js',
to: 'js/element.scrollintoviewifneeded-polyfill.js',
flatten: true
},{
context: 'node_modules',
from: 'classlist-polyfill/src/index.js',
to: 'js/classlist-polyfill.js',
flatten: true
}, {
context: 'node_modules',
from: 'intl/dist/Intl.min.js',
to: 'js/Intl.min.js',
flatten: true
}, {
context: 'node_modules',
from: 'web-animations-js/web-animations.min.js',
to: 'js/web-animations.min.js',
flatten: true
}, {
context: 'node_modules',
from: 'core-js/client/shim.min.js',
to: 'js/shim.min.js',
flatten: true
}, {
context: 'node_modules',
from: 'es6-shim/es6-shim.min.js',
to: 'js/es6-shim.min.js',
flatten: true
}, {
context: 'node_modules',
from: 'es5-shim/es5-shim.min.js',
to: 'js/es5-shim.min.js',
flatten: true
}, {
context: 'node_modules',
from: 'systemjs/dist/system-polyfills.js',
to: 'js/system-polyfills.js',
flatten: true
}, {
context: 'node_modules',
from: 'material-design-lite/material.min.js',
to: 'js/material.min.js',
flatten: true
}, {
context: 'node_modules',
from: 'material-design-lite/material.min.js',
to: 'js/material.min.js',
flatten: true
}, {
context: 'public',
from: 'css/material.orange-blue.min.css',
to: 'css/material.orange-blue.min.css',
flatten: true
}, {
context: 'node_modules',
from: 'material-design-icons/iconfont/',
to: 'css/iconfont/',
flatten: true
}, {
context: 'public',
from: 'js/typedarray.js',
to: 'js/typedarray.js',
flatten: true
}, {
context: 'public',
from: 'js/Blob.js',
to: 'js/Blob.js',
flatten: true
}, {
context: 'public',
from: 'js/formdata.js',
to: 'js/formdata.js',
flatten: true
}, {
context: 'public',
from: 'js/promisePolyfill.js',
to: 'js/promisePolyfill.js',
flatten: true
}, {
context: 'public',
from: 'css/muli-font.css',
to: 'css/muli-font.css',
flatten: true
}
]),
new webpack.optimize.CommonsChunkPlugin({
name: ['app', 'vendor', 'polyfills']
}),
new HtmlWebpackPlugin({
template: 'index.html'
})
],
node: {
fs: 'empty',
module: false
}
};
+66
View File
@@ -0,0 +1,66 @@
var webpackMerge = require('webpack-merge');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var commonConfig = require('./webpack.common.js');
var helpers = require('./helpers');
var CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = webpackMerge(commonConfig, {
devtool: 'cheap-module-eval-source-map',
output: {
path: helpers.root('dist'),
publicPath: 'http://localhost:3000/',
filename: '[name].js',
chunkFilename: '[id].chunk.js'
},
plugins: [
new ExtractTextPlugin('[name].css'),
new CopyWebpackPlugin([
{
from: 'favicon-96x96.png'
},
{
from: 'node_modules/pdfjs-dist/build/pdf.worker.js',
to: 'pdf.worker.js'
},
{
context: 'custom-translation',
from: '**/*.json',
to: 'i18n/custom-translation'
},
// Copy i18n folders for all modules with ng2-alfresco- prefix
{
context: 'node_modules',
from: 'ng2-alfresco-*/src/i18n/*.json',
to: 'node_modules'
},
// Copy i18n folders for all modules with ng2-activiti- prefix
{
context: 'node_modules',
from: 'ng2-activiti-*/src/i18n/*.json',
to: 'node_modules'
},
// Copy asstes folders for all modules with ng2-activiti- prefix
{
context: 'node_modules',
from: 'ng2-activiti-*/src/assets/images/*.*',
to: 'assets/images',
flatten: true
},
// Copy asstes folders for all modules with ng2-alfresco- prefix
{
context: 'node_modules',
from: 'ng2-alfresco-*/src/assets/images/*.*',
to: 'assets/images',
flatten: true
}
])
],
devServer: {
historyApiFallback: true,
stats: 'minimal'
}
});
+101
View File
@@ -0,0 +1,101 @@
var webpack = require('webpack');
var webpackMerge = require('webpack-merge');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var CopyWebpackPlugin = require('copy-webpack-plugin');
var commonConfig = require('./webpack.common.js');
var helpers = require('./helpers');
const ENV = process.env.NODE_ENV = process.env.ENV = 'production';
module.exports = webpackMerge(commonConfig, {
devtool: 'source-map',
output: {
path: helpers.root('dist'),
publicPath: '/',
filename: '[name].[hash].js',
chunkFilename: '[id].[hash].chunk.js'
},
htmlLoader: {
minimize: false // workaround for ng2
},
plugins: [
// Define env variables to help with builds
// Reference: https://webpack.github.io/docs/list-of-plugins.html#defineplugin
new webpack.DefinePlugin({
'process.env': {
'ENV': JSON.stringify(ENV)
}
}),
// Reference: http://webpack.github.io/docs/list-of-plugins.html#noerrorsplugin
// Only emit files when there are no errors
new webpack.NoErrorsPlugin(),
// Reference: http://webpack.github.io/docs/list-of-plugins.html#dedupeplugin
// Dedupe modules in the output
new webpack.optimize.DedupePlugin(),
// Reference: http://webpack.github.io/docs/list-of-plugins.html#uglifyjsplugin
// Minify all javascript, switch loaders to minimizing mode
new webpack.optimize.UglifyJsPlugin({ // https://github.com/angular/angular/issues/10618
mangle: {
keep_fnames: true
},
compressor: {
screw_ie8: true,
warnings: false
}
}),
// Extract css files
// Reference: https://github.com/webpack/extract-text-webpack-plugin
// Disabled when in test mode or not in build mode
new ExtractTextPlugin('[name].[hash].css'),
// Copy assets from the public folder
// Reference: https://github.com/kevlened/copy-webpack-plugin
new CopyWebpackPlugin([
{
from: 'favicon-96x96.png'
},
{
from: 'node_modules/pdfjs-dist/build/pdf.worker.js',
to: 'pdf.worker.js'
},
{
context: 'custom-translation',
from: '**/*.json',
to: 'i18n/custom-translation'
},
// Copy i18n folders for all modules with ng2-alfresco- prefix
{
context: 'node_modules',
from: 'ng2-alfresco-*/src/i18n/*.json',
to: 'node_modules'
},
// Copy i18n folders for all modules with ng2-activiti- prefix
{
context: 'node_modules',
from: 'ng2-activiti-*/src/i18n/*.json',
to: 'node_modules'
},
// Copy asstes folders for all modules with ng2-activiti- prefix
{
context: 'node_modules',
from: 'ng2-activiti-*/src/assets/images/*.*',
to: 'assets/images',
flatten : true
},
// Copy asstes folders for all modules with ng2-alfresco- prefix
{
context: 'node_modules',
from: 'ng2-alfresco-*/src/assets/images/*.*',
to: 'assets/images',
flatten : true
}
])
]
});
+70
View File
@@ -0,0 +1,70 @@
var helpers = require('./helpers');
var fs = require('fs');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var glob = require('glob');
const rootPath = helpers.root('node_modules');
let pattern = '+(alfresco-js-api|ng2-alfresco|ng2-activiti)*';
let options = {
cwd: rootPath,
realpath: true
};
let alfrescoLibs = glob.sync(pattern, options);
module.exports = {
devtool: 'inline-source-map',
resolve: {
extensions: ['', '.ts', '.js'],
modules: [
helpers.root('app'),
helpers.root('node_modules')
],
root: rootPath,
fallback: rootPath
},
resolveLoader: {
alias: {
'systemjs-loader': helpers.root('config', 'loaders', 'system.js')
},
fallback: rootPath
},
module: {
loaders: [
{
test: /\.ts$/,
exclude: /node_modules/,
loaders: ['awesome-typescript-loader', 'angular2-template-loader']
},
{
test: /\.js$/,
include: [
...alfrescoLibs
],
loaders: ['angular2-template-loader', 'source-map-loader', 'systemjs-loader']
},
{
test: /\.html$/,
loader: 'html'
},
{
test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
loader: 'null'
},
{
test: /\.css$/,
loader: 'raw'
}
]
},
node: {
fs: 'empty',
module: false
}
}
+35 -52
View File
@@ -5,69 +5,52 @@
<title>Demo Application - Angular 2</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="app/css/app.css" rel="stylesheet">
<link href="app/css/muli-font.css" rel="stylesheet">
<link rel="icon" type="image/png" href="favicon-96x96.png" sizes="96x96">
<!-- Google Material Design Lite -->
<link href="./assets/material.orange-blue.min.css" rel="stylesheet">
<script src="node_modules/material-design-lite/material.min.js"></script>
<link href="node_modules/material-design-icons/iconfont/material-icons.css" rel="stylesheet">
<link href="node_modules/flag-icon-css/css/flag-icon.min.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Roboto:regular,bold,italic,thin,light,bolditalic,black,medium&amp;lang=en" rel="stylesheet" type="text/css">
<link href="node_modules/md-date-time-picker/dist/css/mdDateTimePicker.css" media="all" rel="stylesheet">
<!-- 1. Load libraries -->
<!-- Polyfill(s) for Safari (pre-10.x) -->
<script src="node_modules/intl/dist/Intl.min.js"></script>
<script src="node_modules/intl/locale-data/jsonp/en.js"></script>
<script src=js/Intl.min.js></script>
<!-- Polyfill(s) for older browsers -->
<script src="node_modules/core-js/client/shim.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/dom4/1.8.3/dom4.js"></script>
<script src="node_modules/element.scrollintoviewifneeded-polyfill/index.js"></script>
<!--[if IE]>
<script src=js/shim.min.js></script>
<script src=//cdnjs.cloudflare.com/ajax/libs/dom4/1.8.3/dom4.js></script>
<script src=js/element.scrollintoviewifneeded-polyfill.js></script>
<script src=js/classlist-polyfill.js></script>
<script src=js/web-animations.min.js></script>
<script src=js/typedarray.js></script>
<script src=js/Blob.js></script>
<script src=js/formdata.js></script>
<script src=https://npmcdn.com/angular2/es6/dev/src/testing/shims_for_IE.js></script>
<script src=js/es5-shim.min.js></script>
<script src=js/es6-shim.min.js></script>
<script src=js/system-polyfills.js></script>
<![endif]-->
<!-- Polyfill(s) for dialogs -->
<script src="node_modules/dialog-polyfill/dialog-polyfill.js"></script>
<link href="node_modules/dialog-polyfill/dialog-polyfill.css" rel="stylesheet" type="text/css" />
<!-- Google Material Design Lite -->
<link href="css/material.orange-blue.min.css" rel="stylesheet">
<script src="js/material.min.js"></script>
<link href="css/iconfont/material-icons.css" rel="stylesheet">
<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/reflect-metadata/Reflect.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="node_modules/moment/min/moment.min.js"></script>
<script src="/app/js/Polyline.js"></script>
<script src="node_modules/pdfjs-dist/web/compatibility.js"></script>
<script src="node_modules/pdfjs-dist/build/pdf.js"></script>
<script src="node_modules/pdfjs-dist/build/pdf.worker.js"></script>
<script src="node_modules/pdfjs-dist/web/pdf_viewer.js"></script>
<script src="node_modules/chart.js/dist/Chart.bundle.min.js"></script>
<script src="node_modules/raphael/raphael.min.js"></script>
<script src="node_modules/md-date-time-picker/dist/js/mdDateTimePicker.min.js"></script>
<script src="node_modules/md-date-time-picker/dist/js/draggabilly.pkgd.min.js"></script>
<style>
.main_header_adf .mdl-layout__drawer-button {
right: 0 !important;
left: initial !important;
left: auto;
<!-- Stencils integration -->
<script src="node_modules/ng2-activiti-form/stencils/runtime.ng1.js"></script>
<script src="node_modules/ng2-activiti-form/stencils/runtime.adf.js"></script>
<script src="http://localhost:9999/activiti-app/app/rest/script-files/controllers"></script>
<!-- 2. Configure SystemJS -->
<script src="systemjs.config.js"></script>
<script>
System.import('app').catch(function(err){ console.error(err); });
</script>
}
</style>
</head>
<!-- 3. Display the application -->
<body>
<alfresco-app>
<div id="loader-container" class="loader-container">
<div class="loader-item">
<div id="loader-spin" class="mdl-progress mdl-js-progress mdl-progress__indeterminate"></div>
<div id="loader-text" class="loader-text">Loading Demo Shell..</div>
</div >
</div>
</alfresco-app>
<alfresco-app>
<div id="loader-container" class="loader-container">
<div class="loader-item">
<div id="loader-spin" class="mdl-progress mdl-js-progress mdl-progress__indeterminate"></div>
<div id="loader-text" class="loader-text">Loading Demo Shell..</div>
</div >
</div>
</alfresco-app>
</body>
</html>
+1
View File
@@ -0,0 +1 @@
module.exports = require('./config/karma.conf.js');
+71 -45
View File
@@ -1,18 +1,17 @@
{
"name": "Alfresco-Angular2-Demo",
"description": "Demo shell for Alfresco Angular2 components",
"version": "0.5.0",
"version": "1.0.0",
"author": "Alfresco Software, Ltd.",
"scripts": {
"clean": "npm install rimraf && rimraf dist node_modules typings",
"build": "npm run tslint && npm run tsc && npm run licensecheck",
"start": "npm run build && npm run serve",
"start:dev": "npm run build && concurrently \"npm run tsc:w\" \"npm run serve:dev\" ",
"clean": "npm install rimraf && npm run clean-build && rimraf dist node_modules typings dist",
"start": "npm run server-versions && webpack-dev-server --inline --progress --port 3000 --max_old_space_size=4096 --max_new_space_size=4096",
"start:dist": "wsrv -s dist/ -p 3000 -a 0.0.0.0",
"clean-build": "rimraf 'app/{,**/}**.js' 'app/{,**/}**.js.map' 'app/{,**/}**.d.ts'",
"test": "karma start",
"build": "npm run server-versions && rimraf dist && webpack --config config/webpack.prod.js --progress --profile --bail",
"server-versions": "rimraf versions.json && npm list --depth=0 --json=true --prod=true > versions.json || true",
"aws": "node app.js",
"tsc": "tsc",
"tsc:w": "tsc -w",
"serve": "wsrv -O http://localhost:3000 -s -p 3000 -a 0.0.0.0 -x ./server/versions.js",
"serve:dev": "wsrv -O http://localhost:3000 -s -l -p 3000 -a 0.0.0.0 -x ./server/versions.js",
"tslint": "tslint -c tslint.json *.ts && tslint -c tslint.json 'app/{,**/}**.ts'",
"licensecheck": "license-check"
},
@@ -53,61 +52,88 @@
"alfresco"
],
"dependencies": {
"@angular/common": "2.0.0",
"@angular/compiler": "2.0.0",
"@angular/core": "2.0.0",
"@angular/forms": "2.0.0",
"@angular/http": "2.0.0",
"@angular/platform-browser": "2.0.0",
"@angular/platform-browser-dynamic": "2.0.0",
"@angular/router": "3.0.0",
"@angular/upgrade": "2.0.0",
"@types/node": "^6.0.42",
"core-js": "^2.4.1",
"reflect-metadata": "^0.1.3",
"rxjs": "5.0.0-beta.12",
"@angular/common": "2.2.2",
"@angular/compiler": "2.2.2",
"@angular/compiler-cli": "2.2.2",
"@angular/core": "2.2.2",
"@angular/forms": "2.2.2",
"@angular/http": "2.2.2",
"@angular/platform-browser": "2.2.2",
"@angular/platform-browser-dynamic": "2.2.2",
"@angular/router": "3.2.2",
"@angular/upgrade": "2.2.2",
"systemjs": "0.19.27",
"core-js": "^2.4.1",
"reflect-metadata": "^0.1.8",
"rxjs": "5.0.0-beta.12",
"zone.js": "^0.6.23",
"rimraf": "2.5.2",
"material-design-icons": "2.2.3",
"material-design-lite": "1.2.1",
"ng2-translate": "2.5.0",
"pdfjs-dist": "1.5.404",
"flag-icon-css": "2.3.0",
"intl": "1.2.4",
"moment": "2.15.1",
"chart.js": "^2.1.4",
"ng2-charts": "1.1.0",
"raphael": "^2.2.6",
"md-date-time-picker": "^2.2.0",
"alfresco-js-api": "^0.5.0",
"ng2-activiti-analytics": "0.5.0",
"ng2-alfresco-core": "0.5.0",
"ng2-alfresco-datatable": "0.5.0",
"ng2-alfresco-documentlist": "0.5.0",
"ng2-alfresco-login": "0.5.0",
"ng2-alfresco-search": "0.5.0",
"ng2-alfresco-upload": "0.5.0",
"ng2-alfresco-viewer": "0.5.0",
"ng2-activiti-form": "0.5.0",
"ng2-activiti-tasklist": "0.5.0",
"ng2-alfresco-userinfo": "0.5.0",
"ng2-activiti-processlist": "0.5.0",
"ng2-alfresco-webscript": "0.5.0",
"ng2-alfresco-tag": "0.5.0",
"alfresco-js-api": "^1.0.0",
"ng2-activiti-analytics": "1.0.0",
"ng2-alfresco-core": "1.0.0",
"ng2-alfresco-datatable": "1.0.0",
"ng2-alfresco-documentlist": "1.0.0",
"ng2-alfresco-login": "1.0.0",
"ng2-alfresco-search": "1.0.0",
"ng2-alfresco-upload": "1.0.0",
"ng2-alfresco-viewer": "1.0.0",
"ng2-activiti-form": "1.0.0",
"ng2-activiti-tasklist": "1.0.0",
"ng2-alfresco-userinfo": "1.0.0",
"ng2-activiti-processlist": "1.0.0",
"ng2-alfresco-webscript": "1.0.0",
"ng2-alfresco-tag": "1.0.0",
"dialog-polyfill": "^0.4.3",
"element.scrollintoviewifneeded-polyfill": "^1.0.1"
},
"devDependencies": {
"@types/core-js": "^0.9.32",
"@types/jasmine": "^2.2.33",
"concurrently": "^2.2.0",
"@types/jasmine": "^2.5.35",
"@types/node": "^6.0.45",
"angular2-template-loader": "^0.6.0",
"awesome-typescript-loader": "^2.2.4",
"classlist-polyfill": "^1.0.3",
"copy-webpack-plugin": "^4.0.1",
"css-loader": "^0.23.1",
"es5-shim": "^4.5.9",
"es6-shim": "^0.35.2",
"extract-text-webpack-plugin": "^1.0.1",
"file-loader": "^0.8.5",
"glob": "^7.1.1",
"html-loader": "^0.4.3",
"html-webpack-plugin": "^2.15.0",
"intl": "^1.2.5",
"jasmine-core": "^2.4.1",
"karma": "^1.2.0",
"karma-jasmine": "^1.0.2",
"karma-mocha-reporter": "^2.2.1",
"karma-phantomjs-launcher": "^1.0.2",
"karma-sourcemap-loader": "^0.3.7",
"karma-webpack": "^1.8.0",
"license-check": "1.1.5",
"mime": "^1.3.4",
"null-loader": "^0.1.1",
"phantomjs-prebuilt": "^2.1.7",
"raw-loader": "^0.5.1",
"rimraf": "^2.5.2",
"script-loader": "^0.7.0",
"source-map-loader": "^0.1.5",
"style-loader": "^0.13.1",
"tslint": "3.15.1",
"typescript": "^2.0.3",
"wsrv": "^0.1.5"
"typescript": "2.0.3",
"web-animations-js": "^2.2.2",
"webpack": "^1.13.0",
"webpack-dev-server": "^1.14.1",
"webpack-merge": "^0.14.0",
"wsrv": "^0.1.6"
},
"license-check-config": {
"src": [
+211
View File
@@ -0,0 +1,211 @@
/* Blob.js
* A Blob implementation.
* 2014-07-24
*
* By Eli Grey, http://eligrey.com
* By Devin Samarin, https://github.com/dsamarin
* License: MIT
* See https://github.com/eligrey/Blob.js/blob/master/LICENSE.md
*/
/*global self, unescape */
/*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true,
plusplus: true */
/*! @source http://purl.eligrey.com/github/Blob.js/blob/master/Blob.js */
(function (view) {
"use strict";
view.URL = view.URL || view.webkitURL;
if (view.Blob && view.URL) {
try {
new Blob;
return;
} catch (e) {}
}
// Internally we use a BlobBuilder implementation to base Blob off of
// in order to support older browsers that only have BlobBuilder
var BlobBuilder = view.BlobBuilder || view.WebKitBlobBuilder || view.MozBlobBuilder || (function(view) {
var
get_class = function(object) {
return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1];
}
, FakeBlobBuilder = function BlobBuilder() {
this.data = [];
}
, FakeBlob = function Blob(data, type, encoding) {
this.data = data;
this.size = data.length;
this.type = type;
this.encoding = encoding;
}
, FBB_proto = FakeBlobBuilder.prototype
, FB_proto = FakeBlob.prototype
, FileReaderSync = view.FileReaderSync
, FileException = function(type) {
this.code = this[this.name = type];
}
, file_ex_codes = (
"NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR "
+ "NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR"
).split(" ")
, file_ex_code = file_ex_codes.length
, real_URL = view.URL || view.webkitURL || view
, real_create_object_URL = real_URL.createObjectURL
, real_revoke_object_URL = real_URL.revokeObjectURL
, URL = real_URL
, btoa = view.btoa
, atob = view.atob
, ArrayBuffer = view.ArrayBuffer
, Uint8Array = view.Uint8Array
, origin = /^[\w-]+:\/*\[?[\w\.:-]+\]?(?::[0-9]+)?/
;
FakeBlob.fake = FB_proto.fake = true;
while (file_ex_code--) {
FileException.prototype[file_ex_codes[file_ex_code]] = file_ex_code + 1;
}
// Polyfill URL
if (!real_URL.createObjectURL) {
URL = view.URL = function(uri) {
var
uri_info = document.createElementNS("http://www.w3.org/1999/xhtml", "a")
, uri_origin
;
uri_info.href = uri;
if (!("origin" in uri_info)) {
if (uri_info.protocol.toLowerCase() === "data:") {
uri_info.origin = null;
} else {
uri_origin = uri.match(origin);
uri_info.origin = uri_origin && uri_origin[1];
}
}
return uri_info;
};
}
URL.createObjectURL = function(blob) {
var
type = blob.type
, data_URI_header
;
if (type === null) {
type = "application/octet-stream";
}
if (blob instanceof FakeBlob) {
data_URI_header = "data:" + type;
if (blob.encoding === "base64") {
return data_URI_header + ";base64," + blob.data;
} else if (blob.encoding === "URI") {
return data_URI_header + "," + decodeURIComponent(blob.data);
} if (btoa) {
return data_URI_header + ";base64," + btoa(blob.data);
} else {
return data_URI_header + "," + encodeURIComponent(blob.data);
}
} else if (real_create_object_URL) {
return real_create_object_URL.call(real_URL, blob);
}
};
URL.revokeObjectURL = function(object_URL) {
if (object_URL.substring(0, 5) !== "data:" && real_revoke_object_URL) {
real_revoke_object_URL.call(real_URL, object_URL);
}
};
FBB_proto.append = function(data/*, endings*/) {
var bb = this.data;
// decode data to a binary string
if (Uint8Array && (data instanceof ArrayBuffer || data instanceof Uint8Array)) {
var
str = ""
, buf = new Uint8Array(data)
, i = 0
, buf_len = buf.length
;
for (; i < buf_len; i++) {
str += String.fromCharCode(buf[i]);
}
bb.push(str);
} else if (get_class(data) === "Blob" || get_class(data) === "File") {
if (FileReaderSync) {
var fr = new FileReaderSync;
bb.push(fr.readAsBinaryString(data));
} else {
// async FileReader won't work as BlobBuilder is sync
throw new FileException("NOT_READABLE_ERR");
}
} else if (data instanceof FakeBlob) {
if (data.encoding === "base64" && atob) {
bb.push(atob(data.data));
} else if (data.encoding === "URI") {
bb.push(decodeURIComponent(data.data));
} else if (data.encoding === "raw") {
bb.push(data.data);
}
} else {
if (typeof data !== "string") {
data += ""; // convert unsupported types to strings
}
// decode UTF-16 to binary string
bb.push(unescape(encodeURIComponent(data)));
}
};
FBB_proto.getBlob = function(type) {
if (!arguments.length) {
type = null;
}
return new FakeBlob(this.data.join(""), type, "raw");
};
FBB_proto.toString = function() {
return "[object BlobBuilder]";
};
FB_proto.slice = function(start, end, type) {
var args = arguments.length;
if (args < 3) {
type = null;
}
return new FakeBlob(
this.data.slice(start, args > 1 ? end : this.data.length)
, type
, this.encoding
);
};
FB_proto.toString = function() {
return "[object Blob]";
};
FB_proto.close = function() {
this.size = 0;
delete this.data;
};
return FakeBlobBuilder;
}(view));
view.Blob = function(blobParts, options) {
var type = options ? (options.type || "") : "";
var builder = new BlobBuilder();
if (blobParts) {
for (var i = 0, len = blobParts.length; i < len; i++) {
if (Uint8Array && blobParts[i] instanceof Uint8Array) {
builder.append(blobParts[i].buffer);
}
else {
builder.append(blobParts[i]);
}
}
}
var blob = builder.getBlob(type);
if (!blob.slice && blob.webkitSlice) {
blob.slice = blob.webkitSlice;
}
return blob;
};
var getPrototypeOf = Object.getPrototypeOf || function(object) {
return object.__proto__;
};
view.Blob.prototype = getPrototypeOf(new view.Blob());
}(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this.content || this));
+37
View File
@@ -0,0 +1,37 @@
/**
* Emulate FormData for some browsers
* MIT License
* (c) 2010 François de Metz
*/
(function(w) {
if (w.FormData)
return;
function FormData() {
this.fake = true;
this.boundary = "--------FormData" + Math.random();
this._fields = [];
}
FormData.prototype.append = function(key, value) {
this._fields.push([key, value]);
}
FormData.prototype.toString = function() {
var boundary = this.boundary;
var body = "";
this._fields.forEach(function(field) {
body += "--" + boundary + "\r\n";
// file upload
if (field[1].name) {
var file = field[1];
body += "Content-Disposition: form-data; name=\""+ field[0] +"\"; filename=\""+ file.name +"\"\r\n";
body += "Content-Type: "+ file.type +"\r\n\r\n";
body += file.getAsBinary() + "\r\n";
} else {
body += "Content-Disposition: form-data; name=\""+ field[0] +"\";\r\n\r\n";
body += field[1] + "\r\n";
}
});
body += "--" + boundary +"--";
return body;
}
w.FormData = FormData;
})(window);
@@ -0,0 +1,3 @@
/* Disable minification (remove `.min` from URL path) for more info */
(function(undefined) {if (!('Symbol' in this && 'iterator' in this.Symbol && !!Array.prototype[Symbol.iterator] && !!Array.prototype.values && (Array.prototype[Symbol.iterator] === Array.prototype.values))) {Object.defineProperty(Array.prototype,"values",{value:Array.prototype[Symbol.iterator],enumerable:!1,writable:!1});}if (!('contains' in String.prototype)) {String.prototype.contains=String.prototype.includes;}var ArrayIterator=function(){var e=function(){var e=function(){return this.length=0,this},t=function(e){if("function"!=typeof e)throw new TypeError(e+" is not a function");return e},_=function(e,n){return this instanceof _?(Object.defineProperties(this,{__list__:{writable:!0,value:e},__context__:{writable:!0,value:n},__nextIndex__:{writable:!0,value:0}}),void(n&&(t(n.on),n.on("_add",this._onAdd.bind(this)),n.on("_delete",this._onDelete.bind(this)),n.on("_clear",this._onClear.bind(this))))):new _(e,n)};return Object.defineProperties(_.prototype,Object.assign({constructor:{value:_,configurable:!0,enumerable:!1,writable:!0},_next:{value:function(){var e;if(this.__list__)return this.__redo__&&(e=this.__redo__.shift(),void 0!==e)?e:this.__nextIndex__<this.__list__.length?this.__nextIndex__++:void this._unBind()},configurable:!0,enumerable:!1,writable:!0},next:{value:function(){return this._createResult(this._next())},configurable:!0,enumerable:!1,writable:!0},_createResult:{value:function(e){return void 0===e?{done:!0,value:void 0}:{done:!1,value:this._resolve(e)}},configurable:!0,enumerable:!1,writable:!0},_resolve:{value:function(e){return this.__list__[e]},configurable:!0,enumerable:!1,writable:!0},_unBind:{value:function(){this.__list__=null,delete this.__redo__,this.__context__&&(this.__context__.off("_add",this._onAdd.bind(this)),this.__context__.off("_delete",this._onDelete.bind(this)),this.__context__.off("_clear",this._onClear.bind(this)),this.__context__=null)},configurable:!0,enumerable:!1,writable:!0},toString:{value:function(){return"[object Iterator]"},configurable:!0,enumerable:!1,writable:!0}},{_onAdd:{value:function(e){if(!(e>=this.__nextIndex__)){if(++this.__nextIndex__,!this.__redo__)return void Object.defineProperty(this,"__redo__",{value:[e],configurable:!0,enumerable:!1,writable:!1});this.__redo__.forEach(function(t,_){t>=e&&(this.__redo__[_]=++t)},this),this.__redo__.push(e)}},configurable:!0,enumerable:!1,writable:!0},_onDelete:{value:function(e){var t;e>=this.__nextIndex__||(--this.__nextIndex__,this.__redo__&&(t=this.__redo__.indexOf(e),t!==-1&&this.__redo__.splice(t,1),this.__redo__.forEach(function(t,_){t>e&&(this.__redo__[_]=--t)},this)))},configurable:!0,enumerable:!1,writable:!0},_onClear:{value:function(){this.__redo__&&e.call(this.__redo__),this.__nextIndex__=0},configurable:!0,enumerable:!1,writable:!0}})),Object.defineProperty(_.prototype,Symbol.iterator,{value:function(){return this},configurable:!0,enumerable:!1,writable:!0}),Object.defineProperty(_.prototype,Symbol.toStringTag,{value:"Iterator",configurable:!1,enumerable:!1,writable:!1}),_}(),t=function(_,n){return this instanceof t?(e.call(this,_),n=n?String.prototype.contains.call(n,"key+value")?"key+value":String.prototype.contains.call(n,"key")?"key":"value":"value",void Object.defineProperty(this,"__kind__",{value:n,configurable:!1,enumerable:!1,writable:!1})):new t(_,n)};return Object.setPrototypeOf&&Object.setPrototypeOf(t,e.prototype),t.prototype=Object.create(e.prototype,{constructor:{value:t,configurable:!0,enumerable:!1,writable:!0},_resolve:{value:function(e){return"value"===this.__kind__?this.__list__[e]:"key+value"===this.__kind__?[e,this.__list__[e]]:e},configurable:!0,enumerable:!1,writable:!0},toString:{value:function(){return"[object Array Iterator]"},configurable:!0,enumerable:!1,writable:!0}}),t}();}).call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
File diff suppressed because it is too large Load Diff
-42
View File
@@ -1,42 +0,0 @@
'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'
};
-76
View File
@@ -1,76 +0,0 @@
/**
* System configuration for Angular 2 samples
* Adjust as necessary for your application needs.
*/
(function (global) {
System.config({
paths: {
// paths serve as alias
'npm:': 'node_modules/'
},
// map tells the System loader where to look for things
map: {
// our app is within the app folder
app: 'app',
// angular bundles
'@angular/core': 'npm:@angular/core/bundles/core.umd.js',
'@angular/common': 'npm:@angular/common/bundles/common.umd.js',
'@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
'@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
'@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
'@angular/http': 'npm:@angular/http/bundles/http.umd.js',
'@angular/router': 'npm:@angular/router/bundles/router.umd.js',
'@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
// other libraries
'rxjs': 'npm:rxjs',
'moment': 'npm:moment/min/moment.min.js',
'ng2-charts' : 'npm:ng2-charts',
'ng2-translate': 'npm:ng2-translate',
'ng2-alfresco-core': 'npm:ng2-alfresco-core/dist',
'ng2-alfresco-datatable': 'npm:ng2-alfresco-datatable/dist',
'ng2-alfresco-documentlist': 'npm:ng2-alfresco-documentlist/dist',
'ng2-alfresco-login': 'npm:ng2-alfresco-login/dist',
'ng2-alfresco-search': 'npm:ng2-alfresco-search/dist',
'ng2-alfresco-upload': 'npm:ng2-alfresco-upload/dist',
'ng2-activiti-form': 'npm:ng2-activiti-form/dist',
'ng2-alfresco-viewer': 'npm:ng2-alfresco-viewer/dist',
'ng2-alfresco-webscript': 'npm:ng2-alfresco-webscript/dist',
'ng2-alfresco-tag': 'npm:ng2-alfresco-tag/dist',
'ng2-activiti-tasklist': 'npm:ng2-activiti-tasklist/dist',
'alfresco-js-api': 'npm:alfresco-js-api/dist',
'ng2-activiti-processlist': 'npm:ng2-activiti-processlist/dist',
'ng2-alfresco-userinfo': 'npm:ng2-alfresco-userinfo/dist',
'ng2-activiti-analytics': 'npm:ng2-activiti-analytics/dist',
'ng2-activiti-diagrams': 'npm:ng2-activiti-diagrams/dist'
},
// packages tells the System loader how to load when no filename and/or no extension
packages: {
app: {
main: './main.js',
defaultExtension: 'js'
},
rxjs: {
defaultExtension: 'js'
},
'ng2-translate': { defaultExtension: 'js' },
'ng2-charts': { defaultExtension: 'js' },
'ng2-alfresco-core': { main: './index.js', defaultExtension: 'js'},
'ng2-alfresco-datatable': { main: './index.js', defaultExtension: 'js'},
'ng2-alfresco-documentlist': { main: './index.js', defaultExtension: 'js'},
'ng2-alfresco-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-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'},
'ng2-alfresco-tag': { main: './index.js', defaultExtension: 'js'},
'alfresco-js-api': { main: './alfresco-js-api.js', defaultExtension: 'js'},
'ng2-alfresco-userinfo': { main: './index.js', defaultExtension: 'js'},
'ng2-activiti-analytics': { main: './index.js', defaultExtension: 'js'},
'ng2-activiti-diagrams': { main: './index.js', defaultExtension: 'js'}
}
});
})(this);
+4 -7
View File
@@ -1,19 +1,16 @@
{
"compilerOptions": {
"target": "es5",
"module": "system",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"removeComments": false,
"lib": ["es2015", "dom"],
"noImplicitAny": false,
"types": ["core-js", "jasmine"]
"suppressImplicitAnyIndexErrors": true
},
"exclude": [
"dist",
"node_modules",
"typings/main",
"typings/main.d.ts"
"node_modules"
]
}
+2 -2
View File
@@ -55,7 +55,7 @@
"no-eval": true,
"no-inferrable-types": false,
"no-internal-module": true,
"no-require-imports": true,
"no-require-imports": false,
"no-shadowed-variable": true,
"no-switch-case-fall-through": true,
"no-trailing-whitespace": true,
@@ -64,7 +64,7 @@
"no-unused-variable": true,
"no-use-before-declare": true,
"no-var-keyword": true,
"no-var-requires": true,
"no-var-requires": false,
"object-literal-sort-keys": false,
"one-line": [
true,
+1
View File
@@ -0,0 +1 @@
module.exports = require('./config/webpack.dev.js');
-14
View File
@@ -1,14 +0,0 @@
{
"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}",
"node_modules/ng2-activiti-tasklist/dist/**/*.{html,css,js}"
]
}
@@ -6,10 +6,14 @@ coverage
dist
src/**/*.js
src/**/*.js.map
src/**/*.d.ts
demo/**/*.js
demo/**/*.js.map
demo/**/*.d.ts
index.js
index.js.map
!systemjs.config.js
*.tgz
/package/
/bundles/
index.d.ts
@@ -2,14 +2,15 @@ npm-debug.log
.idea
coverage/
demo/
node_modules
typings/
fonts/
/.editorconfig
/.travis.yml
/*.js
/*.json
/*.ts
/*.js.map
/karma-test-shim.js
/karma.conf.js
/gulpfile.ts
/.npmignore
@@ -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
@@ -5,15 +5,16 @@
"author": "Alfresco Software, Ltd.",
"main": "index.js",
"scripts": {
"clean": "npm install rimraf && rimraf dist node_modules typings dist",
"clean": "npm install rimraf && npm run clean-build && rimraf dist node_modules typings dist",
"clean-build" : "rimraf 'src/{,**/}**.js' 'src/{,**/}**.js.map' 'src/{,**/}**.d.ts'",
"postinstall": "npm run build",
"start": "npm run build && concurrently \"npm run tsc:w\" \"npm run server\" ",
"server": "wsrv -o -s -l",
"build": "npm run tslint && rimraf dist && tsc",
"build:w": "npm run tslint && rimraf dist && tsc -w",
"build": "npm run tslint && npm run clean-build && npm run tsc",
"build:w": "npm run tslint && rimraf dist && npm run tsc:w",
"tsc": "tsc",
"tsc:w": "tsc -w",
"tslint": "tslint -c tslint.json *.ts && tslint -c tslint.json src/{,**/}**.ts"
"tslint": "tslint -c tslint.json *.ts && tslint -c tslint.json src/{,**/}**.ts -e '{,**/}**.d.ts'"
},
"license": "Apache-2.0",
"contributors": [
@@ -30,41 +31,40 @@
"activiti-diagrams"
],
"dependencies": {
"@angular/common": "2.0.0",
"@angular/compiler": "2.0.0",
"@angular/core": "2.0.0",
"@angular/forms": "2.0.0",
"@angular/http": "2.0.0",
"@angular/platform-browser": "2.0.0",
"@angular/platform-browser-dynamic": "2.0.0",
"@angular/common": "2.2.2",
"@angular/compiler": "2.2.2",
"@angular/compiler-cli": "2.2.2",
"@angular/core": "2.2.2",
"@angular/forms": "2.2.2",
"@angular/http": "2.2.2",
"@angular/platform-browser": "2.2.2",
"@angular/platform-browser-dynamic": "2.2.2",
"@angular/router": "3.2.2",
"@angular/upgrade": "2.2.2",
"core-js": "^2.4.1",
"reflect-metadata": "^0.1.3",
"rxjs": "5.0.0-beta.12",
"systemjs": "0.19.27",
"zone.js": "^0.6.23",
"intl": "1.2.4",
"dialog-polyfill": "^0.4.3",
"element.scrollintoviewifneeded-polyfill": "^1.0.1",
"material-design-icons": "2.2.3",
"material-design-lite": "1.2.1",
"chart.js": "^2.1.4",
"md-date-time-picker": "^2.2.0",
"ng2-charts": "1.1.0",
"moment": "2.15.1",
"raphael": "^2.2.6",
"ng2-translate": "2.5.0",
"alfresco-js-api": "^0.5.0",
"ng2-alfresco-core": "0.5.0",
"ng2-activiti-diagrams": "0.5.0",
"ng2-activiti-analytics": "^0.5.0"
"alfresco-js-api": "^1.0.0",
"ng2-alfresco-core": "1.0.0",
"ng2-activiti-diagrams": "1.0.0",
"ng2-activiti-analytics": "^1.0.0"
},
"devDependencies": {
"@types/node": "^6.0.42",
"@types/core-js": "^0.9.32",
"@types/jasmine": "^2.2.33",
"@types/node": "^6.0.42",
"concurrently": "^2.2.0",
"rimraf": "2.5.2",
"tslint": "^3.8.1",
@@ -18,7 +18,7 @@
import { NgModule, Component, OnInit } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { CoreModule, AlfrescoSettingsService, AlfrescoAuthenticationService } from 'ng2-alfresco-core';
import { CoreModule, AlfrescoSettingsService, AlfrescoAuthenticationService, StorageService } from 'ng2-alfresco-core';
import { AnalyticsModule } from 'ng2-activiti-analytics';
@Component({
@@ -60,7 +60,9 @@ export class AnalyticsDemoComponent implements OnInit {
ticket: string;
constructor(private authService: AlfrescoAuthenticationService, private settingsService: AlfrescoSettingsService) {
constructor(private authService: AlfrescoAuthenticationService,
private settingsService: AlfrescoSettingsService,
private storage: StorageService) {
settingsService.bpmHost = this.host;
settingsService.setProviders('BPM');
@@ -74,7 +76,7 @@ export class AnalyticsDemoComponent implements OnInit {
}
public updateTicket(): void {
localStorage.setItem('ticket-BPM', this.ticket);
this.storage.setItem('ticket-BPM', this.ticket);
}
public updateHost(): void {
@@ -11,7 +11,7 @@
// map tells the System loader where to look for things
map: {
// our app is within the app folder
app: 'dist',
app: 'src',
// angular bundles
'@angular/core': 'npm:@angular/core/bundles/core.umd.js',
'@angular/common': 'npm:@angular/common/bundles/common.umd.js',
@@ -27,9 +27,9 @@
'ng2-charts': 'npm:ng2-charts',
'ng2-translate': 'npm:ng2-translate',
'alfresco-js-api': 'npm:alfresco-js-api/dist',
'ng2-alfresco-core': 'npm:ng2-alfresco-core/dist',
'ng2-activiti-diagrams': 'npm:ng2-activiti-diagrams/dist',
'ng2-activiti-analytics': 'npm:ng2-activiti-analytics/dist'
'ng2-alfresco-core': 'npm:ng2-alfresco-core',
'ng2-activiti-diagrams': 'npm:ng2-activiti-diagrams',
'ng2-activiti-analytics': 'npm:ng2-activiti-analytics'
},
// packages tells the System loader how to load when no filename and/or no extension
packages: {
@@ -40,6 +40,7 @@
rxjs: {
defaultExtension: 'js'
},
'moment': 'npm:moment/min/moment.min.js',
'ng2-translate': { defaultExtension: 'js' },
'ng2-charts': { main: 'ng2-charts.js', defaultExtension: 'js'},
'alfresco-js-api': { main: './alfresco-js-api.js', defaultExtension: 'js'},
@@ -3,11 +3,10 @@
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"sourceMap": true,
"removeComments": true,
"declaration": true,
"skipLibCheck": true,
"noLib": false,
"allowUnreachableCode": false,
"allowUnusedLabels": false,
@@ -15,12 +14,19 @@
"noImplicitReturns": false,
"noImplicitUseStrict": false,
"noFallthroughCasesInSwitch": true,
"outDir": "dist",
"types": ["core-js", "jasmine", "node"]
"removeComments": true,
"declaration": true,
"lib": [
"es2015",
"dom"
],
"suppressImplicitAnyIndexErrors": true
},
"exclude": [
"demo",
"node_modules",
"dist"
]
"node_modules"
],
"angularCompilerOptions": {
"strictMetadataEmit": false,
"skipTemplateCodegen": true
}
}
+312
View File
@@ -0,0 +1,312 @@
import * as gulp from 'gulp';
import * as util from 'gulp-util';
import * as runSequence from 'run-sequence';
import * as gulpLoadPlugins from 'gulp-load-plugins';
import * as merge from 'merge-stream';
import * as rimraf from 'rimraf';
import { join } from 'path';
import * as Builder from 'systemjs-builder';
var autoprefixer = require('autoprefixer');
import * as cssnano from 'cssnano';
import * as filter from 'gulp-filter';
import * as sourcemaps from 'gulp-sourcemaps';
var APP_SRC = `.`;
var CSS_PROD_BUNDLE = 'main.css';
var JS_PROD_SHIMS_BUNDLE = 'shims.js';
var NG_FACTORY_FILE = 'main-prod';
const BUILD_TYPES = {
DEVELOPMENT: 'dev',
PRODUCTION: 'prod'
};
function normalizeDependencies(deps) {
deps
.filter((d) => !/\*/.test(d.src)) // Skip globs
.forEach((d) => d.src = require.resolve(d.src));
return deps;
}
function filterDependency(type: string, d): boolean {
const t = d.buildType || d.env;
d.buildType = t;
if (!t) {
d.buildType = Object.keys(BUILD_TYPES).map(k => BUILD_TYPES[k]);
}
if (!(d.buildType instanceof Array)) {
(<any>d).env = [d.buildType];
}
return d.buildType.indexOf(type) >= 0;
}
function getInjectableDependency() {
var APP_ASSETS = [
{src: `src/css/main.css`, inject: true, vendor: false},
];
var NPM_DEPENDENCIES = [
{src: 'zone.js/dist/zone.js', inject: 'libs'},
{src: 'core-js/client/shim.min.js', inject: 'shims'},
{src: 'intl/dist/Intl.min.js', inject: 'shims'},
{src: 'systemjs/dist/system.src.js', inject: 'shims', buildType:'dev'}
];
return normalizeDependencies(NPM_DEPENDENCIES.filter(filterDependency.bind(null, 'dev')))
.concat(APP_ASSETS.filter(filterDependency.bind(null, 'dev')));
}
const plugins = <any>gulpLoadPlugins();
let tsProjects: any = {};
function makeTsProject(options: Object = {}) {
let optionsHash = JSON.stringify(options);
if (!tsProjects[optionsHash]) {
let config = Object.assign({
typescript: require('typescript')
}, options);
tsProjects[optionsHash] =
plugins.typescript.createProject('tsconfig.json', config);
}
return tsProjects[optionsHash];
}
gulp.task('build.html_css', () => {
const gulpConcatCssConfig = {
targetFile: CSS_PROD_BUNDLE,
options: {
rebaseUrls: false
}
};
const processors = [
autoprefixer({
browsers: [
'ie >= 10',
'ie_mob >= 10',
'ff >= 30',
'chrome >= 34',
'safari >= 7',
'opera >= 23',
'ios >= 7',
'android >= 4.4',
'bb >= 10'
]
})
];
const reportPostCssError = (e: any) => util.log(util.colors.red(e.message));
processors.push(
cssnano({
discardComments: {removeAll: true},
discardUnused: false, // unsafe, see http://goo.gl/RtrzwF
zindex: false, // unsafe, see http://goo.gl/vZ4gbQ
reduceIdents: false // unsafe, see http://goo.gl/tNOPv0
})
);
/**
* Processes the CSS files within `src/client` excluding those in `src/client/assets` using `postcss` with the
* configured processors
* Execute the appropriate component-stylesheet processing method based on user stylesheet preference.
*/
function processComponentStylesheets() {
return gulp.src(join('src/**', '*.css'))
.pipe(plugins.cached('process-component-css'))
.pipe(plugins.postcss(processors))
.on('error', reportPostCssError);
}
/**
* Get a stream of external css files for subsequent processing.
*/
function getExternalCssStream() {
return gulp.src(getExternalCss())
.pipe(plugins.cached('process-external-css'));
}
/**
* Get an array of filenames referring to all external css stylesheets.
*/
function getExternalCss() {
return getInjectableDependency().filter(dep => /\.css$/.test(dep.src)).map(dep => dep.src);
}
/**
* Processes the external CSS files using `postcss` with the configured processors.
*/
function processExternalCss() {
return getExternalCssStream()
.pipe(plugins.postcss(processors))
.pipe(plugins.concatCss(gulpConcatCssConfig.targetFile, gulpConcatCssConfig.options))
.on('error', reportPostCssError);
}
return merge(processComponentStylesheets(), processExternalCss());
});
gulp.task('build.bundles.app', (done) => {
var BUNDLER_OPTIONS = {
format: 'umd',
minify: false,
mangle: false,
sourceMaps: true
};
var CONFIG_TYPESCRIPT = {
baseURL: '.',
transpiler: 'typescript',
typescriptOptions: {
module: 'cjs'
},
map: {
typescript: 'node_modules/typescript/lib/typescript.js',
'@angular': 'node_modules/@angular',
rxjs: 'node_modules/rxjs',
'ng2-translate': 'node_modules/ng2-translate',
'alfresco-js-api': 'node_modules/alfresco-js-api/dist/alfresco-js-api',
'ng2-alfresco-core': 'node_modules/ng2-alfresco-core/',
'ng2-activiti-diagrams': 'node_modules/ng2-activiti-diagrams/',
'ng2-activiti-analytics': 'node_modules/ng2-activiti-analytics/',
'ng2-alfresco-datatable': 'node_modules/ng2-alfresco-datatable/',
'ng2-alfresco-documentlist': 'node_modules/ng2-alfresco-documentlist/',
'ng2-activiti-form': 'node_modules/ng2-activiti-form/',
'ng2-alfresco-login': 'node_modules/ng2-alfresco-login/',
'ng2-activiti-processlist': 'node_modules/ng2-activiti-processlist/',
'ng2-alfresco-search': 'node_modules/ng2-alfresco-search/',
'ng2-activiti-tasklist': 'node_modules/ng2-activiti-tasklist/',
'ng2-alfresco-tag': 'node_modules/ng2-alfresco-tag/',
'ng2-alfresco-upload': 'node_modules/ng2-alfresco-upload/',
'ng2-alfresco-userinfo': 'node_modules/ng2-alfresco-userinfo/',
'ng2-alfresco-viewer': 'node_modules/ng2-alfresco-viewer/',
'ng2-alfresco-webscript': 'node_modules/ng2-alfresco-webscript/',
'ng2-charts': 'node_modules/ng2-charts',
'moment': 'node_modules/moment/min/moment.min'
},
paths: {
'*': '*.js'
},
meta: {
'node_modules/@angular/*': {build: false},
'node_modules/rxjs/*': {build: false},
'node_modules/ng2-translate/*': {build: false},
'node_modules/ng2-charts/*': {build: false},
'node_modules/ng2-alfresco-core/*': {build: false},
'node_modules/ng2-activiti-diagrams/*': {build: false},
'node_modules/ng2-activiti-analytics/*': {build: false},
'node_modules/ng2-alfresco-datatable/*': {build: false},
'node_modules/ng2-alfresco-documentlist/*': {build: false},
'node_modules/ng2-activiti-form/*': {build: false},
'node_modules/ng2-alfresco-login/*': {build: false},
'node_modules/ng2-activiti-processlist/*': {build: false},
'node_modules/ng2-alfresco-search/*': {build: false},
'node_modules/ng2-activiti-tasklist/*': {build: false},
'node_modules/ng2-alfresco-tag/*': {build: false},
'node_modules/ng2-alfresco-upload/*': {build: false},
'node_modules/ng2-alfresco-userinfo/*': {build: false},
'node_modules/ng2-alfresco-viewer/*': {build: false},
'node_modules/ng2-alfresco-webscript/*': {build: false}
}
};
var pkg = require('./package.json');
var namePkg = pkg.name;
var builder = new Builder(CONFIG_TYPESCRIPT);
builder
.buildStatic(APP_SRC + "/index", 'bundles/' + namePkg + '.js', BUNDLER_OPTIONS)
.then(function () {
return done();
})
.catch(function (err) {
return done(err);
});
});
gulp.task('build.assets.prod', () => {
return gulp.src([
join('src/**', '*.ts'),
'index.ts',
join('src/**', '*.css'),
join('src/**', '*.html'),
'!'+join('*/**', '*.d.ts'),
'!'+join('*/**', '*.spec.ts'),
'!gulpfile.ts'])
});
gulp.task('build.bundles', () => {
merge(bundleShims());
/**
* Returns the shim files to be injected.
*/
function getShims() {
let libs = getInjectableDependency()
.filter(d => /\.js$/.test(d.src));
return libs.filter(l => l.inject === 'shims')
.concat(libs.filter(l => l.inject === 'libs'))
.concat(libs.filter(l => l.inject === true))
.map(l => l.src);
}
/**
* Bundles the shim files.
*/
function bundleShims() {
return gulp.src(getShims())
.pipe(plugins.concat(JS_PROD_SHIMS_BUNDLE))
// Strip the first (global) 'use strict' added by reflect-metadata, but don't strip any others to avoid unintended scope leaks.
.pipe(plugins.replace(/('|")use strict\1;var Reflect;/, 'var Reflect;'))
.pipe(gulp.dest('bundles'));
}
});
gulp.task('build.js.prod', () => {
const INLINE_OPTIONS = {
base: APP_SRC,
target: 'es5',
useRelativePaths: true,
removeLineBreaks: true
};
let tsProject = makeTsProject();
let src = [
join('src/**/*.ts'),
join('!src/**/*.d.ts'),
join('!src/**/*.spec.ts'),
`!src/**/${NG_FACTORY_FILE}.ts`
];
let result = gulp.src(src)
.pipe(plugins.plumber())
.pipe(plugins.inlineNg2Template(INLINE_OPTIONS))
.pipe(sourcemaps.init())
.pipe(tsProject())
.once('error', function (e: any) {
this.once('finish', () => process.exit(1));
});
return result.js
.pipe(plugins.template())
.pipe(sourcemaps.write())
.pipe(gulp.dest('src'))
.on('error', (e: any) => {
console.log(e);
});
});
gulp.task('build.prod', (done: any) =>
runSequence(
'build.assets.prod',
'build.html_css',
'build.js.prod',
'build.bundles',
'build.bundles.app',
done));
@@ -5,7 +5,7 @@ jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000;
__karma__.loaded = function() {};
var builtPath = '/base/dist/';
var builtPath = '/base/src/';
function isJsFile(path) {
return path.slice(-3) == '.js';
@@ -29,7 +29,7 @@ var paths = {
};
var map = {
'app': 'base/dist',
'app': 'base/src',
// angular bundles
'@angular/core': 'npm:@angular/core/bundles/core.umd.js',
'@angular/common': 'npm:@angular/common/bundles/common.umd.js',
@@ -57,9 +57,8 @@ var map = {
'moment' : 'npm:moment/min/moment.min.js',
'alfresco-js-api': 'npm:alfresco-js-api/dist',
'ng2-activiti-analytics': 'npm:ng2-activiti-analytics/dist',
'ng2-activiti-diagrams': 'npm:ng2-activiti-diagrams/dist',
'ng2-alfresco-core': 'npm:ng2-alfresco-core/dist'
'ng2-activiti-diagrams': 'npm:ng2-activiti-diagrams',
'ng2-alfresco-core': 'npm:ng2-alfresco-core'
};
var packages = {
@@ -71,7 +70,6 @@ var packages = {
'moment': { defaultExtension: 'js' },
'alfresco-js-api': { main: './alfresco-js-api.js', defaultExtension: 'js'},
'ng2-activiti-analytics': { main: './index.js', defaultExtension: 'js'},
'ng2-activiti-diagrams': { main: './index.js', defaultExtension: 'js'},
'ng2-alfresco-core': { main: './index.js', defaultExtension: 'js'}
};
@@ -24,8 +24,8 @@ module.exports = function (config) {
'node_modules/zone.js/dist/fake-async-test.js',
// RxJs
{pattern: 'node_modules/rxjs/**/*.js', included: false, watched: false},
{pattern: 'node_modules/rxjs/**/*.js.map', included: false, watched: false},
{ pattern: 'node_modules/rxjs/**/*.js', included: false, watched: false },
{ pattern: 'node_modules/rxjs/**/*.js.map', included: false, watched: false },
// Paths loaded via module imports:
// Angular itself
@@ -41,20 +41,25 @@ module.exports = function (config) {
'karma-test-shim.js',
// 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},
{pattern: 'src/**/*.js', included: false, watched: true},
{pattern: 'src/**/*.html', included: true, served: true, watched: true},
{pattern: 'src/**/*.css', included: true, served: true, watched: true},
// ng2-components
{ pattern: 'node_modules/ng2-alfresco-core/dist/**/*.*', included: false, served: true, watched: false },
{ pattern: 'node_modules/ng2-activiti-diagrams/dist/**/*.*', included: false, served: true, watched: false },
{ pattern: 'node_modules/ng2-alfresco-core/src/**/*.*', included: false, served: true, watched: false },
{ pattern: 'node_modules/ng2-alfresco-core/index.js', included: false, served: true, watched: false },
{ pattern: 'node_modules/ng2-activiti-diagrams/src/**/*.*', included: false, served: true, watched: false },
{ pattern: 'node_modules/ng2-activiti-diagrams/index.js', included: false, served: true, watched: false },
{ pattern: 'node_modules/ng2-charts/**/*.js', included: false, served: true, watched: false },
{ pattern: 'node_modules/md-date-time-picker/**/*.js', included: false, served: true, watched: false },
{ pattern: 'node_modules/moment/**/*.js', included: false, served: true, watched: false },
// 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}
{pattern: 'src/**/*.js.map', included: false, watched: false},
{pattern: 'src/**/*.json', included: false, watched: false}
],
exclude: [
@@ -102,7 +107,7 @@ module.exports = function (config) {
// Source files that you wanna generate coverage for.
// Do not include tests or libraries (these files will be instrumented by Istanbul)
preprocessors: {
'dist/**/!(*spec|index|*mock|*model).js': 'coverage'
'src/**/!(*spec|index|*mock|*model).js': 'coverage'
},
coverageReporter: {
@@ -1,28 +1,30 @@
{
"name": "ng2-activiti-analytics",
"description": "Activiti Angular2 Analytics Component",
"version": "0.5.0",
"version": "1.0.0",
"author": "Alfresco Software, Ltd.",
"main": "./dist/index.js",
"typings": "./dist/index.d.ts",
"scripts": {
"clean": "npm install rimraf && rimraf dist node_modules typings",
"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",
"clean": "npm install rimraf && npm run clean-build && rimraf dist node_modules typings",
"clean-build": "rimraf index.js index.js.map index.d.ts'src/{,**/}**.js' 'src/{,**/}**.js.map' 'src/{,**/}**.d.ts' bundles",
"build": "npm run clean-build && npm run tslint && rimraf dist && tsc && license-check && npm run build.umd",
"build:w": "npm run clean-build && npm run tslint && rimraf dist && tsc:w && license-check npm run build.umd",
"tslint": "tslint -c tslint.json 'src/{,**/}**.ts' 'index.ts' -e '{,**/}**.d.ts' -e './gulpfile.ts'",
"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\"",
"test-browser": "npm run build && 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 ng2-activiti-diagrams"
"travis": "npm link ng2-alfresco-core ng2-activiti-diagrams",
"gulp": "gulp",
"build.umd": "gulp build.prod --color --env-config prod --build-type prod",
"reinstall": "npm cache clean && npm install"
},
"main": "./index.js",
"module": "./index.js",
"typings": "./index.d.ts",
"contributors": [
{
"name": "Mario Romano",
@@ -41,6 +43,7 @@
"url": "https://github.com/Alfresco/alfresco-ng2-components/issues"
},
"dependencies": {
"@angular/router": "3.0.0",
"@angular/common": "2.0.0",
"@angular/compiler": "2.0.0",
"@angular/core": "2.0.0",
@@ -53,36 +56,53 @@
"rxjs": "5.0.0-beta.12",
"systemjs": "0.19.27",
"zone.js": "^0.6.23",
"chart.js": "^2.1.4",
"md-date-time-picker": "^2.2.0",
"ng2-charts": "1.1.0",
"moment": "2.15.1",
"raphael": "^2.2.6",
"alfresco-js-api": "^0.5.0",
"alfresco-js-api": "^1.0.0",
"ng2-translate": "2.5.0",
"ng2-alfresco-core": "0.5.0",
"ng2-activiti-diagrams": "0.5.0"
"ng2-alfresco-core": "1.0.0",
"ng2-activiti-diagrams": "1.0.0"
},
"devDependencies": {
"@types/node": "^6.0.42",
"@types/core-js": "^0.9.32",
"@types/jasmine": "^2.2.33",
"@types/node": "^6.0.42",
"concurrently": "^2.2.0",
"cpx": "1.3.1",
"cssnano": "^3.8.1",
"gulp": "^3.9.1",
"gulp-autoprefixer": "^3.1.1",
"gulp-cached": "^1.1.1",
"gulp-concat": "^2.6.1",
"gulp-concat-css": "^2.3.0",
"gulp-filter": "^4.0.0",
"gulp-inline-ng2-template": "^4.0.0",
"gulp-load-plugins": "^1.4.0",
"gulp-plumber": "^1.1.0",
"gulp-postcss": "^6.2.0",
"gulp-replace": "^0.5.4",
"gulp-sourcemaps": "^1.9.1",
"gulp-template": "^4.0.0",
"gulp-typescript": "^3.1.3",
"gulp-uglify": "^2.0.0",
"intl": "^1.2.5",
"jasmine-core": "2.4.1",
"karma": "0.13.22",
"karma-chrome-launcher": "1.0.1",
"karma-coverage": "1.0.0",
"karma-jasmine": "1.0.2",
"karma-jasmine-ajax": "^0.1.13",
"karma-mocha-reporter": "2.0.3",
"karma-jasmine-html-reporter": "0.2.0",
"karma-mocha-reporter": "2.0.3",
"license-check": "1.1.5",
"remap-istanbul": "0.6.3",
"rimraf": "2.5.2",
"run-sequence": "^1.2.2",
"systemjs-builder": "^0.15.34",
"traceur": "0.0.91",
"ts-node": "^1.7.0",
"tslint": "3.15.1",
"typescript": "^2.0.3",
"wsrv": "^0.1.5"
@@ -93,7 +113,7 @@
],
"license-check-config": {
"src": [
"./dist/**/*.js"
"./src/**/*.js"
],
"path": "assets/license_header.txt",
"blocking": true,
@@ -1,9 +1,9 @@
<h2>Process Heat map</h2>
<h4>Process Heat map</h4>
<div *ngIf="hasMetric()">
<form [formGroup]="metricForm" novalidate>
<dropdown-widget [field]="field" [group]="metricForm.controls.metricGroup" [controllerName]="'metric'"
(fieldChanged)="onMetricChanges(field)" [showDefaultOption]="false"></dropdown-widget>
</form>
<activiti-diagram *ngIf="currentMetric" [processDefinitionId]="report.processDefinitionId" [metricPercentages]="currentMetric"></activiti-diagram>
<activiti-diagram *ngIf="currentMetric" [processDefinitionId]="report.processDefinitionId" [metricPercentages]="currentMetric" [metricColor]="currentMetricColors" [metricType]="metricType"></activiti-diagram>
</div>
<div *ngIf="!hasMetric()">No metric found</div>
<div *ngIf="!hasMetric()">No metric found</div>
@@ -33,9 +33,13 @@ describe('Test ng2-activiti-analytics-report-heat-map', () => {
let debug: DebugElement;
let element: HTMLElement;
let totalCountPerc = {'sid-fake-id': 0, 'fake-start-event': 100};
let totalTimePerc = {'sid-fake-id': 10, 'fake-start-event': 30};
let avgTimePercentages = {'sid-fake-id': 5, 'fake-start-event': 50};
let totalCountPerc = { 'sid-fake-id': 0, 'fake-start-event': 100 };
let totalTimePerc = { 'sid-fake-id': 10, 'fake-start-event': 30 };
let avgTimePercentages = { 'sid-fake-id': 5, 'fake-start-event': 50 };
let totalCountValues = { 'sid-fake-id': 2, 'fake-start-event': 3 };
let totalTimeValues = { 'sid-fake-id': 1, 'fake-start-event': 4 };
let avgTimeValues = { 'sid-fake-id': 4, 'fake-start-event': 5 };
beforeEach(async(() => {
TestBed.configureTestingModule({
@@ -65,7 +69,10 @@ describe('Test ng2-activiti-analytics-report-heat-map', () => {
component.report = {
totalCountsPercentages: totalCountPerc,
totalCountValues: totalCountValues,
totalTimePercentages: totalTimePerc,
totalTimeValues: totalTimeValues,
avgTimeValues: avgTimeValues,
avgTimePercentages: avgTimePercentages
};
});
@@ -81,7 +88,7 @@ describe('Test ng2-activiti-analytics-report-heat-map', () => {
});
it('should render the dropdown with the metric options', async(() => {
component.report = {totalCountsPercentages: {'sid-fake-id': 10, 'fake-start-event': 30}};
component.report = { totalCountsPercentages: { 'sid-fake-id': 10, 'fake-start-event': 30 } };
component.onSuccess.subscribe(() => {
fixture.whenStable().then(() => {
@@ -106,21 +113,24 @@ describe('Test ng2-activiti-analytics-report-heat-map', () => {
}));
it('should change the currentmetric width totalCount', async(() => {
let field = {value: 'totalCount'};
let field = { value: 'totalCount' };
component.onMetricChanges(field);
expect(component.currentMetric).toEqual(totalCountPerc);
expect(component.currentMetric).toEqual(totalCountValues);
expect(component.currentMetricColors).toEqual(totalCountPerc);
}));
it('should change the currentmetric width totalTime', async(() => {
let field = {value: 'totalTime'};
let field = { value: 'totalTime' };
component.onMetricChanges(field);
expect(component.currentMetric).toEqual(totalTimePerc);
expect(component.currentMetric).toEqual(totalTimeValues);
expect(component.currentMetricColors).toEqual(totalTimePerc);
}));
it('should change the currentmetric width avgTime', async(() => {
let field = {value: 'avgTime'};
let field = { value: 'avgTime' };
component.onMetricChanges(field);
expect(component.currentMetric).toEqual(avgTimePercentages);
expect(component.currentMetric).toEqual(avgTimeValues);
expect(component.currentMetricColors).toEqual(avgTimePercentages);
}));
});
@@ -40,12 +40,14 @@ export class AnalyticsReportHeatMapComponent implements OnInit {
metricForm: FormGroup;
currentMetric: string;
currentMetricColors: string;
metricType: string;
constructor(private translate: AlfrescoTranslationService,
private analyticsService: AnalyticsService,
private formBuilder: FormBuilder) {
if (translate) {
translate.addTranslationFolder('ng2-activiti-analytics', 'node_modules/ng2-activiti-analytics/dist/src');
translate.addTranslationFolder('ng2-activiti-analytics', 'node_modules/ng2-activiti-analytics/src');
}
}
@@ -64,11 +66,17 @@ export class AnalyticsReportHeatMapComponent implements OnInit {
onMetricChanges(field: any) {
if (field.value === 'totalCount') {
this.currentMetric = this.report.totalCountsPercentages;
this.currentMetric = this.report.totalCountValues;
this.currentMetricColors = this.report.totalCountsPercentages;
this.metricType = 'times';
} else if (field.value === 'totalTime') {
this.currentMetric = this.report.totalTimePercentages;
this.currentMetric = this.report.totalTimeValues;
this.currentMetricColors = this.report.totalTimePercentages;
this.metricType = 'hours';
} else if (field.value === 'avgTime') {
this.currentMetric = this.report.avgTimePercentages;
this.currentMetric = this.report.avgTimeValues;
this.currentMetricColors = this.report.avgTimePercentages;
this.metricType = 'hours';
}
}
@@ -82,8 +82,26 @@ describe('Test ng2-activiti-analytics Report list', () => {
});
it('should return the default reports when the report list is empty', (done) => {
jasmine.Ajax.stubRequest('http://localhost:9999/activiti-app/app/rest/reporting/reports').andReturn({
status: 200,
contentType: 'json',
responseText: []
});
fixture.detectChanges();
jasmine.Ajax.stubRequest('http://localhost:9999/activiti-app/app/rest/reporting/default-reports').andReturn({
status: 200,
contentType: 'json',
responseText: []
});
jasmine.Ajax.stubRequest('http://localhost:9999/activiti-app/app/rest/reporting/reports').andReturn({
status: 200,
contentType: 'json',
responseText: reportList
});
component.onSuccess.subscribe(() => {
fixture.detectChanges();
expect(element.querySelector('#report-list-0 > i').innerHTML).toBe('assignment');
@@ -96,23 +114,6 @@ describe('Test ng2-activiti-analytics Report list', () => {
done();
});
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'json',
responseText: []
});
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'json',
responseText: []
});
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'json',
responseText: reportList
});
});
it('Report render the report list relative to a single app', (done) => {
@@ -57,13 +57,21 @@ export class AnalyticsReportListComponent implements OnInit {
this.reports.push(report);
});
this.getReportListByAppId();
this.getReportList();
}
/**
* Get the report list by app id
* Reload the component
*/
getReportListByAppId() {
reload() {
this.reset();
this.getReportList();
}
/**
* Get the report list
*/
getReportList() {
this.analyticsService.getReportList().subscribe(
(res: ReportParametersModel[]) => {
if (res && res.length === 0) {
@@ -108,6 +116,15 @@ export class AnalyticsReportListComponent implements OnInit {
return this.reports === undefined || (this.reports && this.reports.length === 0);
}
/**
* Reset the list
*/
private reset() {
if (!this.isReportsEmpty()) {
this.reports = [];
}
}
/**
* Select the current report
* @param report
@@ -21,3 +21,30 @@
.dropdown-widget__invalid .mdl-textfield__error {
visibility: visible !important;
}
.large {
font-size: x-large;
margin-top: 24px;
margin-left: 12px;
}
.icon-small i {
float: left;
margin-right: 10px;
display: none;
position: absolute;
}
.icon-small h4 {
clear: left;
margin-left: 26px;
}
.icon-small:hover {
color: rgb(68,138,255);
cursor: pointer;
}
.icon-small:hover .material-icons {
display: block;
}
@@ -1,7 +1,24 @@
<div class="col-md-6">
<div *ngIf="reportParameters">
<form [formGroup]="reportForm" novalidate>
<h1>{{reportParameters.name}}</h1>
<div *ngIf="isEditable">
<input
type="text"
class="mdl-textfield__input large"
id="reportName"
autofocus
data-automation-id="reportName"
[value]="reportParameters.name"
(input)="reportParameters.name=$event.target.value"
(blur)="editTitle($event)"
/>
</div>
<div *ngIf="!isEditable">
<span class="icon-small">
<i class="material-icons">mode_edit</i>
<h4 (click)="editEnable()">{{reportParameters.name}}</h4>
</span>
</div><hr>
<div *ngFor="let field of reportParameters.definition.parameters">
<div [ngSwitch]="field.type">
<div *ngSwitchCase="'integer'">
@@ -55,4 +72,4 @@
</div>
</form>
</div>
</div>
</div>
@@ -87,7 +87,7 @@ describe('Test ng2-analytics-report-parameters Report Parameters ', () => {
component.onSuccessReportParams.subscribe(() => {
fixture.detectChanges();
let dropDown: any = element.querySelector('#select-status');
expect(element.querySelector('h1').innerHTML).toEqual('Fake Task overview status');
expect(element.querySelector('h4').innerHTML).toEqual('Fake Task overview status');
expect(dropDown).toBeDefined();
expect(dropDown.length).toEqual(4);
expect(dropDown[0].innerHTML).toEqual('Choose One');
@@ -280,21 +280,22 @@ describe('Test ng2-analytics-report-parameters Report Parameters ', () => {
done();
});
let reportId = 1;
let change = new SimpleChange(null, reportId);
component.ngOnChanges({ 'reportId': change });
jasmine.Ajax.requests.first().respondWith({
jasmine.Ajax.stubRequest('http://localhost:9999/activiti-app/app/rest/reporting/report-params/1').andReturn({
status: 200,
contentType: 'json',
responseText: analyticParamsMock.reportDefParamProcessDef
});
jasmine.Ajax.requests.mostRecent().respondWith({
jasmine.Ajax.stubRequest('http://localhost:9999/activiti-app/app/rest/reporting/process-definitions').andReturn({
status: 200,
contentType: 'json',
responseText: analyticParamsMock.reportDefParamProcessDefOptionsNoApp
});
let reportId = 1;
let change = new SimpleChange(null, reportId);
component.ngOnChanges({ 'reportId': change });
});
it('Should render a dropdown with all the process definition when the definition parameter type is \'processDefinition\' and the' +
@@ -310,22 +311,24 @@ describe('Test ng2-analytics-report-parameters Report Parameters ', () => {
done();
});
let appId = 1;
component.appId = appId;
let change = new SimpleChange(null, appId);
component.ngOnChanges({ 'appId': change });
jasmine.Ajax.requests.first().respondWith({
jasmine.Ajax.stubRequest('http://localhost:9999/activiti-app/app/rest/reporting/report-params/1').andReturn({
status: 200,
contentType: 'json',
responseText: analyticParamsMock.reportDefParamProcessDef
});
jasmine.Ajax.requests.mostRecent().respondWith({
jasmine.Ajax.stubRequest('http://localhost:9999/activiti-app/api/enterprise/process-definitions').andReturn({
status: 200,
contentType: 'json',
responseText: analyticParamsMock.reportDefParamProcessDefOptionsApp
});
let appId = 1;
component.appId = appId;
component.reportId = 1;
let change = new SimpleChange(null, appId);
component.ngOnChanges({ 'appId': change });
});
it('Should load the task list when a process definition is selected', () => {
@@ -355,21 +358,22 @@ describe('Test ng2-analytics-report-parameters Report Parameters ', () => {
done();
});
let reportId = 1;
let change = new SimpleChange(null, reportId);
component.ngOnChanges({ 'reportId': change });
jasmine.Ajax.requests.first().respondWith({
jasmine.Ajax.stubRequest('http://localhost:9999/activiti-app/app/rest/reporting/report-params/1').andReturn({
status: 200,
contentType: 'json',
responseText: analyticParamsMock.reportDefParamProcessDef
});
jasmine.Ajax.requests.mostRecent().respondWith({
jasmine.Ajax.stubRequest('http://localhost:9999/activiti-app/app/rest/reporting/process-definitions').andReturn({
status: 404,
contentType: 'json',
responseText: []
});
let reportId = 1;
let change = new SimpleChange(null, reportId);
component.ngOnChanges({ 'reportId': change });
});
it('Should emit an error with a 404 response when the report parameters response is not found', (done) => {
@@ -47,6 +47,9 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges {
@Output()
onError = new EventEmitter();
@Output()
onEdit = new EventEmitter();
@Output()
onFormValueChanged = new EventEmitter();
@@ -63,12 +66,13 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges {
private dropDownSub;
private reportParamsSub;
private paramOpts;
private isEditable: boolean = false;
constructor(private translate: AlfrescoTranslationService,
private analyticsService: AnalyticsService,
private formBuilder: FormBuilder ) {
if (translate) {
translate.addTranslationFolder('ng2-activiti-analytics', 'node_modules/ng2-activiti-analytics/dist/src');
translate.addTranslationFolder('ng2-activiti-analytics', 'node_modules/ng2-activiti-analytics/src');
}
}
@@ -92,6 +96,7 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges {
}
ngOnChanges(changes: SimpleChanges) {
this.isEditable = false;
let reportId = changes['reportId'];
if (reportId && reportId.currentValue) {
this.getReportParams(reportId.currentValue);
@@ -210,4 +215,25 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges {
this.reportParamsSub.unsubscribe();
}
}
public editEnable() {
this.isEditable = true;
}
public editDisable() {
this.isEditable = false;
}
public editTitle() {
this.reportParamsSub = this.analyticsService.updateReport(this.reportParameters.id, this.reportParameters.name).subscribe(
(res: ReportParametersModel) => {
this.editDisable();
this.onEdit.emit(this.reportParameters.name);
},
(err: any) => {
console.log(err);
this.onError.emit(err);
}
);
}
}
@@ -1,10 +1,13 @@
<div class="col-md-6">
<analytics-report-parameters [appId]="appId" [reportId]="reportId"
(onFormValueChanged)="reset()" (onSuccess)="showReport($event)"></analytics-report-parameters>
(onFormValueChanged)="reset()"
(onSuccess)="showReport($event)"
(onEdit)="onEditReport($event)">
</analytics-report-parameters>
<div *ngIf="reports">
<div *ngFor="let report of reports">
<h2>{{report.title}}</h2>
<h4>{{report.title}}</h4>
<div [ngSwitch]="report.type">
<div *ngSwitchCase="'pie'">
<div class="col-md-6">
@@ -190,6 +190,7 @@ describe('Test ng2-activiti-analytics Report ', () => {
});
let reportParamQuery = new ReportQuery({status: 'All'});
component.reportId = 1;
component.showReport(reportParamQuery);
jasmine.Ajax.requests.mostRecent().respondWith({
@@ -214,6 +215,7 @@ describe('Test ng2-activiti-analytics Report ', () => {
});
let reportParamQuery = new ReportQuery({status: 'All'});
component.reportId = 1;
component.showReport(reportParamQuery);
jasmine.Ajax.requests.mostRecent().respondWith({
@@ -41,12 +41,15 @@ export class AnalyticsComponent implements OnChanges {
@Output()
onSuccess = new EventEmitter();
@Output()
editReport = new EventEmitter();
@Output()
onError = new EventEmitter();
reportParamQuery = new ReportQuery();
reports: any[];
reports: Chart[];
public barChartOptions: any = {
responsive: true,
@@ -69,7 +72,7 @@ export class AnalyticsComponent implements OnChanges {
private analyticsService: AnalyticsService) {
console.log('AnalyticsComponent');
if (translate) {
translate.addTranslationFolder('ng2-activiti-analytics', 'node_modules/ng2-activiti-analytics/dist/src');
translate.addTranslationFolder('ng2-activiti-analytics', 'node_modules/ng2-activiti-analytics/src');
}
}
@@ -107,4 +110,8 @@ export class AnalyticsComponent implements OnChanges {
let clone = JSON.parse(JSON.stringify(report));
report.datasets = clone.datasets;
}
public onEditReport(name: string) {
this.editReport.emit(name);
}
}
@@ -27,6 +27,8 @@ function dateCheck(c: AbstractControl) {
return result ? {'greaterThan': true} : null;
}
declare let mdDateTimePicker: any;
@Component({
moduleId: module.id,
selector: 'date-range-widget',
@@ -54,15 +56,9 @@ export class DateRangeWidget extends WidgetComponent {
debug: boolean = false;
dialogStart: any = new mdDateTimePicker.default({
type: 'date',
future: moment().add(21, 'years')
});
dialogStart: any;
dialogEnd: any = new mdDateTimePicker.default({
type: 'date',
future: moment().add(21, 'years')
});
dialogEnd: any;
constructor(public elementRef: ElementRef,
private formBuilder: FormBuilder) {
@@ -72,26 +68,39 @@ export class DateRangeWidget extends WidgetComponent {
ngOnInit() {
this.initForm();
this.addAccessibilityLabelToDatePicker();
this.initSartDateDialog();
this.initEndDateDialog();
}
initForm() {
let today = moment().format('YYYY-MM-DD');
let startDateForm = this.field.value ? this.field.value.startDate : '' ;
let startDate = this.convertToMomentDate(startDateForm);
let endDateForm = this.field.value ? this.field.value.endDate : '' ;
let endDate = this.convertToMomentDate(endDateForm);
let startDateControl = new FormControl(today);
let startDateControl = new FormControl(startDate);
startDateControl.setValidators(Validators.required);
this.dateRange.addControl('startDate', startDateControl);
let endDateControl = new FormControl(today);
let endDateControl = new FormControl(endDate);
endDateControl.setValidators(Validators.required);
this.dateRange.addControl('endDate', endDateControl);
this.dateRange.setValidators(dateCheck);
this.dateRange.valueChanges.subscribe(data => this.onGroupValueChanged(data));
this.initSartDateDialog(startDate);
this.initEndDateDialog(endDate);
}
initSartDateDialog() {
initSartDateDialog(date: string) {
let settings: any = {
type: 'date',
past: moment().subtract(100, 'years'),
future: moment().add(100, 'years')
};
settings.init = moment(date, DateRangeWidget.FORMAT_DATE_ACTIVITI);
this.dialogStart = new mdDateTimePicker.default(settings);
this.dialogStart.trigger = this.startElement.nativeElement;
let startDateButton = document.getElementById('startDateButton');
@@ -130,7 +139,16 @@ export class DateRangeWidget extends WidgetComponent {
return span;
}
initEndDateDialog() {
initEndDateDialog(date: string) {
let settings: any = {
type: 'date',
past: moment().subtract(100, 'years'),
future: moment().add(100, 'years')
};
settings.init = moment(date, DateRangeWidget.FORMAT_DATE_ACTIVITI);
this.dialogEnd = new mdDateTimePicker.default(settings);
this.dialogEnd.trigger = this.endElement.nativeElement;
let endDateButton = document.getElementById('endDateButton');
@@ -164,16 +182,24 @@ export class DateRangeWidget extends WidgetComponent {
onGroupValueChanged(data: any) {
if (this.dateRange.valid) {
let dateStart = this.convertMomentDate(this.dateRange.controls['startDate'].value);
let endStart = this.convertMomentDate(this.dateRange.controls['endDate'].value);
let dateStart = this.convertToMomentDateWithTime(this.dateRange.controls['startDate'].value);
let endStart = this.convertToMomentDateWithTime(this.dateRange.controls['endDate'].value);
this.dateRangeChanged.emit({startDate: dateStart, endDate: endStart});
}
}
public convertMomentDate(date: string) {
public convertToMomentDateWithTime(date: string) {
return moment(date, DateRangeWidget.FORMAT_DATE_ACTIVITI, true).format(DateRangeWidget.FORMAT_DATE_ACTIVITI) + 'T00:00:00.000Z';
}
private convertToMomentDate(date: string) {
if (date) {
return moment(date).format(DateRangeWidget.FORMAT_DATE_ACTIVITI);
} else {
return moment().format(DateRangeWidget.FORMAT_DATE_ACTIVITI);
}
}
ngOnDestroy() {
}
@@ -17,6 +17,8 @@
import { Input, AfterViewInit, Output, EventEmitter, SimpleChanges, OnChanges } from '@angular/core';
let componentHandler: any;
/**
* Base widget component.
*/
@@ -15,6 +15,8 @@
* limitations under the License.
*/
import * as moment from 'moment';
export class Chart {
id: string;
type: string;
@@ -76,7 +78,7 @@ export class LineChart extends Chart {
export class BarChart extends Chart {
title: string;
titleKey: string;
labels: string[] = [];
labels: any = [];
datasets: any[] = [];
data: any[] = [];
xAxisType: string;
@@ -72,7 +72,7 @@ export class ReportParameterDetailsModel {
name: string;
nameKey: string;
type: string;
value: string;
value: any;
options: ParameterValueModel[];
dependsOn: string;
@@ -16,9 +16,9 @@
*/
import { Injectable } from '@angular/core';
import { AlfrescoAuthenticationService, AlfrescoSettingsService } from 'ng2-alfresco-core';
import { AlfrescoAuthenticationService, AlfrescoSettingsService, AlfrescoApiService } from 'ng2-alfresco-core';
import { Observable } from 'rxjs/Rx';
import { Response, Http, Headers, RequestOptions, URLSearchParams } from '@angular/http';
import { Response } from '@angular/http';
import { ReportParametersModel, ParameterValueModel } from '../models/report.model';
import { Chart, PieChart, TableChart, BarChart, HeatMapChart, MultiBarChart } from '../models/chart.model';
@@ -26,7 +26,7 @@ import { Chart, PieChart, TableChart, BarChart, HeatMapChart, MultiBarChart } fr
export class AnalyticsService {
constructor(private authService: AlfrescoAuthenticationService,
private http: Http,
public apiService: AlfrescoApiService,
private alfrescoSettingsService: AlfrescoSettingsService) {
}
@@ -35,14 +35,10 @@ export class AnalyticsService {
* @returns {Observable<any>}
*/
getReportList(): Observable<any> {
let url = `${this.alfrescoSettingsService.getBPMApiBaseUrl()}/app/rest/reporting/reports`;
let options = this.getRequestOptions();
return this.http
.get(url, options)
return Observable.fromPromise(this.apiService.getInstance().activiti.reportApi.getReportList())
.map((res: any) => {
let reports: ReportParametersModel[] = [];
let body = res.json();
body.forEach((report: ReportParametersModel) => {
res.forEach((report: ReportParametersModel) => {
let reportModel = new ReportParametersModel(report);
reports.push(reportModel);
});
@@ -51,13 +47,9 @@ export class AnalyticsService {
}
getReportParams(reportId: string): Observable<any> {
let url = `${this.alfrescoSettingsService.getBPMApiBaseUrl()}/app/rest/reporting/report-params/${reportId}`;
let options = this.getRequestOptions();
return this.http
.get(url, options)
return Observable.fromPromise(this.apiService.getInstance().activiti.reportApi.getReportParams(reportId))
.map((res: any) => {
let body = res.json();
return new ReportParametersModel(body);
return new ReportParametersModel(res);
}).catch(this.handleError);
}
@@ -72,7 +64,7 @@ export class AnalyticsService {
}
} else if (type === 'dateInterval') {
return this.getDateIntervalValues();
} else if (type === 'task') {
} else if (type === 'task' && reportId && processDefinitionId) {
return this.getTasksByProcessDefinitionId(reportId, processDefinitionId);
} else {
return Observable.create(observer => {
@@ -124,14 +116,10 @@ export class AnalyticsService {
}
getProcessDefinitionsValuesNoApp(): Observable<any> {
let url = `${this.alfrescoSettingsService.getBPMApiBaseUrl()}/app/rest/reporting/process-definitions`;
let options = this.getRequestOptions();
return this.http
.get(url, options)
return Observable.fromPromise(this.apiService.getInstance().activiti.reportApi.getProcessDefinitions())
.map((res: any) => {
let paramOptions: ParameterValueModel[] = [];
let body = res.json();
body.forEach((opt) => {
res.forEach((opt) => {
paramOptions.push(new ParameterValueModel(opt));
});
return paramOptions;
@@ -139,17 +127,10 @@ export class AnalyticsService {
}
getProcessDefinitionsValues(appId: string): Observable<any> {
let url = `${this.alfrescoSettingsService.getBPMApiBaseUrl()}/app/rest/process-definitions`;
let params: URLSearchParams;
params = new URLSearchParams();
params.set('appDefinitionId', appId);
let options = this.getRequestOptions(params);
return this.http
.get(url, options)
return Observable.fromPromise(this.apiService.getInstance().activiti.processDefinitionsApi.getProcessDefinitions(appId))
.map((res: any) => {
let paramOptions: ParameterValueModel[] = [];
let body = res.json();
body.data.forEach((opt) => {
res.data.forEach((opt) => {
paramOptions.push(new ParameterValueModel(opt));
});
return paramOptions;
@@ -157,42 +138,21 @@ export class AnalyticsService {
}
getTasksByProcessDefinitionId(reportId: string, processDefinitionId: string): Observable<any> {
if (reportId && processDefinitionId) {
let url = `${this.alfrescoSettingsService.getBPMApiBaseUrl()}/app/rest/reporting/report-params/${reportId}/tasks`;
let params: URLSearchParams;
if (processDefinitionId) {
params = new URLSearchParams();
params.set('processDefinitionId', processDefinitionId);
}
let options = this.getRequestOptions(params);
return this.http
.get(url, options)
.map((res: any) => {
let paramOptions: ParameterValueModel[] = [];
let body = res.json();
body.forEach((opt) => {
paramOptions.push(new ParameterValueModel({ id: opt, name: opt }));
});
return paramOptions;
}).catch(this.handleError);
} else {
return Observable.create(observer => {
observer.next(null);
observer.complete();
});
}
return Observable.fromPromise(this.apiService.getInstance().activiti.reportApi.getTasksByProcessDefinitionId(reportId, processDefinitionId))
.map((res: any) => {
let paramOptions: ParameterValueModel[] = [];
res.forEach((opt) => {
paramOptions.push(new ParameterValueModel({ id: opt, name: opt }));
});
return paramOptions;
}).catch(this.handleError);
}
getReportsByParams(reportId: number, paramsQuery: any): Observable<any> {
let url = `${this.alfrescoSettingsService.getBPMApiBaseUrl()}/app/rest/reporting/report-params/${reportId}`;
let body = paramsQuery ? JSON.stringify(paramsQuery) : {};
let options = this.getRequestOptions();
return this.http
.post(url, body, options)
return Observable.fromPromise(this.apiService.getInstance().activiti.reportApi.getReportsByParams(reportId, paramsQuery))
.map((res: any) => {
let elements: Chart[] = [];
let bodyRes = res.json();
bodyRes.elements.forEach((chartData) => {
res.elements.forEach((chartData) => {
if (chartData.type === 'pieChart') {
elements.push(new PieChart(chartData));
} else if (chartData.type === 'table') {
@@ -213,31 +173,24 @@ export class AnalyticsService {
}
public createDefaultReports(): Observable<any> {
let url = `${this.alfrescoSettingsService.getBPMApiBaseUrl()}/app/rest/reporting/default-reports`;
let options = this.getRequestOptions();
let body = {};
return this.http
.post(url, body, options)
return Observable.fromPromise(this.apiService.getInstance().activiti.reportApi.createDefaultReports())
.map(this.toJson)
.catch(this.handleError);
}
public updateReport(reportId: number, name: string): Observable<any> {
return Observable.fromPromise(this.apiService.getInstance().activiti.reportApi.updateReport(reportId, name))
.map((res: any) => {
return res;
console.log('upload');
}).catch(this.handleError);
}
public getHeaders(): Headers {
return new Headers({
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': this.authService.getTicketBpm()
});
}
public getRequestOptions(param?: any): RequestOptions {
let headers = this.getHeaders();
return new RequestOptions({ headers: headers, withCredentials: true, search: param });
}
private handleError(error: Response) {
console.error(error);
return Observable.throw(error.json().error || 'Server error');
}
toJson(res: any) {
return res || {};
}
}
@@ -3,11 +3,10 @@
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"sourceMap": true,
"removeComments": true,
"declaration": true,
"skipLibCheck": true,
"noLib": false,
"allowUnreachableCode": false,
"allowUnusedLabels": false,
@@ -15,12 +14,24 @@
"noImplicitReturns": false,
"noImplicitUseStrict": false,
"noFallthroughCasesInSwitch": true,
"outDir": "dist",
"types": ["core-js", "jasmine", "node"]
"removeComments": true,
"declaration": true,
"lib": [
"es2015",
"dom"
],
"suppressImplicitAnyIndexErrors": true
},
"exclude": [
"demo",
"node_modules",
"dist"
]
"dist",
"tools",
"gulpfile.ts",
"gulpfile.d.ts"
],
"angularCompilerOptions": {
"strictMetadataEmit": false,
"skipTemplateCodegen": true
}
}

Some files were not shown because too many files have changed in this diff Show More