From 60c65f2110f65221bc3a71b2887667e78c53c53e Mon Sep 17 00:00:00 2001
From: rsanchez <rsanchez@curisit.net>
Date: Wed, 22 Mar 2017 17:44:16 +0000
Subject: [PATCH] #3527 fix - Added pack/license actions and a lot of bugfixing
---
securis/src/main/webapp/src/app/forms/user.form.component.ts | 61 +++++++
securis/src/main/webapp/src/app/resources/licenses.ts | 76 ++++++--
securis/src/main/webapp/src/app/forms/base.ts | 6
securis/src/main/webapp/src/app/listing/license.list.component.ts | 65 ++++---
securis/src/main/java/net/curisit/securis/DevFilter.java | 2
securis/src/main/webapp/package.json | 2
securis/src/main/webapp/src/app/listing/pack.list.component.ts | 44 ++--
securis/src/main/webapp/src/app/forms/user.form.html | 71 +++++---
securis/src/main/webapp/src/app/resources/packs.ts | 15 +
securis/src/main/webapp/src/app/listing/pack.list.component.html | 7
securis/src/main/webapp/src/app/common/default.requests.options.ts | 11
securis/src/main/webapp/src/app/forms/pack.form.component.ts | 24 ++
securis/src/main/webapp/src/app/app.module.ts | 4
securis/src/main/webapp/src/app/forms/license.form.component.ts | 15 +
securis/src/main/webapp/src/app/forms/pack.form.html | 16 +
securis/src/main/webapp/systemjs.config.js | 1
securis/src/main/webapp/src/app/listing/license.list.component.html | 8
securis/src/main/webapp/src/app/forms/license.form.html | 13 +
securis/src/main/webapp/src/lang/messages_en.json | 8
19 files changed, 317 insertions(+), 132 deletions(-)
diff --git a/securis/src/main/java/net/curisit/securis/DevFilter.java b/securis/src/main/java/net/curisit/securis/DevFilter.java
index 80f6a3b..1e049c0 100644
--- a/securis/src/main/java/net/curisit/securis/DevFilter.java
+++ b/securis/src/main/java/net/curisit/securis/DevFilter.java
@@ -35,7 +35,7 @@
//res.addHeader("Access-Control-Request-Headers", "*");
res.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
res.addHeader("Access-Control-Allow-Headers", "X-SECURIS-TOKEN, Content-Type");
- res.addHeader("Access-Control-Expose-Headers", "X-SECURIS-ERROR-MSG, X-SECURIS-ERROR-CODE, Content-Type");
+ res.addHeader("Access-Control-Expose-Headers", "X-SECURIS-ERROR-MSG, X-SECURIS-ERROR-CODE, Content-Type, Content-Disposition");
// LOG.info("Added header to: " + res.getHeaderNames());
if (!req.getMethod().equals("OPTIONS")) {
diff --git a/securis/src/main/webapp/package.json b/securis/src/main/webapp/package.json
index f953d0d..b294000 100644
--- a/securis/src/main/webapp/package.json
+++ b/securis/src/main/webapp/package.json
@@ -39,6 +39,7 @@
"angular-2-local-storage": "^1.0.1",
"angular-in-memory-web-api": "~0.2.4",
"core-js": "^2.4.1",
+ "file-saver": "^1.3.3",
"hammerjs": "^2.0.8",
"ng2-toastr": "^1.5.1",
"rxjs": "^5.0.1",
@@ -46,6 +47,7 @@
"zone.js": "^0.7.4"
},
"devDependencies": {
+ "@types/file-saver": "0.0.0",
"@types/jasmine": "2.5.36",
"@types/node": "^6.0.46",
"canonical-path": "0.0.2",
diff --git a/securis/src/main/webapp/src/app/app.module.ts b/securis/src/main/webapp/src/app/app.module.ts
index 57df58a..fe86958 100644
--- a/securis/src/main/webapp/src/app/app.module.ts
+++ b/securis/src/main/webapp/src/app/app.module.ts
@@ -35,11 +35,11 @@
import { LoginFormComponent } from './forms/login.form.component';
import { LicenseFormComponent } from './forms/license.form.component';
+import { ApplicationFormComponent } from './forms/application.form.component';
+import { PackFormComponent } from "./forms/pack.form.component";
import { LicenseTypeFormComponent } from './forms/licensetype.form.component';
import { OrganizationFormComponent } from './forms/organization.form.component';
import { UserFormComponent } from './forms/user.form.component';
-import { ApplicationFormComponent } from './forms/application.form.component';
-import { PackFormComponent } from "./forms/pack.form.component";
import { appRoutes, appRoutingProviders } from './app.routes';
diff --git a/securis/src/main/webapp/src/app/common/default.requests.options.ts b/securis/src/main/webapp/src/app/common/default.requests.options.ts
index 5b3cba2..ce35fb0 100644
--- a/securis/src/main/webapp/src/app/common/default.requests.options.ts
+++ b/securis/src/main/webapp/src/app/common/default.requests.options.ts
@@ -23,11 +23,6 @@
// Set the default 'Content-Type' header
this.headers.set('Content-Type', 'application/json');
- let token = this.store.get<string>('token');
- if (token) {
- this.headers.set('X-SECURIS-TOKEN', token);
-
- }
}
}
@@ -35,11 +30,15 @@
@Injectable()
export class ApiXHRBackend extends XHRBackend {
- constructor(_browserXHR: BrowserXhr, _baseResponseOptions: ResponseOptions, _xsrfStrategy: XSRFStrategy) {
+ constructor(_browserXHR: BrowserXhr, _baseResponseOptions: ResponseOptions, _xsrfStrategy: XSRFStrategy, private store: LocalStorageService) {
super(_browserXHR, _baseResponseOptions, _xsrfStrategy);
}
createConnection(request: Request): XHRConnection {
+ let token = this.store.get<string>('token');
+ if (token) {
+ request.headers.set('X-SECURIS-TOKEN', token);
+ }
if (!request.url.endsWith('.js') && !request.url.endsWith('.json') && !request.url.endsWith('.html') && !request.url.endsWith('.svg')){
request.url = 'http://localhost:8080/securis/' + request.url; // prefix base url
}
diff --git a/securis/src/main/webapp/src/app/forms/base.ts b/securis/src/main/webapp/src/app/forms/base.ts
index b29548d..1fc2ca1 100644
--- a/securis/src/main/webapp/src/app/forms/base.ts
+++ b/securis/src/main/webapp/src/app/forms/base.ts
@@ -56,8 +56,8 @@
protected abstract init(): void;
protected abstract goBack(): void;
- save() {
- var command = this.isNew ? this.resourceServices.create(this.data) : this.resourceServices.modify(this.data.id, this.data);
+ save(fieldId : string = 'id') {
+ var command = this.isNew ? this.resourceServices.create(this.data) : this.resourceServices.modify(this.data[fieldId], this.data);
command.subscribe(
data => {
this.toaster.success(this.$L.get('{} saved sucessfully', this.resourceName.capitalize()));
@@ -94,7 +94,7 @@
this.form_title = this.$L.get('{} data', this.resourceName.capitalize());
this.isNew = true;
!!this.route && this.route.params.subscribe(params => {
- var eleId = +params[idparam]; // (+) converts string 'id' to a number
+ var eleId = params[idparam];
if (!eleId) {
this.data = {};
Object.keys(default_values).forEach((k : string) => this.data[k] = default_values[k]);
diff --git a/securis/src/main/webapp/src/app/forms/license.form.component.ts b/securis/src/main/webapp/src/app/forms/license.form.component.ts
index 90c3ef3..6414714 100644
--- a/securis/src/main/webapp/src/app/forms/license.form.component.ts
+++ b/securis/src/main/webapp/src/app/forms/license.form.component.ts
@@ -50,7 +50,22 @@
reader.readAsText(file);
this.requestFileUploader.clear();
}
+
+
+ licenseAction(action: string) {
+ return this.licenses[action](this.data.id).subscribe(
+ (actionResponse : any) => {
+ this.toaster.success(this.$L.get('Action "{}" executed successfully', action));
+ this.reload();
+ },
+ (err : any) => this.toaster.error(this.$L.get('Action "{}" failed', action))
+ );
+ }
+
+ canBeDeleted() : boolean {
+ return !this.isNew && this.licenses.isActionAvailable('delete', this.data);
+ }
requestFileUploaded(file: File) : void {
console.log(file);
diff --git a/securis/src/main/webapp/src/app/forms/license.form.html b/securis/src/main/webapp/src/app/forms/license.form.html
index 083adcf..84d78b6 100644
--- a/securis/src/main/webapp/src/app/forms/license.form.html
+++ b/securis/src/main/webapp/src/app/forms/license.form.html
@@ -39,7 +39,7 @@
<field-readonly [value]="data.activation_code" label="field.activation_code" flex></field-readonly>
</div>
<div layout="row" layout-fill layout-padding *ngIf="!isNew">
- <field-readonly [value]="data.expiration_date | date: 'dateMedium'" label="field.expiration_date" flex></field-readonly>
+ <field-readonly [value]="data.expiration_date | date: 'mediumDate'" label="field.expiration_date" flex></field-readonly>
<field-readonly [value]="licenses.getStatusName(data.status)" label="field.status" flex></field-readonly>
</div>
<div layout="row" layout-fill layout-padding>
@@ -59,7 +59,7 @@
<span i18n="field.email"></span>
</md-placeholder>
</md-input-container>
- <error-checker [fieldName]="$L.get('field.full_name')" [formField]="form.controls.email"></error-checker>
+ <error-checker [fieldName]="$L.get('field.email')" [formField]="form.controls.email"></error-checker>
</div>
</div>
<div layout="row" layout-fill layout-padding>
@@ -99,7 +99,16 @@
<md-divider></md-divider>
<md-card-actions>
<div layout="row" layout-align="start center" class="margin">
+ <button *ngIf="canBeDeleted()" md-raised-button color="warn" (click)="delete(data.id)">Delete</button>
<span flex></span>
+ <button md-icon-button [mdMenuTriggerFor]="licMenu" aria-label="License menu">
+ <md-icon>more_vert</md-icon>
+ </button>
+ <md-menu #licMenu="mdMenu">
+ <button md-menu-item *ngFor="let action of license_menu_options" (click)="licenseAction(action.command)" [disabled]="!licenses.isActionAvailable(action.command, data)">
+ <md-icon *ngIf="!!action.icon">{{ action.icon }}</md-icon> {{ action.name }}
+ </button>
+ </md-menu>
<button [disabled]="!form.form.valid" md-raised-button color="primary" (click)="save()">Save</button>
<button md-button (click)="goBack()">Cancel</button>
</div>
diff --git a/securis/src/main/webapp/src/app/forms/pack.form.component.ts b/securis/src/main/webapp/src/app/forms/pack.form.component.ts
index 0ac5044..9b7c195 100644
--- a/securis/src/main/webapp/src/app/forms/pack.form.component.ts
+++ b/securis/src/main/webapp/src/app/forms/pack.form.component.ts
@@ -1,7 +1,7 @@
import { Http } from '@angular/http';
import { ToastsManager } from 'ng2-toastr/ng2-toastr';
-import { PacksService, PACK_STATUS } from '../resources/packs';
+import { PacksService, PACK_STATUS, PACK_ACTIONS } from '../resources/packs';
import { LicenseTypesService } from '../resources/license_types';
import { LocaleService } from '../common/i18n';
import { TdDataTableService, TdDataTableSortingOrder, ITdDataTableSortChangeEvent, ITdDataTableColumn } from '@covalent/core';
@@ -21,7 +21,7 @@
organizations : IComboOption[];
licensetypes : IComboOption[];
-
+ pack_menu_options = PACK_ACTIONS;
constructor(private http: Http,
private licenseTypes: LicenseTypesService,
private packs: PacksService,
@@ -65,11 +65,27 @@
);
}
+ packAction(action: string) {
+ return this.packs[action](this.data.id).subscribe(
+ (actionResponse : any) => {
+ this.toaster.success(this.$L.get('Action "{}" executed successfully', action));
+ this.reload();
+ },
+ (err : any) => this.toaster.error(this.$L.get('Action "{}" failed', action))
+ );
+ }
+
changeOrg(event: any) {
- console.log(event);
console.log(this.data.organization_id);
}
-
+
+ canBeDeleted(event: any) : boolean{
+ return !this.isNew && this.packs.isActionAvailable('delete', this.data);
+ }
+
+ convertToEpoch(str: string) : number {
+ return new Date(str).getTime();
+ }
ngAfterViewInit(): void {
this.init();
diff --git a/securis/src/main/webapp/src/app/forms/pack.form.html b/securis/src/main/webapp/src/app/forms/pack.form.html
index afbdb05..42a4bbf 100644
--- a/securis/src/main/webapp/src/app/forms/pack.form.html
+++ b/securis/src/main/webapp/src/app/forms/pack.form.html
@@ -48,7 +48,8 @@
<div layout="row" layout-fill layout-padding>
<div layout="column" layout-fill flex>
<md-input-container flex>
- <input mdInput type="date" [(ngModel)]="data.init_valid_date" name="init_valid_date" required />
+ <input mdInput type="date" [ngModel]="data.init_valid_date | date:'yyyy-MM-dd'"
+ (ngModelChange)="data.init_valid_date = $event" name="init_valid_date" required />
<md-placeholder>
<span i18n="field.end_valid_date"></span>
</md-placeholder>
@@ -57,7 +58,8 @@
</div>
<div layout="column" layout-fill flex>
<md-input-container flex>
- <input mdInput type="date" [(ngModel)]="data.end_valid_date" name="end_valid_date" required />
+ <input mdInput type="date" [ngModel]="data.end_valid_date | date:'yyyy-MM-dd'"
+ (ngModelChange)="data.end_valid_date = $event" name="end_valid_date" required />
<md-placeholder>
<span i18n="field.end_valid_date"></span>
</md-placeholder>
@@ -133,7 +135,17 @@
<md-divider></md-divider>
<md-card-actions>
<div layout="row" layout-align="start center" class="margin">
+ <button *ngIf="canBeDeleted()" md-raised-button color="warn" (click)="delete(data.id)">Delete</button>
<span flex></span>
+
+ <button md-icon-button [mdMenuTriggerFor]="packMenu" aria-label="Pack menu">
+ <md-icon>more_vert</md-icon>
+ </button>
+ <md-menu #packMenu="mdMenu">
+ <button md-menu-item *ngFor="let action of pack_menu_options" (click)="packAction(action.command)" [disabled]="!packs.isActionAvailable(action.command, data)">
+ <md-icon *ngIf="!!action.icon">{{ action.icon }}</md-icon> {{ action.name }}
+ </button>
+ </md-menu>
<button [disabled]="!form.form.valid" md-raised-button color="primary" (click)="save()">Save</button>
<button md-button (click)="goBack()">Cancel</button>
</div>
diff --git a/securis/src/main/webapp/src/app/forms/user.form.component.ts b/securis/src/main/webapp/src/app/forms/user.form.component.ts
index a709db6..c579366 100644
--- a/securis/src/main/webapp/src/app/forms/user.form.component.ts
+++ b/securis/src/main/webapp/src/app/forms/user.form.component.ts
@@ -9,6 +9,7 @@
import { TdMediaService } from '@covalent/core';
import { FormBase, IComboOption } from './base';
import { ActivatedRoute, Router } from '@angular/router';
+import { OrganizationsService } from "../resources/organizations";
var user_example = {
username: 'rym',
@@ -27,10 +28,14 @@
templateUrl: 'src/app/forms/user.form.html'
})
export class UserFormComponent extends FormBase {
-
+ allOrganizations: IComboOption[];
+ orgNames: string[] = [];
+ allRoles: any[] = [{"id":1, "code": "advance", "label":"Advance"}, {"id":2, "code": "admin","label":"Admin"}];
+ user_orgs: string[] = [];
+ user_roles: any = {};
constructor(private http: Http,
private users: UsersService,
- private applications: ApplicationsService,
+ private organizations: OrganizationsService,
router: Router,
toaster: ToastsManager,
route: ActivatedRoute,
@@ -39,16 +44,62 @@
super($L, router, route, toaster, users, $L.get('user'), dialogs);
}
-
+ save() : void {
+ this.data.organizations_ids = [];
+ this.data.roles = [];
+ this.user_orgs.forEach(orgName => {
+ var selectedOrg = this.allOrganizations.find(org => org.label === orgName);
+ this.data.organizations_ids.push(selectedOrg.id);
+ });
+ this.user_roles.advance && this.data.roles.push(1);
+ this.user_roles.admin && this.data.roles.push(2);
+ super.save('username');
+ }
+
+ canBeDeleted() {
+ return this.data && this.data.username !== 'admin' && this.data.username !== '_client';
+ }
+
+ loadCombos() : void {
+ this.organizations.get()
+ .map(list => list.map((org : any) => <IComboOption>{id: org.id, label: org.name}))
+ .subscribe(
+ data => {
+ this.allOrganizations = (<IComboOption[]>data).sort((e1, e2) => e1.label.localeCompare(e2.label));
+ this.orgNames = this.allOrganizations.map(org => org.label);
+ this._loadOrgs();
+ },
+ err => console.error('Error loading organizations')
+ );
+ }
+
goBack(): void {
this.router.navigate([`users`]);
}
-
+ _loadOrgs() {
+ if (this.data && this.data.organizations_ids && this.allOrganizations && this.allOrganizations.length > 0) {
+ this.data.organizations_ids.forEach((orgId : number) => {
+ var selectedOrg = this.allOrganizations.find(org => org.id === orgId);
+ this.user_orgs.push(selectedOrg.label);
+ });
+ }
+ }
init() : void {
+ this.loadCombos();
+ this.user_orgs = [];
+ this.user_roles = {};
super.setFirstFocus();
super.reset();
super.prepareInitialData('username', {
- metadata: []
+ organizations_ids: [],
+ roles: []
+ }, (data) => {
+ this._loadOrgs();
+ data.roles.forEach((roleId : number) => {
+ var selectedRole = this.allRoles.find(r => r.id === roleId);
+ this.user_roles[selectedRole.code] = true;
+ });
+
});
}
diff --git a/securis/src/main/webapp/src/app/forms/user.form.html b/securis/src/main/webapp/src/app/forms/user.form.html
index 6299a7c..1a3caa4 100644
--- a/securis/src/main/webapp/src/app/forms/user.form.html
+++ b/securis/src/main/webapp/src/app/forms/user.form.html
@@ -8,17 +8,15 @@
<button md-icon-button (click)="save()"><md-icon>save</md-icon></button>
</md-toolbar>
<!--
- code: 'CICS',
- creation_timestamp: 1418384439000,
- description: 'Wellbore integrity analysis software',
- id: 1,
- license_filename: 'config_server.lic',
- name: 'CurisIntegrity',
- metadata:
- [ { key: 'max_docs',
- value: '250000',
- readonly: true,
- mandatory: true } ]
+ username: 'rym',
+ roles: [ 1 ],
+ lastLogin: 1488885433000,
+ modificationTimestamp: 1479898458000,
+ email: 'rbouchair@curistec.com',
+ first_name: 'Rym',
+ last_name: 'Bouchair',
+ creation_timestamp: 1479898458000,
+ organizations_ids: [ 1, 2, 5, 6, 7, 8 ]
}
-->
<div class="margin" layout-align-gt-xs="center start" layout-fill="" layout-gt-xs="row">
@@ -31,59 +29,80 @@
<form #form="ngForm" class="inset">
<div layout="column" layout-align="start center">
<div layout="row" layout-fill layout-padding>
- <field-readonly [value]="data.id" label="field.id" flex="15" *ngIf="!isNew"></field-readonly>
<div layout="column" layout-fill flex>
<md-input-container>
- <input #firstField mdInput maxLength="50" type="text" [(ngModel)]="data.code" name="code" required [readonly]="!isNew" />
+ <input #firstField mdInput maxLength="50" type="text" [(ngModel)]="data.username" name="username" required [readonly]="!isNew" />
<md-placeholder>
- <span i18n="field.code"></span>
+ <span i18n="field.username"></span>
</md-placeholder>
</md-input-container>
- <error-checker [fieldName]="getFieldName('code')" [formField]="form.controls.code"></error-checker>
+ <error-checker [fieldName]="getFieldName('username')" [formField]="form.controls.username"></error-checker>
+ </div>
+ <div layout="column" layout-fill flex>
+ <md-input-container flex>
+ <input mdInput type="password" [(ngModel)]="data.password" name="password" [required]="isNew" />
+ <md-placeholder>
+ <span i18n="field.password"></span>
+ </md-placeholder>
+ </md-input-container>
+ <error-checker [fieldName]="getFieldName('password')" [formField]="form.controls.password"></error-checker>
</div>
</div>
<div layout="row" layout-fill layout-padding>
<div layout="column" layout-fill flex>
<md-input-container flex>
- <input mdInput type="text" [(ngModel)]="data.name" name="name" required />
+ <input mdInput type="text" [(ngModel)]="data.first_name" name="first_name" required />
<md-placeholder>
- <span i18n="field.name"></span>
+ <span i18n="field.first_name"></span>
</md-placeholder>
</md-input-container>
- <error-checker [fieldName]="getFieldName('name')" [formField]="form.controls.name"></error-checker>
+ <error-checker [fieldName]="getFieldName('first_name')" [formField]="form.controls.first_name"></error-checker>
</div>
<div layout="column" layout-fill flex>
<md-input-container flex>
- <input mdInput type="text" [(ngModel)]="data.license_filename" name="license_filename" required />
+ <input mdInput type="text" [(ngModel)]="data.last_name" name="last_name" />
<md-placeholder>
- <span i18n="field.license_filename"></span>
+ <span i18n="field.last_name"></span>
</md-placeholder>
</md-input-container>
- <error-checker [fieldName]="getFieldName('license_filename')" [formField]="form.controls.license_filename"></error-checker>
+ <error-checker [fieldName]="getFieldName('last_name')" [formField]="form.controls.last_name"></error-checker>
</div>
</div>
<div layout="row" layout-fill layout-padding>
<div layout="column" layout-fill flex>
<md-input-container flex>
- <textarea mdInput type="text" type="text" [(ngModel)]="data.description" name="description" maxlength="1024"></textarea>
+ <input mdInput type="email" [(ngModel)]="data.email" name="email" required maxlength="200" />
<md-placeholder>
- <span i18n="field.description"></span>
+ <span i18n="field.email"></span>
</md-placeholder>
- <md-hint align="end">(max 1024)</md-hint>
</md-input-container>
+ <error-checker [fieldName]="$L.get('field.email')" [formField]="form.controls.email"></error-checker>
+ </div>
+ </div>
+ <div layout="row" layout-fill layout-padding >
+ <td-chips flex [mdTooltip]="$L.get('Organizations that user can access')" [placeholder]="$L.get('Select organizations')"
+ [items]="orgNames" [(ngModel)]="user_orgs" name="user_orgs" requireMatch>
+ </td-chips>
+ <div layout="column" layout-fill flex="25">
+ <md-checkbox [(ngModel)]="user_roles.advance" name="advance_role" [mdTooltip]="$L.get('Role {}', 'advance')">
+ <span i18n>Advance</span>
+ </md-checkbox>
+ <md-checkbox [(ngModel)]="user_roles.admin" name="admin_role" [mdTooltip]="$L.get('Role {}', 'admin')">
+ <span i18n>Admin</span>
+ </md-checkbox>
</div>
</div>
<div layout="row" layout-fill layout-padding *ngIf="!isNew">
+ <field-readonly [value]="data.lastLogin || '' | timeAgo" label="field.lastLogin" flex></field-readonly>
<field-readonly [value]="data.creation_timestamp | date: 'medium'" label="field.creation_timestamp" flex></field-readonly>
</div>
- <metadata-manager addOrDelete="true" editKeys="true" [metadata]="data.metadata" ></metadata-manager>
</div>
</form>
</md-card-content>
<md-divider></md-divider>
<md-card-actions>
<div layout="row" layout-align="start center" class="margin">
- <button *ngIf="!isNew" md-raised-button color="warn" (click)="delete(data.id)">Delete</button>
+ <button *ngIf="!isNew" [disabled]="!canBeDeleted()" md-raised-button color="warn" (click)="delete(data.username)">Delete</button>
<span flex></span>
<button [disabled]="!form.form.valid" md-raised-button color="primary" (click)="save()">Save</button>
<button md-button (click)="goBack()">Cancel</button>
diff --git a/securis/src/main/webapp/src/app/listing/license.list.component.html b/securis/src/main/webapp/src/app/listing/license.list.component.html
index 1a6ad85..e2b0c30 100644
--- a/securis/src/main/webapp/src/app/listing/license.list.component.html
+++ b/securis/src/main/webapp/src/app/listing/license.list.component.html
@@ -40,9 +40,9 @@
<span style="white-space: nowrap">{{value}}</span>
</div>
</template>
- <template tdDataTableTemplate="status" let-row="row">
+ <template tdDataTableTemplate="status" let-row="row" let-value="value">
<div layout="row" layout-align="start center">
- <md-icon [style.color]="licenses.getStatusColor(row.status)">brightness_1</md-icon> <span>{{licenses.getStatusName(row.status)}}</span>
+ <md-chip selected [mdTooltip]="licenses.getStatusName(value)" [style.background-color]="licenses.getStatusColor(value)" >{{value}}</md-chip>
</div>
</template>
<template tdDataTableTemplate="email" let-row="row" let-value="value">
@@ -63,7 +63,7 @@
<md-icon>more_vert</md-icon>
</button>
<md-menu #licenseMenu="mdMenu">
- <button md-menu-item *ngFor="let action of license_menu_options" (click)="licenseAction(action.command, row)" [disabled]="!isActionAvailable(row)">
+ <button md-menu-item *ngFor="let action of license_menu_options" (click)="licenseAction(action.command, row)" [disabled]="!isActionAvailable(action.command, row)">
<md-icon *ngIf="!!action.icon">{{ action.icon }}</md-icon> {{ action.name }}
</button>
</md-menu>
@@ -74,4 +74,4 @@
<span i18n td-paging-bar-label hide-xs>Rows per page:</span> {{pagingBar.range}} <span hide-xs>of {{pagingBar.total}}</span>
</td-paging-bar>
</div>
-</td-layout-card-over>
\ No newline at end of file
+</td-layout-card-over>
diff --git a/securis/src/main/webapp/src/app/listing/license.list.component.ts b/securis/src/main/webapp/src/app/listing/license.list.component.ts
index 4783054..843f985 100644
--- a/securis/src/main/webapp/src/app/listing/license.list.component.ts
+++ b/securis/src/main/webapp/src/app/listing/license.list.component.ts
@@ -5,9 +5,10 @@
import { Component, AfterViewInit, ViewChild } from '@angular/core';
import { TdMediaService } from '@covalent/core';
import { Location } from '@angular/common';
+import { ToastsManager } from 'ng2-toastr/ng2-toastr';
import { LocaleService } from '../common/i18n';
-import { LicensesService } from '../resources/licenses';
+import { LicensesService, LICENSE_ACTIONS } from '../resources/licenses';
import { PacksService } from '../resources/packs';
import { LicenseFormComponent } from '../forms/license.form.component';
import { ListingBase } from './base';
@@ -43,22 +44,30 @@
{ name: 'menu', label: '' }
];
- license_menu_options : any[] = [{
- icon: 'edit',
- command: 'edit',
- name: 'Edit'
- },{
- icon: 'cancel',
- command: 'cancel',
- name: 'Cancel'
- }]
+ license_menu_options = LICENSE_ACTIONS;
- licenseAction(action: any) {
- console.log(action.command);
+ licenseAction(action: string, license: any) {
+ return this.licenses[action](license.id).subscribe(
+ (actionResponse : any) => {
+ this.toaster.success(this.$L.get('Action "{}" executed successfully', action));
+ this.reload(this.pack.id);
+ },
+ (err : any) => this.toaster.error(this.$L.get('Action "{}" failed', action))
+ );
}
- isActionAvailable(pack : any) : boolean {
- return true;
+ reload(packId: number) : void {
+ this.licenses.getByPack(packId).subscribe(
+ list => {
+ this.data = list;
+ this.refresh();
+ },
+ err => console.error(err)
+ );
+ }
+
+ isActionAvailable(action: string, license : any) : boolean {
+ return this.licenses.isActionAvailable(action, license);
}
constructor( _dataTableService: TdDataTableService,
@@ -66,6 +75,7 @@
private $L: LocaleService,
private router: Router,
private location: Location,
+ private toaster: ToastsManager,
private route: ActivatedRoute,
private dialog: MdDialog,
private licenseForm: LicenseFormComponent,
@@ -75,22 +85,6 @@
}
ngOnInit(): void {
- this.route.params.subscribe(params => {
- var packId = +params['packId']; // (+) converts string 'id' to a number
- this.licenses.getByPack(packId).subscribe(
- list => {
- this.data = list;
- this.refresh();
- },
- err => console.error(err)
- );
- this.packs.get(packId).subscribe(
- packData => {
- this.pack = packData;
- },
- err => console.error(err)
- );
- });
}
goBack() : void {
@@ -111,7 +105,16 @@
ngAfterViewInit(): void {
this.media.broadcast();
-
+ this.route.params.subscribe(params => {
+ var packId = +params['packId']; // (+) converts string 'id' to a number
+ this.reload(packId);
+ this.packs.get(packId).subscribe(
+ packData => {
+ this.pack = packData;
+ },
+ err => console.error(err)
+ );
+ });
}
}
diff --git a/securis/src/main/webapp/src/app/listing/pack.list.component.html b/securis/src/main/webapp/src/app/listing/pack.list.component.html
index 0399351..f08c574 100644
--- a/securis/src/main/webapp/src/app/listing/pack.list.component.html
+++ b/securis/src/main/webapp/src/app/listing/pack.list.component.html
@@ -33,6 +33,11 @@
<span style="white-space: nowrap">{{value}}</span>
</div>
</template>
+ <template tdDataTableTemplate="status" let-row="row" let-value="value">
+ <div layout="row" layout-align="start center">
+ <md-chip selected [mdTooltip]="$L.get('pack.status.' +value)" [style.background-color]="packs.getStatusColor(value)" >{{value}}</md-chip>
+ </div>
+ </template>
<template tdDataTableTemplate="menu" let-row="row" let-index="index">
<div layout="row" layout-align="end center">
<button md-icon-button (click)="edit(row.id)" color="primary"><md-icon>edit</md-icon></button>
@@ -41,7 +46,7 @@
</button>
<md-menu #packMenu="mdMenu">
- <button md-menu-item *ngFor="let action of pack_menu_options" (click)="packAction(action.command, row)" [disabled]="!isActionAvailable(row)">
+ <button md-menu-item *ngFor="let action of pack_menu_options" (click)="packAction(action.command, row)" [disabled]="!packs.isActionAvailable(action.command, row)">
<md-icon *ngIf="!!action.icon">{{ action.icon }}</md-icon> {{ action.name }}
</button>
</md-menu>
diff --git a/securis/src/main/webapp/src/app/listing/pack.list.component.ts b/securis/src/main/webapp/src/app/listing/pack.list.component.ts
index 3060af9..42927b1 100644
--- a/securis/src/main/webapp/src/app/listing/pack.list.component.ts
+++ b/securis/src/main/webapp/src/app/listing/pack.list.component.ts
@@ -1,4 +1,5 @@
import { Router, ActivatedRoute } from '@angular/router';
+import { ToastsManager } from 'ng2-toastr/ng2-toastr';
import { MdDialog, MdDialogConfig } from '@angular/material';
import {
ITdDataTableColumn,
@@ -10,7 +11,7 @@
import { IPageChangeEvent } from '@covalent/core';
import { Component, ViewChild, AfterViewInit } from '@angular/core';
import { TdMediaService } from '@covalent/core';
-import { PacksService } from '../resources/packs';
+import { PacksService, PACK_ACTIONS } from '../resources/packs';
import { PackFormComponent } from '../forms/pack.form.component';
import { LocaleService } from '../common/i18n';
import { ListingBase } from './base';
@@ -57,17 +58,11 @@
{ name: 'licensetype_code', label: 'License type' },
{ name: 'organization_name', label: 'Organization' },
{ name: 'used_licenses', label: 'Licenses', tooltip: 'Initial/Available pack licenses' },
+ { name: 'status', label: 'Status', tooltip: 'Pack status' },
{ name: 'menu', label: '' }
];
- pack_menu_options : any[] = [{
- command: 'edit',
- name: 'Edit'
- },{
- command: 'cancel',
- name: 'Cancel'
- }]
-
+ pack_menu_options = PACK_ACTIONS;
constructor(_dataTableService: TdDataTableService,
private media: TdMediaService,
@@ -75,25 +70,30 @@
private route: ActivatedRoute,
private dialog: MdDialog,
private $L: LocaleService,
+ private toaster: ToastsManager,
private packForm: PackFormComponent,
private packs: PacksService) {
super(_dataTableService);
- this.packs.get().subscribe(
- (list : any[]) => {
- this.data = list;
- this.refresh();
- },
- (err: any) => console.error(err)
- );
}
-
- packAction(action: any) {
- console.log(action.command);
+ reload() : void {
+ this.packs.get().subscribe(
+ (list : any[]) => {
+ this.data = list;
+ this.refresh();
+ },
+ (err: any) => console.error(err)
+ );
}
- isActionAvailable(pack : any) : boolean {
- return true;
+ packAction(action: string, pack: any) {
+ return this.packs[action](pack.id).subscribe(
+ (actionResponse : any) => {
+ this.toaster.success(this.$L.get('Action "{}" executed successfully', action));
+ this.reload();
+ },
+ (err : any) => this.toaster.error(this.$L.get('Action "{}" failed', action))
+ );
}
showLicenses(pack: any) : void {
@@ -115,8 +115,8 @@
}
ngAfterViewInit(): void {
+ this.reload();
this.media.broadcast();
-
}
}
diff --git a/securis/src/main/webapp/src/app/resources/licenses.ts b/securis/src/main/webapp/src/app/resources/licenses.ts
index a82d910..87de7bd 100644
--- a/securis/src/main/webapp/src/app/resources/licenses.ts
+++ b/securis/src/main/webapp/src/app/resources/licenses.ts
@@ -1,26 +1,9 @@
import { LocaleService } from '../common/i18n';
import { Observable } from 'rxjs/Rx';
import { Injectable } from '@angular/core';
-import { Http, RequestOptions } from '@angular/http';
+import { Http, RequestOptions, ResponseContentType, Response } from '@angular/http';
import { SeCurisResourceServices } from './base';
-
-var lic_example = {
- id: 101,
- activation_code: 'f3e2d27e-7f81-4ac7-87ba-b9e38b4fdbb8',
- code: 'CITR01-436-1',
- code_suffix: 1,
- created_by_id: '_client',
- creation_timestamp: 1445898088000,
- email: 'GQuercia@trican.ca',
- expiration_date: 1487523828000,
- full_name: 'George Quercia',
- licenseData: '{"appCode":"CICS","appName":"CurisIntegrity","licenseCode":"CITR01-436-1","activationCode":"f3e2d27e-7f81-4ac7-87ba-b9e38b4fdbb8","expirationDate":1487523828416,"arch":"amd64","osName":"Windows 7","macAddresses":["C4-D9-87-5D-53-72","C4-D9-87-5D-53-76","FC-15-B4-EB-70-F9"],"crcLogo":"10f6379e0e1c00ebc403160307e3c5d0aba0727c9cae0bf1ac7cd19d84fdc80f","metadata":{"a2Mode":"false","datasetPrefix":"TR","extendedMode":"false","maxConcurrentInstances":"-1","maxInstances":"3","maxUsers":"0","maxWellLifeLines":"50","timeThreshold":"0"},"signature":"cjyLYFyhXpWWsMNnG6ER9mtCREgw02aQDnXPSQQWZtiLWbu/GyHZzK+1msLhwuKMGYG6I90s5wp82HVIqhIheHOsov3JfnHgNtYzf3BdkqUinwPFuDqPqkXz5Sjb6bouWkmvTI1TN/s4U2DJOXVnYN4FnYl0/dBTcU9RP4NZlQxMu6oFuRrZSMfdMCxEJYZAU62SWgTSurkdmHhFgwRjIwsOXRWHYsr6vGT//yILI7UvMGbMc6dRCGwyJLPNi4nXwF9PRMLinB7fYK8HxKylTJx2O7bvWCZd6EOdwi6gRI/0HhOqZ7E4DzBDrqEnsHeuH4L47DfRdIMGDnA492F+mg=="}',
- modification_timestamp: 1484931828000,
- pack_code: 'CITR01',
- pack_id: 12,
- request_data: '{"appCode":"CICS","activationCode":"f3e2d27e-7f81-4ac7-87ba-b9e38b4fdbb8","arch":"amd64","osName":"Windows 7","macAddresses":["C4-D9-87-5D-53-72","C4-D9-87-5D-53-76","FC-15-B4-EB-70-F9"],"crcLogo":"10f6379e0e1c00ebc403160307e3c5d0aba0727c9cae0bf1ac7cd19d84fdc80f"}',
- status: 'AC'
-}
+import * as saveAsFile from "file-saver";
export const LIC_STATUS = {
CREATED: 'CR',
@@ -41,6 +24,7 @@
'CA': '#a21717'
};
+
/**
* These transitions could be get from server, class License.Status, but
* we copy them for simplicity, this info won't change easily
@@ -56,6 +40,37 @@
cancel: [LIC_STATUS.REQUESTED, LIC_STATUS.EXPIRED, LIC_STATUS.PREACTIVE, LIC_STATUS.ACTIVE],
'delete': [LIC_STATUS.CREATED, LIC_STATUS.CANCELLED, LIC_STATUS.BLOCKED]
}
+
+export const LICENSE_ACTIONS : any[] = [{
+/* command: 'add_request',
+ icon: 'add_to_photos',
+ name: 'Add request'
+ },{ */
+ command: 'activate',
+ icon: 'play_circle_outline',
+ name: 'Activate'
+ },{
+ command: 'send',
+ icon: 'send',
+ name: 'Send'
+ },{
+ command: 'download',
+ icon: 'file_download',
+ name: 'Download'
+ },{
+ command: 'block',
+ icon: 'do_not_disturb_on',
+ name: 'Block'
+ },{
+ command: 'unblock',
+ icon: 'do_not_disturb_off',
+ name: 'Unblock'
+ },{
+ command: 'cancel',
+ icon: 'cancel',
+ name: 'Cancel'
+ }]
+
@Injectable()
export class LicensesService extends SeCurisResourceServices {
@@ -73,19 +88,36 @@
return super.action(id, "activate");
}
+ public block(id: number) {
+ return super.action(id, "block");
+ }
+
+ public unblock(id: number) {
+ return super.action(id, "unblock");
+ }
+
+ public send(id: number) {
+ return super.action(id, "send");
+ }
+
public cancel(id: number) {
return super.action(id, "cancel");
}
- public putonhold(id: number) {
- return super.action(id, "putonhold");
+ public download(id: number) {
+ let url = `${this.resource}/${id}/download`;
+ return this.http.get(url).map((response : Response) => {
+ let filename = JSON.parse(response.headers.get('Content-Disposition').match(/".*"$/g)[0]);
+ let content = JSON.stringify(response.json(), null, 2);
+ saveAsFile( new Blob([ content ], { type : 'application/octet-stream' }), filename);
+ return Observable.of(true);
+ }).catch(err => super.processErrorResponse(err));
}
public isActionAvailable(action:string, lic:any) {
var validStatuses = LIC_ACTIONS_BY_STATUS[action];
return lic && validStatuses && validStatuses.indexOf(lic.status) !== -1;
}
-
getStatusName(statusCode: string): string {
return this.$L.get(`pack.status.${statusCode}`, this.$L.get('Unknown'));
diff --git a/securis/src/main/webapp/src/app/resources/packs.ts b/securis/src/main/webapp/src/app/resources/packs.ts
index 951db3b..17ce29b 100644
--- a/securis/src/main/webapp/src/app/resources/packs.ts
+++ b/securis/src/main/webapp/src/app/resources/packs.ts
@@ -57,6 +57,21 @@
'delete': [PACK_STATUS.CREATED, PACK_STATUS.CANCELLED]
}
+export const PACK_ACTIONS : any[] = [{
+ command: 'activate',
+ icon: 'play_circle_outline',
+ name: 'Activate'
+ },{
+ command: 'putonhold',
+ icon: 'pause_circle_outline',
+ name: 'Put on hold'
+ },{
+ command: 'cancel',
+ icon: 'cancel',
+ name: 'Cancel'
+ }]
+
+
@Injectable()
export class PacksService extends SeCurisResourceServices {
diff --git a/securis/src/main/webapp/src/lang/messages_en.json b/securis/src/main/webapp/src/lang/messages_en.json
index 1147470..acb0550 100644
--- a/securis/src/main/webapp/src/lang/messages_en.json
+++ b/securis/src/main/webapp/src/lang/messages_en.json
@@ -20,11 +20,17 @@
"field.metadata": "Metadata",
"field.key": "Parameter",
"field.value": "Value",
+ "field.username": "Username",
+ "field.password": "Password",
+ "field.first_name": "Firstname",
+ "field.last_name": "Lastname",
"field.created_by": "Created by",
"field.creation_date": "Creation date",
+ "field.expiration_date": "Expiration date",
"field.request_data": "Request data",
- "field.full_name": "Full name",
+ "field.full_name": "Fullname",
"field.email": "Email",
+ "field.lastLogin": "Last login",
"field.creation_timestamp": "Creation timestamp",
"field.comments": "Comments",
"field.mandatory": "Required",
diff --git a/securis/src/main/webapp/systemjs.config.js b/securis/src/main/webapp/systemjs.config.js
index 4567190..476858d 100644
--- a/securis/src/main/webapp/systemjs.config.js
+++ b/securis/src/main/webapp/systemjs.config.js
@@ -16,6 +16,7 @@
// other libraries
'rxjs': 'npm:rxjs',
'ng2-toastr': 'npm:ng2-toastr',
+ 'file-saver': 'npm:file-saver/FileSaver.js',
'angular-2-local-storage': 'npm:angular-2-local-storage/dist',
'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js'
}
--
Gitblit v1.3.2