Merge branch 'development' into dev-eromano-bundle

This commit is contained in:
Mario Romano
2016-12-15 10:40:01 +00:00
committed by GitHub
17 changed files with 174 additions and 34 deletions

View File

@@ -92,10 +92,17 @@
<div class="page-content"> <div class="page-content">
<div class="mdl-grid"> <div class="mdl-grid">
<div class="mdl-cell mdl-cell--4-col task-column mdl-shadow--2dp"> <div class="mdl-cell mdl-cell--4-col task-column mdl-shadow--2dp">
<analytics-report-list (reportClick)="onReportClick($event)"></analytics-report-list> <analytics-report-list
(reportClick)="onReportClick($event)"
#analyticsreportlist >
</analytics-report-list>
</div> </div>
<div class="mdl-cell mdl-cell--8-col task-column mdl-shadow--2dp"> <div class="mdl-cell mdl-cell--8-col task-column mdl-shadow--2dp">
<activiti-analytics [appId]="appId" *ngIf="report" [reportId]="report.id"></activiti-analytics> <activiti-analytics *ngIf="report"
[appId]="appId"
[reportId]="report.id"
(editReport)="onEditReport($event)">
</activiti-analytics>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -30,6 +30,7 @@ import {
ActivitiStartProcessInstance, ActivitiStartProcessInstance,
ProcessInstance ProcessInstance
} from 'ng2-activiti-processlist'; } from 'ng2-activiti-processlist';
import { AnalyticsReportListComponent } from 'ng2-activiti-analytics';
import { ActivatedRoute } from '@angular/router'; import { ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs/Rx'; import { Subscription } from 'rxjs/Rx';
import { import {
@@ -75,6 +76,9 @@ export class ActivitiDemoComponent implements AfterViewInit {
@ViewChild(ActivitiStartProcessInstance) @ViewChild(ActivitiStartProcessInstance)
activitiStartProcess: ActivitiStartProcessInstance; activitiStartProcess: ActivitiStartProcessInstance;
@ViewChild(AnalyticsReportListComponent)
analyticsreportlist: AnalyticsReportListComponent;
@Input() @Input()
appId: number; appId: number;
@@ -183,6 +187,10 @@ export class ActivitiDemoComponent implements AfterViewInit {
this.currentProcessInstanceId = processInstanceId; this.currentProcessInstanceId = processInstanceId;
} }
onEditReport(name: string) {
this.analyticsreportlist.reload();
}
navigateStartProcess() { navigateStartProcess() {
this.currentProcessInstanceId = currentProcessIdNew; this.currentProcessInstanceId = currentProcessIdNew;
} }
@@ -225,11 +233,11 @@ export class ActivitiDemoComponent implements AfterViewInit {
} }
loadStencilScriptsInPageFromActiviti() { loadStencilScriptsInPageFromActiviti() {
this.apiService.getInstance().activiti.scriptFileApi.getControllers().then(function (response) { this.apiService.getInstance().activiti.scriptFileApi.getControllers().then(response => {
if (response) { if (response) {
let s = document.createElement('script'); let s = document.createElement('script');
s.type = 'text/javascript'; s.type = 'text/javascript';
s.src = response; s.text = response;
this.elementRef.nativeElement.appendChild(s); this.elementRef.nativeElement.appendChild(s);
} }
}); });

View File

@@ -6,6 +6,7 @@
"scripts": { "scripts": {
"clean": "npm install rimraf && npm run clean-build && rimraf dist node_modules typings dist", "clean": "npm install rimraf && npm run clean-build && rimraf dist node_modules typings dist",
"start": "webpack-dev-server --inline --progress --port 3000", "start": "webpack-dev-server --inline --progress --port 3000",
"start:dist": "wsrv -s dist/ -p 3000 -a 0.0.0.0",
"clean-build": "rimraf 'app/{,**/}**.js' 'app/{,**/}**.js.map' 'app/{,**/}**.d.ts'", "clean-build": "rimraf 'app/{,**/}**.js' 'app/{,**/}**.js.map' 'app/{,**/}**.d.ts'",
"test": "karma start", "test": "karma start",
"build": "rimraf dist && webpack --config config/webpack.prod.js --progress --profile --bail", "build": "rimraf dist && webpack --config config/webpack.prod.js --progress --profile --bail",
@@ -124,7 +125,12 @@
"typescript": "2.0.3", "typescript": "2.0.3",
"webpack": "^1.13.0", "webpack": "^1.13.0",
"webpack-dev-server": "^1.14.1", "webpack-dev-server": "^1.14.1",
"webpack-merge": "^0.14.0" "webpack-merge": "^0.14.0",
"source-map-loader": "^0.1.5",
"script-loader": "^0.7.0",
"copy-webpack-plugin": "^4.0.1",
"glob": "^7.1.1",
"wsrv": "^0.1.6"
}, },
"license-check-config": { "license-check-config": {
"src": [ "src": [

View File

@@ -57,13 +57,21 @@ export class AnalyticsReportListComponent implements OnInit {
this.reports.push(report); this.reports.push(report);
}); });
this.getReportListByAppId(); this.getReportList();
} }
/** /**
* Get the report list by app id * Reload the component
*/ */
getReportListByAppId() { reload() {
this.reset();
this.getReportList();
}
/**
* Get the report list
*/
getReportList() {
this.analyticsService.getReportList().subscribe( this.analyticsService.getReportList().subscribe(
(res: ReportParametersModel[]) => { (res: ReportParametersModel[]) => {
if (res && res.length === 0) { if (res && res.length === 0) {
@@ -108,6 +116,15 @@ export class AnalyticsReportListComponent implements OnInit {
return this.reports === undefined || (this.reports && this.reports.length === 0); return this.reports === undefined || (this.reports && this.reports.length === 0);
} }
/**
* Reset the list
*/
private reset() {
if (!this.isReportsEmpty()) {
this.reports = [];
}
}
/** /**
* Select the current report * Select the current report
* @param report * @param report

View File

@@ -21,3 +21,7 @@
.dropdown-widget__invalid .mdl-textfield__error { .dropdown-widget__invalid .mdl-textfield__error {
visibility: visible !important; visibility: visible !important;
} }
.large {
font-size: x-large;
}

View File

@@ -1,7 +1,18 @@
<div class="col-md-6"> <div class="col-md-6">
<div *ngIf="reportParameters"> <div *ngIf="reportParameters">
<form [formGroup]="reportForm" novalidate> <form [formGroup]="reportForm" novalidate>
<h4>{{reportParameters.name}}</h4> <div *ngIf="isEditable">
<input
type="text"
class="mdl-textfield__input large"
id="reportName"
data-automation-id="reportName"
[value]="reportParameters.name"
(input)="reportParameters.name=$event.target.value"
(blur)="editTitle($event)"
/>
</div>
<h4 *ngIf="!isEditable" (click)="editEnable()">{{reportParameters.name}}</h4>
<div *ngFor="let field of reportParameters.definition.parameters"> <div *ngFor="let field of reportParameters.definition.parameters">
<div [ngSwitch]="field.type"> <div [ngSwitch]="field.type">
<div *ngSwitchCase="'integer'"> <div *ngSwitchCase="'integer'">

View File

@@ -47,6 +47,9 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges {
@Output() @Output()
onError = new EventEmitter(); onError = new EventEmitter();
@Output()
onEdit = new EventEmitter();
@Output() @Output()
onFormValueChanged = new EventEmitter(); onFormValueChanged = new EventEmitter();
@@ -63,6 +66,7 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges {
private dropDownSub; private dropDownSub;
private reportParamsSub; private reportParamsSub;
private paramOpts; private paramOpts;
private isEditable: boolean = false;
constructor(private translate: AlfrescoTranslationService, constructor(private translate: AlfrescoTranslationService,
private analyticsService: AnalyticsService, private analyticsService: AnalyticsService,
@@ -210,4 +214,25 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges {
this.reportParamsSub.unsubscribe(); this.reportParamsSub.unsubscribe();
} }
} }
public editEnable() {
this.isEditable = true;
}
public editDisable() {
this.isEditable = false;
}
public editTitle() {
this.reportParamsSub = this.analyticsService.updateReport(this.reportParameters.id, this.reportParameters.name).subscribe(
(res: ReportParametersModel) => {
this.editDisable();
this.onEdit.emit(this.reportParameters.name);
},
(err: any) => {
console.log(err);
this.onError.emit(err);
}
);
}
} }

View File

@@ -1,6 +1,9 @@
<div class="col-md-6"> <div class="col-md-6">
<analytics-report-parameters [appId]="appId" [reportId]="reportId" <analytics-report-parameters [appId]="appId" [reportId]="reportId"
(onFormValueChanged)="reset()" (onSuccess)="showReport($event)"></analytics-report-parameters> (onFormValueChanged)="reset()"
(onSuccess)="showReport($event)"
(onEdit)="onEditReport($event)">
</analytics-report-parameters>
<div *ngIf="reports"> <div *ngIf="reports">
<div *ngFor="let report of reports"> <div *ngFor="let report of reports">

View File

@@ -41,12 +41,15 @@ export class AnalyticsComponent implements OnChanges {
@Output() @Output()
onSuccess = new EventEmitter(); onSuccess = new EventEmitter();
@Output()
editReport = new EventEmitter();
@Output() @Output()
onError = new EventEmitter(); onError = new EventEmitter();
reportParamQuery = new ReportQuery(); reportParamQuery = new ReportQuery();
reports: any[]; reports: Chart[];
public barChartOptions: any = { public barChartOptions: any = {
responsive: true, responsive: true,
@@ -107,4 +110,8 @@ export class AnalyticsComponent implements OnChanges {
let clone = JSON.parse(JSON.stringify(report)); let clone = JSON.parse(JSON.stringify(report));
report.datasets = clone.datasets; report.datasets = clone.datasets;
} }
public onEditReport(name: string) {
this.editReport.emit(name);
}
} }

View File

@@ -178,6 +178,13 @@ export class AnalyticsService {
.catch(this.handleError); .catch(this.handleError);
} }
public updateReport(reportId: number, name: string): Observable<any> {
return Observable.fromPromise(this.apiService.getInstance().activiti.reportApi.updateReport(reportId, name))
.map((res: any) => {
console.log('upload');
}).catch(this.handleError);
}
private handleError(error: Response) { private handleError(error: Response) {
console.error(error); console.error(error);
return Observable.throw(error.json().error || 'Server error'); return Observable.throw(error.json().error || 'Server error');

View File

@@ -28,7 +28,7 @@
{{ 'DETAILS.TASKS.NO_ACTIVE' | translate }} {{ 'DETAILS.TASKS.NO_ACTIVE' | translate }}
</div> </div>
<div *ngIf="processInstanceDetails && processInstanceDetails.startFormDefined"> <div *ngIf="hasStartFormDefined()">
<span class="activiti-label">{{ 'DETAILS.LABELS.START_FORM'|translate }}</span> <span class="activiti-label">{{ 'DETAILS.LABELS.START_FORM'|translate }}</span>
<!--IF START TASK COMPLETED --> <!--IF START TASK COMPLETED -->
@@ -78,7 +78,7 @@
</div> </div>
</dialog> </dialog>
<dialog class="mdl-dialog task-details-dialog" #startDialog> <dialog *ngIf="hasStartFormDefined()" class="mdl-dialog task-details-dialog" #startDialog>
<h4 class="mdl-dialog__title">{{ 'DETAILS.LABELS.START_FORM'|translate }}</h4> <h4 class="mdl-dialog__title">{{ 'DETAILS.LABELS.START_FORM'|translate }}</h4>
<div class="mdl-dialog__content form__size"> <div class="mdl-dialog__content form__size">
<activiti-start-form [processId]="processId" [processDefinitionId]="processInstanceDetails?.processDefinitionId" <activiti-start-form [processId]="processId" [processDefinitionId]="processInstanceDetails?.processDefinitionId"

View File

@@ -134,6 +134,10 @@ export class ActivitiProcessInstanceTasks implements OnInit, OnChanges {
} }
} }
hasStartFormDefined(): boolean {
return this.processInstanceDetails && this.processInstanceDetails.startFormDefined === true;
}
getUserFullName(user: any) { getUserFullName(user: any) {
if (user) { if (user) {
return (user.firstName && user.firstName !== 'null' return (user.firstName && user.firstName !== 'null'

View File

@@ -18,10 +18,10 @@
<label class="mdl-textfield__label" for="processName">{{'START_PROCESS.DIALOG.LABEL.NAME'|translate}}</label> <label class="mdl-textfield__label" for="processName">{{'START_PROCESS.DIALOG.LABEL.NAME'|translate}}</label>
</div> </div>
<activiti-start-form *ngIf="hasStartForm()" [processDefinitionId]="currentProcessDef.id" <activiti-start-form *ngIf="hasStartForm()" [processDefinitionId]="currentProcessDef.id"
(formSaved)='onFormSaved($event)' (formSaved)="onFormSaved($event)"
(formCompleted)='onFormCompleted($event)' (formCompleted)="onFormCompleted($event)"
(formLoaded)='onFormLoaded($event)' (formLoaded)="onFormLoaded($event)"
(onError)='onFormError($event)'> (onError)="onFormError($event)">
</activiti-start-form> </activiti-start-form>
</div> </div>
<div class="mdl-card__actions mdl-card--border" *ngIf="showStartButton"> <div class="mdl-card__actions mdl-card--border" *ngIf="showStartButton">

View File

@@ -140,6 +140,7 @@ export class AlfrescoAuthenticationService {
public removeTicket(): void { public removeTicket(): void {
this.storage.removeItem('ticket-ECM'); this.storage.removeItem('ticket-ECM');
this.storage.removeItem('ticket-BPM'); this.storage.removeItem('ticket-BPM');
this.alfrescoApi.setTicket(undefined, undefined);
} }
/** /**

View File

@@ -22,9 +22,15 @@ import { AlfrescoContentService } from './AlfrescoContent.service';
import { AlfrescoApiService } from './AlfrescoApi.service'; import { AlfrescoApiService } from './AlfrescoApi.service';
import { StorageService } from './storage.service'; import { StorageService } from './storage.service';
declare let jasmine: any;
describe('AlfrescoContentService', () => { describe('AlfrescoContentService', () => {
let injector, contentService: AlfrescoContentService, authService: AlfrescoAuthenticationService, node; let injector, contentService: AlfrescoContentService;
let authService: AlfrescoAuthenticationService;
let settingsService: AlfrescoSettingsService;
let storage: StorageService;
let node: any;
const nodeId = 'fake-node-id'; const nodeId = 'fake-node-id';
@@ -36,29 +42,56 @@ describe('AlfrescoContentService', () => {
AlfrescoSettingsService, AlfrescoSettingsService,
StorageService StorageService
]); ]);
spyOn(localStorage, 'getItem').and.callFake(function (key) {
return 'myTicket';
});
contentService = injector.get(AlfrescoContentService);
authService = injector.get(AlfrescoAuthenticationService); authService = injector.get(AlfrescoAuthenticationService);
authService.login('fake-username', 'fake-password'); settingsService = injector.get(AlfrescoSettingsService);
contentService = injector.get(AlfrescoContentService);
storage = injector.get(StorageService);
storage.clear();
node = { node = {
entry: { entry: {
id: nodeId id: nodeId
} }
}; };
jasmine.Ajax.install();
}); });
it('should return a valid content URL', () => { afterEach(() => {
expect(contentService.getContentUrl(node)).toBe('http://localhost:8080/alfresco/api/' + jasmine.Ajax.uninstall();
'-default-/public/alfresco/versions/1/nodes/fake-node-id/content?attachment=false&alf_ticket=myTicket');
}); });
it('should return a valid thumbnail URL', () => { beforeEach(() => {
expect(contentService.getDocumentThumbnailUrl(node)) settingsService.setProviders('ECM');
.toBe('http://localhost:8080/alfresco/api/-default-/public/alfresco' + });
'/versions/1/nodes/fake-node-id/renditions/doclib/content?attachment=false&alf_ticket=myTicket');
it('should return a valid content URL', (done) => {
authService.login('fake-username', 'fake-password').subscribe(() => {
expect(contentService.getContentUrl(node)).toBe('http://localhost:8080/alfresco/api/' +
'-default-/public/alfresco/versions/1/nodes/fake-node-id/content?attachment=false&alf_ticket=fake-post-ticket');
done();
});
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 201,
contentType: 'application/json',
responseText: JSON.stringify({'entry': {'id': 'fake-post-ticket', 'userId': 'admin'}})
});
});
it('should return a valid thumbnail URL', (done) => {
authService.login('fake-username', 'fake-password').subscribe(() => {
expect(contentService.getDocumentThumbnailUrl(node))
.toBe('http://localhost:8080/alfresco/api/-default-/public/alfresco' +
'/versions/1/nodes/fake-node-id/renditions/doclib/content?attachment=false&alf_ticket=fake-post-ticket');
done();
});
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 201,
contentType: 'application/json',
responseText: JSON.stringify({'entry': {'id': 'fake-post-ticket', 'userId': 'admin'}})
});
}); });
}); });

View File

@@ -23,13 +23,14 @@
class="mdl-textfield__input" class="mdl-textfield__input"
id="name" id="name"
required required
value="Untitled folder" [(ngModel)]="folderName"
placeholder="Folder name"
data-automation-id="name" data-automation-id="name"
autocapitalize="none" #name/> autocapitalize="none" #name/>
</div> </div>
</div> </div>
<div class="mdl-dialog__actions"> <div class="mdl-dialog__actions">
<button type="button" (click)="createFolder(name.value)" class="mdl-button">{{ 'BUTTON.CREATE' | translate }}</button> <button type="button" [disabled]="isFolderNameEmpty()" (click)="createFolder(folderName)" class="mdl-button">{{ 'BUTTON.CREATE' | translate }}</button>
<button type="button" (click)="cancel()" class="mdl-button close">{{ 'BUTTON.CANCEL' | translate }}</button> <button type="button" (click)="cancel()" class="mdl-button close">{{ 'BUTTON.CANCEL' | translate}}</button>
</div> </div>
</dialog> </dialog>

View File

@@ -55,6 +55,8 @@ export class DocumentMenuAction implements OnInit {
message: string; message: string;
folderName: string = '';
constructor( constructor(
private documentListService: DocumentListService, private documentListService: DocumentListService,
private translate: AlfrescoTranslationService) { private translate: AlfrescoTranslationService) {
@@ -72,7 +74,7 @@ export class DocumentMenuAction implements OnInit {
.subscribe( .subscribe(
res => { res => {
let relativeDir = this.currentFolderPath; let relativeDir = this.currentFolderPath;
console.log(relativeDir); this.folderName = '';
this.success.emit({value: relativeDir}); this.success.emit({value: relativeDir});
}, },
error => { error => {
@@ -128,4 +130,8 @@ export class DocumentMenuAction implements OnInit {
} }
return message; return message;
} }
isFolderNameEmpty() {
return this.folderName === '' ? true : false;
}
} }