mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-31 17:38:48 +00:00
1.6.0 (#2029)
* fix upload area snackbar behaviour * SASS support for components ability to use '.scss' files from within components * [ADF-610] Upload button and DnD area should not upload hidden files and folders (#1908) [ADF-610] upload cleanup - more strongly typing - api improvements * Upload cleanup and api improvements - remove old unused settings (formFields variable) - individual options for uploaded files (i.e. versioning) - upload button and drag-and-drop area now set individual settings for file versioning * exclude hidden files from upload * [ADF-640] reload document list on folder upload (#1895) * reload document list on folder upload - extend UploadService with 'folderCreated' event to be able reacting on folder uploads globally - extend Demo Shell to reload document list on UploadService events (folderCreated) * readme updates * [ADF-621] show drop effect on folders only (#1897) * show drop effect on folders only - fix `hasValue` api for data rows (avoid 'false' value to be evaluated as missing value) - support for evaluating drop support for rows - document list enables upload zones for folders only * api improvements as per code review * [ADF-242] Fixed behaviour for saving/deleting reports (#1905) * [ADF-242] - fix for deleting - saving a report * [ADF - 242] added test for fixed feature on reports save - delete * Added translation key * [ADF-604] Upgrade @angular/material to latest version (#1909) * update dependencies and module imports * fix template warnings and fix import issues * migrate Activiti Form to MdTabsModule * fix unit tests * fix tests * fix unit tests * fix unit tests * disable test that fails only on travis * upgrade activiti form component to angular/material * fix test (remove MDL class check) * [ADF-613] Add plain text viewer (#1873) * add plain text viewer * different devices optimizations * returns types * [ADF-573] support for toggling enabled state (#1912) * [ADF-602] Accordion component - Add basic documentation (#1913) * Add basic documentation Accordion component * Update README.md * [ADF-680] Added previous page check when page has no more elements (#1911) * [ADF-242] - fix for deleting - saving a report * [ADF - 242] added test for fixed feature on reports save - delete * [ADF-680] - Fixed behaviour when deleting all files on last page of document list * Start adding test for documentlist check * Added test for check double page load * [ADF-680] - removed commented test code * [ADF-680] Added changes from peer review * [ADF-680] added return type * [ADF-667] selection mode and row styles (#1914) * selection mode and row styles - single/multiple/none selection modes for DataTable component (and Document List) - support for custom row styles (inline and classname values) - fix karma config (material themes) - readme updates - package-lock.json files for NPM5 support - updated DataTable demo to demonstrate selection modes and row styles * remove package lock files * move demo projects to webpack (#1915) * wav and Mp3 enabling viewer (#1916) * add option only demo shell version change for update version script * ADF-402 add the show diagram button (#1917) * [ADF-707] Ability to select a row on a dynamic table (#1921) * [ADF-710] Create an Process Attachment List component (#1919) * added new component to list the process attachments with view, download and delete functionality * added unit test cases for activit-process-attachment-list component * exported new process attachment list component * added documentation for process-attachment-list component * [ADF-712] Task Attachment - Provide a way to attach a new content (#1898) * create button, download, view functionality added in task attachment list component * created sevice to attach document to task * added new component to create/uplaod attachment to task * added new component to create/uplaod attachment to task * added test case for create task attachment component * added test case for create task attachment component * added input to block upload document to ECM * fixed create task attachment spec file issue * changed alfresco-upload to alfresco-core upload directive * removed attachCreate button and emitter from task-attachment-list * removed uploadToEcm input and checkValidity method from alfresco-upload * added documentation for task-attachment-list and create-task-attachment components * [ADF-696] Entire accordion group header should be clickable (#1918) * #ADF-696 Added new input to show/hide expand icon, click event is activated for the complete heading * #ADF-696 tslint fix * #ADF-696 Added documentation for new input and removed unwanted div * [ADF-721] Fix translation reference for dev task (#1923) * move translation files in the bundles folder * fix after review ripristinate tslint and remove override tsconfig * [ADF-709] add autofocus when a new row is added on dynamic table widget (#1927) * [ADF-709] add autofocus when a new row is added on dynamic table widget * [ADF-709] removed wrong reference for template * [ADF-713] Process Attachment - Provide a way to attach a new content (#1920) * added service to get all the related content of the process instance * added new component to create/upload attachment for process instance * added unit test cases for create-process-attachment component * exported create-process-attachment component * added documentation for create-process-attachment component * Add data-automation-id to multi select checkbox (#1924) * [ADF-571] upload feature rework (#1922) * upload feature rework lots of improvements for upload dialog and underlying services * readme update - readme cleanup - remove some old comments from code - update readme with new events for Upload Service * restore prerequisites section in readme * fix i18n issue with webpack * exported report and chart models (#1925) * fix file upload bug (#1928) - proper extraction of File objects from the FileList * lock files for npm 5 (#1930) add lock files for npm v5; does nothing for earlier versions, so is not harmful * Source Mapping is not working on test debugging (#1931) * coverage single components run fix * remove spec.ts from coverage * make the coverage and the istanbul-instrumenter-loader works only over the console test because a problem on the remapping for the browser test * move tslint on the main folder of any component * remove build:w from readme * stop build tslint error also in spec files * clear karma file from unnecessary files * add set -f for build all script in order to accept * * fix lint problem and failing tests * fix failing test search component * add loader test for viewer * fix tslint error userinfo * --max_old_space_size=2048 remove * fix tslint error uploader unused EventEmitter * remove spec|index|.*mock|.*model|.*event from coverage * move coverage separate file and get component to calculate coverage as input * remove old 'banned' demo from login screen (#1929) * add sleep time flag in publish script * rollback demo tag * fix pacakge.json tag * [ADF-686] add blobFile as input (#1933) * coverage fix (#1934) * [ADF-702] Task/Process Filter - Provide a way to change the default filter (#1932) * [ADF-702] Task/Process Filter - Provide a way to change the default filter * Provide a way to select a custom menu filter * Improve activiti process filter * Add internal link * Change link name * add link * [ADF-744] Attachment List is not displayed within Processes. (#1937) * Use the adf process attachment list indise demo shell * Change documentation * support for healdess chrome (#1939) * #ADF-696 Now accordion opens/closes on click of group header along with emitting heading click event (#1936) * add info and link on current last git commit (#1940) * [ADF-754] toolbar component (#1938) * toolbar component - simple toolbar component (core lib) - readme updates (core lib) - update demo shell with toolbar component demo (document list) * update unit tests * [ADF-763] Add Chrome default browser for karma chrome launcher for Chrome versi… (#1941) * Add Chrome default browser for karma chrome launcher for Chrome version<59 * Fixing intermittently failing test in ng2-activiti-analytics component * Adding new icon (sent) for Bootstrap to Material icon mapping (#1943) * fix blob input in text viewer (#1942) * GitHub issue & pull request template change (#1945) * Update ISSUE_TEMPLATE.md * Update PULL_REQUEST_TEMPLATE.md * [ADF-689] Fix alfresco-document-menu-action styling (z-index) (#1944) * fix translation wrong folder creation issue * [ADF-773] Fix datatable custom template render (#1947) * [ADF-780] centralised call for process filters api (#1950) * [ADF-780] centralised call for process filters api * [ADF-780] updated conversion to string * [ADF-741] Add the create task attachment component to the demo shell (#1946) * Add the create task attachment component to the demo shell * Add translation keys * Add return to methods * fix thumbnail task process list (#1951) * [ADF-643] upload enhancements (#1949) * rework folder uploading - flatterns hierarchy on folder upload - performs a single traversal for the entire folder heirarchy and ends with a comple file list - allows now dropping folders on existing folders - overall code improvements * fix unit tests * readme updates * clean old and unused code * code cleanup * limit concurrent uploads * update code as per review * fix upload button for Safari * fixes for Safari - Safari compatibility - code updates based on review * fix code * fix unit tests * [ADF-589] Login component different bug fixes (#1953) * Basic style changes * Further design changes * Responsive design fixes * Different sign in button style for the different login steps * #ADF-780 Fixed getProcessFilterByName to get the correct filter for the given appId and name (#1952) * fix issues with the require keyword (angular cli) (#1954) * [ADF-799] add HappyPack to webpack conf (#1956) * update npm5 lock files * [ADF-740] Add button for process attachment list (#1955) * [ADF-740] adding button to allow user to upload related content on process instance * [ADF-740] add button for attachment content list for process * changed locatin for translation * [ADF-740] added test for add button for process attach * [ADF-740] added PR request changes * [ADF-802] fix error on uploading file to attachment list (#1957) * [ADF-802] fix error on uploading file to attachment list * [ADF-802] improved for loop * [ADF-797] remove dist folder from npm distributed package , leave src and bundles (#1961) * [ADF-804] webpack proxy setup to avoid CORS problem (#1960) * package lock update * update travis to node 8 (#1965) * upload service exposes created nodes (#1964) * [ADF-591] documentation refinements (#1959) * refine ng2-activiti-analytics * refine ng2-activiti-diagrams docs * refine ng2-activiti-form * refine ng2-activiti-processlist * refine ng2-activiti-tasklist * refine ng2-alfresco-core * refine ng2-alfresco-datatable * refine ng2-alfresco-datatable * refine gn2-alfresco-login * refine ng2-alfresco-search * refine ng2-alfresco-social * refine ng2-alfresco-tag * refine ng2-alfresco-upload * refine ng2-alfresco-userinfo * refine ng2-alfresco-viewer * refine ng2-alfresco-webscript * various readme cleanups * fix builds related to node-sass library (#1966) * update dependencies and remove old lock files * update sass loader * updated lock files * [ADF-578] Remember me functionality (#1962) * Remember me functionality * Happy pack to ng2-components' package.json * Build fix * Adding tabindices to viewer control elements (#1968) * karma conf all single browser * Fix current page number issue (#1970) * [ADF-524] Datatable loading state (#1958) * loading state datatable * modify readme after review * [ADF-78] Update CORS help (#1973) * Fix host configuration in demo-shell when no port is present (#1971) * remove brachet * [ADF-494] fixed readonly rendering for forms (#1972) * [ADF-494] improved disabling for form * [ADF-494] fixed readonly rendering for forms * [ADF-814] application configuration service (#1969) * app configuration service * api improvements and readme update * extend readme and add defaults * unit tests for app config service * [ADF-716] Task Header - Use a custom view inside the component (#1967) * Use a generic custom view inside the task header * Move the component into core component and change name * Missing file * Fix unit test * fix unit test component name * fix issue with shared Code settings - remove obsolete rules for .js/.ts - hide .happypack folder in the project tree * [ADF-810] fix default value radio button (#1975) * [ADF-510] Drag&Drop check permission to allow user to upload a file (#1948) * [ADF-510] added permission check for drag&drop * Improved code for drag and drop side * Added test for drag and drop upload area changes * Added test for document list permissions check * [ADF-510] rebased branch after changes applied to upload * [ADF-510] rebased branch and fixed tests * [ADF-717] upgrade i18n and charting dependencies (#1976) * remove app-specific polyfill dependencies remove polyfill dependencies never used by component libraries * upgrade i18n dependencies * upgrade ng2-charts dependency * fix unit tests * update demo projects * [ADF-524] Fix empty state after the loading introduction (#1980) * fix empty state after the loading introduction * Update document-list.component.spec.ts remove typo * [ADF-838] Table of content automatic creation (#1981) * readonly value set * Table of content automatic creation (#1982) * add missing intl dependency for demo shell (#1984) * [ADF-833] DataTable - improve the single and double click event (#1979) * Improve the single and double click event * Fix unit test * Task header basic documentation (#1985) * Disable upload attachment when the task is completed (#1987) * [ADF-847] upgrade to use application configuration service (#1986) * migrate core lib to use server-side app config * fix unit tests * update Search tests - update tests - upgrade tests to use TestBed * update UserInfo tests * update Social tests * update tests * update unit tests * cleanup old code * update about page * update demo shell readme * dev and prod configurations * updated package-lock file and removed duplicates in package.json * [ADF-851] execute-outcome event for form service (#1989) * execute-outcome event for form service * readme updates * fix loading state excluding other state during the loading (#1991) * Fix compilation error (#1993) * [ADF-883] Fix build errors (#1992) * [ADF-793] Ability to create PDF renditions in case of non supported formats (#1994) * Style changes and button * Convert to PDF button * Convert to PDF button part II. * Convert within the Not Supported Format component * Rendition loading skeleton * Conversion is working. * Convert button behaviour tests * Rebasing fix. * app settings page (#1997) - custom app setttings service to use isolated storage (demo shell) - restore settings UI - redirect angular and rxjs to the same version as components use. * [ADF-822] Added the npm-prepublish script (#1978) * added the npm prepublish script * changed permissions to prepublish script * changed to npm run prepublish * prepare the pr * removed useless code to the script * remove flags lib from demo shell (#1983) * remove flags lib from demo shell greatly reduce demo shell webpack resources by switching off flags (only 3 icons were displayed in the past) * merge package.json * add icons * Fix typo error * [ADF-794] Add people assignment component (#1977) * Add people component * exported people service * added people-list component to show the involved user list * changed people-search component layout * changed people-list usage in people component * changed people-list data table from custom template to data adapter * changes people-search component related to people-list * changes in activiti-people related to people-list and people-search component * changed data adapter to direct data column setting to data-table * removed ngChanges and added User and UserEvent models * added User and UserEvent model in emitter and other emitter handler * added user event model * changed activiti-people component with latest UX changes * addedand changed translate keys to the components * added hasUser method to check the condition in html * fixed tslint issue and test case issue in activiti-people component * added test case for actviti-people-list component * test case added for activiti-people-search component * changed activiti-people test cases according to latest UX changes * added description for activiti-people component * changed test case to fix component.upgradeElement issue * changes requested by Vito Albano #1 * splitted getDisplayUser into getDisplayUser and getInitialUsername * introduce check type definition * [ADF-897] - ActivitiPeopleList - use the adf prefix (#2001) * Use the adf as prexif instead of activiti * Fix typo * Fix wrong import * support binding [form] data directly (#1996) - ability to bind [form] data directly inside `<activiti-form>` component - ability to parse forms with FormService - demo of the custom form in demo shell * [ADF-778] cancel window for upload dialog shows only on complete (#2003) * [ADF-778] Added new behaviour to upload dialog * [ADF-778] cancel window for upload dialog shows only on complete * [ADF-778] changed variable name to showCloseButton * Create task/process attachment Compilation error (#2004) * fix tslint errors minor fix for "Unnecessary semicolon" TSLint rule * [ADF-842] Fixed type for taskdetails (#2009) * fix type definition (#2002) * Use the activiti people with the new look and feel inside the demo shell (#2008) * add rxjs and @angular in tsconfig.json * [ADF-843] Form events bus (#1990) * form events bus * event test bus fix * fix test after code review * fix types errors * change to public formservice * make optional formservice * [ADF-915] Add option to change the JS-API with different version in the update package * Missing keys (#2011) * [ADF-845] breadcrumb root option added and style review (#1999) * breadcrumb root option added and style review * new breadcrumbs * split onchange in a method * update readme with a note for old pefix tag * fix tslint errors * fix breadcrumb test * [ADF-922] Regenerate package-lock.json files for every package and create script for doing that in the future (#2012) * Updated package-lock.json files * npm-relock-pkgs.sh * Update README.md * Fix ng2-alfresco-search sass problem * SASS version update (#2013) * sass update * update sass loader * vjsapi option prepublish * prepublish script deprecation in favour of prepublishOnly node 8 (#2010) * modify prePublish script with preoPublishOnly * install rimraf globally * fix clean scripts demo folders * move appveyor to node 8 * Appveyor test (#1998) * reduce memory * remove max-old-space * remove increase memory * create new TaskDetailsModel in loadNextTask (#2017) * Fix readme document list * [ADF-907] - Form reacts to data added in input (#2016) * [ADF-907] Enable activiti form to react on value data changes * [ADF-907] - Form reacts to data added in input] * [ADF - 907] added mock json for form * [ADF-907] added new event of the form to the event list * [ADF - 907] Added return column to README * [ADF - 907] Added return column to README * Script add pkg and clean update * install globally pkg pre build * Fix upload related content (#2019) * regeneration TOC and add automatic list component generator (#2022) * Fix upload process attachment (#2024) * update typescript (#2026) * update viewer readme * fix type definition variables * NgZone type passed parameter * fix tslint error in tasklist * Add screenshot (#2028) * fix search miss typing * bump version 1.6.0 (#2027)
This commit is contained in:
2
ng2-components/ng2-activiti-form/.gitignore
vendored
2
ng2-components/ng2-activiti-form/.gitignore
vendored
@@ -8,7 +8,6 @@ dist
|
||||
src/**/*.js
|
||||
src/**/*.js.map
|
||||
src/**/*.d.ts
|
||||
demo/**/*.js
|
||||
demo/**/*.js.map
|
||||
demo/**/*.d.ts
|
||||
index.js
|
||||
@@ -18,3 +17,4 @@ index.js.map
|
||||
/package/
|
||||
/bundles/
|
||||
index.d.ts
|
||||
/.happypack
|
||||
|
@@ -4,6 +4,7 @@ npm-debug.log
|
||||
|
||||
coverage/
|
||||
demo/
|
||||
dist/
|
||||
node_modules
|
||||
typings/
|
||||
fonts/
|
||||
@@ -15,3 +16,4 @@ fonts/
|
||||
/karma.conf.js
|
||||
/gulpfile.ts
|
||||
/.npmignore
|
||||
/.happypack
|
||||
|
@@ -1,35 +1,37 @@
|
||||
# Activiti Form Component for Angular 2
|
||||
<p>
|
||||
<a title='Build Status Travis' href="https://travis-ci.org/Alfresco/alfresco-ng2-components">
|
||||
<img src='https://travis-ci.org/Alfresco/alfresco-ng2-components.svg?branch=master' alt='travis
|
||||
Status' />
|
||||
</a>
|
||||
<a title='Build Status AppVeyor' href="https://ci.appveyor.com/project/alfresco/alfresco-ng2-components">
|
||||
<img src='https://ci.appveyor.com/api/projects/status/github/Alfresco/alfresco-ng2-components' alt='travis
|
||||
Status' />
|
||||
</a>
|
||||
<a href='https://codecov.io/gh/Alfresco/alfresco-ng2-components'>
|
||||
<img src='https://img.shields.io/codecov/c/github/Alfresco/alfresco-ng2-components/master.svg?maxAge=2592000' alt='Coverage Status' />
|
||||
</a>
|
||||
<a href='https://www.npmjs.com/package/ng2-activiti-form'>
|
||||
<img src='https://img.shields.io/npm/dtng2-activiti-form.svg' alt='npm downloads' />
|
||||
</a>
|
||||
<a href='https://github.com/Alfresco/alfresco-ng2-components/blob/master/LICENSE'>
|
||||
<img src='https://img.shields.io/hexpm/l/plug.svg' alt='license' />
|
||||
</a>
|
||||
<a href='https://www.alfresco.com/'>
|
||||
<img src='https://img.shields.io/badge/style-component-green.svg?label=alfresco' alt='alfresco component' />
|
||||
</a>
|
||||
<a href='https://angular.io/'>
|
||||
<img src='https://img.shields.io/badge/style-2-red.svg?label=angular' alt='angular 2' />
|
||||
</a>
|
||||
<a href='https://www.typescriptlang.org/docs/tutorial.html'>
|
||||
<img src='https://img.shields.io/badge/style-lang-blue.svg?label=typescript' alt='typescript' />
|
||||
</a>
|
||||
<a href='https://www.alfresco.com/'>
|
||||
<img src='https://img.shields.io/badge/style-%3E5.0.0-blue.svg?label=node%20version' alt='node version' />
|
||||
</a>
|
||||
</p>
|
||||
# APS Form Component
|
||||
|
||||
<!-- markdown-toc start - Don't edit this section. npm run toc to generate it-->
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
- [Library Contents](#library-contents)
|
||||
* [Components](#components)
|
||||
* [Services](#services)
|
||||
- [Prerequisites](#prerequisites)
|
||||
- [Install](#install)
|
||||
- [ActivitiForm Component](#activitiform-component)
|
||||
* [Properties](#properties)
|
||||
* [Advanced properties](#advanced-properties)
|
||||
* [Events](#events)
|
||||
* [Controlling outcome execution behaviour](#controlling-outcome-execution-behaviour)
|
||||
- [Activiti Content Component](#activiti-content-component)
|
||||
* [Properties](#properties-1)
|
||||
* [Events](#events-1)
|
||||
- [FormService Service](#formservice-service)
|
||||
* [Events](#events-2)
|
||||
* [Methods](#methods)
|
||||
- [Common scenarios](#common-scenarios)
|
||||
* [Changing field value based on another field](#changing-field-value-based-on-another-field)
|
||||
* [Listen all form Events](#listen-all-form-events)
|
||||
- [See also](#see-also)
|
||||
- [Build from sources](#build-from-sources)
|
||||
- [NPM scripts](#npm-scripts)
|
||||
- [Demo](#demo)
|
||||
- [License](#license)
|
||||
|
||||
<!-- tocstop -->
|
||||
|
||||
<!-- markdown-toc end -->
|
||||
|
||||
See it live: [Form Quickstart](https://embed.plnkr.co/YSLXTqb3DtMhVJSqXKkE/)
|
||||
|
||||
@@ -54,128 +56,25 @@ See it live: [Form Quickstart](https://embed.plnkr.co/YSLXTqb3DtMhVJSqXKkE/)
|
||||
Before you start using this development framework, make sure you have installed all required software and done all the
|
||||
necessary configuration, see this [page](https://github.com/Alfresco/alfresco-ng2-components/blob/master/PREREQUISITES.md).
|
||||
|
||||
> If you plan using this component with projects generated by Angular CLI, please refer to the following article: [Using ADF with Angular CLI](https://github.com/Alfresco/alfresco-ng2-components/wiki/Angular-CLI)
|
||||
|
||||
## Install
|
||||
|
||||
Follow the 3 steps below:
|
||||
|
||||
1. Npm
|
||||
|
||||
```sh
|
||||
npm install ng2-activiti-form --save
|
||||
```
|
||||
|
||||
2. Html
|
||||
|
||||
Include these dependencies in your index.html page:
|
||||
|
||||
```html
|
||||
|
||||
<!-- Moment js -->
|
||||
<script src="node_modules/moment/min/moment.min.js"></script>
|
||||
|
||||
<!-- Date picker -->
|
||||
<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>
|
||||
<link rel="stylesheet" href="node_modules/md-date-time-picker/dist/css/mdDateTimePicker.css" media="all">
|
||||
|
||||
<!-- Google Material Design Lite -->
|
||||
<link rel="stylesheet" href="node_modules/material-design-lite/material.min.css">
|
||||
<script src="node_modules/material-design-lite/material.min.js"></script>
|
||||
<link rel="stylesheet" href="node_modules/material-design-icons/iconfont/material-icons.css">
|
||||
|
||||
<!-- Load the Angular Material 2 stylesheet -->
|
||||
<link href="node_modules/@angular/material/core/theming/prebuilt/deeppurple-amber.css" rel="stylesheet">
|
||||
|
||||
<!-- 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>
|
||||
|
||||
<!-- 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>
|
||||
|
||||
<!-- Polyfill(s) for dialogs -->
|
||||
<script src="node_modules/dialog-polyfill/dialog-polyfill.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="node_modules/dialog-polyfill/dialog-polyfill.css" />
|
||||
<style>._dialog_overlay { position: static !important; } </style>
|
||||
|
||||
<!-- Modules -->
|
||||
<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>
|
||||
```
|
||||
|
||||
3. SystemJs
|
||||
|
||||
Add the following components to your systemjs.config.js file:
|
||||
|
||||
- moment
|
||||
- ng2-translate
|
||||
- ng2-alfresco-core
|
||||
- alfresco-js-api
|
||||
- ng2-activiti-form
|
||||
|
||||
Please refer to the following example file: [systemjs.config.js](demo/systemjs.config.js) .
|
||||
|
||||
```sh
|
||||
npm install ng2-activiti-form
|
||||
```
|
||||
|
||||
## ActivitiForm Component
|
||||
|
||||
### Basic usage
|
||||
|
||||
The component shows a Form from Activiti
|
||||
|
||||
```html
|
||||
<activiti-form [taskId]="taskId"></activiti-form>
|
||||
<activiti-form
|
||||
[taskId]="taskId">
|
||||
</activiti-form>
|
||||
```
|
||||
|
||||
Usage example of this component :
|
||||
|
||||
**main.ts**
|
||||
|
||||
```ts
|
||||
import { NgModule, Component } 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 { ActivitiFormModule } from 'ng2-activiti-form';
|
||||
|
||||
@Component({
|
||||
selector: 'activiti-app-demo',
|
||||
template: `<activiti-form [taskId]="77501"></activiti-form>`
|
||||
})
|
||||
|
||||
export class FormDemoComponent {
|
||||
|
||||
constructor(private authService: AlfrescoAuthenticationService, private settingsService: AlfrescoSettingsService) {
|
||||
settingsService.bpmHost = 'http://localhost:9999';
|
||||
|
||||
this.authService.login('admin', 'admin').subscribe(
|
||||
ticket => {
|
||||
console.log(ticket);
|
||||
},
|
||||
error => {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
BrowserModule,
|
||||
CoreModule.forRoot(),
|
||||
ActivitiFormModule.forRoot()
|
||||
],
|
||||
declarations: [FormDemoComponent],
|
||||
bootstrap: [FormDemoComponent]
|
||||
})
|
||||
export class AppModule {
|
||||
}
|
||||
|
||||
platformBrowserDynamic().bootstrapModule(AppModule);
|
||||
```
|
||||
|
||||
### Display form instance by task id
|
||||
**Display form instance by task id:**
|
||||
|
||||
```html
|
||||
<activiti-form
|
||||
@@ -185,7 +84,7 @@ platformBrowserDynamic().bootstrapModule(AppModule);
|
||||
|
||||
For an existing Task both form and values will be fetched and displayed.
|
||||
|
||||
### Display form definition by form id
|
||||
**Display form definition by form id:**
|
||||
|
||||
```html
|
||||
<activiti-form
|
||||
@@ -196,7 +95,7 @@ For an existing Task both form and values will be fetched and displayed.
|
||||
|
||||
Only form definition will be fetched.
|
||||
|
||||
### Display form definition by form name
|
||||
**Display form definition by form name:**
|
||||
|
||||
```html
|
||||
<activiti-form
|
||||
@@ -205,7 +104,7 @@ Only form definition will be fetched.
|
||||
</activiti-form>
|
||||
```
|
||||
|
||||
### Display form definition by ECM nodeId
|
||||
**Display form definition by ECM nodeId:**
|
||||
|
||||
In this case the metadata of the node are showed in an activiti Form.
|
||||
If there is no form definied in activiti for the type of the node,
|
||||
@@ -217,7 +116,7 @@ a new form will be automaticaly created in Activiti.
|
||||
</activiti-form>
|
||||
```
|
||||
|
||||
### Display form definition by form name, and store the form field as metadata.
|
||||
**Display form definition by form name, and store the form field as metadata:**
|
||||
|
||||
The param nameNode is optional.
|
||||
|
||||
@@ -230,7 +129,7 @@ The param nameNode is optional.
|
||||
</activiti-form>
|
||||
```
|
||||
|
||||
### Display form definition by ECM nodeId
|
||||
**Display form definition by ECM nodeId:**
|
||||
|
||||
In this case the metadata of the node are showed in an activiti Form,
|
||||
and store the form field as metadata. The param nameNode is optional.
|
||||
@@ -244,51 +143,51 @@ and store the form field as metadata. The param nameNode is optional.
|
||||
</activiti-form>
|
||||
```
|
||||
|
||||
### Configuration
|
||||
|
||||
#### Properties
|
||||
### Properties
|
||||
|
||||
The recommended set of properties can be found in the following table:
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `taskId` | string | | Task id to fetch corresponding form and values. |
|
||||
| `formId` | string | | The id of the form definition to load and display with custom values. |
|
||||
| `formName` | string | | Name of hte form definition to load and display with custom values. |
|
||||
| `data` | FormValues | | Custom form values map to be used with the rendered form. |
|
||||
| `showTitle` | boolean | true | Toggle rendering of the form title. |
|
||||
| `showCompleteButton` | boolean | true | Toggle rendering of the `Complete` outcome button. |
|
||||
| `showSaveButton` | boolean | true | Toggle rendering of the `Save` outcome button. |
|
||||
| `showDebugButton` | boolean | false | Toggle debug options. |
|
||||
| `readOnly` | boolean | false | Toggle readonly state of the form. Enforces all form widgets render readonly if enabled. |
|
||||
| `showRefreshButton` | boolean | true | Toggle rendering of the `Refresh` button. |
|
||||
| `showValidationIcon` | boolean | true | Toggle rendering of the validation icon next form title. |
|
||||
| `saveMetadata` | boolean | false | Store the value of the form as metadata. |
|
||||
| `path` | string | | Path of the folder where to store the metadata. |
|
||||
| `nameNode` (optional) | string | true | Name to assign to the new node where the metadata are stored. |
|
||||
| taskId | string | | Task id to fetch corresponding form and values. |
|
||||
| formId | string | | The id of the form definition to load and display with custom values. |
|
||||
| formName | string | | Name of hte form definition to load and display with custom values. |
|
||||
| data | FormValues | | Custom form values map to be used with the rendered form. |
|
||||
| showTitle | boolean | true | Toggle rendering of the form title. |
|
||||
| showCompleteButton | boolean | true | Toggle rendering of the `Complete` outcome button. |
|
||||
| showSaveButton | boolean | true | Toggle rendering of the `Save` outcome button. |
|
||||
| readOnly | boolean | false | Toggle readonly state of the form. Enforces all form widgets render readonly if enabled. |
|
||||
| showRefreshButton | boolean | true | Toggle rendering of the `Refresh` button. |
|
||||
| showValidationIcon | boolean | true | Toggle rendering of the validation icon next form title. |
|
||||
| saveMetadata | boolean | false | Store the value of the form as metadata. |
|
||||
| path | string | | Path of the folder where to store the metadata. |
|
||||
| nameNode | string | true | Name to assign to the new node where the metadata are stored. |
|
||||
|
||||
##### Advanced properties
|
||||
### Advanced properties
|
||||
|
||||
The following properties are for complex customisation purposes:
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `form` | FormModel | | Underlying form model instance. |
|
||||
| `debugMode` | boolean | false | Toggle debug mode, allows displaying additional data for development and debugging purposes. |
|
||||
| form | FormModel | | Underlying form model instance. |
|
||||
| showDebugButton | boolean | false | Toggle debug options. |
|
||||
| debugMode | boolean | false | Toggle debug mode, allows displaying additional data for development and debugging purposes. |
|
||||
|
||||
#### Events
|
||||
### Events
|
||||
|
||||
| Name | Description |
|
||||
| --- | --- |
|
||||
| `formLoaded` | Invoked when form is loaded or reloaded. |
|
||||
| `formSaved` | Invoked when form is submitted with `Save` or custom outcomes. |
|
||||
| `formCompleted` | Invoked when form is submitted with `Complete` outcome. |
|
||||
| `executeOutcome` | Invoked when any outcome is executed, default behaviour can be prevented via `event.preventDefault()` |
|
||||
| `onError` | Invoked at any error |
|
||||
| Name | Return Type | Description |
|
||||
| --- | --- | --- |
|
||||
| formLoaded | [FormModel](https://github.com/Alfresco/alfresco-ng2-components/blob/master/ng2-components/ng2-activiti-form/src/components/widgets/core/form.model.ts) | Invoked when form is loaded or reloaded. |
|
||||
| formSaved | [FormModel](https://github.com/Alfresco/alfresco-ng2-components/blob/master/ng2-components/ng2-activiti-form/src/components/widgets/core/form.model.ts) | Invoked when form is submitted with `Save` or custom outcomes. |
|
||||
| formCompleted | [FormModel](https://github.com/Alfresco/alfresco-ng2-components/blob/master/ng2-components/ng2-activiti-form/src/components/widgets/core/form.model.ts) | Invoked when form is submitted with `Complete` outcome. |
|
||||
| formDataRefreshed | [FormModel](https://github.com/Alfresco/alfresco-ng2-components/blob/master/ng2-components/ng2-activiti-form/src/components/widgets/core/form.model.ts) | Invoked when form values are refreshed due a data property change |
|
||||
| executeOutcome | [FormOutcomeEvent](https://github.com/Alfresco/alfresco-ng2-components/blob/master/ng2-components/ng2-activiti-form/src/components/widgets/core/form-outcome-event.model.ts) | Invoked when any outcome is executed, default behaviour can be prevented via `event.preventDefault()` |
|
||||
| onError | any | Invoked at any error |
|
||||
|
||||
All `form*` events receive an instance of the `FormModel` as event argument for ease of development:
|
||||
|
||||
**MyView.component.html**
|
||||
|
||||
```html
|
||||
<activiti-form
|
||||
[taskId]="selectedTask?.id"
|
||||
@@ -297,13 +196,14 @@ All `form*` events receive an instance of the `FormModel` as event argument for
|
||||
```
|
||||
|
||||
**MyView.component.ts**
|
||||
|
||||
```ts
|
||||
onFormSaved(form: FormModel) {
|
||||
console.log(form);
|
||||
}
|
||||
```
|
||||
|
||||
#### Controlling outcome execution behaviour
|
||||
### Controlling outcome execution behaviour
|
||||
|
||||
If absolutely needed it is possible taking full control over form outcome execution by means of `executeOutcome` event.
|
||||
This event is fired upon each outcome execution, both system and custom ones.
|
||||
@@ -314,6 +214,7 @@ This allows for example having custom form validation scenarios and/or additiona
|
||||
Alternatively you may want just running additional code on outcome execution without suppressing default one.
|
||||
|
||||
**MyView.component.html**
|
||||
|
||||
```html
|
||||
<activiti-form
|
||||
[taskId]="selectedTask?.id"
|
||||
@@ -322,6 +223,7 @@ Alternatively you may want just running additional code on outcome execution wit
|
||||
```
|
||||
|
||||
**MyView.component.ts**
|
||||
|
||||
```ts
|
||||
import { FormOutcomeEvent } from 'ng2-activiti-form';
|
||||
|
||||
@@ -355,48 +257,49 @@ will also be executed after your custom code.**
|
||||
|
||||
## Activiti Content Component
|
||||
|
||||
### Basic usage
|
||||
|
||||
The component shows the content preview.
|
||||
|
||||
```html
|
||||
<activiti-content [contentId]="'1001'"></activiti-content>
|
||||
<activiti-content
|
||||
[contentId]="'1001'">
|
||||
</activiti-content>
|
||||
```
|
||||
|
||||
### Configuration
|
||||
|
||||
#### Properties
|
||||
### Properties
|
||||
|
||||
The recommended set of properties can be found in the following table:
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `contentId` | string | | The content id to show. |
|
||||
| contentId | string | | The content id to show. |
|
||||
|
||||
#### Events
|
||||
### Events
|
||||
|
||||
| Name | Description |
|
||||
| --- | --- |
|
||||
| `contentClick` | Invoked when the content is clicked. |
|
||||
| contentClick | Invoked when the content is clicked. |
|
||||
|
||||
## FormService
|
||||
## FormService Service
|
||||
|
||||
```ts
|
||||
import { Component } from '@angular/core';
|
||||
import { FormService, FormEvent, FormFieldEvent } from 'ng2-activiti-form';
|
||||
|
||||
@Component(...)
|
||||
class MyComponent {
|
||||
|
||||
constructor(private formService: FormService) {
|
||||
constructor(formService: FormService) {
|
||||
|
||||
formService.formLoaded.subscribe((e: FormEvent) => {
|
||||
console.log(`Form loaded: ${e.form.id}`);
|
||||
});
|
||||
formService.formLoaded.subscribe(
|
||||
(e: FormEvent) => {
|
||||
console.log(`Form loaded: ${e.form.id}`);
|
||||
}
|
||||
);
|
||||
|
||||
formService.formFieldValueChanged.subscribe((e: FormFieldEvent) => {
|
||||
console.log(`Field value changed. Form: ${e.form.id}, Field: ${e.field.id}, Value: ${e.field.value}`);
|
||||
});
|
||||
formService.formFieldValueChanged.subscribe(
|
||||
(e: FormFieldEvent) => {
|
||||
console.log(`Field value changed. Form: ${e.form.id}, Field: ${e.field.id}, Value: ${e.field.value}`);
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@@ -413,6 +316,8 @@ class MyComponent {
|
||||
| taskCompletedError | FormErrorEvent | Raised when a task is completed unsuccessfully |
|
||||
| taskSaved | FormEvent | Raised when a task is saved successfully |
|
||||
| taskSavedError | FormErrorEvent | Raised when a task is saved unsuccessfully |
|
||||
| executeOutcome | FormOutcomeEvent | Raised when a form outcome is executed |
|
||||
| formEvents | Event | You can subscribe to this event to listen : ( click, blur, change, focus, focusin, focusout, input, invalid, select) of any elements in the form , see doc below|
|
||||
|
||||
### Methods
|
||||
|
||||
@@ -466,6 +371,17 @@ The result should be as following:
|
||||
|
||||

|
||||
|
||||
### Listen all form Events
|
||||
|
||||
If you want listen all the events fired the form you can subscribe to this Subject :
|
||||
|
||||
```ts
|
||||
formService.formEvents.subscribe((event: Event) => {
|
||||
console.log('Event fired:' + event.type);
|
||||
console.log('Event Target:' + event.target);
|
||||
});
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Form Stencils with Angular 2](docs/stencils.md)
|
||||
@@ -473,50 +389,15 @@ The result should be as following:
|
||||
|
||||
## Build from sources
|
||||
|
||||
Alternatively you can build component from sources with the following commands:
|
||||
|
||||
You can build component from sources with the following commands:
|
||||
|
||||
```sh
|
||||
npm install
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Build the files and keep watching for changes
|
||||
|
||||
```sh
|
||||
$ npm run build:w
|
||||
```
|
||||
|
||||
## Running unit tests
|
||||
|
||||
```sh
|
||||
npm test
|
||||
```
|
||||
|
||||
### Running unit tests in browser
|
||||
|
||||
```sh
|
||||
npm test-browser
|
||||
```
|
||||
|
||||
This task rebuilds all the code, runs tslint, license checks and other quality check tools
|
||||
before performing unit testing.
|
||||
|
||||
### Code coverage
|
||||
|
||||
```sh
|
||||
npm run coverage
|
||||
```
|
||||
|
||||
## Demo
|
||||
|
||||
If you want have a demo of how the component works, please check the demo folder :
|
||||
|
||||
```sh
|
||||
cd demo
|
||||
npm install
|
||||
npm start
|
||||
```
|
||||
> The `build` task rebuilds all the code, runs tslint, license checks
|
||||
> and other quality check tools before performing unit testing.
|
||||
|
||||
## NPM scripts
|
||||
|
||||
@@ -527,6 +408,16 @@ npm start
|
||||
| npm run test-browser | Run unit tests in the browser
|
||||
| npm run coverage | Run unit tests and display code coverage report |
|
||||
|
||||
## Demo
|
||||
|
||||
Please check the demo folder for a demo project
|
||||
|
||||
```sh
|
||||
cd demo
|
||||
npm install
|
||||
npm start
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
[Apache Version 2.0](https://github.com/Alfresco/alfresco-ng2-components/blob/master/LICENSE)
|
||||
[Apache Version 2.0](https://github.com/Alfresco/alfresco-ng2-components/blob/master/LICENSE)
|
35
ng2-components/ng2-activiti-form/config/webpack.build.js
Normal file
35
ng2-components/ng2-activiti-form/config/webpack.build.js
Normal file
@@ -0,0 +1,35 @@
|
||||
const webpack = require('webpack');
|
||||
const webpackMerge = require('webpack-merge');
|
||||
const commonConfig = require('./webpack.common.js');
|
||||
|
||||
module.exports = webpackMerge(commonConfig, {
|
||||
|
||||
devtool: 'cheap-module-source-map',
|
||||
|
||||
externals: [
|
||||
/^\@angular\//,
|
||||
/^rxjs\//,
|
||||
'moment',
|
||||
'raphael',
|
||||
'ng2-charts',
|
||||
'alfresco-js-api',
|
||||
'ng2-alfresco-core',
|
||||
'ng2-alfresco-datatable',
|
||||
'ng2-activiti-analytics',
|
||||
'ng2-activiti-diagrams',
|
||||
'ng2-activiti-form',
|
||||
"ng2-activiti-tasklist",
|
||||
'ng2-alfresco-documentlist'
|
||||
],
|
||||
|
||||
output: {
|
||||
filename: './bundles/[name].js',
|
||||
library: '[name]',
|
||||
libraryTarget: 'umd',
|
||||
chunkFilename: '[id].chunk.js'
|
||||
},
|
||||
|
||||
entry: {
|
||||
"ng2-activiti-form": "./index.ts"
|
||||
}
|
||||
});
|
@@ -2,6 +2,11 @@ const webpack = require('webpack');
|
||||
const helpers = require('./helpers');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||
var HappyPack = require('happypack');
|
||||
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
|
||||
|
||||
const ENV = process.env.NODE_ENV = process.env.ENV = 'production';
|
||||
|
||||
module.exports = {
|
||||
|
||||
@@ -12,22 +17,14 @@ module.exports = {
|
||||
}
|
||||
},
|
||||
|
||||
// require those dependencies but don't bundle them
|
||||
externals: [
|
||||
/^\@angular\//,
|
||||
/^rxjs\//,
|
||||
'moment',
|
||||
'raphael',
|
||||
'ng2-charts',
|
||||
'alfresco-js-api',
|
||||
'ng2-alfresco-core',
|
||||
'ng2-alfresco-datatable',
|
||||
'ng2-activiti-analytics',
|
||||
'ng2-activiti-diagrams',
|
||||
'ng2-activiti-form',
|
||||
"ng2-activiti-tasklist",
|
||||
'ng2-alfresco-documentlist'
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
"ng2-alfresco-core": helpers.root('../ng2-alfresco-core/index.ts')
|
||||
},
|
||||
extensions: ['.ts', '.js'],
|
||||
symlinks: false,
|
||||
modules: [helpers.root('../../ng2-components'), helpers.root('node_modules')]
|
||||
},
|
||||
|
||||
module: {
|
||||
rules: [
|
||||
@@ -37,25 +34,19 @@ module.exports = {
|
||||
loader: 'source-map-loader',
|
||||
exclude: [/node_modules/, /bundles/, /dist/, /demo/]
|
||||
},
|
||||
{
|
||||
enforce: 'pre',
|
||||
test: /\.ts$/,
|
||||
use: 'source-map-loader',
|
||||
exclude: [/node_modules/, /bundles/, /dist/, /demo/]
|
||||
},
|
||||
{
|
||||
enforce: 'pre',
|
||||
test: /\.ts$/,
|
||||
loader: 'tslint-loader',
|
||||
options: {
|
||||
emitErrors: true,
|
||||
configFile: path.resolve(__dirname, './assets/tslint.json')
|
||||
failOnHint: true
|
||||
},
|
||||
exclude: [/node_modules/, /bundles/, /dist/, /demo/]
|
||||
},
|
||||
{
|
||||
test: /\.ts$/,
|
||||
use: ['ts-loader', 'angular2-template-loader'],
|
||||
loader: ['happypack/loader?id=ts', 'angular2-template-loader'],
|
||||
exclude: [/node_modules/, /bundles/, /dist/, /demo/]
|
||||
},
|
||||
{
|
||||
@@ -67,7 +58,13 @@ module.exports = {
|
||||
test: /\.css$/,
|
||||
loader: ['to-string-loader', 'css-loader'],
|
||||
exclude: [/node_modules/, /bundles/, /dist/, /demo/]
|
||||
},{
|
||||
},
|
||||
{
|
||||
test: /\.component.scss$/,
|
||||
use: ['to-string-loader', 'raw-loader', 'sass-loader'],
|
||||
exclude: [/node_modules/, /bundles/, /dist/, /demo/]
|
||||
},
|
||||
{
|
||||
enforce: 'pre',
|
||||
test: /\.ts$/,
|
||||
loader: 'license-check',
|
||||
@@ -95,15 +92,29 @@ module.exports = {
|
||||
]
|
||||
},
|
||||
|
||||
resolve: {
|
||||
extensions: ['.ts', '.js'],
|
||||
symlinks: false,
|
||||
modules: [
|
||||
'../ng2-components', 'node_modules'
|
||||
]
|
||||
},
|
||||
|
||||
plugins: [
|
||||
new ForkTsCheckerWebpackPlugin(),
|
||||
new HappyPack({
|
||||
id: 'ts',
|
||||
threads: 8,
|
||||
loaders: [
|
||||
{
|
||||
path: 'ts-loader',
|
||||
query: {
|
||||
happyPackMode: true,
|
||||
"compilerOptions": {
|
||||
"paths": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}),
|
||||
|
||||
new CopyWebpackPlugin([{
|
||||
from: `src/i18n/`,
|
||||
to: `bundles/assets/${path.basename(helpers.root(''))}/i18n/`
|
||||
}]),
|
||||
|
||||
new webpack.NoEmitOnErrorsPlugin(),
|
||||
|
||||
new webpack.BannerPlugin(fs.readFileSync(path.resolve(__dirname, './assets/license_header_add.txt'), 'utf8')),
|
||||
@@ -112,11 +123,19 @@ module.exports = {
|
||||
/angular(\\|\/)core(\\|\/)@angular/,
|
||||
helpers.root('./src'),
|
||||
{}
|
||||
)
|
||||
),
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': {
|
||||
'ENV': JSON.stringify(ENV)
|
||||
}
|
||||
}),
|
||||
new webpack.LoaderOptionsPlugin({
|
||||
htmlLoader: {
|
||||
minimize: false // workaround for ng2
|
||||
}
|
||||
})
|
||||
],
|
||||
|
||||
devtool: 'cheap-module-source-map',
|
||||
|
||||
node: {
|
||||
fs: 'empty',
|
||||
module: false
|
||||
|
22
ng2-components/ng2-activiti-form/config/webpack.coverage.js
Normal file
22
ng2-components/ng2-activiti-form/config/webpack.coverage.js
Normal file
@@ -0,0 +1,22 @@
|
||||
const webpack = require('webpack');
|
||||
const webpackMerge = require('webpack-merge');
|
||||
const testConfig = require('./webpack.test.js');
|
||||
const helpers = require('./helpers');
|
||||
|
||||
module.exports = webpackMerge(testConfig, {
|
||||
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
enforce: 'post',
|
||||
test: /^(?!(.*spec|index|.*mock|.*model|.*event)).*\.ts?$/,
|
||||
include: [helpers.root('src')],
|
||||
loader: 'istanbul-instrumenter-loader',
|
||||
exclude: [
|
||||
/node_modules/,
|
||||
/test/
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
@@ -1,85 +1,8 @@
|
||||
const webpack = require('webpack');
|
||||
const helpers = require('./helpers');
|
||||
const webpackMerge = require('webpack-merge');
|
||||
const commonConfig = require('./webpack.common.js');
|
||||
|
||||
const ENV = process.env.NODE_ENV = process.env.ENV = 'production';
|
||||
module.exports = webpackMerge(commonConfig, {
|
||||
|
||||
module.exports = {
|
||||
|
||||
devtool: 'inline-source-map',
|
||||
|
||||
resolve: {
|
||||
extensions: ['.ts', '.js'],
|
||||
symlinks: false,
|
||||
modules: [helpers.root('../ng2-components'), helpers.root('node_modules')]
|
||||
},
|
||||
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
enforce: 'pre',
|
||||
test: /\.js$/,
|
||||
loader: 'source-map-loader',
|
||||
exclude: [/node_modules/, /bundles/, /dist/, /demo/]
|
||||
},
|
||||
{
|
||||
test: /\.ts$/,
|
||||
loaders: ['ts-loader?' + JSON.stringify({ transpileOnly: true}), 'angular2-template-loader'],
|
||||
exclude: [/node_modules/, /bundles/, /dist/, /demo/]
|
||||
},
|
||||
{
|
||||
test: /\.html$/,
|
||||
loader: 'html-loader',
|
||||
exclude: [/node_modules/, /bundles/, /dist/, /demo/]
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
loader: ['to-string-loader', 'css-loader'],
|
||||
exclude: [/node_modules/, /bundles/, /dist/, /demo/]
|
||||
},
|
||||
{
|
||||
test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico|pdf)$/,
|
||||
loader: 'file-loader',
|
||||
query: {
|
||||
name: '[path][name].[ext]',
|
||||
outputPath: (url)=> {
|
||||
return url.replace('src', 'dist');
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
enforce: 'post',
|
||||
test: /\.ts$/,
|
||||
loader: 'istanbul-instrumenter-loader',
|
||||
exclude: [
|
||||
/node_modules/,
|
||||
/test/
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
plugins: [
|
||||
new webpack.NoEmitOnErrorsPlugin(),
|
||||
|
||||
new webpack.ContextReplacementPlugin(
|
||||
/angular(\\|\/)core(\\|\/)@angular/,
|
||||
helpers.root('./src'),
|
||||
{}
|
||||
),
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': {
|
||||
'ENV': JSON.stringify(ENV)
|
||||
}
|
||||
}),
|
||||
new webpack.LoaderOptionsPlugin({
|
||||
htmlLoader: {
|
||||
minimize: false // workaround for ng2
|
||||
}
|
||||
})
|
||||
],
|
||||
|
||||
node: {
|
||||
fs: 'empty',
|
||||
module: false
|
||||
}
|
||||
};
|
||||
devtool: 'inline-source-map'
|
||||
});
|
||||
|
10
ng2-components/ng2-activiti-form/demo/config/helpers.js
Normal file
10
ng2-components/ng2-activiti-form/demo/config/helpers.js
Normal file
@@ -0,0 +1,10 @@
|
||||
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;
|
126
ng2-components/ng2-activiti-form/demo/config/webpack.common.js
Normal file
126
ng2-components/ng2-activiti-form/demo/config/webpack.common.js
Normal file
@@ -0,0 +1,126 @@
|
||||
const webpack = require('webpack');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||
const ExtractTextPlugin = require("extract-text-webpack-plugin");
|
||||
const helpers = require('./helpers');
|
||||
const path = require('path');
|
||||
|
||||
const alfrescoLibs = [
|
||||
'ng2-activiti-form'
|
||||
];
|
||||
|
||||
module.exports = {
|
||||
entry: {
|
||||
'polyfills': './src/polyfills.ts',
|
||||
'vendor': './src/vendor.ts',
|
||||
'dist': './src/main.ts'
|
||||
},
|
||||
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
enforce: 'pre',
|
||||
test: /\.js$/,
|
||||
include: [helpers.root('src'), helpers.root('../ng2-components')],
|
||||
loader: 'source-map-loader',
|
||||
exclude: [ /node_modules/, /public/, /resources/, /dist/]
|
||||
},
|
||||
{
|
||||
test: /\.ts$/,
|
||||
include: [helpers.root('src'), helpers.root('..')],
|
||||
loader: [
|
||||
'ts-loader',
|
||||
'angular2-template-loader'
|
||||
],
|
||||
exclude: [ /node_modules/, /public/, /resources/, /dist/]
|
||||
},
|
||||
{
|
||||
enforce: 'pre',
|
||||
test: /\.ts$/,
|
||||
loader: 'tslint-loader',
|
||||
include: [helpers.root('src')],
|
||||
options: {
|
||||
emitErrors: true
|
||||
},
|
||||
exclude: [ /node_modules/, /public/, /resources/, /dist/]
|
||||
},
|
||||
{
|
||||
enforce: 'pre',
|
||||
test: /\.ts$/,
|
||||
use: 'source-map-loader',
|
||||
exclude: [ /public/, /resources/, /dist/]
|
||||
},
|
||||
{
|
||||
test: /\.html$/,
|
||||
loader: 'html-loader',
|
||||
exclude: [ /node_modules/, /public/, /resources/, /dist/]
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
exclude: [helpers.root('src'), helpers.root('../ng2-components')],
|
||||
loader: ExtractTextPlugin.extract({
|
||||
fallback: 'style-loader',
|
||||
use: 'css-loader?sourceMap'
|
||||
})
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
include: [helpers.root('src'), helpers.root('../ng2-components')],
|
||||
loader: 'raw-loader'
|
||||
},
|
||||
{
|
||||
test: /\.component.scss$/,
|
||||
use: ['to-string-loader', 'raw-loader', 'sass-loader']
|
||||
},
|
||||
{
|
||||
test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
|
||||
loader: 'file-loader?name=assets/[name].[hash].[ext]'
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
plugins: [
|
||||
// Workaround for angular/angular#11580
|
||||
new webpack.ContextReplacementPlugin(
|
||||
// The (\\|\/) piece accounts for path separators in *nix and Windows
|
||||
/angular(\\|\/)core(\\|\/)@angular/,
|
||||
helpers.root('./src'), // location of your src
|
||||
{} // a map of your routes
|
||||
),
|
||||
new HtmlWebpackPlugin({
|
||||
template: './index.html'
|
||||
}),
|
||||
|
||||
new CopyWebpackPlugin([
|
||||
... alfrescoLibs.map(lib => {
|
||||
return {
|
||||
context: `../ng2-components/${lib}/bundles/assets/` ,
|
||||
from: '**/*',
|
||||
to: `assets/`
|
||||
}
|
||||
}),
|
||||
{
|
||||
context: 'resources/i18n',
|
||||
from: '**/*.json',
|
||||
to: 'resources/i18n'
|
||||
}
|
||||
]),
|
||||
|
||||
new webpack.optimize.CommonsChunkPlugin({
|
||||
name: ['src', 'vendor', 'polyfills']
|
||||
})
|
||||
],
|
||||
|
||||
devServer: {
|
||||
contentBase: helpers.root('dist'),
|
||||
compress: true,
|
||||
port: 3000,
|
||||
historyApiFallback: true,
|
||||
host: '0.0.0.0',
|
||||
inline: true
|
||||
},
|
||||
|
||||
node: {
|
||||
fs: 'empty'
|
||||
}
|
||||
};
|
36
ng2-components/ng2-activiti-form/demo/config/webpack.dev.js
Normal file
36
ng2-components/ng2-activiti-form/demo/config/webpack.dev.js
Normal file
@@ -0,0 +1,36 @@
|
||||
const webpack = require('webpack');
|
||||
const webpackMerge = require('webpack-merge');
|
||||
const ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||
const commonConfig = require('./webpack.common.js');
|
||||
const helpers = require('./helpers');
|
||||
const path = require('path');
|
||||
|
||||
module.exports = webpackMerge(commonConfig, {
|
||||
|
||||
devtool: 'cheap-module-eval-source-map',
|
||||
|
||||
output: {
|
||||
path: helpers.root('dist'),
|
||||
filename: '[name].js',
|
||||
chunkFilename: '[id].chunk.js'
|
||||
},
|
||||
|
||||
resolve: {
|
||||
alias: {
|
||||
"ng2-alfresco-core$": path.resolve(__dirname, '../../ng2-alfresco-core/index.ts'),
|
||||
"ng2-activiti-form$": path.resolve(__dirname, '../../ng2-activiti-form/index.ts')
|
||||
},
|
||||
extensions: ['.ts', '.js'],
|
||||
modules: [path.resolve(__dirname, '../node_modules')]
|
||||
},
|
||||
|
||||
plugins: [
|
||||
new webpack.NoEmitOnErrorsPlugin(),
|
||||
new ExtractTextPlugin('[name].[hash].css'),
|
||||
new webpack.LoaderOptionsPlugin({
|
||||
htmlLoader: {
|
||||
minimize: false // workaround for ng2
|
||||
}
|
||||
})
|
||||
]
|
||||
});
|
65
ng2-components/ng2-activiti-form/demo/config/webpack.prod.js
Normal file
65
ng2-components/ng2-activiti-form/demo/config/webpack.prod.js
Normal file
@@ -0,0 +1,65 @@
|
||||
const webpack = require('webpack');
|
||||
const webpackMerge = require('webpack-merge');
|
||||
const ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||
const commonConfig = require('./webpack.common.js');
|
||||
const helpers = require('./helpers');
|
||||
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||
|
||||
const ENV = process.env.NODE_ENV = process.env.ENV = 'production';
|
||||
|
||||
const alfrescoLibs = [
|
||||
'ng2-activiti-form'
|
||||
];
|
||||
|
||||
module.exports = webpackMerge(commonConfig, {
|
||||
|
||||
devtool: 'source-map',
|
||||
|
||||
output: {
|
||||
path: helpers.root('dist'),
|
||||
publicPath: '/',
|
||||
filename: '[name].[hash].js',
|
||||
chunkFilename: '[id].[hash].chunk.js'
|
||||
},
|
||||
|
||||
resolve: {
|
||||
extensions: ['.ts', '.js'],
|
||||
modules: [helpers.root('node_modules')]
|
||||
},
|
||||
|
||||
plugins: [
|
||||
new CopyWebpackPlugin([
|
||||
... alfrescoLibs.map(lib => {
|
||||
return {
|
||||
context: `node_modules/${lib}/bundles/assets/` ,
|
||||
from: '**/*',
|
||||
to: `assets/`
|
||||
}
|
||||
})
|
||||
]),
|
||||
new webpack.NoEmitOnErrorsPlugin(),
|
||||
new webpack.optimize.UglifyJsPlugin({ // https://github.com/angular/angular/issues/10618
|
||||
mangle: {
|
||||
keep_fnames: true
|
||||
},
|
||||
compress: {
|
||||
warnings: false
|
||||
},
|
||||
output: {
|
||||
comments: false
|
||||
},
|
||||
sourceMap: true
|
||||
}),
|
||||
new ExtractTextPlugin('[name].[hash].css'),
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': {
|
||||
'ENV': JSON.stringify(ENV)
|
||||
}
|
||||
}),
|
||||
new webpack.LoaderOptionsPlugin({
|
||||
htmlLoader: {
|
||||
minimize: false // workaround for ng2
|
||||
}
|
||||
})
|
||||
]
|
||||
});
|
@@ -6,47 +6,8 @@
|
||||
<title>Alfresco Angular 2 Activiti Form - Demo</title>
|
||||
<base href="./">
|
||||
|
||||
<!-- Moment js -->
|
||||
<script src="node_modules/moment/min/moment.min.js"></script>
|
||||
|
||||
<!-- Date picker -->
|
||||
<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>
|
||||
<link rel="stylesheet" href="node_modules/md-date-time-picker/dist/css/mdDateTimePicker.css" media="all">
|
||||
|
||||
<!-- Google Material Design Lite -->
|
||||
<link rel="stylesheet" href="node_modules/material-design-lite/material.min.css">
|
||||
<script src="node_modules/material-design-lite/material.min.js"></script>
|
||||
<link rel="stylesheet" href="node_modules/material-design-icons/iconfont/material-icons.css">
|
||||
|
||||
<!-- 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>
|
||||
|
||||
<!-- 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>
|
||||
|
||||
<!-- Polyfill(s) for dialogs -->
|
||||
<script src="node_modules/dialog-polyfill/dialog-polyfill.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="node_modules/dialog-polyfill/dialog-polyfill.css" />
|
||||
<style>._dialog_overlay { position: static !important; } </style>
|
||||
|
||||
<!-- Modules -->
|
||||
<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="systemjs.config.js"></script>
|
||||
<script>
|
||||
System.import('app').catch(function(err){ console.error(err); });
|
||||
</script>
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
</head>
|
||||
<style> .chart {display: block; width: 100%;}</style>
|
||||
|
||||
|
||||
<body>
|
||||
|
||||
<alfresco-app-demo></alfresco-app-demo>
|
||||
|
79
ng2-components/ng2-activiti-form/demo/package-lock.json
generated
Normal file
79
ng2-components/ng2-activiti-form/demo/package-lock.json
generated
Normal file
@@ -0,0 +1,79 @@
|
||||
{
|
||||
"name": "ng2-activiti-form-demo",
|
||||
"version": "0.1.0",
|
||||
"lockfileVersion": 1,
|
||||
"dependencies": {
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
|
||||
"dev": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.8",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz",
|
||||
"integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=",
|
||||
"dev": true
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
|
||||
"dev": true
|
||||
},
|
||||
"fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
|
||||
"dev": true
|
||||
},
|
||||
"glob": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
|
||||
"integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
|
||||
"dev": true
|
||||
},
|
||||
"inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
|
||||
"dev": true
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
|
||||
"dev": true
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||
"dev": true
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||
"dev": true
|
||||
},
|
||||
"path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
|
||||
"dev": true
|
||||
},
|
||||
"rimraf": {
|
||||
"version": "2.6.1",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz",
|
||||
"integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=",
|
||||
"dev": true
|
||||
},
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
}
|
@@ -3,19 +3,16 @@
|
||||
"description": "Alfresco Activiti Form Component - Demo",
|
||||
"version": "0.1.0",
|
||||
"author": "Alfresco Software, Ltd.",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"clean": "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 && npm run clean-build && npm run tsc",
|
||||
"build:w": "npm run tslint && rimraf dist && npm run tsc:w",
|
||||
"travis": "npm link ng2-alfresco-core ng2-activiti-form",
|
||||
"tsc": "tsc",
|
||||
"tsc:w": "tsc -w",
|
||||
"tslint": "tslint -c tslint.json *.ts && tslint -c tslint.json src/{,**/}**.ts -e '{,**/}**.d.ts'"
|
||||
"build": "rimraf dist && npm run webpack -- --config config/webpack.prod.js --progress --profile --bail",
|
||||
"build:dev": "rimraf dist && npm run webpack -- --config config/webpack.dev.js --progress --profile --bail",
|
||||
"start:dist": "wsrv -s dist/ -p 3000 -a 0.0.0.0",
|
||||
"start": "npm run webpack-dev-server -- --config config/webpack.prod.js --progress --content-base app/",
|
||||
"start:dev": "npm run webpack-dev-server -- --config config/webpack.dev.js --progress --content-base app/",
|
||||
"clean": "npm run clean-build && rimraf dist node_modules typings dist",
|
||||
"clean-build": "rimraf 'app/{,**/}**.js' 'app/{,**/}**.js.map' 'app/{,**/}**.d.ts'",
|
||||
"webpack-dev-server": "node --max_old_space_size=4096 node_modules/webpack-dev-server/bin/webpack-dev-server.js",
|
||||
"webpack": "webpack"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"contributors": [
|
||||
@@ -41,18 +38,16 @@
|
||||
"@angular/platform-browser": "~4.0.0",
|
||||
"@angular/platform-browser-dynamic": "~4.0.0",
|
||||
"@angular/router": "~4.0.0",
|
||||
|
||||
"@angular/material": "2.0.0-beta.1",
|
||||
"alfresco-js-api": "~1.5.0",
|
||||
"alfresco-js-api": "~1.6.0",
|
||||
"core-js": "2.4.1",
|
||||
"hammerjs": "2.0.8",
|
||||
"ng2-alfresco-core": "1.5.0",
|
||||
"ng2-translate": "5.0.0",
|
||||
"ng2-alfresco-core": "1.6.0",
|
||||
"@ngx-translate/core": "^7.0.0",
|
||||
"reflect-metadata": "0.1.10",
|
||||
"rxjs": "5.1.0",
|
||||
"systemjs": "0.19.27",
|
||||
"zone.js": "0.7.6",
|
||||
|
||||
"intl": "1.2.4",
|
||||
"dialog-polyfill": "0.4.7",
|
||||
"element.scrollintoviewifneeded-polyfill": "1.0.1",
|
||||
@@ -60,15 +55,60 @@
|
||||
"material-design-lite": "1.2.1",
|
||||
"moment": "2.15.1",
|
||||
"md-date-time-picker": "2.2.0",
|
||||
"ng2-activiti-form": "1.5.0"
|
||||
"ng2-activiti-form": "1.6.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jasmine": "^2.2.33",
|
||||
"@types/node": "^6.0.42",
|
||||
"concurrently": "^2.2.0",
|
||||
"rimraf": "2.5.2",
|
||||
"tslint": "^3.8.1",
|
||||
"typescript": "^2.0.3",
|
||||
"wsrv": "^0.1.5"
|
||||
"@types/hammerjs": "^2.0.34",
|
||||
"@types/jasmine": "2.5.35",
|
||||
"@types/node": "6.0.45",
|
||||
"angular2-template-loader": "^0.6.2",
|
||||
"autoprefixer": "^6.5.4",
|
||||
"copy-webpack-plugin": "^4.0.1",
|
||||
"css-loader": "^0.23.1",
|
||||
"css-to-string-loader": "^0.1.2",
|
||||
"cssnano": "^3.8.1",
|
||||
"extract-text-webpack-plugin": "^2.0.0-rc.3",
|
||||
"file-loader": "0.11.1",
|
||||
"html-loader": "^0.4.4",
|
||||
"html-webpack-plugin": "^2.28.0",
|
||||
"istanbul-instrumenter-loader": "0.2.0",
|
||||
"jasmine-ajax": "^3.2.0",
|
||||
"jasmine-core": "2.4.1",
|
||||
"karma": "^0.13.22",
|
||||
"karma-chrome-launcher": "~1.0.1",
|
||||
"karma-coverage": "^1.1.1",
|
||||
"karma-jasmine": "~1.0.2",
|
||||
"karma-jasmine-ajax": "^0.1.13",
|
||||
"karma-jasmine-html-reporter": "0.2.0",
|
||||
"karma-mocha-reporter": "^2.2.2",
|
||||
"karma-remap-istanbul": "^0.6.0",
|
||||
"karma-sourcemap-loader": "^0.3.7",
|
||||
"karma-systemjs": "^0.16.0",
|
||||
"karma-webpack": "^2.0.2",
|
||||
"loader-utils": "^1.1.0",
|
||||
"merge-stream": "^1.0.1",
|
||||
"node-sass": "^3.13.1",
|
||||
"null-loader": "^0.1.1",
|
||||
"package-json-merge": "0.0.1",
|
||||
"raw-loader": "^0.5.1",
|
||||
"remap-istanbul": "^0.6.3",
|
||||
"rimraf": "^2.6.1",
|
||||
"run-sequence": "^1.2.2",
|
||||
"sass-loader": "6.0.2",
|
||||
"script-loader": "0.7.0",
|
||||
"source-map-loader": "^0.1.6",
|
||||
"style-loader": "^0.13.1",
|
||||
"systemjs-builder": "^0.15.34",
|
||||
"to-string-loader": "^1.1.4",
|
||||
"traceur": "^0.0.91",
|
||||
"ts-loader": "^2.0.0",
|
||||
"ts-node": "^1.7.0",
|
||||
"tslint": "^4.4.2",
|
||||
"tslint-loader": "^3.3.0",
|
||||
"typescript": "^2.1.6",
|
||||
"webpack": "^2.2.1",
|
||||
"webpack-dev-server": "^2.3.0",
|
||||
"webpack-merge": "2.6.1",
|
||||
"wsrv": "^0.1.7"
|
||||
}
|
||||
}
|
||||
|
17
ng2-components/ng2-activiti-form/demo/src/polyfills.ts
Normal file
17
ng2-components/ng2-activiti-form/demo/src/polyfills.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import 'core-js/es6';
|
||||
import 'core-js/es7/reflect';
|
||||
import 'intl';
|
||||
|
||||
require('zone.js/dist/zone'); // IE 8-11
|
||||
require('element.scrollintoviewifneeded-polyfill'); // IE/FF
|
||||
|
||||
if (process.env.ENV === 'production') {
|
||||
// Production
|
||||
|
||||
} else {
|
||||
// Development
|
||||
|
||||
Error['stackTraceLimit'] = Infinity;
|
||||
|
||||
require('zone.js/dist/long-stack-trace-zone');
|
||||
}
|
26
ng2-components/ng2-activiti-form/demo/src/vendor.ts
Normal file
26
ng2-components/ng2-activiti-form/demo/src/vendor.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
// 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';
|
||||
|
||||
// hammerjs
|
||||
import 'hammerjs';
|
||||
|
||||
// Alfresco
|
||||
import 'alfresco-js-api';
|
||||
import 'ng2-activiti-form';
|
||||
|
||||
// Google Material Design Lite
|
||||
import 'material-design-lite/material.js';
|
||||
import 'material-design-lite/dist/material.orange-blue.min.css';
|
||||
import 'material-design-icons/iconfont/material-icons.css';
|
||||
|
||||
// Polyfill(s) for dialogs
|
||||
require('script-loader!dialog-polyfill/dialog-polyfill');
|
||||
import 'dialog-polyfill/dialog-polyfill.css';
|
@@ -1,54 +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: 'src',
|
||||
// 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',
|
||||
'@angular/material': 'npm:@angular/material/bundles/material.umd.js',
|
||||
'@angular/animations': 'npm:@angular/animations/bundles/animations.umd.min.js',
|
||||
'@angular/animations/browser':'npm:@angular/animations/bundles/animations-browser.umd.js',
|
||||
'@angular/platform-browser/animations': 'npm:@angular/platform-browser/bundles/platform-browser-animations.umd.js',
|
||||
|
||||
// other libraries
|
||||
'rxjs': 'npm:rxjs',
|
||||
'moment': 'npm:moment/min/moment.min.js',
|
||||
'ng2-translate': 'npm:ng2-translate',
|
||||
'alfresco-js-api': 'npm:alfresco-js-api/dist',
|
||||
'ng2-alfresco-core': 'npm:ng2-alfresco-core',
|
||||
'ng2-activiti-form': 'npm:ng2-activiti-form'
|
||||
},
|
||||
// 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'
|
||||
},
|
||||
'moment': { defaultExtension: 'js' },
|
||||
'ng2-translate': { defaultExtension: 'js' },
|
||||
'ng2-charts': { main: 'ng2-charts.js', defaultExtension: 'js'},
|
||||
'alfresco-js-api': { main: './alfresco-js-api.js', defaultExtension: 'js'},
|
||||
'ng2-alfresco-core': { main: './bundles/ng2-alfresco-core.js', defaultExtension: 'js'},
|
||||
'ng2-activiti-form': { main: './bundles/ng2-activiti-form.js', defaultExtension: 'js'}
|
||||
}
|
||||
});
|
||||
})(this);
|
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"target": "es5",
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
@@ -16,6 +17,7 @@
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"removeComments": true,
|
||||
"declaration": true,
|
||||
"outDir": "./dist",
|
||||
"lib": [
|
||||
"es2015",
|
||||
"dom"
|
||||
@@ -23,7 +25,9 @@
|
||||
"suppressImplicitAnyIndexErrors": true
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
"demo",
|
||||
"node_modules",
|
||||
"dist"
|
||||
],
|
||||
"angularCompilerOptions": {
|
||||
"strictMetadataEmit": false,
|
||||
|
@@ -1,124 +1,118 @@
|
||||
{
|
||||
"rules": {
|
||||
"align": [
|
||||
true,
|
||||
"parameters",
|
||||
"arguments",
|
||||
"statements"
|
||||
],
|
||||
"ban": false,
|
||||
"class-name": true,
|
||||
"comment-format": [
|
||||
true,
|
||||
"check-space",
|
||||
"check-lowercase"
|
||||
],
|
||||
"curly": true,
|
||||
"eofline": true,
|
||||
"forin": true,
|
||||
"indent": [
|
||||
true,
|
||||
"spaces"
|
||||
],
|
||||
"interface-name": false,
|
||||
"jsdoc-format": true,
|
||||
"label-position": true,
|
||||
"label-undefined": true,
|
||||
"max-line-length": [
|
||||
true,
|
||||
180
|
||||
],
|
||||
"member-ordering": [
|
||||
true,
|
||||
"public-before-private",
|
||||
"static-before-instance",
|
||||
"variables-before-functions"
|
||||
],
|
||||
"no-any": false,
|
||||
"no-arg": true,
|
||||
"no-bitwise": false,
|
||||
"no-conditional-assignment": true,
|
||||
"no-consecutive-blank-lines": true,
|
||||
"no-console": [
|
||||
true,
|
||||
"debug",
|
||||
"info",
|
||||
"time",
|
||||
"timeEnd",
|
||||
"trace"
|
||||
],
|
||||
"no-construct": true,
|
||||
"no-constructor-vars": false,
|
||||
"no-debugger": true,
|
||||
"no-duplicate-key": true,
|
||||
"no-duplicate-variable": true,
|
||||
"no-empty": false,
|
||||
"no-eval": true,
|
||||
"no-inferrable-types": false,
|
||||
"no-internal-module": true,
|
||||
"no-require-imports": false,
|
||||
"no-shadowed-variable": true,
|
||||
"no-switch-case-fall-through": true,
|
||||
"no-trailing-whitespace": true,
|
||||
"no-unreachable": true,
|
||||
"no-unused-expression": true,
|
||||
"no-unused-variable": true,
|
||||
"no-use-before-declare": true,
|
||||
"no-var-keyword": true,
|
||||
"no-var-requires": true,
|
||||
"object-literal-sort-keys": false,
|
||||
"one-line": [
|
||||
true,
|
||||
"check-open-brace",
|
||||
"check-catch",
|
||||
"check-else",
|
||||
"check-whitespace"
|
||||
],
|
||||
"quotemark": [
|
||||
true,
|
||||
"single",
|
||||
"avoid-escape"
|
||||
],
|
||||
"radix": true,
|
||||
"semicolon": true,
|
||||
"switch-default": true,
|
||||
"trailing-comma": [
|
||||
true,
|
||||
{
|
||||
"multiline": "never",
|
||||
"singleline": "never"
|
||||
}
|
||||
],
|
||||
"triple-equals": [
|
||||
true,
|
||||
"allow-null-check"
|
||||
],
|
||||
"typedef": false,
|
||||
"typedef-whitespace": [
|
||||
true,
|
||||
{
|
||||
"call-signature": "nospace",
|
||||
"index-signature": "nospace",
|
||||
"parameter": "nospace",
|
||||
"property-declaration": "nospace",
|
||||
"variable-declaration": "nospace"
|
||||
}
|
||||
],
|
||||
"use-strict": false,
|
||||
"variable-name": [
|
||||
true,
|
||||
"check-format",
|
||||
"allow-leading-underscore",
|
||||
"ban-keywords"
|
||||
],
|
||||
"whitespace": [
|
||||
true,
|
||||
"check-branch",
|
||||
"check-operator",
|
||||
"check-separator",
|
||||
"check-type",
|
||||
"check-module",
|
||||
"check-decl"
|
||||
]
|
||||
}
|
||||
"rules": {
|
||||
"align": [
|
||||
true,
|
||||
"parameters",
|
||||
"statements"
|
||||
],
|
||||
"ban": false,
|
||||
"class-name": true,
|
||||
"comment-format": [
|
||||
true,
|
||||
"check-space"
|
||||
],
|
||||
"curly": true,
|
||||
"eofline": true,
|
||||
"forin": true,
|
||||
"indent": [
|
||||
true,
|
||||
"spaces"
|
||||
],
|
||||
"interface-name": false,
|
||||
"jsdoc-format": true,
|
||||
"label-position": true,
|
||||
"max-line-length": [
|
||||
true,
|
||||
180
|
||||
],
|
||||
"member-ordering": [
|
||||
true,
|
||||
"static-before-instance",
|
||||
"variables-before-functions"
|
||||
],
|
||||
"no-any": false,
|
||||
"no-arg": true,
|
||||
"no-bitwise": false,
|
||||
"no-conditional-assignment": true,
|
||||
"no-consecutive-blank-lines": true,
|
||||
"no-console": [
|
||||
true,
|
||||
"debug",
|
||||
"info",
|
||||
"time",
|
||||
"timeEnd",
|
||||
"trace"
|
||||
],
|
||||
"no-construct": true,
|
||||
"no-constructor-vars": false,
|
||||
"no-debugger": true,
|
||||
"no-duplicate-variable": true,
|
||||
"no-empty": false,
|
||||
"no-eval": true,
|
||||
"no-inferrable-types": false,
|
||||
"no-internal-module": true,
|
||||
"no-require-imports": false,
|
||||
"no-shadowed-variable": true,
|
||||
"no-switch-case-fall-through": true,
|
||||
"no-trailing-whitespace": true,
|
||||
"no-unused-expression": true,
|
||||
"no-unused-variable": true,
|
||||
"no-use-before-declare": true,
|
||||
"no-var-keyword": true,
|
||||
"no-var-requires": false,
|
||||
"object-literal-sort-keys": false,
|
||||
"one-line": [
|
||||
true,
|
||||
"check-open-brace",
|
||||
"check-catch",
|
||||
"check-else",
|
||||
"check-whitespace"
|
||||
],
|
||||
"quotemark": [
|
||||
true,
|
||||
"single",
|
||||
"avoid-escape"
|
||||
],
|
||||
"radix": true,
|
||||
"semicolon": true,
|
||||
"switch-default": true,
|
||||
"trailing-comma": [
|
||||
true,
|
||||
{
|
||||
"multiline": "never",
|
||||
"singleline": "never"
|
||||
}
|
||||
],
|
||||
"triple-equals": [
|
||||
true,
|
||||
"allow-null-check"
|
||||
],
|
||||
"typedef": false,
|
||||
"typedef-whitespace": [
|
||||
true,
|
||||
{
|
||||
"call-signature": "nospace",
|
||||
"index-signature": "nospace",
|
||||
"parameter": "nospace",
|
||||
"property-declaration": "nospace",
|
||||
"variable-declaration": "nospace"
|
||||
}
|
||||
],
|
||||
"use-strict": false,
|
||||
"variable-name": [
|
||||
true,
|
||||
"check-format",
|
||||
"allow-leading-underscore",
|
||||
"ban-keywords"
|
||||
],
|
||||
"whitespace": [
|
||||
true,
|
||||
"check-branch",
|
||||
"check-operator",
|
||||
"check-separator",
|
||||
"check-type",
|
||||
"check-module",
|
||||
"check-decl"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
1
ng2-components/ng2-activiti-form/demo/webpack.config.js
Normal file
1
ng2-components/ng2-activiti-form/demo/webpack.config.js
Normal file
@@ -0,0 +1 @@
|
||||
module.exports = require('./config/webpack.dev.js');
|
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
import { NgModule, ModuleWithProviders } from '@angular/core';
|
||||
import { MdCheckboxModule, MdTabsModule, MdCardModule, MdButtonModule, MdIconModule, MdSlideToggleModule } from '@angular/material';
|
||||
import { CoreModule } from 'ng2-alfresco-core';
|
||||
|
||||
import { ActivitiForm } from './src/components/activiti-form.component';
|
||||
@@ -64,7 +65,13 @@ export const ACTIVITI_FORM_PROVIDERS: any[] = [
|
||||
@NgModule({
|
||||
imports: [
|
||||
CoreModule,
|
||||
HttpModule
|
||||
HttpModule,
|
||||
MdCheckboxModule,
|
||||
MdTabsModule,
|
||||
MdCardModule,
|
||||
MdButtonModule,
|
||||
MdIconModule,
|
||||
MdSlideToggleModule
|
||||
],
|
||||
declarations: [
|
||||
...ACTIVITI_FORM_DIRECTIVES,
|
||||
@@ -77,7 +84,13 @@ export const ACTIVITI_FORM_PROVIDERS: any[] = [
|
||||
...ACTIVITI_FORM_PROVIDERS
|
||||
],
|
||||
exports: [
|
||||
...ACTIVITI_FORM_DIRECTIVES
|
||||
...ACTIVITI_FORM_DIRECTIVES,
|
||||
MdCheckboxModule,
|
||||
MdTabsModule,
|
||||
MdCardModule,
|
||||
MdButtonModule,
|
||||
MdIconModule,
|
||||
MdSlideToggleModule
|
||||
]
|
||||
})
|
||||
export class ActivitiFormModule {
|
||||
|
@@ -8,16 +8,14 @@ module.exports = function (config) {
|
||||
|
||||
files: [
|
||||
'./node_modules/hammerjs/hammer.js',
|
||||
{pattern: './node_modules/@angular/material/prebuilt-themes/indigo-pink.css', included: true, watched: false},
|
||||
|
||||
//diagrams
|
||||
'./node_modules/chart.js/dist/Chart.js',
|
||||
'./node_modules/alfresco-js-api/dist/alfresco-js-api.js',
|
||||
'./node_modules/raphael/raphael.js',
|
||||
'./node_modules/moment/min/moment.min.js',
|
||||
'./node_modules/md-date-time-picker/dist/js/mdDateTimePicker.js',
|
||||
|
||||
{pattern: './node_modules/ng2-translate/**/*.js', included: false, 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},
|
||||
|
||||
@@ -27,7 +25,7 @@ module.exports = function (config) {
|
||||
{pattern: './src/**/*.ts', included: false, served: true, watched: false}
|
||||
],
|
||||
|
||||
webpack: webpackConfig,
|
||||
webpack: (config.mode === 'coverage') ? require('./webpack.coverage') : require('./webpack.test'),
|
||||
|
||||
webpackMiddleware: {
|
||||
stats: 'errors-only'
|
||||
|
7166
ng2-components/ng2-activiti-form/package-lock.json
generated
Normal file
7166
ng2-components/ng2-activiti-form/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,16 +1,17 @@
|
||||
{
|
||||
"name": "ng2-activiti-form",
|
||||
"description": "Alfresco Activiti Form Component for Angular 2",
|
||||
"version": "1.5.0",
|
||||
"version": "1.6.0",
|
||||
"author": "Alfresco Software, Ltd.",
|
||||
"scripts": {
|
||||
"clean": "rimraf dist node_modules typings bundles coverage .npmrc",
|
||||
"clean-lock": "rimraf package-lock.json",
|
||||
"rimraf": "rimraf",
|
||||
"build": "webpack --config webpack.build.js --progress --profile --bail",
|
||||
"test": "karma start karma.conf.js --reporters mocha,coverage --single-run --component",
|
||||
"test": "karma start karma.conf.js --reporters mocha,coverage --single-run --mode coverage",
|
||||
"test-browser": "karma start karma.conf.js --reporters kjhtml --component",
|
||||
"coverage": "npm run test && wsrv -o -p 9875 ./coverage/report",
|
||||
"prepublish" : "npm run build"
|
||||
"prepublishOnly": "npm run build"
|
||||
},
|
||||
"main": "bundles/ng2-activiti-form.js",
|
||||
"repository": {
|
||||
@@ -43,14 +44,14 @@
|
||||
"@angular/platform-browser": "~4.0.0",
|
||||
"@angular/platform-browser-dynamic": "~4.0.0",
|
||||
"@angular/router": "~4.0.0",
|
||||
"@angular/material": "2.0.0-beta.1",
|
||||
"alfresco-js-api": "~1.5.0",
|
||||
"@angular/material": "2.0.0-beta.6",
|
||||
"alfresco-js-api": "~1.6.0",
|
||||
"core-js": "2.4.1",
|
||||
"hammerjs": "2.0.8",
|
||||
"md-date-time-picker": "2.2.0",
|
||||
"moment": "2.15.1",
|
||||
"ng2-alfresco-core": "1.5.0",
|
||||
"ng2-translate": "5.0.0",
|
||||
"ng2-alfresco-core": "1.6.0",
|
||||
"@ngx-translate/core": "^7.0.0",
|
||||
"reflect-metadata": "0.1.10",
|
||||
"rxjs": "5.1.0",
|
||||
"systemjs": "0.19.27",
|
||||
@@ -68,6 +69,8 @@
|
||||
"cssnano": "^3.8.1",
|
||||
"extract-text-webpack-plugin": "^2.0.0-rc.3",
|
||||
"file-loader": "0.11.1",
|
||||
"fork-ts-checker-webpack-plugin": "^0.2.3",
|
||||
"happypack": "3.0.0",
|
||||
"html-loader": "^0.4.4",
|
||||
"html-webpack-plugin": "^2.28.0",
|
||||
"istanbul-instrumenter-loader": "0.2.0",
|
||||
@@ -86,12 +89,14 @@
|
||||
"karma-webpack": "^2.0.2",
|
||||
"loader-utils": "^1.1.0",
|
||||
"merge-stream": "^1.0.1",
|
||||
"node-sass": "^4.5.3",
|
||||
"null-loader": "^0.1.1",
|
||||
"package-json-merge": "0.0.1",
|
||||
"raw-loader": "^0.5.1",
|
||||
"remap-istanbul": "^0.6.3",
|
||||
"rimraf": "^2.5.4",
|
||||
"rimraf": "^2.6.1",
|
||||
"run-sequence": "^1.2.2",
|
||||
"sass-loader": "^6.0.5",
|
||||
"script-loader": "0.7.0",
|
||||
"source-map-loader": "^0.1.6",
|
||||
"style-loader": "^0.13.1",
|
||||
@@ -102,7 +107,7 @@
|
||||
"ts-node": "^1.7.0",
|
||||
"tslint": "^4.4.2",
|
||||
"tslint-loader": "^3.3.0",
|
||||
"typescript": "^2.1.6",
|
||||
"typescript": "^2.3.4",
|
||||
"webpack": "^2.2.1",
|
||||
"webpack-dev-server": "^2.3.0",
|
||||
"webpack-merge": "2.6.1",
|
||||
|
@@ -0,0 +1,275 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export let fakeForm = {
|
||||
id: 1001,
|
||||
name: 'ISSUE_FORM',
|
||||
processDefinitionId: 'ISSUE_APP:1:2504',
|
||||
processDefinitionName: 'ISSUE_APP',
|
||||
processDefinitionKey: 'ISSUE_APP',
|
||||
taskId: '7506',
|
||||
taskDefinitionKey: 'sid-F67A2996-1684-4774-855A-4591490081FD',
|
||||
tabs: [],
|
||||
fields: [
|
||||
{
|
||||
fieldType: 'ContainerRepresentation',
|
||||
id: '1498212398417',
|
||||
name: 'Label',
|
||||
type: 'container',
|
||||
value: null,
|
||||
required: false,
|
||||
readOnly: false,
|
||||
overrideId: false,
|
||||
colspan: 1,
|
||||
placeholder: null,
|
||||
minLength: 0,
|
||||
maxLength: 0,
|
||||
minValue: null,
|
||||
maxValue: null,
|
||||
regexPattern: null,
|
||||
optionType: null,
|
||||
hasEmptyValue: null,
|
||||
options: null,
|
||||
restUrl: null,
|
||||
restResponsePath: null,
|
||||
restIdProperty: null,
|
||||
restLabelProperty: null,
|
||||
tab: null,
|
||||
className: null,
|
||||
dateDisplayFormat: null,
|
||||
layout: null,
|
||||
sizeX: 2,
|
||||
sizeY: 1,
|
||||
row: -1,
|
||||
col: -1,
|
||||
visibilityCondition: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
{
|
||||
fieldType: 'RestFieldRepresentation',
|
||||
id: 'label',
|
||||
name: 'Label',
|
||||
type: 'dropdown',
|
||||
value: 'Choose one...',
|
||||
required: false,
|
||||
readOnly: false,
|
||||
overrideId: false,
|
||||
colspan: 1,
|
||||
placeholder: null,
|
||||
minLength: 0,
|
||||
maxLength: 0,
|
||||
minValue: null,
|
||||
maxValue: null,
|
||||
regexPattern: null,
|
||||
optionType: null,
|
||||
hasEmptyValue: true,
|
||||
options: [
|
||||
{
|
||||
id: 'empty',
|
||||
name: 'Choose one...'
|
||||
},
|
||||
{
|
||||
id: 'option_1',
|
||||
name: 'test1'
|
||||
},
|
||||
{
|
||||
id: 'option_2',
|
||||
name: 'test2'
|
||||
},
|
||||
{
|
||||
id: 'option_3',
|
||||
name: 'test3'
|
||||
}
|
||||
],
|
||||
restUrl: null,
|
||||
restResponsePath: null,
|
||||
restIdProperty: null,
|
||||
restLabelProperty: null,
|
||||
tab: null,
|
||||
className: null,
|
||||
params: {
|
||||
existingColspan: 1,
|
||||
maxColspan: 2
|
||||
},
|
||||
dateDisplayFormat: null,
|
||||
layout: {
|
||||
row: -1,
|
||||
column: -1,
|
||||
colspan: 1
|
||||
},
|
||||
sizeX: 1,
|
||||
sizeY: 1,
|
||||
row: -1,
|
||||
col: -1,
|
||||
visibilityCondition: null,
|
||||
endpoint: null,
|
||||
requestHeaders: null
|
||||
}
|
||||
],
|
||||
2: [
|
||||
{
|
||||
fieldType: 'RestFieldRepresentation',
|
||||
id: 'raduio',
|
||||
name: 'raduio',
|
||||
type: 'radio-buttons',
|
||||
value: null,
|
||||
required: false,
|
||||
readOnly: false,
|
||||
overrideId: false,
|
||||
colspan: 1,
|
||||
placeholder: null,
|
||||
minLength: 0,
|
||||
maxLength: 0,
|
||||
minValue: null,
|
||||
maxValue: null,
|
||||
regexPattern: null,
|
||||
optionType: null,
|
||||
hasEmptyValue: null,
|
||||
options: [
|
||||
{
|
||||
id: 'option_1',
|
||||
name: 'Option 1'
|
||||
},
|
||||
{
|
||||
id: 'option_2',
|
||||
name: 'Option 2'
|
||||
},
|
||||
{
|
||||
id: 'option_3',
|
||||
name: 'Option 3'
|
||||
}
|
||||
],
|
||||
restUrl: null,
|
||||
restResponsePath: null,
|
||||
restIdProperty: null,
|
||||
restLabelProperty: null,
|
||||
tab: null,
|
||||
className: null,
|
||||
params: {
|
||||
existingColspan: 1,
|
||||
maxColspan: 1
|
||||
},
|
||||
dateDisplayFormat: null,
|
||||
layout: {
|
||||
row: -1,
|
||||
column: -1,
|
||||
colspan: 1
|
||||
},
|
||||
sizeX: 1,
|
||||
sizeY: 2,
|
||||
row: -1,
|
||||
col: -1,
|
||||
visibilityCondition: null,
|
||||
endpoint: null,
|
||||
requestHeaders: null
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
fieldType: 'ContainerRepresentation',
|
||||
id: '1498212413062',
|
||||
name: 'Label',
|
||||
type: 'container',
|
||||
value: null,
|
||||
required: false,
|
||||
readOnly: false,
|
||||
overrideId: false,
|
||||
colspan: 1,
|
||||
placeholder: null,
|
||||
minLength: 0,
|
||||
maxLength: 0,
|
||||
minValue: null,
|
||||
maxValue: null,
|
||||
regexPattern: null,
|
||||
optionType: null,
|
||||
hasEmptyValue: null,
|
||||
options: null,
|
||||
restUrl: null,
|
||||
restResponsePath: null,
|
||||
restIdProperty: null,
|
||||
restLabelProperty: null,
|
||||
tab: null,
|
||||
className: null,
|
||||
dateDisplayFormat: null,
|
||||
layout: null,
|
||||
sizeX: 2,
|
||||
sizeY: 1,
|
||||
row: -1,
|
||||
col: -1,
|
||||
visibilityCondition: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'date',
|
||||
name: 'date',
|
||||
type: 'date',
|
||||
value: null,
|
||||
required: false,
|
||||
readOnly: false,
|
||||
overrideId: false,
|
||||
colspan: 1,
|
||||
placeholder: null,
|
||||
minLength: 0,
|
||||
maxLength: 0,
|
||||
minValue: null,
|
||||
maxValue: null,
|
||||
regexPattern: null,
|
||||
optionType: null,
|
||||
hasEmptyValue: null,
|
||||
options: null,
|
||||
restUrl: null,
|
||||
restResponsePath: null,
|
||||
restIdProperty: null,
|
||||
restLabelProperty: null,
|
||||
tab: null,
|
||||
className: null,
|
||||
params: {
|
||||
existingColspan: 1,
|
||||
maxColspan: 2
|
||||
},
|
||||
dateDisplayFormat: null,
|
||||
layout: {
|
||||
row: -1,
|
||||
column: -1,
|
||||
colspan: 1
|
||||
},
|
||||
sizeX: 1,
|
||||
sizeY: 1,
|
||||
row: -1,
|
||||
col: -1,
|
||||
visibilityCondition: null
|
||||
}
|
||||
],
|
||||
2: []
|
||||
}
|
||||
}
|
||||
],
|
||||
outcomes: [],
|
||||
javascriptEvents: [],
|
||||
className: '',
|
||||
style: '',
|
||||
customFieldTemplates: {},
|
||||
metadata: {},
|
||||
variables: [],
|
||||
customFieldsValueInfo: {},
|
||||
gridsterForm: false,
|
||||
globalDateFormat: 'D-M-YYYY'
|
||||
};
|
@@ -20,6 +20,7 @@ import { DebugElement, SimpleChange } from '@angular/core';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
import { CoreModule, AlfrescoTranslationService, ContentService } from 'ng2-alfresco-core';
|
||||
import { MdTabsModule } from '@angular/material';
|
||||
|
||||
import { ActivitiContent } from './activiti-content.component';
|
||||
import { FormService } from '../services/form.service';
|
||||
@@ -66,6 +67,7 @@ describe('ActivitiContent', () => {
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
MdTabsModule,
|
||||
CoreModule.forRoot()
|
||||
],
|
||||
declarations: [
|
||||
|
@@ -53,7 +53,7 @@ export class ActivitiContent implements OnChanges {
|
||||
private logService: LogService,
|
||||
private contentService: ContentService) {
|
||||
if (this.translate) {
|
||||
this.translate.addTranslationFolder('ng2-activiti-form', 'node_modules/ng2-activiti-form/src');
|
||||
this.translate.addTranslationFolder('ng2-activiti-form', 'assets/ng2-activiti-form');
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -21,12 +21,14 @@
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.activiti-form-hide-button {
|
||||
display: none;
|
||||
.activiti-form-reload-button {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.activiti-debug-button {
|
||||
float: right;
|
||||
.activiti-form-hide-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.activiti-task-title {
|
||||
|
@@ -2,13 +2,23 @@
|
||||
<div *ngIf="!hasForm()">
|
||||
<h3 class="activiti-task-title">Please select a Task</h3>
|
||||
</div>
|
||||
<div *ngIf="hasForm()">
|
||||
<div class="mdl-card mdl-shadow--2dp activiti-form-container {{form.className}}">
|
||||
<div class="mdl-card__title">
|
||||
<i *ngIf="showValidationIcon" class="material-icons">{{ form.isValid ? 'event_available' : 'event_busy' }}</i>
|
||||
<h2 *ngIf="isTitleEnabled()" class="mdl-card__title-text">{{form.taskName}}</h2>
|
||||
</div>
|
||||
<div class="mdl-card__media">
|
||||
<div *ngIf="hasForm()" class="{{form.className}}">
|
||||
<md-card>
|
||||
<md-card-header>
|
||||
<md-card-title>
|
||||
<h4 *ngIf="isTitleEnabled()">
|
||||
<div *ngIf="showRefreshButton" class="activiti-form-reload-button">
|
||||
<button md-icon-button (click)="onRefreshClicked()">
|
||||
<md-icon>refresh</md-icon>
|
||||
</button>
|
||||
</div>
|
||||
<md-icon>{{ form.isValid ? 'event_available' : 'event_busy' }}</md-icon>
|
||||
<span>{{form.taskName}}</span>
|
||||
|
||||
</h4>
|
||||
</md-card-title>
|
||||
</md-card-header>
|
||||
<md-card-content>
|
||||
<div *ngIf="form.hasTabs()">
|
||||
<tabs-widget [tabs]="form.tabs" (formTabChanged)="checkVisibility($event);"></tabs-widget>
|
||||
</div>
|
||||
@@ -18,40 +28,26 @@
|
||||
<form-field [field]="field.field"></form-field>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="form.hasOutcomes()" class="mdl-card__actions mdl-card--border">
|
||||
</md-card-content>
|
||||
<md-card-actions *ngIf="form.hasOutcomes()">
|
||||
<!--[class.mdl-button--colored]="!outcome.isSystem"-->
|
||||
<button *ngFor="let outcome of form.outcomes"
|
||||
alfresco-mdl-button
|
||||
md-button
|
||||
[disabled]="!isOutcomeButtonEnabled(outcome)"
|
||||
[class.mdl-button--colored]="!outcome.isSystem"
|
||||
[class.activiti-form-hide-button]="!isOutcomeButtonVisible(outcome, form.readOnly)"
|
||||
(click)="onOutcomeClicked(outcome, $event)">
|
||||
{{outcome.name}}
|
||||
{{outcome.name | uppercase}}
|
||||
</button>
|
||||
</div>
|
||||
<div *ngIf="showRefreshButton" class="mdl-card__menu" >
|
||||
<button (click)="onRefreshClicked()"
|
||||
class="mdl-button mdl-button--icon mdl-js-button mdl-js-ripple-effect">
|
||||
<i class="material-icons">refresh</i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</md-card-actions>
|
||||
</md-card>
|
||||
</div>
|
||||
</div>
|
||||
<!--
|
||||
For debugging and data visualisation purposes,
|
||||
will be removed during future revisions
|
||||
-->
|
||||
<div *ngIf="showDebugButton" class="activiti-form-debug-container">
|
||||
|
||||
<div class="activiti-debug-button">
|
||||
<label class="mdl-switch mdl-js-switch mdl-js-ripple-effect" for="switch-1" [class.is-checked]="debugMode">
|
||||
<input type="checkbox" id="switch-1" class="mdl-switch__input" [(ngModel)]="debugMode">
|
||||
<span class="mdl-switch__label"></span>
|
||||
<span class="debug-toggle-text">Debug mode</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div *ngIf="showDebugButton" class="activiti-form-debug-container">
|
||||
<md-slide-toggle [(ngModel)]="debugMode">Debug mode</md-slide-toggle>
|
||||
<div *ngIf="debugMode && hasForm()">
|
||||
<h4>Values</h4>
|
||||
<pre>{{form.values | json}}</pre>
|
||||
|
@@ -23,6 +23,7 @@ import { FormModel, FormOutcomeModel, FormFieldModel, FormOutcomeEvent, FormFiel
|
||||
import { FormService } from './../services/form.service';
|
||||
import { WidgetVisibilityService } from './../services/widget-visibility.service';
|
||||
import { NodeService } from './../services/node.service';
|
||||
import { fakeForm } from '../assets/activiti-form.component.mock';
|
||||
|
||||
describe('ActivitiForm', () => {
|
||||
|
||||
@@ -107,14 +108,14 @@ describe('ActivitiForm', () => {
|
||||
it('should enable custom outcome buttons', () => {
|
||||
let formModel = new FormModel();
|
||||
formComponent.form = formModel;
|
||||
let outcome = new FormOutcomeModel(formModel, {id: 'action1', name: 'Action 1'});
|
||||
let outcome = new FormOutcomeModel(formModel, { id: 'action1', name: 'Action 1' });
|
||||
expect(formComponent.isOutcomeButtonVisible(outcome, formComponent.form.readOnly)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should allow controlling [complete] button visibility', () => {
|
||||
let formModel = new FormModel();
|
||||
formComponent.form = formModel;
|
||||
let outcome = new FormOutcomeModel(formModel, {id: '$save', name: FormOutcomeModel.SAVE_ACTION});
|
||||
let outcome = new FormOutcomeModel(formModel, { id: '$save', name: FormOutcomeModel.SAVE_ACTION });
|
||||
|
||||
formComponent.showSaveButton = true;
|
||||
expect(formComponent.isOutcomeButtonVisible(outcome, formComponent.form.readOnly)).toBeTruthy();
|
||||
@@ -127,7 +128,7 @@ describe('ActivitiForm', () => {
|
||||
let formModel = new FormModel();
|
||||
formModel.readOnly = true;
|
||||
formComponent.form = formModel;
|
||||
let outcome = new FormOutcomeModel(formModel, {id: '$complete', name: FormOutcomeModel.COMPLETE_ACTION});
|
||||
let outcome = new FormOutcomeModel(formModel, { id: '$complete', name: FormOutcomeModel.COMPLETE_ACTION });
|
||||
|
||||
formComponent.showCompleteButton = true;
|
||||
expect(formComponent.isOutcomeButtonVisible(outcome, formComponent.form.readOnly)).toBeTruthy();
|
||||
@@ -137,23 +138,23 @@ describe('ActivitiForm', () => {
|
||||
let formModel = new FormModel();
|
||||
formModel.readOnly = true;
|
||||
formComponent.form = formModel;
|
||||
let outcome = new FormOutcomeModel(formModel, {id: '$save', name: FormOutcomeModel.SAVE_ACTION});
|
||||
let outcome = new FormOutcomeModel(formModel, { id: '$save', name: FormOutcomeModel.SAVE_ACTION });
|
||||
|
||||
formComponent.showSaveButton = true;
|
||||
expect(formComponent.isOutcomeButtonVisible(outcome, formComponent.form.readOnly)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should show [custom-outcome] button with readOnly form and selected custom-outcome', () => {
|
||||
let formModel = new FormModel({selectedOutcome: 'custom-outcome'});
|
||||
let formModel = new FormModel({ selectedOutcome: 'custom-outcome' });
|
||||
formModel.readOnly = true;
|
||||
formComponent.form = formModel;
|
||||
let outcome = new FormOutcomeModel(formModel, {id: '$customoutome', name: 'custom-outcome'});
|
||||
let outcome = new FormOutcomeModel(formModel, { id: '$customoutome', name: 'custom-outcome' });
|
||||
|
||||
formComponent.showCompleteButton = true;
|
||||
formComponent.showSaveButton = true;
|
||||
expect(formComponent.isOutcomeButtonVisible(outcome, formComponent.form.readOnly)).toBeTruthy();
|
||||
|
||||
outcome = new FormOutcomeModel(formModel, {id: '$customoutome2', name: 'custom-outcome2'});
|
||||
outcome = new FormOutcomeModel(formModel, { id: '$customoutome2', name: 'custom-outcome2' });
|
||||
expect(formComponent.isOutcomeButtonVisible(outcome, formComponent.form.readOnly)).toBeFalsy();
|
||||
});
|
||||
|
||||
@@ -161,7 +162,7 @@ describe('ActivitiForm', () => {
|
||||
let formModel = new FormModel();
|
||||
formModel.readOnly = false;
|
||||
formComponent.form = formModel;
|
||||
let outcome = new FormOutcomeModel(formModel, {id: '$save', name: FormOutcomeModel.COMPLETE_ACTION});
|
||||
let outcome = new FormOutcomeModel(formModel, { id: '$save', name: FormOutcomeModel.COMPLETE_ACTION });
|
||||
|
||||
formComponent.showCompleteButton = true;
|
||||
expect(formComponent.isOutcomeButtonVisible(outcome, formComponent.form.readOnly)).toBeTruthy();
|
||||
@@ -191,7 +192,7 @@ describe('ActivitiForm', () => {
|
||||
it('should get process variable if is a process task', () => {
|
||||
spyOn(formService, 'getTaskForm').and.callFake((taskId) => {
|
||||
return Observable.create(observer => {
|
||||
observer.next({taskId: taskId});
|
||||
observer.next({ taskId: taskId });
|
||||
observer.complete();
|
||||
});
|
||||
});
|
||||
@@ -199,7 +200,7 @@ describe('ActivitiForm', () => {
|
||||
spyOn(visibilityService, 'getTaskProcessVariable').and.returnValue(Observable.of({}));
|
||||
spyOn(formService, 'getTask').and.callFake((taskId) => {
|
||||
return Observable.create(observer => {
|
||||
observer.next({taskId: taskId, processDefinitionId: '10201'});
|
||||
observer.next({ taskId: taskId, processDefinitionId: '10201' });
|
||||
observer.complete();
|
||||
});
|
||||
});
|
||||
@@ -214,7 +215,7 @@ describe('ActivitiForm', () => {
|
||||
it('should not get process variable if is not a process task', () => {
|
||||
spyOn(formService, 'getTaskForm').and.callFake((taskId) => {
|
||||
return Observable.create(observer => {
|
||||
observer.next({taskId: taskId});
|
||||
observer.next({ taskId: taskId });
|
||||
observer.complete();
|
||||
});
|
||||
});
|
||||
@@ -222,7 +223,7 @@ describe('ActivitiForm', () => {
|
||||
spyOn(visibilityService, 'getTaskProcessVariable').and.returnValue(Observable.of({}));
|
||||
spyOn(formService, 'getTask').and.callFake((taskId) => {
|
||||
return Observable.create(observer => {
|
||||
observer.next({taskId: taskId, processDefinitionId: 'null'});
|
||||
observer.next({ taskId: taskId, processDefinitionId: 'null' });
|
||||
observer.complete();
|
||||
});
|
||||
});
|
||||
@@ -259,7 +260,7 @@ describe('ActivitiForm', () => {
|
||||
const taskId = '<task id>';
|
||||
|
||||
let change = new SimpleChange(null, taskId, true);
|
||||
formComponent.ngOnChanges({'taskId': change});
|
||||
formComponent.ngOnChanges({ 'taskId': change });
|
||||
|
||||
expect(formComponent.getFormByTaskId).toHaveBeenCalledWith(taskId);
|
||||
});
|
||||
@@ -269,7 +270,7 @@ describe('ActivitiForm', () => {
|
||||
const formId = '123';
|
||||
|
||||
let change = new SimpleChange(null, formId, true);
|
||||
formComponent.ngOnChanges({'formId': change});
|
||||
formComponent.ngOnChanges({ 'formId': change });
|
||||
|
||||
expect(formComponent.getFormDefinitionByFormId).toHaveBeenCalledWith(formId);
|
||||
});
|
||||
@@ -279,7 +280,7 @@ describe('ActivitiForm', () => {
|
||||
const formName = '<form>';
|
||||
|
||||
let change = new SimpleChange(null, formName, true);
|
||||
formComponent.ngOnChanges({'formName': change});
|
||||
formComponent.ngOnChanges({ 'formName': change });
|
||||
|
||||
expect(formComponent.getFormDefinitionByFormName).toHaveBeenCalledWith(formName);
|
||||
});
|
||||
@@ -304,7 +305,7 @@ describe('ActivitiForm', () => {
|
||||
spyOn(formComponent, 'getFormDefinitionByFormId').and.stub();
|
||||
spyOn(formComponent, 'getFormDefinitionByFormName').and.stub();
|
||||
|
||||
formComponent.ngOnChanges({'tag': new SimpleChange(null, 'hello world', true)});
|
||||
formComponent.ngOnChanges({ 'tag': new SimpleChange(null, 'hello world', true) });
|
||||
|
||||
expect(formComponent.getFormByTaskId).not.toHaveBeenCalled();
|
||||
expect(formComponent.getFormDefinitionByFormId).not.toHaveBeenCalled();
|
||||
@@ -314,7 +315,7 @@ describe('ActivitiForm', () => {
|
||||
it('should complete form on custom outcome click', () => {
|
||||
let formModel = new FormModel();
|
||||
let outcomeName = 'Custom Action';
|
||||
let outcome = new FormOutcomeModel(formModel, {id: 'custom1', name: outcomeName});
|
||||
let outcome = new FormOutcomeModel(formModel, { id: 'custom1', name: outcomeName });
|
||||
|
||||
let saved = false;
|
||||
formComponent.form = formModel;
|
||||
@@ -379,7 +380,7 @@ describe('ActivitiForm', () => {
|
||||
it('should do nothing when clicking outcome for readonly form', () => {
|
||||
let formModel = new FormModel();
|
||||
const outcomeName = 'Custom Action';
|
||||
let outcome = new FormOutcomeModel(formModel, {id: 'custom1', name: outcomeName});
|
||||
let outcome = new FormOutcomeModel(formModel, { id: 'custom1', name: outcomeName });
|
||||
|
||||
formComponent.form = formModel;
|
||||
spyOn(formComponent, 'completeTaskForm').and.stub();
|
||||
@@ -398,7 +399,7 @@ describe('ActivitiForm', () => {
|
||||
it('should require loaded form when clicking outcome', () => {
|
||||
let formModel = new FormModel();
|
||||
const outcomeName = 'Custom Action';
|
||||
let outcome = new FormOutcomeModel(formModel, {id: 'custom1', name: outcomeName});
|
||||
let outcome = new FormOutcomeModel(formModel, { id: 'custom1', name: outcomeName });
|
||||
|
||||
formComponent.readOnly = false;
|
||||
formComponent.form = null;
|
||||
@@ -407,7 +408,7 @@ describe('ActivitiForm', () => {
|
||||
|
||||
it('should not execute unknown system outcome', () => {
|
||||
let formModel = new FormModel();
|
||||
let outcome = new FormOutcomeModel(formModel, {id: 'unknown', name: 'Unknown', isSystem: true});
|
||||
let outcome = new FormOutcomeModel(formModel, { id: 'unknown', name: 'Unknown', isSystem: true });
|
||||
|
||||
formComponent.form = formModel;
|
||||
expect(formComponent.onOutcomeClicked(outcome)).toBeFalsy();
|
||||
@@ -415,12 +416,12 @@ describe('ActivitiForm', () => {
|
||||
|
||||
it('should require custom action name to complete form', () => {
|
||||
let formModel = new FormModel();
|
||||
let outcome = new FormOutcomeModel(formModel, {id: 'custom'});
|
||||
let outcome = new FormOutcomeModel(formModel, { id: 'custom' });
|
||||
|
||||
formComponent.form = formModel;
|
||||
expect(formComponent.onOutcomeClicked(outcome)).toBeFalsy();
|
||||
|
||||
outcome = new FormOutcomeModel(formModel, {id: 'custom', name: 'Custom'});
|
||||
outcome = new FormOutcomeModel(formModel, { id: 'custom', name: 'Custom' });
|
||||
spyOn(formComponent, 'completeTaskForm').and.stub();
|
||||
expect(formComponent.onOutcomeClicked(outcome)).toBeTruthy();
|
||||
});
|
||||
@@ -429,7 +430,7 @@ describe('ActivitiForm', () => {
|
||||
spyOn(formService, 'getTask').and.returnValue(Observable.of({}));
|
||||
spyOn(formService, 'getTaskForm').and.callFake((taskId) => {
|
||||
return Observable.create(observer => {
|
||||
observer.next({taskId: taskId});
|
||||
observer.next({ taskId: taskId });
|
||||
observer.complete();
|
||||
});
|
||||
});
|
||||
@@ -465,7 +466,7 @@ describe('ActivitiForm', () => {
|
||||
spyOn(formService, 'getTask').and.returnValue(Observable.of({}));
|
||||
spyOn(formService, 'getTaskForm').and.callFake((taskId) => {
|
||||
return Observable.create(observer => {
|
||||
observer.next({taskId: taskId});
|
||||
observer.next({ taskId: taskId });
|
||||
observer.complete();
|
||||
});
|
||||
});
|
||||
@@ -481,7 +482,7 @@ describe('ActivitiForm', () => {
|
||||
it('should fetch and parse form definition by id', () => {
|
||||
spyOn(formService, 'getFormDefinitionById').and.callFake((formId) => {
|
||||
return Observable.create(observer => {
|
||||
observer.next({id: formId});
|
||||
observer.next({ id: formId });
|
||||
observer.complete();
|
||||
});
|
||||
});
|
||||
@@ -520,7 +521,7 @@ describe('ActivitiForm', () => {
|
||||
|
||||
spyOn(formService, 'getFormDefinitionById').and.callFake((formName) => {
|
||||
return Observable.create(observer => {
|
||||
observer.next({name: formName});
|
||||
observer.next({ name: formName });
|
||||
observer.complete();
|
||||
});
|
||||
});
|
||||
@@ -556,8 +557,8 @@ describe('ActivitiForm', () => {
|
||||
let formModel = new FormModel({
|
||||
taskId: '123',
|
||||
fields: [
|
||||
{id: 'field1'},
|
||||
{id: 'field2'}
|
||||
{ id: 'field1' },
|
||||
{ id: 'field2' }
|
||||
]
|
||||
});
|
||||
formComponent.form = formModel;
|
||||
@@ -573,7 +574,7 @@ describe('ActivitiForm', () => {
|
||||
spyOn(formService, 'saveTaskForm').and.callFake(() => Observable.throw(error));
|
||||
spyOn(formComponent, 'handleError').and.stub();
|
||||
|
||||
formComponent.form = new FormModel({taskId: '123'});
|
||||
formComponent.form = new FormModel({ taskId: '123' });
|
||||
formComponent.saveTaskForm();
|
||||
|
||||
expect(formComponent.handleError).toHaveBeenCalledWith(error);
|
||||
@@ -618,8 +619,8 @@ describe('ActivitiForm', () => {
|
||||
let formModel = new FormModel({
|
||||
taskId: '123',
|
||||
fields: [
|
||||
{id: 'field1'},
|
||||
{id: 'field2'}
|
||||
{ id: 'field1' },
|
||||
{ id: 'field2' }
|
||||
]
|
||||
});
|
||||
|
||||
@@ -638,7 +639,7 @@ describe('ActivitiForm', () => {
|
||||
let form = formComponent.parseForm({
|
||||
id: '<id>',
|
||||
fields: [
|
||||
{id: 'field1', type: FormFieldTypes.CONTAINER}
|
||||
{ id: 'field1', type: FormFieldTypes.CONTAINER }
|
||||
]
|
||||
});
|
||||
|
||||
@@ -651,7 +652,7 @@ describe('ActivitiForm', () => {
|
||||
it('should provide outcomes for form definition', () => {
|
||||
spyOn(formComponent, 'getFormDefinitionOutcomes').and.callThrough();
|
||||
|
||||
let form = formComponent.parseForm({id: '<id>'});
|
||||
let form = formComponent.parseForm({ id: '<id>' });
|
||||
expect(formComponent.getFormDefinitionOutcomes).toHaveBeenCalledWith(form);
|
||||
});
|
||||
|
||||
@@ -724,7 +725,7 @@ describe('ActivitiForm', () => {
|
||||
let metadata = {};
|
||||
spyOn(nodeService, 'getNodeMetadata').and.returnValue(
|
||||
Observable.create(observer => {
|
||||
observer.next({metadata: metadata});
|
||||
observer.next({ metadata: metadata });
|
||||
observer.complete();
|
||||
})
|
||||
);
|
||||
@@ -800,4 +801,44 @@ describe('ActivitiForm', () => {
|
||||
expect(formComponent.isOutcomeButtonEnabled(outcome)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should raise [executeOutcome] event for formService', (done) => {
|
||||
formService.executeOutcome.subscribe(() => {
|
||||
done();
|
||||
});
|
||||
|
||||
let outcome = new FormOutcomeModel(new FormModel(), {
|
||||
id: ActivitiForm.CUSTOM_OUTCOME_ID,
|
||||
name: 'Custom'
|
||||
});
|
||||
|
||||
formComponent.form = new FormModel();
|
||||
formComponent.onOutcomeClicked(outcome);
|
||||
});
|
||||
|
||||
it('should refresh form values when data is changed', () => {
|
||||
formComponent.form = new FormModel(fakeForm);
|
||||
let formFields = formComponent.form.getFormFields();
|
||||
|
||||
let labelField = formFields.find(field => field.id === 'label');
|
||||
let radioField = formFields.find(field => field.id === 'raduio');
|
||||
expect(labelField.value).toBe('empty');
|
||||
expect(radioField.value).toBeNull();
|
||||
|
||||
let formValues: any = {};
|
||||
formValues.label = {
|
||||
id: 'option_1',
|
||||
name: 'test1'
|
||||
};
|
||||
formValues.raduio = { id: 'option_1', name: 'Option 1' };
|
||||
let change = new SimpleChange(null, formValues, false);
|
||||
formComponent.data = formValues;
|
||||
formComponent.ngOnChanges({ 'data': change });
|
||||
|
||||
formFields = formComponent.form.getFormFields();
|
||||
labelField = formFields.find(field => field.id === 'label');
|
||||
radioField = formFields.find(field => field.id === 'raduio');
|
||||
expect(labelField.value).toBe('option_1');
|
||||
expect(radioField.value).toBe('option_1');
|
||||
});
|
||||
|
||||
});
|
||||
|
@@ -28,48 +28,6 @@ import { WidgetVisibilityService } from './../services/widget-visibility.servic
|
||||
|
||||
declare var componentHandler: any;
|
||||
|
||||
/**
|
||||
* @Input
|
||||
* ActivitiForm can show 4 types of forms searching by 4 type of params:
|
||||
* 1) Form attached to a task passing the {taskId}.
|
||||
*
|
||||
* 2) Form that are only defined with the {formId} (in this case you receive only the form definition and the form will not be
|
||||
* attached to any process, useful in case you want to use ActivitiForm as form designer), in this case you can pass also other 2
|
||||
* parameters:
|
||||
* - {saveOption} as parameter to tell what is the function to call on the save action.
|
||||
* - {data} to fill the form field with some data, the id of the form must to match the name of the field of the provided data object.
|
||||
*
|
||||
* 3) Form that are only defined with the {formName} (in this case you receive only the form definition and the form will not be
|
||||
* attached to any process, useful in case you want to use ActivitiForm as form designer),
|
||||
* in this case you can pass also other 2 parameters:
|
||||
* - {saveOption} as parameter to tell what is the function to call on the save action.
|
||||
* - {data} to fill the form field with some data, the id of the form must to match the name of the field of the provided data object.
|
||||
*
|
||||
* 4) Form that show the metadata of a {nodeId}
|
||||
*
|
||||
* {showTitle} boolean - to hide the title of the form pass false, default true;
|
||||
*
|
||||
* {showRefreshButton} boolean - to hide the refresh button of the form pass false, default true;
|
||||
*
|
||||
* {showDebugButton} boolean - to show the debug options, default false;
|
||||
*
|
||||
* {showCompleteButton} boolean - to hide the complete button of the form pass false, default true;
|
||||
*
|
||||
* {showSaveButton} boolean - to hide the save button of the form pass false, default true;
|
||||
*
|
||||
* {saveMetadata} boolean - store the value of the form as metadata, default false;
|
||||
*
|
||||
* {path} string - path of the folder where to store the metadata;
|
||||
*
|
||||
* {nameNode} string (optional) - Name to assign to the new node where the metadata are stored;
|
||||
*
|
||||
* @Output
|
||||
* {formLoaded} EventEmitter - This event is fired when the form is loaded, it pass all the value in the form.
|
||||
* {formSaved} EventEmitter - This event is fired when the form is saved, it pass all the value in the form.
|
||||
* {formCompleted} EventEmitter - This event is fired when the form is completed, it pass all the value in the form.
|
||||
*
|
||||
* @returns {ActivitiForm} .
|
||||
*/
|
||||
@Component({
|
||||
selector: 'activiti-form',
|
||||
templateUrl: './activiti-form.component.html',
|
||||
@@ -82,6 +40,9 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
|
||||
static START_PROCESS_OUTCOME_ID: string = '$startProcess';
|
||||
static CUSTOM_OUTCOME_ID: string = '$custom';
|
||||
|
||||
@Input()
|
||||
form: FormModel;
|
||||
|
||||
@Input()
|
||||
taskId: string;
|
||||
|
||||
@@ -139,14 +100,15 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
|
||||
@Output()
|
||||
formLoaded: EventEmitter<FormModel> = new EventEmitter<FormModel>();
|
||||
|
||||
@Output()
|
||||
formDataRefreshed: EventEmitter<FormModel> = new EventEmitter<FormModel>();
|
||||
|
||||
@Output()
|
||||
executeOutcome: EventEmitter<FormOutcomeEvent> = new EventEmitter<FormOutcomeEvent>();
|
||||
|
||||
@Output()
|
||||
onError: EventEmitter<any> = new EventEmitter<any>();
|
||||
|
||||
form: FormModel;
|
||||
|
||||
debugMode: boolean = false;
|
||||
|
||||
constructor(protected formService: FormService,
|
||||
@@ -243,6 +205,12 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
|
||||
this.loadFormForEcmNode();
|
||||
return;
|
||||
}
|
||||
|
||||
let data = changes['data'];
|
||||
if (data && data.currentValue) {
|
||||
this.refreshFormData();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -253,9 +221,7 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
|
||||
onOutcomeClicked(outcome: FormOutcomeModel): boolean {
|
||||
if (!this.readOnly && outcome && this.form) {
|
||||
|
||||
let args = new FormOutcomeEvent(outcome);
|
||||
this.executeOutcome.emit(args);
|
||||
if (args.defaultPrevented) {
|
||||
if (!this.onExecuteOutcome(outcome)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -467,6 +433,12 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
|
||||
}
|
||||
}
|
||||
|
||||
private refreshFormData() {
|
||||
this.form = new FormModel(this.form.json, this.data, this.readOnly, this.formService);
|
||||
this.onFormLoaded(this.form);
|
||||
this.onFormDataRefreshed(this.form);
|
||||
}
|
||||
|
||||
private loadFormForEcmNode(): void {
|
||||
this.nodeService.getNodeMetadata(this.nodeId).subscribe(data => {
|
||||
this.data = data.metadata;
|
||||
@@ -514,6 +486,11 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
|
||||
this.formService.formLoaded.next(new FormEvent(form));
|
||||
}
|
||||
|
||||
protected onFormDataRefreshed(form: FormModel) {
|
||||
this.formDataRefreshed.emit(form);
|
||||
this.formService.formDataRefreshed.next(new FormEvent(form));
|
||||
}
|
||||
|
||||
protected onTaskSaved(form: FormModel) {
|
||||
this.formSaved.emit(form);
|
||||
this.formService.taskSaved.next(new FormEvent(form));
|
||||
@@ -533,4 +510,20 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
|
||||
this.handleError(error);
|
||||
this.formService.taskCompletedError.next(new FormErrorEvent(form, error));
|
||||
}
|
||||
|
||||
protected onExecuteOutcome(outcome: FormOutcomeModel): boolean {
|
||||
let args = new FormOutcomeEvent(outcome);
|
||||
|
||||
this.formService.executeOutcome.next(args);
|
||||
if (args.defaultPrevented) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.executeOutcome.emit(args);
|
||||
if (args.defaultPrevented) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@@ -18,6 +18,7 @@
|
||||
import { SimpleChange } from '@angular/core';
|
||||
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
import { MdTabsModule } from '@angular/material';
|
||||
|
||||
import { ActivitiStartForm } from './activiti-start-form.component';
|
||||
import { FormFieldComponent } from './form-field/form-field.component';
|
||||
@@ -43,7 +44,9 @@ describe('ActivitiStartForm', () => {
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [CoreModule.forRoot()],
|
||||
imports: [
|
||||
MdTabsModule,
|
||||
CoreModule.forRoot()],
|
||||
declarations: [
|
||||
ActivitiStartForm,
|
||||
FormFieldComponent,
|
||||
|
@@ -88,7 +88,7 @@ export class ActivitiStartForm extends ActivitiForm implements AfterViewChecked,
|
||||
super(formService, visibilityService, null, null, logService);
|
||||
|
||||
if (this.translate) {
|
||||
this.translate.addTranslationFolder('ng2-activiti-form', 'node_modules/ng2-activiti-form/src');
|
||||
this.translate.addTranslationFolder('ng2-activiti-form', 'assets/ng2-activiti-form');
|
||||
}
|
||||
|
||||
this.showTitle = false;
|
||||
|
@@ -17,13 +17,37 @@
|
||||
|
||||
import { AmountWidget } from './amount.widget';
|
||||
import { FormFieldModel } from './../core/form-field.model';
|
||||
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||
import { CoreModule } from 'ng2-alfresco-core';
|
||||
import { FormService } from './../../../services/form.service';
|
||||
import { EcmModelService } from './../../../services/ecm-model.service';
|
||||
import { ActivitiAlfrescoContentService } from '../../../services/activiti-alfresco.service';
|
||||
|
||||
describe('AmountWidget', () => {
|
||||
|
||||
let widget: AmountWidget;
|
||||
let fixture: ComponentFixture<AmountWidget>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
CoreModule.forRoot()
|
||||
],
|
||||
declarations: [
|
||||
AmountWidget
|
||||
],
|
||||
providers: [
|
||||
FormService,
|
||||
EcmModelService,
|
||||
ActivitiAlfrescoContentService
|
||||
]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
widget = new AmountWidget();
|
||||
fixture = TestBed.createComponent(AmountWidget);
|
||||
|
||||
widget = fixture.componentInstance;
|
||||
});
|
||||
|
||||
it('should setup currentcy from field', () => {
|
||||
|
@@ -16,12 +16,14 @@
|
||||
*/
|
||||
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { WidgetComponent } from './../widget.component';
|
||||
import { WidgetComponent , baseHost } from './../widget.component';
|
||||
import { FormService } from './../../../services/form.service';
|
||||
|
||||
@Component({
|
||||
selector: 'amount-widget',
|
||||
templateUrl: './amount.widget.html',
|
||||
styleUrls: ['./amount.widget.css']
|
||||
styleUrls: ['./amount.widget.css'],
|
||||
host: baseHost
|
||||
})
|
||||
export class AmountWidget extends WidgetComponent implements OnInit {
|
||||
|
||||
@@ -29,6 +31,10 @@ export class AmountWidget extends WidgetComponent implements OnInit {
|
||||
|
||||
currency: string = AmountWidget.DEFAULT_CURRENCY;
|
||||
|
||||
constructor(public formService: FormService) {
|
||||
super(formService);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
if (this.field && this.field.currency) {
|
||||
this.currency = this.field.currency;
|
||||
|
@@ -2,11 +2,11 @@
|
||||
<label [attr.for]="field.id">{{field.name}}<span *ngIf="isRequired()">*</span></label>
|
||||
<div>
|
||||
<span *ngIf="hasFile()" class="attach-widget__file mdl-chip"><span class="mdl-chip__text">{{getLinkedFileName()}}</span></span>
|
||||
<button #browseFile (click)="showDialog();" class="mdl-button mdl-js-button mdl-js-ripple-effect attach-widget__browser">
|
||||
<button #browseFile [disabled]="field.readOnly" (click)="showDialog();" class="mdl-button mdl-js-button mdl-js-ripple-effect attach-widget__browser">
|
||||
<i class="material-icons">image</i>
|
||||
Browse {{selectedFolderSiteName}}
|
||||
</button>
|
||||
<button *ngIf="hasFile" (click)="reset(file);" class="mdl-button mdl-js-button mdl-js-ripple-effect attach-widget__reset">Clear</button>
|
||||
<button *ngIf="hasFile" [disabled]="field.readOnly" (click)="reset(file);" class="mdl-button mdl-js-button mdl-js-ripple-effect attach-widget__reset">Clear</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@@ -16,32 +16,55 @@
|
||||
*/
|
||||
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
import { LogServiceMock } from 'ng2-alfresco-core';
|
||||
import { AttachWidget } from './attach.widget';
|
||||
import { ActivitiAlfrescoContentService } from '../../../services/activiti-alfresco.service';
|
||||
import { FormFieldModel } from './../core/form-field.model';
|
||||
import { FormFieldTypes } from '../core/form-field-types';
|
||||
import { ExternalContent } from '../core/external-content';
|
||||
import { ExternalContentLink } from '../core/external-content-link';
|
||||
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||
import { CoreModule } from 'ng2-alfresco-core';
|
||||
import { FormService } from './../../../services/form.service';
|
||||
import { EcmModelService } from './../../../services/ecm-model.service';
|
||||
|
||||
describe('AttachWidget', () => {
|
||||
|
||||
let widget: AttachWidget;
|
||||
let fixture: ComponentFixture<AttachWidget>;
|
||||
let element: HTMLElement;
|
||||
let contentService: ActivitiAlfrescoContentService;
|
||||
let dialogPolyfill: any;
|
||||
let logService: LogServiceMock;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
CoreModule.forRoot()
|
||||
],
|
||||
declarations: [
|
||||
AttachWidget
|
||||
],
|
||||
providers: [
|
||||
FormService,
|
||||
EcmModelService,
|
||||
ActivitiAlfrescoContentService
|
||||
]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
logService = new LogServiceMock();
|
||||
contentService = new ActivitiAlfrescoContentService(null, logService);
|
||||
widget = new AttachWidget(contentService, logService);
|
||||
fixture = TestBed.createComponent(AttachWidget);
|
||||
contentService = TestBed.get(ActivitiAlfrescoContentService);
|
||||
|
||||
element = fixture.nativeElement;
|
||||
widget = fixture.componentInstance;
|
||||
|
||||
dialogPolyfill = {
|
||||
registerDialog(obj: any) {
|
||||
obj.showModal = function () {
|
||||
obj.showModal = () => {
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
window['dialogPolyfill'] = dialogPolyfill;
|
||||
});
|
||||
|
||||
@@ -98,7 +121,7 @@ describe('AttachWidget', () => {
|
||||
expect(widget.selectedFolderNodes).toEqual(nodes);
|
||||
});
|
||||
|
||||
it('should link file on select', () => {
|
||||
xit('should link file on select', () => {
|
||||
let link = <ExternalContentLink> {};
|
||||
spyOn(contentService, 'linkAlfrescoNode').and.returnValue(
|
||||
Observable.create(observer => {
|
||||
|
@@ -17,18 +17,19 @@
|
||||
|
||||
import { Component, OnInit, Input, Output, EventEmitter, ViewChild } from '@angular/core';
|
||||
import { LogService } from 'ng2-alfresco-core';
|
||||
import { WidgetComponent } from './../widget.component';
|
||||
import { WidgetComponent , baseHost } from './../widget.component';
|
||||
import { ActivitiAlfrescoContentService } from '../../../services/activiti-alfresco.service';
|
||||
import { ExternalContent } from '../core/external-content';
|
||||
import { ExternalContentLink } from '../core/external-content-link';
|
||||
import { FormFieldModel } from '../core/form-field.model';
|
||||
import { FormService } from './../../../services/form.service';
|
||||
|
||||
declare let dialogPolyfill: any;
|
||||
|
||||
@Component({
|
||||
selector: 'attach-widget',
|
||||
templateUrl: './attach.widget.html',
|
||||
styleUrls: ['./attach.widget.css']
|
||||
styleUrls: ['./attach.widget.css'], host: baseHost
|
||||
})
|
||||
export class AttachWidget extends WidgetComponent implements OnInit {
|
||||
|
||||
@@ -52,9 +53,10 @@ export class AttachWidget extends WidgetComponent implements OnInit {
|
||||
@ViewChild('dialog')
|
||||
dialog: any;
|
||||
|
||||
constructor(private contentService: ActivitiAlfrescoContentService,
|
||||
constructor(public formService: FormService,
|
||||
private contentService: ActivitiAlfrescoContentService,
|
||||
private logService: LogService) {
|
||||
super();
|
||||
super(formService);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
|
@@ -16,17 +16,19 @@
|
||||
*/
|
||||
|
||||
import { Component } from '@angular/core';
|
||||
import { WidgetComponent } from './../widget.component';
|
||||
import { WidgetComponent , baseHost} from './../widget.component';
|
||||
import { WidgetVisibilityService } from '../../../services/widget-visibility.service';
|
||||
import { FormService } from './../../../services/form.service';
|
||||
|
||||
@Component({
|
||||
selector: 'checkbox-widget',
|
||||
templateUrl: './checkbox.widget.html'
|
||||
templateUrl: './checkbox.widget.html',
|
||||
host: baseHost
|
||||
})
|
||||
export class CheckboxWidget extends WidgetComponent {
|
||||
|
||||
constructor(private visibilityService: WidgetVisibilityService) {
|
||||
super();
|
||||
constructor(private visibilityService: WidgetVisibilityService, public formService: FormService) {
|
||||
super(formService);
|
||||
}
|
||||
|
||||
onChange() {
|
||||
|
@@ -20,19 +20,55 @@ import { ContainerWidgetModel } from './container.widget.model';
|
||||
import { FormModel } from './../core/form.model';
|
||||
import { FormFieldTypes } from './../core/form-field-types';
|
||||
import { FormFieldModel } from './../core/form-field.model';
|
||||
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||
import { CoreModule } from 'ng2-alfresco-core';
|
||||
import { WIDGET_DIRECTIVES } from '../index';
|
||||
import { MASK_DIRECTIVE } from '../index';
|
||||
import { FormFieldComponent } from './../../form-field/form-field.component';
|
||||
import { ActivitiContent } from './../../activiti-content.component';
|
||||
import { fakeFormJson } from '../../../services/assets/widget-visibility.service.mock';
|
||||
import { MdTabsModule } from '@angular/material';
|
||||
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||
import { CoreModule } from 'ng2-alfresco-core';
|
||||
import { FormService } from './../../../services/form.service';
|
||||
import { EcmModelService } from './../../../services/ecm-model.service';
|
||||
import { ActivitiAlfrescoContentService } from '../../../services/activiti-alfresco.service';
|
||||
|
||||
describe('ContainerWidget', () => {
|
||||
|
||||
let widget: ContainerWidget;
|
||||
let fixture: ComponentFixture<ContainerWidget>;
|
||||
let element: HTMLElement;
|
||||
let contentService: ActivitiAlfrescoContentService;
|
||||
let componentHandler;
|
||||
let dialogPolyfill;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
CoreModule.forRoot(),
|
||||
MdTabsModule
|
||||
],
|
||||
declarations: [FormFieldComponent, ActivitiContent, WIDGET_DIRECTIVES, MASK_DIRECTIVE],
|
||||
providers: [
|
||||
FormService,
|
||||
EcmModelService,
|
||||
ActivitiAlfrescoContentService
|
||||
]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ContainerWidget);
|
||||
contentService = TestBed.get(ActivitiAlfrescoContentService);
|
||||
|
||||
element = fixture.nativeElement;
|
||||
widget = fixture.componentInstance;
|
||||
|
||||
dialogPolyfill = {
|
||||
registerDialog(obj: any) {
|
||||
obj.showModal = function () {
|
||||
};
|
||||
}
|
||||
};
|
||||
componentHandler = jasmine.createSpyObj('componentHandler', [
|
||||
'upgradeAllRegistered'
|
||||
]);
|
||||
@@ -42,25 +78,22 @@ describe('ContainerWidget', () => {
|
||||
|
||||
it('should wrap field with model instance', () => {
|
||||
let field = new FormFieldModel(null);
|
||||
let container = new ContainerWidget();
|
||||
container.field = field;
|
||||
container.ngOnInit();
|
||||
expect(container.content).toBeDefined();
|
||||
expect(container.content.field).toBe(field);
|
||||
widget.field = field;
|
||||
widget.ngOnInit();
|
||||
expect(widget.content).toBeDefined();
|
||||
expect(widget.content.field).toBe(field);
|
||||
});
|
||||
|
||||
it('should upgrade MDL content on view init', () => {
|
||||
let container = new ContainerWidget();
|
||||
container.ngAfterViewInit();
|
||||
widget.ngAfterViewInit();
|
||||
expect(componentHandler.upgradeAllRegistered).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should setup MDL content only if component handler available', () => {
|
||||
let container = new ContainerWidget();
|
||||
expect(container.setupMaterialComponents()).toBeTruthy();
|
||||
expect(widget.setupMaterialComponents()).toBeTruthy();
|
||||
|
||||
window['componentHandler'] = null;
|
||||
expect(container.setupMaterialComponents()).toBeFalsy();
|
||||
expect(widget.setupMaterialComponents()).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should toggle underlying group container', () => {
|
||||
@@ -71,7 +104,6 @@ describe('ContainerWidget', () => {
|
||||
}
|
||||
}));
|
||||
|
||||
let widget = new ContainerWidget();
|
||||
widget.content = container;
|
||||
|
||||
expect(container.isExpanded).toBeTruthy();
|
||||
@@ -86,7 +118,6 @@ describe('ContainerWidget', () => {
|
||||
type: FormFieldTypes.GROUP
|
||||
}));
|
||||
|
||||
let widget = new ContainerWidget();
|
||||
widget.content = container;
|
||||
|
||||
expect(container.isExpanded).toBeTruthy();
|
||||
@@ -95,6 +126,7 @@ describe('ContainerWidget', () => {
|
||||
});
|
||||
|
||||
it('should toggle only group container', () => {
|
||||
|
||||
let container = new ContainerWidgetModel(new FormFieldModel(new FormModel(), {
|
||||
type: FormFieldTypes.CONTAINER,
|
||||
params: {
|
||||
@@ -102,7 +134,6 @@ describe('ContainerWidget', () => {
|
||||
}
|
||||
}));
|
||||
|
||||
let widget = new ContainerWidget();
|
||||
widget.content = container;
|
||||
|
||||
expect(container.isExpanded).toBeTruthy();
|
||||
@@ -111,7 +142,6 @@ describe('ContainerWidget', () => {
|
||||
});
|
||||
|
||||
it('should send an event when a value is changed in the form', (done) => {
|
||||
let widget = new ContainerWidget();
|
||||
let fakeForm = new FormModel();
|
||||
let fakeField = new FormFieldModel(fakeForm, {id: 'fakeField', value: 'fakeValue'});
|
||||
widget.fieldChanged.subscribe(field => {
|
||||
@@ -125,22 +155,8 @@ describe('ContainerWidget', () => {
|
||||
});
|
||||
|
||||
describe('when template is ready', () => {
|
||||
let containerWidgetComponent: ContainerWidget;
|
||||
let fixture: ComponentFixture<ContainerWidget>;
|
||||
let element: HTMLElement;
|
||||
let fakeContainerVisible: ContainerWidgetModel;
|
||||
let fakeContainerInvisible: ContainerWidgetModel;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [CoreModule],
|
||||
declarations: [FormFieldComponent, ActivitiContent, WIDGET_DIRECTIVES, MASK_DIRECTIVE]
|
||||
}).compileComponents().then(() => {
|
||||
fixture = TestBed.createComponent(ContainerWidget);
|
||||
containerWidgetComponent = fixture.componentInstance;
|
||||
element = fixture.nativeElement;
|
||||
});
|
||||
}));
|
||||
let fakeContainerVisible;
|
||||
let fakeContainerInvisible;
|
||||
|
||||
beforeEach(() => {
|
||||
componentHandler = jasmine.createSpyObj('componentHandler', ['upgradeAllRegistered', 'upgradeElement']);
|
||||
@@ -167,7 +183,7 @@ describe('ContainerWidget', () => {
|
||||
});
|
||||
|
||||
it('should show the container header when it is visible', () => {
|
||||
containerWidgetComponent.content = fakeContainerVisible;
|
||||
widget.content = fakeContainerVisible;
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable()
|
||||
.then(() => {
|
||||
@@ -178,7 +194,7 @@ describe('ContainerWidget', () => {
|
||||
});
|
||||
|
||||
it('should not show the container header when it is not visible', () => {
|
||||
containerWidgetComponent.content = fakeContainerInvisible;
|
||||
widget.content = fakeContainerInvisible;
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable()
|
||||
.then(() => {
|
||||
@@ -187,23 +203,23 @@ describe('ContainerWidget', () => {
|
||||
});
|
||||
|
||||
it('should hide header when it becomes not visible', async(() => {
|
||||
containerWidgetComponent.content = fakeContainerVisible;
|
||||
widget.content = fakeContainerVisible;
|
||||
fixture.detectChanges();
|
||||
containerWidgetComponent.fieldChanged.subscribe((res) => {
|
||||
containerWidgetComponent.content.field.isVisible = false;
|
||||
widget.fieldChanged.subscribe((res) => {
|
||||
widget.content.field.isVisible = false;
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable()
|
||||
.then(() => {
|
||||
expect(element.querySelector('.container-widget__header').classList.contains('hidden')).toBe(true);
|
||||
});
|
||||
});
|
||||
containerWidgetComponent.onFieldChanged(null);
|
||||
widget.onFieldChanged(null);
|
||||
}));
|
||||
|
||||
it('should show header when it becomes visible', async(() => {
|
||||
containerWidgetComponent.content = fakeContainerInvisible;
|
||||
containerWidgetComponent.fieldChanged.subscribe((res) => {
|
||||
containerWidgetComponent.content.field.isVisible = true;
|
||||
widget.content = fakeContainerInvisible;
|
||||
widget.fieldChanged.subscribe((res) => {
|
||||
widget.content.field.isVisible = true;
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable()
|
||||
.then(() => {
|
||||
@@ -213,7 +229,7 @@ describe('ContainerWidget', () => {
|
||||
expect(element.querySelector('#container-header-label').innerHTML).toContain('fake-cont-2-name');
|
||||
});
|
||||
});
|
||||
containerWidgetComponent.onFieldChanged(null);
|
||||
widget.onFieldChanged(null);
|
||||
}));
|
||||
|
||||
});
|
||||
|
@@ -17,19 +17,25 @@
|
||||
|
||||
import { Component, AfterViewInit, OnInit } from '@angular/core';
|
||||
import { ContainerWidgetModel } from './container.widget.model';
|
||||
import { WidgetComponent } from './../widget.component';
|
||||
import { WidgetComponent , baseHost } from './../widget.component';
|
||||
import { FormService } from './../../../services/form.service';
|
||||
|
||||
declare var componentHandler: any;
|
||||
|
||||
@Component({
|
||||
selector: 'container-widget',
|
||||
templateUrl: './container.widget.html',
|
||||
styleUrls: ['./container.widget.css']
|
||||
styleUrls: ['./container.widget.css'],
|
||||
host: baseHost
|
||||
})
|
||||
export class ContainerWidget extends WidgetComponent implements OnInit, AfterViewInit {
|
||||
|
||||
content: ContainerWidgetModel;
|
||||
|
||||
constructor(public formService: FormService) {
|
||||
super(formService);
|
||||
}
|
||||
|
||||
onExpanderClicked() {
|
||||
if (this.content && this.content.isCollapsible()) {
|
||||
this.content.isExpanded = !this.content.isExpanded;
|
||||
|
@@ -68,7 +68,7 @@ describe('FormFieldModel', () => {
|
||||
expect(field.options).toBeDefined();
|
||||
expect(field.options.length).toBe(0);
|
||||
|
||||
field = new FormFieldModel(new FormModel(), { options: null });
|
||||
field = new FormFieldModel(new FormModel(), {options: null});
|
||||
expect(field.options).toBeDefined();
|
||||
expect(field.options.length).toBe(0);
|
||||
});
|
||||
@@ -77,13 +77,13 @@ describe('FormFieldModel', () => {
|
||||
let field = new FormFieldModel(new FormModel(), null);
|
||||
expect(field.params).toEqual({});
|
||||
|
||||
field = new FormFieldModel(new FormModel(), { params: null });
|
||||
field = new FormFieldModel(new FormModel(), {params: null});
|
||||
expect(field.params).toEqual({});
|
||||
});
|
||||
|
||||
it('should update form on every value change', () => {
|
||||
let form = new FormModel();
|
||||
let field = new FormFieldModel(form, { id: 'field1' });
|
||||
let field = new FormFieldModel(form, {id: 'field1'});
|
||||
let value = 10;
|
||||
|
||||
spyOn(field, 'updateForm').and.callThrough();
|
||||
@@ -105,7 +105,7 @@ describe('FormFieldModel', () => {
|
||||
|
||||
it('should take own readonly state if form is writable', () => {
|
||||
let form = new FormModel();
|
||||
let field = new FormFieldModel(form, { readOnly: true });
|
||||
let field = new FormFieldModel(form, {readOnly: true});
|
||||
|
||||
expect(form.readOnly).toBeFalsy();
|
||||
expect(field.readOnly).toBeTruthy();
|
||||
@@ -241,8 +241,8 @@ describe('FormFieldModel', () => {
|
||||
let field = new FormFieldModel(new FormModel(), {
|
||||
type: FormFieldTypes.RADIO_BUTTONS,
|
||||
options: [
|
||||
{ id: 'opt1', value: 'Option 1' },
|
||||
{ id: 'opt2', value: 'Option 2' }
|
||||
{id: 'opt1', value: 'Option 1'},
|
||||
{id: 'opt2', value: 'Option 2'}
|
||||
],
|
||||
value: 'opt2'
|
||||
});
|
||||
@@ -279,8 +279,8 @@ describe('FormFieldModel', () => {
|
||||
id: 'dropdown-2',
|
||||
type: FormFieldTypes.DROPDOWN,
|
||||
options: [
|
||||
{ id: 'opt1', name: 'Option 1' },
|
||||
{ id: 'opt2', name: 'Option 2' }
|
||||
{id: 'opt1', name: 'Option 1'},
|
||||
{id: 'opt2', name: 'Option 2'}
|
||||
]
|
||||
});
|
||||
|
||||
@@ -294,8 +294,8 @@ describe('FormFieldModel', () => {
|
||||
id: 'radio-1',
|
||||
type: FormFieldTypes.RADIO_BUTTONS,
|
||||
options: [
|
||||
{ id: 'opt1', value: 'Option 1' },
|
||||
{ id: 'opt2', value: 'Option 2' }
|
||||
{id: 'opt1', value: 'Option 1'},
|
||||
{id: 'opt2', value: 'Option 2'}
|
||||
]
|
||||
});
|
||||
|
||||
@@ -309,8 +309,8 @@ describe('FormFieldModel', () => {
|
||||
id: 'radio-2',
|
||||
type: FormFieldTypes.RADIO_BUTTONS,
|
||||
options: [
|
||||
{ id: 'opt1', value: 'Option 1' },
|
||||
{ id: 'opt2', value: 'Option 2' }
|
||||
{id: 'opt1', value: 'Option 1'},
|
||||
{id: 'opt2', value: 'Option 2'}
|
||||
]
|
||||
});
|
||||
|
||||
@@ -332,21 +332,21 @@ describe('FormFieldModel', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should be able to check if the field has options available', () =>{
|
||||
it('should be able to check if the field has options available', () => {
|
||||
let form = new FormModel();
|
||||
let field = new FormFieldModel(form, {
|
||||
id: 'dropdown-happy',
|
||||
type: FormFieldTypes.DROPDOWN,
|
||||
options: [
|
||||
{ id: 'opt1', name: 'Option 1' },
|
||||
{ id: 'opt2', name: 'Option 2' }
|
||||
{id: 'opt1', name: 'Option 1'},
|
||||
{id: 'opt2', name: 'Option 2'}
|
||||
]
|
||||
});
|
||||
|
||||
expect(field.hasOptions()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should return false if field has no options', () =>{
|
||||
it('should return false if field has no options', () => {
|
||||
let form = new FormModel();
|
||||
let field = new FormFieldModel(form, {
|
||||
id: 'dropdown-sad',
|
||||
|
@@ -105,6 +105,11 @@ export class FormFieldModel extends FormWidgetModel {
|
||||
return this._readOnly;
|
||||
}
|
||||
|
||||
set readOnly(readOnly: boolean) {
|
||||
this._readOnly = readOnly;
|
||||
this.updateForm();
|
||||
}
|
||||
|
||||
get isValid(): boolean {
|
||||
return this._isValid;
|
||||
}
|
||||
@@ -292,8 +297,6 @@ export class FormFieldModel extends FormWidgetModel {
|
||||
let rbEntry: FormFieldOption[] = this.options.filter(opt => opt.id === this.value);
|
||||
if (rbEntry.length > 0) {
|
||||
this.form.values[this.id] = rbEntry[0];
|
||||
} else if (this.options.length > 0) {
|
||||
this.form.values[this.id] = this.options[0];
|
||||
}
|
||||
break;
|
||||
case FormFieldTypes.UPLOAD:
|
||||
|
@@ -109,7 +109,7 @@ export class FormModel {
|
||||
}
|
||||
if (json.fields) {
|
||||
let saveOutcome = new FormOutcomeModel(this, { id: FormModel.SAVE_OUTCOME, name: 'Save', isSystem: true });
|
||||
let completeOutcome = new FormOutcomeModel(this, {id: FormModel.COMPLETE_OUTCOME, name: 'Complete', isSystem: true });
|
||||
let completeOutcome = new FormOutcomeModel(this, { id: FormModel.COMPLETE_OUTCOME, name: 'Complete', isSystem: true });
|
||||
let startProcessOutcome = new FormOutcomeModel(this, { id: FormModel.START_PROCESS_OUTCOME, name: 'Start Process', isSystem: true });
|
||||
|
||||
let customOutcomes = (json.outcomes || []).map(obj => new FormOutcomeModel(this, obj));
|
||||
@@ -137,7 +137,7 @@ export class FormModel {
|
||||
let field = this.fields[i];
|
||||
|
||||
if (field instanceof ContainerModel) {
|
||||
let container = <ContainerModel> field;
|
||||
let container = <ContainerModel>field;
|
||||
result.push(container.field);
|
||||
result.push(...container.field.fields);
|
||||
}
|
||||
@@ -203,7 +203,11 @@ export class FormModel {
|
||||
for (let field of this.getFormFields()) {
|
||||
if (data[field.id]) {
|
||||
field.json.value = data[field.id];
|
||||
field.value = data[field.id];
|
||||
field.value = field.parseValue(field.json);
|
||||
if (field.type === FormFieldTypes.DROPDOWN ||
|
||||
field.type === FormFieldTypes.RADIO_BUTTONS) {
|
||||
field.value = data[field.id].id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -15,19 +15,40 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ElementRef } from '@angular/core';
|
||||
import { DateWidget } from './date.widget';
|
||||
import { FormFieldModel } from './../core/form-field.model';
|
||||
import { FormModel } from './../core/form.model';
|
||||
import { CoreModule } from 'ng2-alfresco-core';
|
||||
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||
import * as moment from 'moment';
|
||||
import { CoreModule } from 'ng2-alfresco-core';
|
||||
import { FormService } from './../../../services/form.service';
|
||||
import { EcmModelService } from './../../../services/ecm-model.service';
|
||||
import { ActivitiAlfrescoContentService } from '../../../services/activiti-alfresco.service';
|
||||
import { ElementRef } from '@angular/core';
|
||||
|
||||
describe('DateWidget', () => {
|
||||
|
||||
let widget: DateWidget;
|
||||
let fixture: ComponentFixture<DateWidget>;
|
||||
let componentHandler;
|
||||
let nativeElement: any;
|
||||
let elementRef: ElementRef;
|
||||
let element: HTMLElement;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
CoreModule.forRoot()
|
||||
],
|
||||
declarations: [
|
||||
DateWidget
|
||||
],
|
||||
providers: [
|
||||
FormService,
|
||||
ActivitiAlfrescoContentService,
|
||||
EcmModelService
|
||||
]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
nativeElement = {
|
||||
@@ -35,9 +56,12 @@ describe('DateWidget', () => {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
elementRef = new ElementRef(nativeElement);
|
||||
widget = new DateWidget(elementRef);
|
||||
let componentHandler = jasmine.createSpyObj('componentHandler', ['upgradeAllRegistered', 'upgradeElement']);
|
||||
|
||||
fixture = TestBed.createComponent(DateWidget);
|
||||
|
||||
element = fixture.nativeElement;
|
||||
widget = fixture.componentInstance;
|
||||
componentHandler = jasmine.createSpyObj('componentHandler', ['upgradeAllRegistered', 'upgradeElement']);
|
||||
window['componentHandler'] = componentHandler;
|
||||
});
|
||||
|
||||
@@ -82,6 +106,7 @@ describe('DateWidget', () => {
|
||||
});
|
||||
|
||||
it('should setup trigger element', () => {
|
||||
widget.elementRef = new ElementRef(nativeElement);
|
||||
let el = {};
|
||||
spyOn(nativeElement, 'querySelector').and.returnValue(el);
|
||||
widget.field = new FormFieldModel(null, {id: 'fake-id'});
|
||||
@@ -91,9 +116,8 @@ describe('DateWidget', () => {
|
||||
});
|
||||
|
||||
it('should not setup trigger element', () => {
|
||||
let w = new DateWidget(null);
|
||||
w.ngOnInit();
|
||||
expect(w.datePicker.trigger).toBeFalsy();
|
||||
widget.ngOnInit();
|
||||
expect(widget.datePicker.trigger).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should eval visibility on date changed', () => {
|
||||
@@ -120,6 +144,7 @@ describe('DateWidget', () => {
|
||||
});
|
||||
|
||||
it('should update field value on date selected', () => {
|
||||
widget.elementRef = new ElementRef(nativeElement);
|
||||
widget.field = new FormFieldModel(null, {type: 'date'});
|
||||
widget.ngOnInit();
|
||||
|
||||
@@ -141,77 +166,58 @@ describe('DateWidget', () => {
|
||||
});
|
||||
|
||||
it('should not update material textfield on date selected', () => {
|
||||
let w = new DateWidget(null);
|
||||
spyOn(w, 'setupMaterialTextField').and.callThrough();
|
||||
widget.elementRef = undefined;
|
||||
spyOn(widget, 'setupMaterialTextField').and.callThrough();
|
||||
|
||||
w.field = new FormFieldModel(null, {type: 'date'});
|
||||
w.ngOnInit();
|
||||
widget.field = new FormFieldModel(null, {type: 'date'});
|
||||
widget.ngOnInit();
|
||||
|
||||
w.datePicker.time = moment();
|
||||
w.onDateSelected();
|
||||
expect(w.setupMaterialTextField).not.toHaveBeenCalled();
|
||||
widget.datePicker.time = moment();
|
||||
widget.onDateSelected();
|
||||
expect(widget.setupMaterialTextField).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should send field change event when a new date is picked from data picker', (done) => {
|
||||
let w = new DateWidget(null);
|
||||
spyOn(w, 'setupMaterialTextField').and.callThrough();
|
||||
w.field = new FormFieldModel(null, {value: '9-9-9999', type: 'date'});
|
||||
w.ngOnInit();
|
||||
w.datePicker.time = moment('9-9-9999', w.field.dateDisplayFormat);
|
||||
w.fieldChanged.subscribe((field) => {
|
||||
spyOn(widget, 'setupMaterialTextField').and.callThrough();
|
||||
widget.field = new FormFieldModel(null, {value: '9-9-9999', type: 'date'});
|
||||
widget.ngOnInit();
|
||||
widget.datePicker.time = moment('9-9-9999', widget.field.dateDisplayFormat);
|
||||
widget.fieldChanged.subscribe((field) => {
|
||||
expect(field).toBeDefined();
|
||||
expect(field).not.toBeNull();
|
||||
expect(field.value).toEqual('9-9-9999');
|
||||
done();
|
||||
});
|
||||
w.onDateSelected();
|
||||
widget.onDateSelected();
|
||||
});
|
||||
|
||||
it('should send field change event when date is changed in input text', (done) => {
|
||||
let w = new DateWidget(null);
|
||||
spyOn(w, 'setupMaterialTextField').and.callThrough();
|
||||
w.field = new FormFieldModel(null, {value: '9-9-9999', type: 'date'});
|
||||
w.ngOnInit();
|
||||
w.datePicker.time = moment('9-9-9999', w.field.dateDisplayFormat);
|
||||
w.fieldChanged.subscribe((field) => {
|
||||
spyOn(widget, 'setupMaterialTextField').and.callThrough();
|
||||
widget.field = new FormFieldModel(null, {value: '9-9-9999', type: 'date'});
|
||||
widget.ngOnInit();
|
||||
widget.datePicker.time = moment('9-9-9999', widget.field.dateDisplayFormat);
|
||||
widget.fieldChanged.subscribe((field) => {
|
||||
expect(field).toBeDefined();
|
||||
expect(field).not.toBeNull();
|
||||
expect(field.value).toEqual('9-9-9999');
|
||||
done();
|
||||
});
|
||||
|
||||
w.onDateChanged();
|
||||
widget.onDateChanged();
|
||||
});
|
||||
|
||||
describe('template check', () => {
|
||||
let dateWidget: DateWidget;
|
||||
let fixture: ComponentFixture<DateWidget>;
|
||||
let element: HTMLElement;
|
||||
let componentHandler;
|
||||
|
||||
beforeEach(async(() => {
|
||||
componentHandler = jasmine.createSpyObj('componentHandler', ['upgradeAllRegistered', 'upgradeElement']);
|
||||
window['componentHandler'] = componentHandler;
|
||||
TestBed.configureTestingModule({
|
||||
imports: [CoreModule],
|
||||
declarations: [DateWidget]
|
||||
}).compileComponents().then(() => {
|
||||
fixture = TestBed.createComponent(DateWidget);
|
||||
dateWidget = fixture.componentInstance;
|
||||
element = fixture.nativeElement;
|
||||
});
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
spyOn(dateWidget, 'setupMaterialTextField').and.stub();
|
||||
dateWidget.field = new FormFieldModel(new FormModel(), {
|
||||
spyOn(widget, 'setupMaterialTextField').and.stub();
|
||||
widget.field = new FormFieldModel(new FormModel(), {
|
||||
id: 'date-field-id',
|
||||
name: 'date-name',
|
||||
value: '9-9-9999',
|
||||
type: 'date',
|
||||
readOnly: 'false'
|
||||
});
|
||||
dateWidget.field.isVisible = true;
|
||||
widget.field.isVisible = true;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
@@ -231,7 +237,7 @@ describe('DateWidget', () => {
|
||||
}));
|
||||
|
||||
it('should hide not visible date widget', async(() => {
|
||||
dateWidget.field.isVisible = false;
|
||||
widget.field.isVisible = false;
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable()
|
||||
.then(() => {
|
||||
@@ -241,9 +247,9 @@ describe('DateWidget', () => {
|
||||
}));
|
||||
|
||||
it('should become visibile if the visibility change to true', async(() => {
|
||||
dateWidget.field.isVisible = false;
|
||||
widget.field.isVisible = false;
|
||||
fixture.detectChanges();
|
||||
dateWidget.fieldChanged.subscribe((field) => {
|
||||
widget.fieldChanged.subscribe((field) => {
|
||||
field.isVisible = true;
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable()
|
||||
@@ -254,11 +260,11 @@ describe('DateWidget', () => {
|
||||
expect(dateElement.value).toEqual('9-9-9999');
|
||||
});
|
||||
});
|
||||
dateWidget.checkVisibility(dateWidget.field);
|
||||
widget.checkVisibility(widget.field);
|
||||
}));
|
||||
|
||||
it('should be hided if the visibility change to false', async(() => {
|
||||
dateWidget.fieldChanged.subscribe((field) => {
|
||||
widget.fieldChanged.subscribe((field) => {
|
||||
field.isVisible = false;
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable()
|
||||
@@ -266,7 +272,7 @@ describe('DateWidget', () => {
|
||||
expect(element.querySelector('#data-widget')).toBeNull();
|
||||
});
|
||||
});
|
||||
dateWidget.checkVisibility(dateWidget.field);
|
||||
widget.checkVisibility(widget.field);
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
@@ -16,8 +16,9 @@
|
||||
*/
|
||||
|
||||
import { Component, ElementRef, OnInit, AfterViewChecked } from '@angular/core';
|
||||
import { WidgetComponent } from './../widget.component';
|
||||
import { WidgetComponent , baseHost } from './../widget.component';
|
||||
import * as moment from 'moment';
|
||||
import { FormService } from './../../../services/form.service';
|
||||
|
||||
declare let mdDateTimePicker: any;
|
||||
declare var componentHandler: any;
|
||||
@@ -25,14 +26,16 @@ declare var componentHandler: any;
|
||||
@Component({
|
||||
selector: 'date-widget',
|
||||
templateUrl: './date.widget.html',
|
||||
styleUrls: ['./date.widget.css']
|
||||
styleUrls: ['./date.widget.css'],
|
||||
host: baseHost
|
||||
})
|
||||
export class DateWidget extends WidgetComponent implements OnInit, AfterViewChecked {
|
||||
|
||||
datePicker: any;
|
||||
|
||||
constructor(private elementRef: ElementRef) {
|
||||
super();
|
||||
constructor(public formService: FormService,
|
||||
public elementRef: ElementRef) {
|
||||
super(formService);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
|
@@ -16,13 +16,19 @@
|
||||
*/
|
||||
|
||||
import { Component } from '@angular/core';
|
||||
import { WidgetComponent } from './../widget.component';
|
||||
import { WidgetComponent , baseHost } from './../widget.component';
|
||||
import { FormService } from './../../../services/form.service';
|
||||
|
||||
@Component({
|
||||
selector: 'display-text-widget',
|
||||
templateUrl: './display-text.widget.html',
|
||||
styleUrls: ['./display-text.widget.css']
|
||||
styleUrls: ['./display-text.widget.css'],
|
||||
host: baseHost
|
||||
})
|
||||
export class DisplayTextWidget extends WidgetComponent {
|
||||
|
||||
constructor(public formService: FormService) {
|
||||
super(formService);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -16,30 +16,49 @@
|
||||
*/
|
||||
|
||||
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||
import { CoreModule, LogServiceMock } from 'ng2-alfresco-core';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
import { DisplayValueWidget } from './display-value.widget';
|
||||
import { FormService } from '../../../services/form.service';
|
||||
import { ActivitiContent } from '../../activiti-content.component';
|
||||
import { EcmModelService } from '../../../services/ecm-model.service';
|
||||
import { FormFieldModel } from './../core/form-field.model';
|
||||
import { FormFieldTypes } from '../core/form-field-types';
|
||||
import { FormModel } from '../core/form.model';
|
||||
import { WidgetVisibilityService } from '../../../services/widget-visibility.service';
|
||||
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||
import { CoreModule } from 'ng2-alfresco-core';
|
||||
import { FormService } from './../../../services/form.service';
|
||||
import { EcmModelService } from './../../../services/ecm-model.service';
|
||||
|
||||
describe('DisplayValueWidget', () => {
|
||||
|
||||
let widget: DisplayValueWidget;
|
||||
let fixture: ComponentFixture<DisplayValueWidget>;
|
||||
let element: HTMLElement;
|
||||
let formService: FormService;
|
||||
let visibilityService: WidgetVisibilityService;
|
||||
let logService: LogServiceMock;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
CoreModule.forRoot()
|
||||
],
|
||||
declarations: [
|
||||
DisplayValueWidget,
|
||||
ActivitiContent
|
||||
],
|
||||
providers: [
|
||||
FormService,
|
||||
EcmModelService,
|
||||
WidgetVisibilityService
|
||||
],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
logService = new LogServiceMock();
|
||||
formService = new FormService(null, null, logService);
|
||||
visibilityService = new WidgetVisibilityService(null, logService);
|
||||
widget = new DisplayValueWidget(formService, visibilityService);
|
||||
fixture = TestBed.createComponent(DisplayValueWidget);
|
||||
formService = TestBed.get(FormService);
|
||||
|
||||
element = fixture.nativeElement;
|
||||
widget = fixture.componentInstance;
|
||||
});
|
||||
|
||||
it('should require field to setup default value', () => {
|
||||
@@ -609,35 +628,15 @@ describe('DisplayValueWidget', () => {
|
||||
});
|
||||
|
||||
describe('UI check', () => {
|
||||
let widgetUI: DisplayValueWidget;
|
||||
let fixture: ComponentFixture<DisplayValueWidget>;
|
||||
let element: HTMLElement;
|
||||
let componentHandler;
|
||||
|
||||
beforeEach(async(() => {
|
||||
componentHandler = jasmine.createSpyObj('componentHandler', ['upgradeAllRegistered', 'upgradeElement']);
|
||||
window['componentHandler'] = componentHandler;
|
||||
TestBed.configureTestingModule({
|
||||
imports: [CoreModule],
|
||||
declarations: [
|
||||
DisplayValueWidget,
|
||||
ActivitiContent
|
||||
],
|
||||
providers: [
|
||||
EcmModelService,
|
||||
FormService,
|
||||
WidgetVisibilityService
|
||||
],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
}).compileComponents().then(() => {
|
||||
fixture = TestBed.createComponent(DisplayValueWidget);
|
||||
widgetUI = fixture.componentInstance;
|
||||
element = fixture.nativeElement;
|
||||
});
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
spyOn(widgetUI, 'setupMaterialTextField').and.stub();
|
||||
spyOn(widget, 'setupMaterialTextField').and.stub();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -646,7 +645,7 @@ describe('DisplayValueWidget', () => {
|
||||
});
|
||||
|
||||
it('should show the checkbox on when [BOOLEAN] field is true', async(() => {
|
||||
widgetUI.field = new FormFieldModel(null, {
|
||||
widget.field = new FormFieldModel(null, {
|
||||
id: 'fake-checkbox-id',
|
||||
type: FormFieldTypes.DISPLAY_VALUE,
|
||||
value: 'true',
|
||||
@@ -667,7 +666,7 @@ describe('DisplayValueWidget', () => {
|
||||
}));
|
||||
|
||||
it('should show the checkbox off when [BOOLEAN] field is false', async(() => {
|
||||
widgetUI.field = new FormFieldModel(null, {
|
||||
widget.field = new FormFieldModel(null, {
|
||||
id: 'fake-checkbox-id',
|
||||
type: FormFieldTypes.DISPLAY_VALUE,
|
||||
value: 'false',
|
||||
@@ -688,7 +687,7 @@ describe('DisplayValueWidget', () => {
|
||||
}));
|
||||
|
||||
it('should show the dropdown value taken from options when field has options', async(() => {
|
||||
widgetUI.field = new FormFieldModel(null, {
|
||||
widget.field = new FormFieldModel(null, {
|
||||
id: 'fake-dropdown-id',
|
||||
type: FormFieldTypes.DISPLAY_VALUE,
|
||||
value: '1',
|
||||
@@ -713,7 +712,7 @@ describe('DisplayValueWidget', () => {
|
||||
}));
|
||||
|
||||
it('should show the dropdown value taken from value when field has no options', async(() => {
|
||||
widgetUI.field = new FormFieldModel(null, {
|
||||
widget.field = new FormFieldModel(null, {
|
||||
id: 'fake-dropdown-id',
|
||||
type: FormFieldTypes.DISPLAY_VALUE,
|
||||
value: 'FAKE',
|
||||
|
@@ -17,7 +17,7 @@
|
||||
|
||||
import { Component, OnInit, Output, EventEmitter } from '@angular/core';
|
||||
import * as moment from 'moment';
|
||||
import { WidgetComponent } from './../widget.component';
|
||||
import { WidgetComponent , baseHost } from './../widget.component';
|
||||
import { FormFieldTypes } from '../core/form-field-types';
|
||||
import { FormService } from '../../../services/form.service';
|
||||
import { FormFieldOption } from './../core/form-field-option';
|
||||
@@ -27,7 +27,8 @@ import { NumberFieldValidator } from '../core/form-field-validator';
|
||||
@Component({
|
||||
selector: 'display-value-widget',
|
||||
templateUrl: './display-value.widget.html',
|
||||
styleUrls: ['./display-value.widget.css']
|
||||
styleUrls: ['./display-value.widget.css'],
|
||||
host: baseHost
|
||||
})
|
||||
export class DisplayValueWidget extends WidgetComponent implements OnInit {
|
||||
|
||||
@@ -49,9 +50,9 @@ export class DisplayValueWidget extends WidgetComponent implements OnInit {
|
||||
hasFile: boolean = false;
|
||||
showDocumentContent: boolean = true;
|
||||
|
||||
constructor(private formService: FormService,
|
||||
constructor(public formService: FormService,
|
||||
private visibilityService: WidgetVisibilityService) {
|
||||
super();
|
||||
super(formService);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
|
@@ -4,6 +4,7 @@
|
||||
<select class="dropdown-widget__select"
|
||||
[attr.id]="field.id"
|
||||
[(ngModel)]="field.value"
|
||||
[disabled]="field.readOnly"
|
||||
(ngModelChange)="checkVisibility(field)">
|
||||
<option *ngFor="let opt of field.options" [value]="getOptionValue(opt, field.value)" [id]="opt.id">{{opt.name}}</option>
|
||||
</select>
|
||||
|
@@ -253,6 +253,24 @@ describe('DropdownWidget', () => {
|
||||
expect(dropDownElement.selectedOptions[0].textContent).toBe('Choose one...');
|
||||
});
|
||||
}));
|
||||
|
||||
it('should be disabled when the field is readonly', async(() => {
|
||||
dropDownWidget.field = new FormFieldModel(new FormModel({ processDefinitionId: 'fake-process-id' }), {
|
||||
id: 'dropdown-id',
|
||||
name: 'date-name',
|
||||
type: 'dropdown',
|
||||
readOnly: 'true',
|
||||
restUrl: 'fake-rest-url'
|
||||
});
|
||||
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable()
|
||||
.then(() => {
|
||||
let dropDownElement: HTMLSelectElement = <HTMLSelectElement> element.querySelector('#dropdown-id');
|
||||
expect(dropDownElement).not.toBeNull();
|
||||
expect(dropDownElement.disabled).toBeTruthy();
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -18,21 +18,22 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { LogService } from 'ng2-alfresco-core';
|
||||
import { FormService } from '../../../services/form.service';
|
||||
import { WidgetComponent } from './../widget.component';
|
||||
import { WidgetComponent , baseHost } from './../widget.component';
|
||||
import { FormFieldOption } from './../core/form-field-option';
|
||||
import { WidgetVisibilityService } from '../../../services/widget-visibility.service';
|
||||
|
||||
@Component({
|
||||
selector: 'dropdown-widget',
|
||||
templateUrl: './dropdown.widget.html',
|
||||
styleUrls: ['./dropdown.widget.css']
|
||||
styleUrls: ['./dropdown.widget.css'],
|
||||
host: baseHost
|
||||
})
|
||||
export class DropdownWidget extends WidgetComponent implements OnInit {
|
||||
|
||||
constructor(private formService: FormService,
|
||||
constructor(public formService: FormService,
|
||||
private visibilityService: WidgetVisibilityService,
|
||||
private logService: LogService) {
|
||||
super();
|
||||
super(formService);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
|
@@ -4,7 +4,7 @@
|
||||
|
||||
<div *ngIf="!editMode">
|
||||
<div class="dynamic-table-widget__table-container">
|
||||
<table class="mdl-data-table mdl-js-data-table dynamic-table-widget__table">
|
||||
<table class="mdl-data-table mdl-js-data-table dynamic-table-widget__table" id="dynamic-table-{{content.id}}">
|
||||
<thead>
|
||||
<tr>
|
||||
<th *ngFor="let column of content.visibleColumns"
|
||||
@@ -14,8 +14,8 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let row of content.rows"
|
||||
[class.dynamic-table-widget__row-selected]="row.selected">
|
||||
<tr *ngFor="let row of content.rows; let idx = index" tabindex="0" id="{{content.id}}-row-{{idx}}"
|
||||
[class.dynamic-table-widget__row-selected]="row.selected" (keyup)="onKeyPressed($event, row)">
|
||||
<td *ngFor="let column of content.visibleColumns"
|
||||
class="mdl-data-table__cell--non-numeric"
|
||||
(click)="onRowClicked(row)">
|
||||
@@ -38,6 +38,7 @@
|
||||
<i class="material-icons">arrow_downward</i>
|
||||
</button>
|
||||
<button class="mdl-button mdl-js-button mdl-button--icon"
|
||||
id="{{content.id}}-add-row"
|
||||
(click)="addNewRow()">
|
||||
<i class="material-icons">add_circle_outline</i>
|
||||
</button>
|
||||
|
@@ -19,26 +19,104 @@ import { LogServiceMock } from 'ng2-alfresco-core';
|
||||
import { DynamicTableWidget } from './dynamic-table.widget';
|
||||
import { DynamicTableModel, DynamicTableRow, DynamicTableColumn } from './dynamic-table.widget.model';
|
||||
import { FormModel, FormFieldTypes, FormFieldModel } from './../core/index';
|
||||
import { ActivitiAlfrescoContentService } from '../../../services/activiti-alfresco.service';
|
||||
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||
import { RowEditorComponent } from './editors/row.editor';
|
||||
import { DropdownEditorComponent } from './editors/dropdown/dropdown.editor';
|
||||
import { DateEditorComponent } from './editors/date/date.editor';
|
||||
import { BooleanEditorComponent } from './editors/boolean/boolean.editor';
|
||||
import { TextEditorComponent } from './editors/text/text.editor';
|
||||
import { CoreModule, LogService } from 'ng2-alfresco-core';
|
||||
import { FormService } from './../../../services/form.service';
|
||||
import { EcmModelService } from './../../../services/ecm-model.service';
|
||||
import { WidgetVisibilityService } from '../../../services/widget-visibility.service';
|
||||
|
||||
let fakeFormField = {
|
||||
id: 'fake-dynamic-table',
|
||||
name: 'fake-label',
|
||||
value: [{1: 1, 2: 2, 3: 4}],
|
||||
required: false,
|
||||
readOnly: false,
|
||||
overrideId: false,
|
||||
colspan: 1,
|
||||
placeholder: null,
|
||||
minLength: 0,
|
||||
maxLength: 0,
|
||||
params: {
|
||||
existingColspan: 1,
|
||||
maxColspan: 1
|
||||
},
|
||||
sizeX: 2,
|
||||
sizeY: 2,
|
||||
row: -1,
|
||||
col: -1,
|
||||
columnDefinitions: [
|
||||
{
|
||||
id: 1,
|
||||
name: 1,
|
||||
type: 'String',
|
||||
visible: true
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 2,
|
||||
type: 'String',
|
||||
visible: true
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 3,
|
||||
type: 'String',
|
||||
visible: true
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
describe('DynamicTableWidget', () => {
|
||||
|
||||
let widget: DynamicTableWidget;
|
||||
let fixture: ComponentFixture<DynamicTableWidget>;
|
||||
let element: HTMLElement;
|
||||
let table: DynamicTableModel;
|
||||
let visibilityService: WidgetVisibilityService;
|
||||
let logService: LogServiceMock;
|
||||
let logService: LogService;
|
||||
let componentHandler: any;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
CoreModule.forRoot()
|
||||
],
|
||||
declarations: [DynamicTableWidget, RowEditorComponent,
|
||||
DropdownEditorComponent, DateEditorComponent, BooleanEditorComponent, TextEditorComponent],
|
||||
providers: [
|
||||
FormService,
|
||||
{provide: LogService, useClass: LogServiceMock},
|
||||
ActivitiAlfrescoContentService,
|
||||
EcmModelService,
|
||||
WidgetVisibilityService
|
||||
]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
logService = new LogServiceMock();
|
||||
const field = new FormFieldModel(new FormModel());
|
||||
logService = TestBed.get(LogService);
|
||||
table = new DynamicTableModel(field);
|
||||
visibilityService = new WidgetVisibilityService(null, logService);
|
||||
widget = new DynamicTableWidget(null, visibilityService, logService);
|
||||
let changeDetectorSpy = jasmine.createSpyObj('cd', ['detectChanges']);
|
||||
let nativeElementSpy = jasmine.createSpyObj('nativeElement', ['querySelector']);
|
||||
changeDetectorSpy.nativeElement = nativeElementSpy;
|
||||
let elementRefSpy = jasmine.createSpyObj('elementRef', ['']);
|
||||
elementRefSpy.nativeElement = nativeElementSpy;
|
||||
|
||||
fixture = TestBed.createComponent(DynamicTableWidget);
|
||||
element = fixture.nativeElement;
|
||||
widget = fixture.componentInstance;
|
||||
widget.content = table;
|
||||
|
||||
});
|
||||
|
||||
it('should select row on click', () => {
|
||||
let row = <DynamicTableRow> { selected: false };
|
||||
let row = <DynamicTableRow> {selected: false};
|
||||
widget.onRowClicked(row);
|
||||
|
||||
expect(row.selected).toBeTruthy();
|
||||
@@ -46,7 +124,7 @@ describe('DynamicTableWidget', () => {
|
||||
});
|
||||
|
||||
it('should requre table to select clicked row', () => {
|
||||
let row = <DynamicTableRow> { selected: false };
|
||||
let row = <DynamicTableRow> {selected: false};
|
||||
widget.content = null;
|
||||
widget.onRowClicked(row);
|
||||
|
||||
@@ -54,7 +132,7 @@ describe('DynamicTableWidget', () => {
|
||||
});
|
||||
|
||||
it('should reset selected row', () => {
|
||||
let row = <DynamicTableRow> { selected: false };
|
||||
let row = <DynamicTableRow> {selected: false};
|
||||
widget.content.rows.push(row);
|
||||
widget.content.selectedRow = row;
|
||||
expect(widget.content.selectedRow).toBe(row);
|
||||
@@ -66,7 +144,7 @@ describe('DynamicTableWidget', () => {
|
||||
});
|
||||
|
||||
it('should check selection', () => {
|
||||
let row = <DynamicTableRow> { selected: false };
|
||||
let row = <DynamicTableRow> {selected: false};
|
||||
widget.content.rows.push(row);
|
||||
widget.content.selectedRow = row;
|
||||
expect(widget.hasSelection()).toBeTruthy();
|
||||
@@ -144,7 +222,7 @@ describe('DynamicTableWidget', () => {
|
||||
expect(widget.editMode).toBeFalsy();
|
||||
expect(widget.editRow).toBeFalsy();
|
||||
|
||||
let row = <DynamicTableRow> { value: true };
|
||||
let row = <DynamicTableRow> {value: true};
|
||||
widget.content.selectedRow = row;
|
||||
|
||||
expect(widget.editSelection()).toBeTruthy();
|
||||
@@ -154,7 +232,7 @@ describe('DynamicTableWidget', () => {
|
||||
});
|
||||
|
||||
it('should copy row', () => {
|
||||
let row = <DynamicTableRow> { value: { opt: { key: '1', value: 1 } } };
|
||||
let row = <DynamicTableRow> {value: {opt: {key: '1', value: 1}}};
|
||||
let copy = widget.copyRow(row);
|
||||
expect(copy.value).toEqual(row.value);
|
||||
});
|
||||
@@ -166,14 +244,14 @@ describe('DynamicTableWidget', () => {
|
||||
|
||||
it('should retrieve cell value', () => {
|
||||
const value = '<value>';
|
||||
let row = <DynamicTableRow> { value: { key: value } };
|
||||
let column = <DynamicTableColumn> { id: 'key' };
|
||||
let row = <DynamicTableRow> {value: {key: value}};
|
||||
let column = <DynamicTableColumn> {id: 'key'};
|
||||
|
||||
expect(widget.getCellValue(row, column)).toBe(value);
|
||||
});
|
||||
|
||||
it('should save changes and add new row', () => {
|
||||
let row = <DynamicTableRow> { isNew: true, value: { key: 'value' } };
|
||||
let row = <DynamicTableRow> {isNew: true, value: {key: 'value'}};
|
||||
widget.editMode = true;
|
||||
widget.editRow = row;
|
||||
|
||||
@@ -186,7 +264,7 @@ describe('DynamicTableWidget', () => {
|
||||
});
|
||||
|
||||
it('should save changes and update row', () => {
|
||||
let row = <DynamicTableRow> { isNew: false, value: { key: 'value' } };
|
||||
let row = <DynamicTableRow> {isNew: false, value: {key: 'value'}};
|
||||
widget.editMode = true;
|
||||
widget.editRow = row;
|
||||
widget.content.selectedRow = row;
|
||||
@@ -244,16 +322,69 @@ describe('DynamicTableWidget', () => {
|
||||
});
|
||||
|
||||
it('should prepend default currency for amount columns', () => {
|
||||
let row = <DynamicTableRow> { value: { key: '100' } };
|
||||
let column = <DynamicTableColumn> { id: 'key', type: 'Amount' };
|
||||
let row = <DynamicTableRow> {value: {key: '100'}};
|
||||
let column = <DynamicTableColumn> {id: 'key', type: 'Amount'};
|
||||
let actual = widget.getCellValue(row, column);
|
||||
expect(actual).toBe('$ 100');
|
||||
});
|
||||
|
||||
it('should prepend custom currency for amount columns', () => {
|
||||
let row = <DynamicTableRow> { value: { key: '100' } };
|
||||
let column = <DynamicTableColumn> { id: 'key', type: 'Amount', amountCurrency: 'GBP' };
|
||||
let row = <DynamicTableRow> {value: {key: '100'}};
|
||||
let column = <DynamicTableColumn> {id: 'key', type: 'Amount', amountCurrency: 'GBP'};
|
||||
let actual = widget.getCellValue(row, column);
|
||||
expect(actual).toBe('GBP 100');
|
||||
});
|
||||
|
||||
describe('when template is ready', () => {
|
||||
|
||||
beforeEach(async(() => {
|
||||
componentHandler = jasmine.createSpyObj('componentHandler', ['upgradeAllRegistered', 'upgradeElement']);
|
||||
window['componentHandler'] = componentHandler;
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
widget.field = new FormFieldModel(new FormModel({taskId: 'fake-task-id'}), fakeFormField);
|
||||
widget.field.type = FormFieldTypes.DYNAMIC_TABLE;
|
||||
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
fixture.destroy();
|
||||
TestBed.resetTestingModule();
|
||||
});
|
||||
|
||||
it('should select a row when press space bar', async(() => {
|
||||
let rowElement = element.querySelector('#fake-dynamic-table-row-0');
|
||||
|
||||
expect(element.querySelector('#dynamic-table-fake-dynamic-table')).not.toBeNull();
|
||||
expect(rowElement).not.toBeNull();
|
||||
expect(rowElement.className).toBeFalsy();
|
||||
|
||||
let event: any = new Event('keyup');
|
||||
event.keyCode = 32;
|
||||
rowElement.dispatchEvent(event);
|
||||
fixture.detectChanges();
|
||||
|
||||
fixture.whenStable().then(() => {
|
||||
let selectedRow = element.querySelector('#fake-dynamic-table-row-0');
|
||||
expect(selectedRow.className).toBe('dynamic-table-widget__row-selected');
|
||||
});
|
||||
}));
|
||||
|
||||
it('should focus on add button when a new row is saved', async(() => {
|
||||
let addNewRowButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#fake-dynamic-table-add-row');
|
||||
|
||||
expect(element.querySelector('#dynamic-table-fake-dynamic-table')).not.toBeNull();
|
||||
expect(addNewRowButton).not.toBeNull();
|
||||
|
||||
widget.addNewRow();
|
||||
widget.onSaveChanges();
|
||||
fixture.detectChanges();
|
||||
|
||||
fixture.whenStable().then(() => {
|
||||
expect(document.activeElement.id).toBe('fake-dynamic-table-add-row');
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
@@ -15,17 +15,19 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Component, ElementRef, OnInit, Input } from '@angular/core';
|
||||
import { Component, ElementRef, OnInit, Input, ChangeDetectorRef } from '@angular/core';
|
||||
import { LogService } from 'ng2-alfresco-core';
|
||||
import { WidgetComponent } from './../widget.component';
|
||||
import { WidgetComponent , baseHost } from './../widget.component';
|
||||
import { DynamicTableModel, DynamicTableRow, DynamicTableColumn } from './dynamic-table.widget.model';
|
||||
import { WidgetVisibilityService } from '../../../services/widget-visibility.service';
|
||||
import { FormFieldModel } from '../core/form-field.model';
|
||||
import { FormService } from './../../../services/form.service';
|
||||
|
||||
@Component({
|
||||
selector: 'dynamic-table-widget',
|
||||
templateUrl: './dynamic-table.widget.html',
|
||||
styleUrls: ['./dynamic-table.widget.css']
|
||||
styleUrls: ['./dynamic-table.widget.css'],
|
||||
host: baseHost
|
||||
})
|
||||
export class DynamicTableWidget extends WidgetComponent implements OnInit {
|
||||
|
||||
@@ -42,10 +44,14 @@ export class DynamicTableWidget extends WidgetComponent implements OnInit {
|
||||
editMode: boolean = false;
|
||||
editRow: DynamicTableRow = null;
|
||||
|
||||
constructor(private elementRef: ElementRef,
|
||||
private selectArrayCode = [32, 0, 13];
|
||||
|
||||
constructor(public formService: FormService,
|
||||
public elementRef: ElementRef,
|
||||
private visibilityService: WidgetVisibilityService,
|
||||
private logService: LogService) {
|
||||
super();
|
||||
private logService: LogService,
|
||||
private cd: ChangeDetectorRef) {
|
||||
super(formService);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
@@ -55,6 +61,20 @@ export class DynamicTableWidget extends WidgetComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
forceFocusOnAddButton() {
|
||||
if (this.content) {
|
||||
this.cd.detectChanges();
|
||||
let buttonAddRow = <HTMLButtonElement>this.elementRef.nativeElement.querySelector('#' + this.content.id + '-add-row');
|
||||
if (this.isDynamicTableReady(buttonAddRow)) {
|
||||
buttonAddRow.focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private isDynamicTableReady(buttonAddRow) {
|
||||
return this.field && !this.editMode && buttonAddRow;
|
||||
}
|
||||
|
||||
isValid() {
|
||||
let result = true;
|
||||
|
||||
@@ -71,6 +91,16 @@ export class DynamicTableWidget extends WidgetComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
onKeyPressed($event: KeyboardEvent, row: DynamicTableRow) {
|
||||
if (this.content && this.isEnterOrSpacePressed($event.keyCode)) {
|
||||
this.content.selectedRow = row;
|
||||
}
|
||||
}
|
||||
|
||||
private isEnterOrSpacePressed(keycode) {
|
||||
return this.selectArrayCode.indexOf(keycode) !== -1;
|
||||
}
|
||||
|
||||
hasSelection(): boolean {
|
||||
return !!(this.content && this.content.selectedRow);
|
||||
}
|
||||
@@ -147,11 +177,13 @@ export class DynamicTableWidget extends WidgetComponent implements OnInit {
|
||||
this.logService.error(this.ERROR_MODEL_NOT_FOUND);
|
||||
}
|
||||
this.editMode = false;
|
||||
this.forceFocusOnAddButton();
|
||||
}
|
||||
|
||||
onCancelChanges() {
|
||||
this.editMode = false;
|
||||
this.editRow = null;
|
||||
this.forceFocusOnAddButton();
|
||||
}
|
||||
|
||||
copyRow(row: DynamicTableRow): DynamicTableRow {
|
||||
|
@@ -43,7 +43,7 @@ export class DateEditorComponent implements OnInit {
|
||||
@Input()
|
||||
column: DynamicTableColumn;
|
||||
|
||||
constructor(private elementRef: ElementRef) {}
|
||||
constructor(public elementRef: ElementRef) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.settings = {
|
||||
|
@@ -39,7 +39,7 @@ export class DropdownEditorComponent implements OnInit {
|
||||
@Input()
|
||||
column: DynamicTableColumn;
|
||||
|
||||
constructor(private formService: FormService,
|
||||
constructor(public formService: FormService,
|
||||
private logService: LogService) {
|
||||
}
|
||||
|
||||
|
@@ -16,14 +16,15 @@
|
||||
*/
|
||||
|
||||
import { Component, OnInit, ElementRef } from '@angular/core';
|
||||
import { WidgetComponent } from './../widget.component';
|
||||
import { WidgetComponent , baseHost } from './../widget.component';
|
||||
import { FormService } from '../../../services/form.service';
|
||||
import { GroupModel } from './../core/group.model';
|
||||
|
||||
@Component({
|
||||
selector: 'functional-group-widget',
|
||||
templateUrl: './functional-group.widget.html',
|
||||
styleUrls: ['./functional-group.widget.css']
|
||||
styleUrls: ['./functional-group.widget.css'],
|
||||
host: baseHost
|
||||
})
|
||||
export class FunctionalGroupWidget extends WidgetComponent implements OnInit {
|
||||
|
||||
@@ -33,9 +34,9 @@ export class FunctionalGroupWidget extends WidgetComponent implements OnInit {
|
||||
minTermLength: number = 1;
|
||||
groupId: string;
|
||||
|
||||
constructor(private formService: FormService,
|
||||
private elementRef: ElementRef) {
|
||||
super();
|
||||
constructor(public formService: FormService,
|
||||
public elementRef: ElementRef) {
|
||||
super(formService);
|
||||
}
|
||||
|
||||
// TODO: investigate, called 2 times
|
||||
|
@@ -25,7 +25,7 @@ describe('HyperlinkWidget', () => {
|
||||
let widget: HyperlinkWidget;
|
||||
|
||||
beforeEach(() => {
|
||||
widget = new HyperlinkWidget();
|
||||
widget = new HyperlinkWidget(null);
|
||||
});
|
||||
|
||||
it('should get link text from field display text', () => {
|
||||
|
@@ -16,18 +16,24 @@
|
||||
*/
|
||||
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { WidgetComponent } from './../widget.component';
|
||||
import { WidgetComponent , baseHost } from './../widget.component';
|
||||
import { FormService } from './../../../services/form.service';
|
||||
|
||||
@Component({
|
||||
selector: 'hyperlink-widget',
|
||||
templateUrl: './hyperlink.widget.html',
|
||||
styleUrls: ['./hyperlink.widget.css']
|
||||
styleUrls: ['./hyperlink.widget.css'],
|
||||
host: baseHost
|
||||
})
|
||||
export class HyperlinkWidget extends WidgetComponent implements OnInit {
|
||||
|
||||
linkUrl: string = WidgetComponent.DEFAULT_HYPERLINK_URL;
|
||||
linkText: string = null;
|
||||
|
||||
constructor(public formService: FormService) {
|
||||
super(formService);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
if (this.field) {
|
||||
this.linkUrl = this.getHyperlinkUrl(this.field);
|
||||
|
@@ -22,7 +22,7 @@ describe('MultilineTextWidget', () => {
|
||||
let widget: MultilineTextWidget;
|
||||
|
||||
beforeEach(() => {
|
||||
widget = new MultilineTextWidget();
|
||||
widget = new MultilineTextWidget(null);
|
||||
});
|
||||
|
||||
it('should exist', () => {
|
||||
|
@@ -16,12 +16,18 @@
|
||||
*/
|
||||
|
||||
import { Component } from '@angular/core';
|
||||
import { WidgetComponent } from './../widget.component';
|
||||
import { WidgetComponent , baseHost } from './../widget.component';
|
||||
import { FormService } from './../../../services/form.service';
|
||||
|
||||
@Component({
|
||||
selector: 'multiline-text-widget',
|
||||
templateUrl: './multiline-text.widget.html',
|
||||
styleUrls: ['./multiline-text.widget.css']
|
||||
styleUrls: ['./multiline-text.widget.css'],
|
||||
host: baseHost
|
||||
})
|
||||
export class MultilineTextWidget extends WidgetComponent {
|
||||
|
||||
constructor(public formService: FormService) {
|
||||
super(formService);
|
||||
}
|
||||
}
|
||||
|
@@ -22,7 +22,7 @@ describe('NumberWidget', () => {
|
||||
let widget: NumberWidget;
|
||||
|
||||
beforeEach(() => {
|
||||
widget = new NumberWidget();
|
||||
widget = new NumberWidget(null);
|
||||
});
|
||||
|
||||
it('should exist', () => {
|
||||
|
@@ -16,12 +16,19 @@
|
||||
*/
|
||||
|
||||
import { Component } from '@angular/core';
|
||||
import { WidgetComponent } from './../widget.component';
|
||||
import { WidgetComponent , baseHost } from './../widget.component';
|
||||
import { FormService } from './../../../services/form.service';
|
||||
|
||||
@Component({
|
||||
selector: 'number-widget',
|
||||
templateUrl: './number.widget.html',
|
||||
styleUrls: ['./number.widget.css']
|
||||
styleUrls: ['./number.widget.css'],
|
||||
host: baseHost
|
||||
})
|
||||
export class NumberWidget extends WidgetComponent {
|
||||
|
||||
constructor(public formService: FormService) {
|
||||
super(formService);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
import { Component, OnInit, ElementRef } from '@angular/core';
|
||||
import { WidgetComponent } from './../widget.component';
|
||||
import { WidgetComponent , baseHost } from './../widget.component';
|
||||
import { FormService } from '../../../services/form.service';
|
||||
import { GroupModel } from '../core/group.model';
|
||||
import { GroupUserModel } from '../core/group-user.model';
|
||||
@@ -24,7 +24,8 @@ import { GroupUserModel } from '../core/group-user.model';
|
||||
@Component({
|
||||
selector: 'people-widget',
|
||||
templateUrl: './people.widget.html',
|
||||
styleUrls: ['./people.widget.css']
|
||||
styleUrls: ['./people.widget.css'],
|
||||
host: baseHost
|
||||
})
|
||||
export class PeopleWidget extends WidgetComponent implements OnInit {
|
||||
|
||||
@@ -34,9 +35,9 @@ export class PeopleWidget extends WidgetComponent implements OnInit {
|
||||
users: GroupUserModel[] = [];
|
||||
groupId: string;
|
||||
|
||||
constructor(private formService: FormService,
|
||||
private elementRef: ElementRef) {
|
||||
super();
|
||||
constructor(public formService: FormService,
|
||||
public elementRef: ElementRef) {
|
||||
super(formService);
|
||||
}
|
||||
|
||||
// TODO: investigate, called 2 times
|
||||
|
@@ -17,7 +17,7 @@
|
||||
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { LogService } from 'ng2-alfresco-core';
|
||||
import { WidgetComponent } from './../widget.component';
|
||||
import { WidgetComponent , baseHost } from './../widget.component';
|
||||
import { FormService } from '../../../services/form.service';
|
||||
import { FormFieldOption } from './../core/form-field-option';
|
||||
import { WidgetVisibilityService } from '../../../services/widget-visibility.service';
|
||||
@@ -25,14 +25,15 @@ import { WidgetVisibilityService } from '../../../services/widget-visibility.ser
|
||||
@Component({
|
||||
selector: 'radio-buttons-widget',
|
||||
templateUrl: './radio-buttons.widget.html',
|
||||
styleUrls: ['./radio-buttons.widget.css']
|
||||
styleUrls: ['./radio-buttons.widget.css'],
|
||||
host: baseHost
|
||||
})
|
||||
export class RadioButtonsWidget extends WidgetComponent implements OnInit {
|
||||
|
||||
constructor(private formService: FormService,
|
||||
constructor(public formService: FormService,
|
||||
private visibilityService: WidgetVisibilityService,
|
||||
private logService: LogService) {
|
||||
super();
|
||||
super(formService);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
|
@@ -1,20 +1,9 @@
|
||||
<div *ngIf="hasTabs()" class="alfresco-tabs-widget">
|
||||
<div alfresco-mdl-tabs>
|
||||
<div class="mdl-tabs__tab-bar">
|
||||
<a *ngFor="let tab of visibleTabs; let isFirst = first"
|
||||
id="title-{{tab.id}}"
|
||||
[href]="'#' + tab.id"
|
||||
class="mdl-tabs__tab" [class.is-active]="isFirst">
|
||||
{{tab.title}}
|
||||
</a>
|
||||
</div>
|
||||
<div *ngFor="let tab of visibleTabs; let isFirst = first"
|
||||
class="mdl-tabs__panel"
|
||||
[class.is-active]="isFirst"
|
||||
[attr.id]="tab.id">
|
||||
<div *ngFor="let field of tab.fields">
|
||||
<md-tab-group>
|
||||
<md-tab *ngFor="let tab of visibleTabs" [label]="tab.title">
|
||||
<div *ngFor="let field of tab.fields">
|
||||
<form-field [field]="field.field"></form-field>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</md-tab>
|
||||
</md-tab-group>
|
||||
</div>
|
||||
|
@@ -26,6 +26,7 @@ import { MASK_DIRECTIVE } from '../index';
|
||||
import { FormFieldComponent } from './../../form-field/form-field.component';
|
||||
import { ActivitiContent } from './../../activiti-content.component';
|
||||
import { CoreModule } from 'ng2-alfresco-core';
|
||||
import { MdTabsModule } from '@angular/material';
|
||||
|
||||
describe('TabsWidget', () => {
|
||||
|
||||
@@ -104,7 +105,7 @@ describe('TabsWidget', () => {
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [CoreModule],
|
||||
imports: [CoreModule, MdTabsModule],
|
||||
declarations: [FormFieldComponent, ActivitiContent, WIDGET_DIRECTIVES, MASK_DIRECTIVE]
|
||||
}).compileComponents().then(() => {
|
||||
fixture = TestBed.createComponent(TabsWidget);
|
||||
@@ -140,22 +141,17 @@ describe('TabsWidget', () => {
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable()
|
||||
.then(() => {
|
||||
expect(element.querySelector('#tab-id-visible')).toBeDefined();
|
||||
expect(element.querySelector('#tab-id-visible')).not.toBeNull();
|
||||
expect(element.querySelector('#tab-id-invisible')).toBeNull();
|
||||
expect(element.querySelector('#title-tab-id-visible')).toBeDefined();
|
||||
expect(element.querySelector('#title-tab-id-visible').innerHTML).toContain('tab-title-visible');
|
||||
});
|
||||
});
|
||||
|
||||
it('should show tab when it became visible', async(() => {
|
||||
xit('should show tab when it became visible', async(() => {
|
||||
fixture.detectChanges();
|
||||
tabWidgetComponent.formTabChanged.subscribe((res) => {
|
||||
tabWidgetComponent.tabs[1].isVisible = true;
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable()
|
||||
.then(() => {
|
||||
expect(element.querySelector('#tab-id-invisible')).not.toBeNull();
|
||||
expect(element.querySelector('#title-tab-id-invisible').innerHTML).toContain('tab-title-invisible');
|
||||
});
|
||||
});
|
||||
|
@@ -8,7 +8,7 @@
|
||||
[value]="field.value"
|
||||
[(ngModel)]="field.value"
|
||||
(ngModelChange)="onFieldChanged(field)"
|
||||
[disabled]="field.readOnly"
|
||||
[attr.disabled]="field.readOnly ? true : null"
|
||||
[textMask]="{mask: mask, isReversed: isMaskReversed}"
|
||||
placeholder="{{field.placeholder}}">
|
||||
<span *ngIf="field.validationSummary" class="mdl-textfield__error">{{field.validationSummary}}</span>
|
||||
|
@@ -17,60 +17,57 @@
|
||||
|
||||
import { TextWidget } from './text.widget';
|
||||
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||
import { CoreModule } from 'ng2-alfresco-core';
|
||||
import { InputMaskDirective } from './text-mask.component';
|
||||
import { FormFieldModel } from '../core/form-field.model';
|
||||
import { FormModel } from '../core/form.model';
|
||||
import { FormFieldTypes } from '../core/form-field-types';
|
||||
|
||||
import { CoreModule } from 'ng2-alfresco-core';
|
||||
import { FormService } from './../../../services/form.service';
|
||||
import { EcmModelService } from './../../../services/ecm-model.service';
|
||||
import { ActivitiAlfrescoContentService } from '../../../services/activiti-alfresco.service';
|
||||
|
||||
describe('TextWidget', () => {
|
||||
|
||||
let widget: TextWidget;
|
||||
let fixture: ComponentFixture<TextWidget>;
|
||||
let componentHandler;
|
||||
let element: HTMLElement;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
CoreModule.forRoot()
|
||||
],
|
||||
declarations: [
|
||||
TextWidget,
|
||||
InputMaskDirective
|
||||
],
|
||||
providers: [
|
||||
FormService,
|
||||
EcmModelService,
|
||||
ActivitiAlfrescoContentService
|
||||
]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
widget = new TextWidget();
|
||||
|
||||
componentHandler = jasmine.createSpyObj('componentHandler', [
|
||||
'upgradeAllRegistered'
|
||||
]);
|
||||
fixture = TestBed.createComponent(TextWidget);
|
||||
|
||||
widget = fixture.componentInstance;
|
||||
element = fixture.nativeElement;
|
||||
componentHandler = jasmine.createSpyObj('componentHandler', ['upgradeAllRegistered', 'upgradeElement']);
|
||||
window['componentHandler'] = componentHandler;
|
||||
});
|
||||
|
||||
describe('when template is ready', () => {
|
||||
let textWidget: TextWidget;
|
||||
let fixture: ComponentFixture<TextWidget>;
|
||||
let element: HTMLInputElement;
|
||||
let componentHandler;
|
||||
|
||||
beforeEach(async(() => {
|
||||
componentHandler = jasmine.createSpyObj('componentHandler', ['upgradeAllRegistered', 'upgradeElement']);
|
||||
window['componentHandler'] = componentHandler;
|
||||
}));
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [CoreModule],
|
||||
declarations: [TextWidget, InputMaskDirective]
|
||||
}).compileComponents().then(() => {
|
||||
fixture = TestBed.createComponent(TextWidget);
|
||||
textWidget = fixture.componentInstance;
|
||||
element = fixture.nativeElement;
|
||||
});
|
||||
}));
|
||||
|
||||
afterEach(() => {
|
||||
fixture.destroy();
|
||||
TestBed.resetTestingModule();
|
||||
});
|
||||
|
||||
describe('and no mask is configured on text element', () => {
|
||||
|
||||
let inputElement: HTMLInputElement;
|
||||
|
||||
beforeEach(() => {
|
||||
textWidget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
|
||||
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
|
||||
id: 'text-id',
|
||||
name: 'text-name',
|
||||
value: '',
|
||||
@@ -84,13 +81,24 @@ describe('TextWidget', () => {
|
||||
|
||||
it('should raise ngModelChange event', async(() => {
|
||||
inputElement.value = 'TEXT';
|
||||
expect(textWidget.field.value).toBe('');
|
||||
expect(widget.field.value).toBe('');
|
||||
inputElement.dispatchEvent(new Event('input'));
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
expect(textWidget.field).not.toBeNull();
|
||||
expect(textWidget.field.value).not.toBeNull();
|
||||
expect(textWidget.field.value).toBe('TEXT');
|
||||
expect(widget.field).not.toBeNull();
|
||||
expect(widget.field.value).not.toBeNull();
|
||||
expect(widget.field.value).toBe('TEXT');
|
||||
});
|
||||
}));
|
||||
|
||||
it('should be disabled on readonly forms', async(() => {
|
||||
widget.field.form.readOnly = true;
|
||||
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
expect(inputElement).toBeDefined();
|
||||
expect(inputElement).not.toBeNull();
|
||||
expect(inputElement.disabled).toBeTruthy();
|
||||
});
|
||||
}));
|
||||
});
|
||||
@@ -100,7 +108,7 @@ describe('TextWidget', () => {
|
||||
let inputElement: HTMLInputElement;
|
||||
|
||||
beforeEach(() => {
|
||||
textWidget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
|
||||
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
|
||||
id: 'text-id',
|
||||
name: 'text-name',
|
||||
value: '',
|
||||
@@ -122,7 +130,7 @@ describe('TextWidget', () => {
|
||||
expect(element.querySelector('#text-id')).not.toBeNull();
|
||||
|
||||
inputElement.value = 'F';
|
||||
textWidget.field.value = 'F';
|
||||
widget.field.value = 'F';
|
||||
let event: any = new Event('keyup');
|
||||
event.keyCode = '70';
|
||||
inputElement.dispatchEvent(event);
|
||||
@@ -139,7 +147,7 @@ describe('TextWidget', () => {
|
||||
expect(element.querySelector('#text-id')).not.toBeNull();
|
||||
|
||||
inputElement.value = 'F';
|
||||
textWidget.field.value = 'F';
|
||||
widget.field.value = 'F';
|
||||
inputElement.dispatchEvent(new Event('input'));
|
||||
fixture.detectChanges();
|
||||
|
||||
@@ -154,15 +162,15 @@ describe('TextWidget', () => {
|
||||
expect(element.querySelector('#text-id')).not.toBeNull();
|
||||
|
||||
inputElement.value = '1';
|
||||
textWidget.field.value = '1';
|
||||
widget.field.value = '1';
|
||||
let event: any = new Event('keyup');
|
||||
event.keyCode = '49';
|
||||
inputElement.dispatchEvent(event);
|
||||
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
let inputElement: HTMLInputElement = <HTMLInputElement>element.querySelector('#text-id');
|
||||
expect(inputElement.value).toBe('1');
|
||||
let textEle: HTMLInputElement = <HTMLInputElement>element.querySelector('#text-id');
|
||||
expect(textEle.value).toBe('1');
|
||||
});
|
||||
}));
|
||||
|
||||
@@ -170,15 +178,15 @@ describe('TextWidget', () => {
|
||||
expect(element.querySelector('#text-id')).not.toBeNull();
|
||||
|
||||
inputElement.value = '12345678';
|
||||
textWidget.field.value = '12345678';
|
||||
widget.field.value = '12345678';
|
||||
let event: any = new Event('keyup');
|
||||
event.keyCode = '49';
|
||||
inputElement.dispatchEvent(event);
|
||||
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
let inputElement: HTMLInputElement = <HTMLInputElement>element.querySelector('#text-id');
|
||||
expect(inputElement.value).toBe('12-345,67%');
|
||||
let textEle: HTMLInputElement = <HTMLInputElement>element.querySelector('#text-id');
|
||||
expect(textEle.value).toBe('12-345,67%');
|
||||
});
|
||||
}));
|
||||
});
|
||||
@@ -188,11 +196,11 @@ describe('TextWidget', () => {
|
||||
let inputElement: HTMLInputElement;
|
||||
|
||||
beforeEach(() => {
|
||||
textWidget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
|
||||
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
|
||||
id: 'text-id',
|
||||
name: 'text-name',
|
||||
value: '',
|
||||
params: { existingColspan: 1, maxColspan: 2, inputMask: "#.##0,00%", inputMaskReversed: true },
|
||||
params: { existingColspan: 1, maxColspan: 2, inputMask: '#.##0,00%', inputMaskReversed: true },
|
||||
type: FormFieldTypes.TEXT,
|
||||
readOnly: false
|
||||
});
|
||||
@@ -210,18 +218,17 @@ describe('TextWidget', () => {
|
||||
expect(element.querySelector('#text-id')).not.toBeNull();
|
||||
|
||||
inputElement.value = '1234';
|
||||
textWidget.field.value = '1234';
|
||||
widget.field.value = '1234';
|
||||
let event: any = new Event('keyup');
|
||||
event.keyCode = '49';
|
||||
inputElement.dispatchEvent(event);
|
||||
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
let inputElement: HTMLInputElement = <HTMLInputElement>element.querySelector('#text-id');
|
||||
expect(inputElement.value).toBe('12,34%');
|
||||
let textEle: HTMLInputElement = <HTMLInputElement>element.querySelector('#text-id');
|
||||
expect(textEle.value).toBe('12,34%');
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
@@ -16,18 +16,24 @@
|
||||
*/
|
||||
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { WidgetComponent } from './../widget.component';
|
||||
import { WidgetComponent , baseHost } from './../widget.component';
|
||||
import { FormService } from './../../../services/form.service';
|
||||
|
||||
@Component({
|
||||
selector: 'text-widget',
|
||||
templateUrl: './text.widget.html',
|
||||
styleUrls: ['./text.widget.css']
|
||||
styleUrls: ['./text.widget.css'],
|
||||
host: baseHost
|
||||
})
|
||||
export class TextWidget extends WidgetComponent implements OnInit {
|
||||
|
||||
private mask;
|
||||
private isMaskReversed;
|
||||
|
||||
constructor(public formService: FormService) {
|
||||
super(formService);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
if (this.field.params && this.field.params['inputMask']) {
|
||||
this.mask = this.field.params['inputMask'];
|
||||
|
@@ -18,14 +18,15 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { LogService } from 'ng2-alfresco-core';
|
||||
import { FormService } from './../../../services/form.service';
|
||||
import { WidgetComponent } from './../widget.component';
|
||||
import { WidgetComponent , baseHost } from './../widget.component';
|
||||
import { FormFieldOption } from './../core/form-field-option';
|
||||
import { WidgetVisibilityService } from '../../../services/widget-visibility.service';
|
||||
|
||||
@Component({
|
||||
selector: 'typeahead-widget',
|
||||
templateUrl: './typeahead.widget.html',
|
||||
styleUrls: ['./typeahead.widget.css']
|
||||
styleUrls: ['./typeahead.widget.css'],
|
||||
host: baseHost
|
||||
})
|
||||
export class TypeaheadWidget extends WidgetComponent implements OnInit {
|
||||
|
||||
@@ -34,10 +35,10 @@ export class TypeaheadWidget extends WidgetComponent implements OnInit {
|
||||
value: string;
|
||||
options: FormFieldOption[] = [];
|
||||
|
||||
constructor(private formService: FormService,
|
||||
constructor(public formService: FormService,
|
||||
private visibilityService: WidgetVisibilityService,
|
||||
private logService: LogService) {
|
||||
super();
|
||||
super(formService);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
|
@@ -16,7 +16,8 @@
|
||||
*/
|
||||
|
||||
import { Component } from '@angular/core';
|
||||
import { WidgetComponent } from './../widget.component';
|
||||
import { WidgetComponent , baseHost } from './../widget.component';
|
||||
import { FormService } from './../../../services/form.service';
|
||||
|
||||
@Component({
|
||||
selector: 'unknown-widget',
|
||||
@@ -25,7 +26,12 @@ import { WidgetComponent } from './../widget.component';
|
||||
<i class="material-icons">error_outline</i>
|
||||
<span style="color: red">Unknown type: {{field.type}}</span>
|
||||
</div>
|
||||
`
|
||||
`,
|
||||
host: baseHost
|
||||
})
|
||||
export class UnknownWidget extends WidgetComponent {
|
||||
|
||||
constructor(public formService: FormService) {
|
||||
super(formService);
|
||||
}
|
||||
}
|
||||
|
@@ -8,6 +8,7 @@
|
||||
#file
|
||||
type="file"
|
||||
[attr.id]="field.id"
|
||||
[disabled]="field.readOnly"
|
||||
class="upload-widget__file"
|
||||
(change)="onFileChanged($event)">
|
||||
<button *ngIf="hasFile" (click)="reset(file);"
|
||||
|
@@ -19,9 +19,14 @@ import { UploadWidget } from './upload.widget';
|
||||
import { FormFieldModel } from './../core/form-field.model';
|
||||
import { FormFieldTypes } from '../core/form-field-types';
|
||||
import { FormService } from '../../../services/form.service';
|
||||
import { EcmModelService } from '../../../services/ecm-model.service';
|
||||
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||
import { CoreModule } from 'ng2-alfresco-core';
|
||||
import { FormModel } from '../core/form.model';
|
||||
|
||||
describe('UploadWidget', () => {
|
||||
|
||||
let componentHandler;
|
||||
let widget: UploadWidget;
|
||||
let formService: FormService;
|
||||
|
||||
@@ -37,7 +42,7 @@ describe('UploadWidget', () => {
|
||||
widget.field = new FormFieldModel(null, {
|
||||
type: FormFieldTypes.UPLOAD,
|
||||
value: [
|
||||
{name: encodedFileName}
|
||||
{ name: encodedFileName }
|
||||
]
|
||||
});
|
||||
|
||||
@@ -71,7 +76,7 @@ describe('UploadWidget', () => {
|
||||
widget.field = new FormFieldModel(null, {
|
||||
type: FormFieldTypes.UPLOAD,
|
||||
value: [
|
||||
{name: 'filename'}
|
||||
{ name: 'filename' }
|
||||
]
|
||||
});
|
||||
widget.reset();
|
||||
@@ -79,4 +84,58 @@ describe('UploadWidget', () => {
|
||||
expect(widget.field.json.value).toBeNull();
|
||||
});
|
||||
|
||||
describe('when template is ready', () => {
|
||||
let uploadWidget: UploadWidget;
|
||||
let fixture: ComponentFixture<UploadWidget>;
|
||||
let element: HTMLInputElement;
|
||||
let inputElement: HTMLInputElement;
|
||||
|
||||
beforeEach(async(() => {
|
||||
componentHandler = jasmine.createSpyObj('componentHandler', ['upgradeAllRegistered', 'upgradeElement']);
|
||||
window['componentHandler'] = componentHandler;
|
||||
}));
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [CoreModule],
|
||||
declarations: [UploadWidget],
|
||||
providers: [FormService, EcmModelService]
|
||||
}).compileComponents().then(() => {
|
||||
fixture = TestBed.createComponent(UploadWidget);
|
||||
uploadWidget = fixture.componentInstance;
|
||||
element = fixture.nativeElement;
|
||||
});
|
||||
}));
|
||||
|
||||
afterEach(() => {
|
||||
fixture.destroy();
|
||||
TestBed.resetTestingModule();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
uploadWidget.field = new FormFieldModel(new FormModel({ taskId: 'fake-upload-id' }), {
|
||||
id: 'upload-id',
|
||||
name: 'upload-name',
|
||||
value: '',
|
||||
type: FormFieldTypes.UPLOAD,
|
||||
readOnly: false
|
||||
});
|
||||
|
||||
fixture.detectChanges();
|
||||
inputElement = <HTMLInputElement>element.querySelector('#upload-id');
|
||||
});
|
||||
|
||||
it('should be disabled on readonly forms', async(() => {
|
||||
uploadWidget.field.form.readOnly = true;
|
||||
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
expect(inputElement).toBeDefined();
|
||||
expect(inputElement).not.toBeNull();
|
||||
expect(inputElement.disabled).toBeTruthy();
|
||||
});
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
@@ -17,13 +17,14 @@
|
||||
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { LogService } from 'ng2-alfresco-core';
|
||||
import { WidgetComponent } from './../widget.component';
|
||||
import { WidgetComponent , baseHost } from './../widget.component';
|
||||
import { FormService } from '../../../services/form.service';
|
||||
|
||||
@Component({
|
||||
selector: 'upload-widget',
|
||||
templateUrl: './upload.widget.html',
|
||||
styleUrls: ['./upload.widget.css']
|
||||
styleUrls: ['./upload.widget.css'],
|
||||
host: baseHost
|
||||
})
|
||||
export class UploadWidget extends WidgetComponent implements OnInit {
|
||||
|
||||
@@ -31,9 +32,9 @@ export class UploadWidget extends WidgetComponent implements OnInit {
|
||||
fileName: string;
|
||||
displayText: string;
|
||||
|
||||
constructor(private formService: FormService,
|
||||
constructor(public formService: FormService,
|
||||
private logService: LogService) {
|
||||
super();
|
||||
super(formService);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
|
@@ -15,101 +15,130 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||
import { ElementRef } from '@angular/core';
|
||||
import { WidgetComponent } from './widget.component';
|
||||
import { FormFieldModel } from './core/form-field.model';
|
||||
import { FormModel } from './core/form.model';
|
||||
import { FormService } from './../../services/form.service';
|
||||
import { CoreModule } from 'ng2-alfresco-core';
|
||||
import { EcmModelService } from './../../services/ecm-model.service';
|
||||
import { ActivitiAlfrescoContentService } from '../../services/activiti-alfresco.service';
|
||||
|
||||
describe('WidgetComponent', () => {
|
||||
|
||||
let widget: WidgetComponent;
|
||||
let fixture: ComponentFixture<WidgetComponent>;
|
||||
let element: HTMLElement;
|
||||
let componentHandler;
|
||||
let formService: FormService;
|
||||
|
||||
beforeEach(async(() => {
|
||||
componentHandler = jasmine.createSpyObj('componentHandler', ['upgradeAllRegistered', 'upgradeElement']);
|
||||
window['componentHandler'] = componentHandler;
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
CoreModule.forRoot()
|
||||
],
|
||||
declarations: [WidgetComponent],
|
||||
providers: [
|
||||
FormService,
|
||||
EcmModelService,
|
||||
ActivitiAlfrescoContentService
|
||||
]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
componentHandler = jasmine.createSpyObj('componentHandler', [
|
||||
'upgradeAllRegistered'
|
||||
]);
|
||||
fixture = TestBed.createComponent(WidgetComponent);
|
||||
formService = TestBed.get(FormService);
|
||||
|
||||
element = fixture.nativeElement;
|
||||
widget = fixture.componentInstance;
|
||||
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
describe('Events', () => {
|
||||
|
||||
it('should click event be redirect on the form event service', (done) => {
|
||||
widget.formService.formEvents.subscribe(() => {
|
||||
done();
|
||||
});
|
||||
|
||||
element.click();
|
||||
});
|
||||
|
||||
window['componentHandler'] = componentHandler;
|
||||
});
|
||||
|
||||
it('should upgrade MDL content on view init', () => {
|
||||
let component = new WidgetComponent();
|
||||
component.ngAfterViewInit();
|
||||
widget.ngAfterViewInit();
|
||||
expect(componentHandler.upgradeAllRegistered).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should setup MDL content only if component handler available', () => {
|
||||
let component = new WidgetComponent();
|
||||
expect(component.setupMaterialComponents(componentHandler)).toBeTruthy();
|
||||
expect(component.setupMaterialComponents()).toBeFalsy();
|
||||
expect(widget.setupMaterialComponents(componentHandler)).toBeTruthy();
|
||||
expect(widget.setupMaterialComponents()).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should check field', () => {
|
||||
let component = new WidgetComponent();
|
||||
|
||||
expect(component.hasField()).toBeFalsy();
|
||||
component.field = new FormFieldModel(new FormModel());
|
||||
expect(component.hasField()).toBeTruthy();
|
||||
expect(widget.hasField()).toBeFalsy();
|
||||
widget.field = new FormFieldModel(new FormModel());
|
||||
expect(widget.hasField()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should send an event after view init', (done) => {
|
||||
let component = new WidgetComponent();
|
||||
let fakeForm = new FormModel();
|
||||
let fakeField = new FormFieldModel(fakeForm, {id: 'fakeField', value: 'fakeValue'});
|
||||
component.field = fakeField;
|
||||
widget.field = fakeField;
|
||||
|
||||
component.fieldChanged.subscribe(field => {
|
||||
widget.fieldChanged.subscribe(field => {
|
||||
expect(field).not.toBe(null);
|
||||
expect(field.id).toBe('fakeField');
|
||||
expect(field.value).toBe('fakeValue');
|
||||
done();
|
||||
});
|
||||
|
||||
component.ngAfterViewInit();
|
||||
widget.ngAfterViewInit();
|
||||
});
|
||||
|
||||
it('should send an event when a field is changed', (done) => {
|
||||
let component = new WidgetComponent();
|
||||
let fakeForm = new FormModel();
|
||||
let fakeField = new FormFieldModel(fakeForm, {id: 'fakeField', value: 'fakeValue'});
|
||||
component.fieldChanged.subscribe(field => {
|
||||
widget.fieldChanged.subscribe(field => {
|
||||
expect(field).not.toBe(null);
|
||||
expect(field.id).toBe('fakeField');
|
||||
expect(field.value).toBe('fakeValue');
|
||||
done();
|
||||
});
|
||||
|
||||
component.checkVisibility(fakeField);
|
||||
widget.checkVisibility(fakeField);
|
||||
});
|
||||
|
||||
it('should eval isRequired state of the field', () => {
|
||||
let widget = new WidgetComponent();
|
||||
expect(widget.isRequired()).toBeFalsy();
|
||||
|
||||
widget.field = new FormFieldModel(null);
|
||||
expect(widget.isRequired()).toBeFalsy();
|
||||
|
||||
widget.field = new FormFieldModel(null, { required: false });
|
||||
widget.field = new FormFieldModel(null, {required: false});
|
||||
expect(widget.isRequired()).toBeFalsy();
|
||||
|
||||
widget.field = new FormFieldModel(null, { required: true });
|
||||
widget.field = new FormFieldModel(null, {required: true});
|
||||
expect(widget.isRequired()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should require element reference to setup textfield', () => {
|
||||
let widget = new WidgetComponent();
|
||||
expect(widget.setupMaterialTextField(null, {}, 'value')).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should require component handler to setup textfield', () => {
|
||||
let elementRef = new ElementRef(null);
|
||||
let widget = new WidgetComponent();
|
||||
expect(widget.setupMaterialTextField(elementRef, null, 'value')).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should require field value to setup textfield', () => {
|
||||
let elementRef = new ElementRef(null);
|
||||
let widget = new WidgetComponent();
|
||||
expect(widget.setupMaterialTextField(elementRef, {}, null)).toBeFalsy();
|
||||
});
|
||||
|
||||
@@ -119,15 +148,15 @@ describe('WidgetComponent', () => {
|
||||
querySelector: function () {
|
||||
return {
|
||||
MaterialTextfield: {
|
||||
change: function() {
|
||||
change: function () {
|
||||
changeCalled = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
let widget = new WidgetComponent();
|
||||
expect(widget.setupMaterialTextField(elementRef, {}, 'value')).toBeTruthy();
|
||||
expect(changeCalled).toBeTruthy();
|
||||
});
|
||||
|
||||
});
|
||||
|
@@ -15,14 +15,32 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Input, AfterViewInit, Output, EventEmitter, ElementRef } from '@angular/core';
|
||||
import { Component, Input, AfterViewInit, Output, EventEmitter, ElementRef } from '@angular/core';
|
||||
import { FormFieldModel } from './core/index';
|
||||
import { FormService } from './../../services/form.service';
|
||||
|
||||
declare var componentHandler: any;
|
||||
declare let componentHandler: any;
|
||||
|
||||
export const baseHost = {
|
||||
'(click)': 'event($event)',
|
||||
'(blur)': 'event($event)',
|
||||
'(change)': 'event($event)',
|
||||
'(focus)': 'event($event)',
|
||||
'(focusin)': 'event($event)',
|
||||
'(focusout)': 'event($event)',
|
||||
'(input)': 'event($event)',
|
||||
'(invalid)': 'event($event)',
|
||||
'(select)': 'event($event)'
|
||||
};
|
||||
|
||||
/**
|
||||
* Base widget component.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'base-widget',
|
||||
template: '',
|
||||
host: baseHost
|
||||
})
|
||||
export class WidgetComponent implements AfterViewInit {
|
||||
|
||||
static DEFAULT_HYPERLINK_URL: string = '#';
|
||||
@@ -35,6 +53,9 @@ export class WidgetComponent implements AfterViewInit {
|
||||
@Output()
|
||||
fieldChanged: EventEmitter<FormFieldModel> = new EventEmitter<FormFieldModel>();
|
||||
|
||||
constructor(public formService?: FormService) {
|
||||
}
|
||||
|
||||
hasField() {
|
||||
return this.field ? true : false;
|
||||
}
|
||||
@@ -111,4 +132,8 @@ export class WidgetComponent implements AfterViewInit {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected event(event: Event): void {
|
||||
this.formService.formEvents.next(event);
|
||||
}
|
||||
}
|
||||
|
@@ -95,6 +95,16 @@ export class ActivitiContentService {
|
||||
.catch(err => this.handleError(err));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all the related content of the process instance
|
||||
* @param processInstanceId
|
||||
* @returns {any}
|
||||
*/
|
||||
createProcessRelatedContent(processInstanceId: string, content: any, opts?: any): Observable<any> {
|
||||
return Observable.fromPromise(this.apiService.getInstance().activiti.contentApi.createRelatedContentOnProcessInstance(processInstanceId, content, opts))
|
||||
.catch(err => this.handleError(err));
|
||||
}
|
||||
|
||||
toJson(res: any) {
|
||||
if (res) {
|
||||
return res || {};
|
||||
@@ -123,4 +133,9 @@ export class ActivitiContentService {
|
||||
let icon = this.mimeTypeIcons[mimeType];
|
||||
return icon || ActivitiContentService.DEFAULT_MIME_TYPE_ICON;
|
||||
}
|
||||
|
||||
createTaskRelatedContent(taskId: string, file: any, opts?: any) {
|
||||
return Observable.fromPromise(this.apiService.getInstance().activiti.contentApi.createRelatedContentOnTask(taskId, file, opts))
|
||||
.catch(err => this.handleError(err));
|
||||
}
|
||||
}
|
||||
|
@@ -15,14 +15,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ReflectiveInjector } from '@angular/core';
|
||||
import {
|
||||
AlfrescoAuthenticationService,
|
||||
AlfrescoSettingsService,
|
||||
AlfrescoApiService,
|
||||
StorageService,
|
||||
LogService
|
||||
} from 'ng2-alfresco-core';
|
||||
import { TestBed, async } from '@angular/core/testing';
|
||||
import { CoreModule, AlfrescoApiService, LogService } from 'ng2-alfresco-core';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
import { FormService } from './form.service';
|
||||
import { Response, ResponseOptions } from '@angular/http';
|
||||
@@ -69,24 +63,26 @@ function createFakeBlob() {
|
||||
|
||||
describe('Form service', () => {
|
||||
|
||||
let service, injector, apiService, logService;
|
||||
let service: FormService;
|
||||
let apiService: AlfrescoApiService;
|
||||
let logService: LogService;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
CoreModule
|
||||
],
|
||||
providers: [
|
||||
EcmModelService,
|
||||
FormService
|
||||
]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
injector = ReflectiveInjector.resolveAndCreate([
|
||||
AlfrescoSettingsService,
|
||||
AlfrescoApiService,
|
||||
AlfrescoAuthenticationService,
|
||||
EcmModelService,
|
||||
StorageService,
|
||||
FormService,
|
||||
LogService
|
||||
]);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
service = injector.get(FormService);
|
||||
apiService = injector.get(AlfrescoApiService);
|
||||
logService = injector.get(LogService);
|
||||
service = TestBed.get(FormService);
|
||||
apiService = TestBed.get(AlfrescoApiService);
|
||||
logService = TestBed.get(LogService);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -530,7 +526,7 @@ describe('Form service', () => {
|
||||
|
||||
function stubCreateForm() {
|
||||
jasmine.Ajax.stubRequest(
|
||||
'http://localhost:9999/activiti-app/api/enterprise/models'
|
||||
'http://localhost:3000/bpm/activiti-app/api/enterprise/models'
|
||||
).andReturn({
|
||||
status: 200,
|
||||
statusText: 'HTTP/1.1 200 OK',
|
||||
@@ -541,7 +537,7 @@ describe('Form service', () => {
|
||||
|
||||
function stubGetEcmModel() {
|
||||
jasmine.Ajax.stubRequest(
|
||||
'http://localhost:8080/alfresco/api/-default-/private/alfresco/versions/1/cmm/activitiFormsModel/types'
|
||||
'http://localhost:3000/ecm/alfresco/api/-default-/private/alfresco/versions/1/cmm/activitiFormsModel/types'
|
||||
).andReturn({
|
||||
status: 200,
|
||||
statusText: 'HTTP/1.1 200 OK',
|
||||
@@ -562,7 +558,7 @@ describe('Form service', () => {
|
||||
|
||||
function stubAddFieldsToAForm() {
|
||||
jasmine.Ajax.stubRequest(
|
||||
'http://localhost:9999/activiti-app/api/enterprise/editor/form-models/' + formId
|
||||
'http://localhost:3000/bpm/activiti-app/api/enterprise/editor/form-models/' + formId
|
||||
).andReturn({
|
||||
status: 200,
|
||||
statusText: 'HTTP/1.1 200 OK',
|
||||
|
@@ -18,7 +18,7 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable, Subject } from 'rxjs/Rx';
|
||||
import { AlfrescoApiService, LogService } from 'ng2-alfresco-core';
|
||||
import { FormValues } from './../components/widgets/core/index';
|
||||
import { FormModel, FormValues, FormOutcomeEvent, FormOutcomeModel } from './../components/widgets/core/index';
|
||||
import { FormDefinitionModel } from '../models/form-definition.model';
|
||||
import { EcmModelService } from './ecm-model.service';
|
||||
import { GroupModel } from './../components/widgets/core/group.model';
|
||||
@@ -33,18 +33,39 @@ export class FormService {
|
||||
static GENERIC_ERROR_MESSAGE: string = 'Server error';
|
||||
|
||||
formLoaded: Subject<FormEvent> = new Subject<FormEvent>();
|
||||
formDataRefreshed: Subject<FormEvent> = new Subject<FormEvent>();
|
||||
formFieldValueChanged: Subject<FormFieldEvent> = new Subject<FormFieldEvent>();
|
||||
formEvents: Subject<Event> = new Subject<Event>();
|
||||
taskCompleted: Subject<FormEvent> = new Subject<FormEvent>();
|
||||
taskCompletedError: Subject<FormErrorEvent> = new Subject<FormErrorEvent>();
|
||||
taskSaved: Subject<FormEvent> = new Subject<FormEvent>();
|
||||
taskSavedError: Subject<FormErrorEvent> = new Subject<FormErrorEvent>();
|
||||
formContentClicked: Subject<ContentLinkModel> = new Subject<ContentLinkModel>();
|
||||
|
||||
executeOutcome: Subject<FormOutcomeEvent> = new Subject<FormOutcomeEvent>();
|
||||
|
||||
constructor(private ecmModelService: EcmModelService,
|
||||
private apiService: AlfrescoApiService,
|
||||
private logService: LogService) {
|
||||
}
|
||||
|
||||
parseForm(json: any, data?: FormValues, readOnly: boolean = false): FormModel {
|
||||
if (json) {
|
||||
let form = new FormModel(json, data, readOnly, this);
|
||||
if (!json.fields) {
|
||||
form.outcomes = [
|
||||
new FormOutcomeModel(form, {
|
||||
id: '$custom',
|
||||
name: FormOutcomeModel.SAVE_ACTION,
|
||||
isSystem: true
|
||||
})
|
||||
];
|
||||
}
|
||||
return form;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Form with a fields for each metadata properties
|
||||
* @returns {Observable<any>}
|
||||
|
@@ -35,7 +35,9 @@
|
||||
"ng2-alfresco-viewer": ["../ng2-alfresco-viewer/"],
|
||||
"ng2-alfresco-webscript": ["../ng2-alfresco-webscript/"],
|
||||
"ng2-alfresco-userinfo": ["../ng2-alfresco-userinfo"],
|
||||
"alfresco-js-api": ["../node_modules/alfresco-js-api/"]
|
||||
"alfresco-js-api": ["./node_modules/alfresco-js-api/"],
|
||||
"@angular/*": ["./node_modules/@angular/*"],
|
||||
"rxjs/*": ["./node_modules/rxjs/*"]
|
||||
},
|
||||
"lib": [
|
||||
"es2015",
|
||||
|
@@ -1,17 +1 @@
|
||||
const webpack = require('webpack');
|
||||
const webpackMerge = require('webpack-merge');
|
||||
const commonConfig = require('./config/webpack.common.js');
|
||||
|
||||
module.exports = webpackMerge(commonConfig, {
|
||||
|
||||
output: {
|
||||
filename: './bundles/[name].js',
|
||||
library: '[name]',
|
||||
libraryTarget: 'umd',
|
||||
chunkFilename: '[id].chunk.js'
|
||||
},
|
||||
|
||||
entry: {
|
||||
"ng2-activiti-form": "./index.ts"
|
||||
}
|
||||
});
|
||||
module.exports = require('./config/webpack.build.js');
|
||||
|
1
ng2-components/ng2-activiti-form/webpack.coverage.js
Normal file
1
ng2-components/ng2-activiti-form/webpack.coverage.js
Normal file
@@ -0,0 +1 @@
|
||||
module.exports = require('./config/webpack.coverage.js');
|
@@ -1,8 +1 @@
|
||||
const webpack = require('webpack');
|
||||
const webpackMerge = require('webpack-merge');
|
||||
const testConfig = require('./config/webpack.test.js');
|
||||
|
||||
module.exports = webpackMerge(testConfig, {
|
||||
|
||||
|
||||
});
|
||||
module.exports = require('./config/webpack.test.js');
|
||||
|
Reference in New Issue
Block a user