#3527 feature - Added pack form
6 files added
10 files modified
| .. | .. |
|---|
| 37 | 37 | res.addHeader("Access-Control-Allow-Headers", "X-SECURIS-TOKEN, Content-Type"); |
|---|
| 38 | 38 | res.addHeader("Access-Control-Expose-Headers", "X-SECURIS-ERROR-MSG, X-SECURIS-ERROR-CODE, Content-Type"); |
|---|
| 39 | 39 | |
|---|
| 40 | | - LOG.info("Added header to: " + res.getHeaderNames()); |
|---|
| 40 | + // LOG.info("Added header to: " + res.getHeaderNames()); |
|---|
| 41 | 41 | if (!req.getMethod().equals("OPTIONS")) { |
|---|
| 42 | 42 | fc.doFilter(sreq, sres); |
|---|
| 43 | 43 | } |
|---|
| .. | .. |
|---|
| 28 | 28 | .td-data-table-row > .td-data-table-cell:first-child, |
|---|
| 29 | 29 | .td-data-table-row > .td-data-table-column:first-child { |
|---|
| 30 | 30 | max-width: 30px !important; |
|---|
| 31 | +} |
|---|
| 32 | + |
|---|
| 33 | +md-dialog-actions > .mat-button { |
|---|
| 34 | + margin-left: 5px !important; |
|---|
| 35 | + margin-right: 5px !important; |
|---|
| 36 | +} |
|---|
| 37 | + |
|---|
| 38 | +.label-value { |
|---|
| 39 | + margin-top: 20px; |
|---|
| 40 | +} |
|---|
| 41 | + |
|---|
| 42 | +input:read-only { |
|---|
| 43 | + color: rgba(0, 0, 0, 0.50) !important; |
|---|
| 31 | 44 | } |
|---|
| .. | .. |
|---|
| 1 | +import { ErrorCheckerComponent } from './common/error.checker'; |
|---|
| 1 | 2 | import { NgModule } from '@angular/core'; |
|---|
| 2 | 3 | import { BrowserModule } from '@angular/platform-browser'; |
|---|
| 3 | 4 | import { CommonModule } from '@angular/common'; |
|---|
| .. | .. |
|---|
| 11 | 12 | import { ToastModule } from 'ng2-toastr/ng2-toastr'; |
|---|
| 12 | 13 | |
|---|
| 13 | 14 | import { AppHomeComponent } from './app.component'; |
|---|
| 15 | +import { I18nDirective } from './common/i18n'; |
|---|
| 14 | 16 | import { UserService } from './user.service'; |
|---|
| 15 | 17 | import { PacksService } from './resources/packs'; |
|---|
| 16 | 18 | import { LicenseTypesService } from './resources/license_types'; |
|---|
| .. | .. |
|---|
| 25 | 27 | import { appRoutes, appRoutingProviders } from './app.routes'; |
|---|
| 26 | 28 | import { requestOptionsProvider, requestBackendProvider } from './common/default.requests.options'; |
|---|
| 27 | 29 | import { LocaleServiceModule } from './common/i18n'; |
|---|
| 30 | +import { SeCurisSession } from './common/session'; |
|---|
| 28 | 31 | import { PackFormComponent } from "./forms/pack.form.component"; |
|---|
| 29 | 32 | |
|---|
| 30 | 33 | @NgModule({ |
|---|
| .. | .. |
|---|
| 48 | 51 | PackListComponent, |
|---|
| 49 | 52 | PackFormComponent, |
|---|
| 50 | 53 | LoginFormComponent, |
|---|
| 54 | + ErrorCheckerComponent, |
|---|
| 55 | + I18nDirective, |
|---|
| 51 | 56 | AppHomeComponent |
|---|
| 52 | 57 | ], |
|---|
| 53 | 58 | bootstrap: [ AppHomeComponent ], |
|---|
| 54 | 59 | entryComponents: [ PackFormComponent ], |
|---|
| 55 | 60 | providers: [ |
|---|
| 61 | + SeCurisSession, |
|---|
| 56 | 62 | UserService, |
|---|
| 57 | 63 | PacksService, |
|---|
| 58 | 64 | LicensesService, |
|---|
| .. | .. |
|---|
| 31 | 31 | |
|---|
| 32 | 32 | } |
|---|
| 33 | 33 | } |
|---|
| 34 | | - |
|---|
| 34 | + |
|---|
| 35 | 35 | @Injectable() |
|---|
| 36 | 36 | export class ApiXHRBackend extends XHRBackend { |
|---|
| 37 | 37 | |
|---|
| .. | .. |
|---|
| 40 | 40 | } |
|---|
| 41 | 41 | |
|---|
| 42 | 42 | createConnection(request: Request): XHRConnection { |
|---|
| 43 | | - if (!request.url.endsWith('.js') && !request.url.endsWith('.html') && !request.url.endsWith('.svg')){ |
|---|
| 43 | + if (!request.url.endsWith('.js') && !request.url.endsWith('.json') && !request.url.endsWith('.html') && !request.url.endsWith('.svg')){ |
|---|
| 44 | 44 | request.url = 'http://localhost:8080/securis/' + request.url; // prefix base url |
|---|
| 45 | 45 | } |
|---|
| 46 | 46 | return super.createConnection(request); |
|---|
| .. | .. |
|---|
| 1 | +import { Http } from '@angular/http'; |
|---|
| 2 | +import { PacksService } from '../resources/packs'; |
|---|
| 3 | +import { LocaleService } from '../common/i18n'; |
|---|
| 4 | +import { TdDataTableService, TdDataTableSortingOrder, ITdDataTableSortChangeEvent, ITdDataTableColumn } from '@covalent/core'; |
|---|
| 5 | +import { IPageChangeEvent } from '@covalent/core'; |
|---|
| 6 | +import { Component, Input, AfterViewInit } from '@angular/core'; |
|---|
| 7 | +import { TdMediaService } from '@covalent/core'; |
|---|
| 8 | + |
|---|
| 9 | +@Component({ |
|---|
| 10 | + selector: 'error-checker', |
|---|
| 11 | + template: ` |
|---|
| 12 | + <div *ngIf="formField?.touched && formField.invalid" layout="column"> |
|---|
| 13 | + <span *ngFor="let err of getFieldErrors()" align="end">{{err}}</span> |
|---|
| 14 | + </div>` |
|---|
| 15 | +}) |
|---|
| 16 | +export class ErrorCheckerComponent { |
|---|
| 17 | + |
|---|
| 18 | + @Input() formField: any; |
|---|
| 19 | + @Input() fieldName: string; |
|---|
| 20 | + |
|---|
| 21 | + constructor(private $L: LocaleService) { |
|---|
| 22 | + console.log('contructor: ' + this.formField); |
|---|
| 23 | + } |
|---|
| 24 | + |
|---|
| 25 | + getFieldErrors() : string[] { |
|---|
| 26 | + if (this.formField.valid) { |
|---|
| 27 | + return [] |
|---|
| 28 | + } else { |
|---|
| 29 | + return (<string[]>Object.keys(this.formField.errors)).map((err:string) => this.getErrorMsg(err)); |
|---|
| 30 | + } |
|---|
| 31 | + } |
|---|
| 32 | + |
|---|
| 33 | + private updateFieldErrors() { |
|---|
| 34 | + } |
|---|
| 35 | + |
|---|
| 36 | + private getErrorMsg(err: string) : string{ |
|---|
| 37 | + switch(err) { |
|---|
| 38 | + case 'required': { |
|---|
| 39 | + return this.fieldName + ' '+ this.$L.get('is required'); |
|---|
| 40 | + } |
|---|
| 41 | + case 'number': { |
|---|
| 42 | + return this.fieldName + ' '+ this.$L.get('should be a number'); |
|---|
| 43 | + } |
|---|
| 44 | + default: { |
|---|
| 45 | + return this.fieldName + ' '+ this.$L.get('unknown error') + ' ' + err; |
|---|
| 46 | + } |
|---|
| 47 | + } |
|---|
| 48 | + } |
|---|
| 49 | + |
|---|
| 50 | + log(obj: any) { |
|---|
| 51 | + console.log(obj) |
|---|
| 52 | + } |
|---|
| 53 | + |
|---|
| 54 | +} |
|---|
| 55 | + |
|---|
| .. | .. |
|---|
| 5 | 5 | // Use as reference: https://github.com/ngx-translate/core/tree/master/src |
|---|
| 6 | 6 | @Injectable() |
|---|
| 7 | 7 | export class LocaleService { |
|---|
| 8 | | - get URL_TPL() {return 'src/lang/messages-{0}.json'}; |
|---|
| 8 | + get URL_TPL() {return 'src/lang/messages_{0}.json'}; |
|---|
| 9 | 9 | |
|---|
| 10 | + private _devLang : string = 'en'; |
|---|
| 10 | 11 | private _currentLang : string = null; |
|---|
| 11 | 12 | private _messages : any = null; |
|---|
| 12 | 13 | private _elements = new Array<ElementRef>(); |
|---|
| 13 | 14 | private constructor(private http: Http, @Inject('INITIAL_LANG') initLang: string) { |
|---|
| 14 | | - this._currentLang = initLang || this.getBrowserLang(); |
|---|
| 15 | + this.lang = initLang || this.getBrowserLang(); |
|---|
| 15 | 16 | } |
|---|
| 16 | 17 | |
|---|
| 17 | 18 | get lang() : string { |
|---|
| .. | .. |
|---|
| 21 | 22 | set lang(newLang: string) { |
|---|
| 22 | 23 | this._currentLang = newLang; |
|---|
| 23 | 24 | this.http.get(this._format(this.URL_TPL, newLang)).subscribe((data) => { |
|---|
| 24 | | - this._messages = data; |
|---|
| 25 | + this._messages = data.json(); |
|---|
| 25 | 26 | this.reloadTexts(); |
|---|
| 26 | 27 | }); |
|---|
| 27 | 28 | } |
|---|
| .. | .. |
|---|
| 48 | 49 | /** |
|---|
| 49 | 50 | * It works similar to MessageFormat in Java |
|---|
| 50 | 51 | */ |
|---|
| 51 | | - _format(str: string, ...params: Array<string>) { |
|---|
| 52 | + _format(str: string, ...params: string[]) { |
|---|
| 52 | 53 | |
|---|
| 53 | 54 | return str.replace(/\{(\d+)\}/g, function(match, index) { |
|---|
| 54 | 55 | return params[index]; |
|---|
| .. | .. |
|---|
| 78 | 79 | * $L.get('hello'); // This returns "hola" |
|---|
| 79 | 80 | * $L.get('Hello {0}!!', 'John'); // This returns: "Hola John!!" if language is spanish |
|---|
| 80 | 81 | */ |
|---|
| 81 | | - get(msg: string) : string { |
|---|
| 82 | + get(msg: string, ...params: string[] ) : string { |
|---|
| 82 | 83 | if (msg == null) { |
|---|
| 83 | 84 | return ''; |
|---|
| 84 | 85 | } |
|---|
| .. | .. |
|---|
| 90 | 91 | trans_msg = this._messages[msg]; |
|---|
| 91 | 92 | } else if (this._messages[msg.toLowerCase()]) { |
|---|
| 92 | 93 | trans_msg = this._messages[msg.toLowerCase()]; |
|---|
| 93 | | - } else { |
|---|
| 94 | | - this._currentLang !== 'es' && console.error("Missing i18 key: " + msg); |
|---|
| 94 | + } else { |
|---|
| 95 | + (this._currentLang !== this._devLang) && console.error("Missing i18 key: " + msg); |
|---|
| 95 | 96 | trans_msg = msg; |
|---|
| 96 | 97 | } |
|---|
| 97 | 98 | } |
|---|
| 98 | 99 | // Enviar evento cuando el idioma cambia al $rootScope |
|---|
| 99 | 100 | |
|---|
| 100 | 101 | if (arguments.length === 1) return trans_msg; |
|---|
| 101 | | - var params = Array.prototype.slice.call(arguments, 1); |
|---|
| 102 | | - return this._format.apply(trans_msg, params); |
|---|
| 102 | + return this._format(trans_msg, ...params); |
|---|
| 103 | 103 | } |
|---|
| 104 | 104 | |
|---|
| 105 | 105 | } |
|---|
| .. | .. |
|---|
| 108 | 108 | @Directive({ selector: '[i18n]' }) |
|---|
| 109 | 109 | export class I18nDirective { |
|---|
| 110 | 110 | constructor(private el: ElementRef, private renderer: Renderer, private $L: LocaleService) { |
|---|
| 111 | + console.log(el); |
|---|
| 111 | 112 | } |
|---|
| 112 | 113 | |
|---|
| 113 | 114 | ngAfterViewChecked() { |
|---|
| .. | .. |
|---|
| 124 | 125 | }) |
|---|
| 125 | 126 | export class LocaleServiceModule { |
|---|
| 126 | 127 | static withConfig(initLang?: string): ModuleWithProviders { |
|---|
| 127 | | - console.log('Init lang with ' + initLang); |
|---|
| 128 | 128 | return { |
|---|
| 129 | 129 | ngModule: LocaleServiceModule, |
|---|
| 130 | 130 | providers: [ |
|---|
| .. | .. |
|---|
| 1 | +import { LocalStorageService } from 'angular-2-local-storage'; |
|---|
| 2 | +import { Injectable } from '@angular/core'; |
|---|
| 3 | + |
|---|
| 4 | + |
|---|
| 5 | +@Injectable() |
|---|
| 6 | +export class SeCurisSession { |
|---|
| 7 | + |
|---|
| 8 | + sessionData: any = {} |
|---|
| 9 | + |
|---|
| 10 | + constructor(private store: LocalStorageService) { |
|---|
| 11 | + |
|---|
| 12 | + } |
|---|
| 13 | + |
|---|
| 14 | + public get(key: string): any { |
|---|
| 15 | + return this.sessionData[key]; |
|---|
| 16 | + } |
|---|
| 17 | + |
|---|
| 18 | + public exists(key: string): boolean { |
|---|
| 19 | + return this.sessionData[key] != undefined; |
|---|
| 20 | + } |
|---|
| 21 | + |
|---|
| 22 | + public set(key: string, value: any): void { |
|---|
| 23 | + this.sessionData[key] = value; |
|---|
| 24 | + } |
|---|
| 25 | + |
|---|
| 26 | + public remove(key: string) : void { |
|---|
| 27 | + delete this.sessionData[key]; |
|---|
| 28 | + } |
|---|
| 29 | +} |
|---|
| 30 | + |
|---|
| .. | .. |
|---|
| 1 | +import { Http } from '@angular/http'; |
|---|
| 2 | +import { LicensesService } from '../resources/licenses'; |
|---|
| 3 | +import { LocaleService } from '../common/i18n'; |
|---|
| 4 | +import { TdDataTableService, TdDataTableSortingOrder, ITdDataTableSortChangeEvent, ITdDataTableColumn } from '@covalent/core'; |
|---|
| 5 | +import { IPageChangeEvent } from '@covalent/core'; |
|---|
| 6 | +import { Component, AfterViewInit } from '@angular/core'; |
|---|
| 7 | +import { TdMediaService } from '@covalent/core'; |
|---|
| 8 | +import { IComboOption } from './base'; |
|---|
| 9 | + |
|---|
| 10 | +@Component({ |
|---|
| 11 | + selector: 'license-form', |
|---|
| 12 | + templateUrl: 'src/app/forms/license.form.html' |
|---|
| 13 | +}) |
|---|
| 14 | +export class LicenseFormComponent implements AfterViewInit { |
|---|
| 15 | + |
|---|
| 16 | + form_title: string = 'Title'; |
|---|
| 17 | + form_subtitle: string = ''; |
|---|
| 18 | + data: any = {}; |
|---|
| 19 | + isNew : boolean = true; |
|---|
| 20 | + |
|---|
| 21 | + constructor(private http: Http, |
|---|
| 22 | + private packs: LicensesService, |
|---|
| 23 | + private $L: LocaleService) { |
|---|
| 24 | + |
|---|
| 25 | + } |
|---|
| 26 | + |
|---|
| 27 | + private loadCombos(): void { |
|---|
| 28 | + /* |
|---|
| 29 | + this.http.get('organization') |
|---|
| 30 | + .map(response => response.json().map((org : any) => <IComboOption>{id: org.id, label: `(${org.code}) ${org.name}`})) |
|---|
| 31 | + .subscribe( |
|---|
| 32 | + data => this.organizations = (<IComboOption[]>data).sort((e1, e2) => e1.label.localeCompare(e2.label)), |
|---|
| 33 | + err => console.error('Error loading orgs') |
|---|
| 34 | + ); |
|---|
| 35 | + */ |
|---|
| 36 | + } |
|---|
| 37 | + |
|---|
| 38 | + log(obj: any) { |
|---|
| 39 | + console.log(obj) |
|---|
| 40 | + } |
|---|
| 41 | + |
|---|
| 42 | + ngOnInit(): void { |
|---|
| 43 | + this.loadCombos(); |
|---|
| 44 | + this.data = {}; |
|---|
| 45 | + this.form_title = this.$L.get('License data'); |
|---|
| 46 | + this.form_subtitle = this.$L.get(this.isNew ? 'Create a new license': 'Modify the license data') ; |
|---|
| 47 | + } |
|---|
| 48 | + |
|---|
| 49 | + |
|---|
| 50 | + ngAfterViewInit(): void { |
|---|
| 51 | + } |
|---|
| 52 | +} |
|---|
| 53 | + |
|---|
| .. | .. |
|---|
| 1 | +<form #packForm="ngForm" class="inset" (keyup.enter)="save()"> |
|---|
| 2 | + <md-card> |
|---|
| 3 | + <md-card-title> |
|---|
| 4 | + {{form_title}} |
|---|
| 5 | + </md-card-title> |
|---|
| 6 | + <md-card-subtitle> |
|---|
| 7 | + {{form_subtitle}} |
|---|
| 8 | + </md-card-subtitle> |
|---|
| 9 | +<md-divider></md-divider> |
|---|
| 10 | + <md-card-content> |
|---|
| 11 | + <div layout="column" layout-align="start center" layout-fill> |
|---|
| 12 | + <div layout="row" layout-fill layout-padding> |
|---|
| 13 | + <div layout="column" layout-fill flex="50"> |
|---|
| 14 | + <md-input-container> |
|---|
| 15 | + <input mdInput maxLength="50" type="text" [(ngModel)]="data.code" name="code" required /> |
|---|
| 16 | + <md-placeholder> |
|---|
| 17 | + <span i18n>Code</span> |
|---|
| 18 | + </md-placeholder> |
|---|
| 19 | + </md-input-container> |
|---|
| 20 | + {{log(packForm.controls)}} |
|---|
| 21 | + <div *ngIf="packForm.controls.code?.touched && packForm.controls.code.invalid" layout="column"> |
|---|
| 22 | + <span *ngIf="packForm.controls.code.errors.required" align="end">Code is required</span> |
|---|
| 23 | + <span align="end">Code is ok</span> |
|---|
| 24 | + </div> |
|---|
| 25 | + </div> |
|---|
| 26 | + <!-- TODO: <div class="alert inline-alert alert-warning" ng-show="packForm.code.$invalid"> |
|---|
| 27 | + <span class="glyphicon glyphicon-warning-sign"></span> |
|---|
| 28 | + <span ng-show="packForm.code.$error.maxlength" ng-bind="maxLengthErrorMsg('Code', maxlength.code)" |
|---|
| 29 | + class="ng-binding ng-hide">Code length is too long (max: 50).</span> |
|---|
| 30 | + <span ng-show="packForm.code.$error.required" ng-bind="mandatoryFieldErrorMsg('Code')" class="ng-binding">'Code' is required.</span> |
|---|
| 31 | + </div> --> |
|---|
| 32 | + <md-input-container flex="50"> |
|---|
| 33 | + <input mdInput type="number" type="text" [(ngModel)]="data.num_licenses" name="num_licenses" required /> |
|---|
| 34 | + <md-placeholder> |
|---|
| 35 | + <span i18n>Num. licenses</span> |
|---|
| 36 | + </md-placeholder> |
|---|
| 37 | + </md-input-container> |
|---|
| 38 | + </div> |
|---|
| 39 | + <div layout="row" layout-align="start center" layout-fill layout-padding> |
|---|
| 40 | + <md-input-container flex> |
|---|
| 41 | + <input mdInput type="date" type="text" [(ngModel)]="data.init_valid_date" name="init_valid_date" required /> |
|---|
| 42 | + <md-placeholder> |
|---|
| 43 | + <span i18n>Initial date</span> |
|---|
| 44 | + </md-placeholder> |
|---|
| 45 | + <md-hint align="end">YYYY-MM-DD</md-hint> |
|---|
| 46 | + </md-input-container> |
|---|
| 47 | + <md-input-container flex> |
|---|
| 48 | + <input mdInput type="date" type="text" [(ngModel)]="data.end_valid_date" name="end_valid_date" required /> |
|---|
| 49 | + <md-placeholder> |
|---|
| 50 | + <span i18n>End date</span> |
|---|
| 51 | + </md-placeholder> |
|---|
| 52 | + <md-hint align="end">YYYY-MM-DD</md-hint> |
|---|
| 53 | + </md-input-container> |
|---|
| 54 | + </div> |
|---|
| 55 | + <div layout="row" layout-fill layout-padding> |
|---|
| 56 | + <md-select flex placeholder="Organization" [(ngModel)]="data.organization_id" name="organization_id"> |
|---|
| 57 | + <md-option *ngFor="let org of organizations" [value]="org.id"> |
|---|
| 58 | + {{org.label}} |
|---|
| 59 | + </md-option> |
|---|
| 60 | + </md-select> |
|---|
| 61 | + <md-select flex placeholder="License type" [(ngModel)]="data.license_type_id" name="license_type_id"> |
|---|
| 62 | + <md-option *ngFor="let lt of licensetypes" [value]="lt.id"> |
|---|
| 63 | + {{lt.label}} |
|---|
| 64 | + </md-option> |
|---|
| 65 | + </md-select> |
|---|
| 66 | + </div> |
|---|
| 67 | + </div> |
|---|
| 68 | +</md-card-content> |
|---|
| 69 | +<md-divider></md-divider> |
|---|
| 70 | +<md-card-actions> |
|---|
| 71 | + <button [disabled]="!packForm.form.valid" md-raised-button color="primary" (click)="save()">Save</button> |
|---|
| 72 | + <button md-button md-dialog-close>Cancel</button> |
|---|
| 73 | +</md-card-actions> |
|---|
| 74 | +</md-card> |
|---|
| 75 | +</form> |
|---|
| .. | .. |
|---|
| 1 | 1 | import { Http } from '@angular/http'; |
|---|
| 2 | +import { ToastsManager } from 'ng2-toastr/ng2-toastr'; |
|---|
| 3 | + |
|---|
| 2 | 4 | import { PacksService } from '../resources/packs'; |
|---|
| 5 | +import { LicenseTypesService } from '../resources/license_types'; |
|---|
| 3 | 6 | import { LocaleService } from '../common/i18n'; |
|---|
| 4 | 7 | import { TdDataTableService, TdDataTableSortingOrder, ITdDataTableSortChangeEvent, ITdDataTableColumn } from '@covalent/core'; |
|---|
| 5 | 8 | import { IPageChangeEvent } from '@covalent/core'; |
|---|
| 6 | 9 | import { Component, AfterViewInit } from '@angular/core'; |
|---|
| 7 | 10 | import { TdMediaService } from '@covalent/core'; |
|---|
| 8 | 11 | import { IComboOption } from './base'; |
|---|
| 12 | + |
|---|
| 13 | + |
|---|
| 9 | 14 | |
|---|
| 10 | 15 | @Component({ |
|---|
| 11 | 16 | selector: 'pack-form', |
|---|
| .. | .. |
|---|
| 19 | 24 | licensetypes : IComboOption[]; |
|---|
| 20 | 25 | data: any = {}; |
|---|
| 21 | 26 | isNew : boolean = true; |
|---|
| 22 | | - |
|---|
| 27 | + fields: any = { |
|---|
| 28 | + 'code': '', |
|---|
| 29 | + 'num_licenses': '', |
|---|
| 30 | + 'init_valid_date': '', |
|---|
| 31 | + 'end_valid_date': '', |
|---|
| 32 | + 'license_preactivation': '', |
|---|
| 33 | + 'license_type_id': '', |
|---|
| 34 | + 'organization_id': '', |
|---|
| 35 | + 'licensetype_code': '', |
|---|
| 36 | + 'organization_name': '', |
|---|
| 37 | + 'preactivation_valid_period': '', |
|---|
| 38 | + 'renew_valid_period': '', |
|---|
| 39 | + 'application_name': '', |
|---|
| 40 | + 'status': '', |
|---|
| 41 | + 'metadata': '', |
|---|
| 42 | + 'comments': '', |
|---|
| 43 | + 'key': '', |
|---|
| 44 | + 'value': '', |
|---|
| 45 | + } |
|---|
| 23 | 46 | constructor(private http: Http, |
|---|
| 47 | + private toaster: ToastsManager, |
|---|
| 48 | + private licenseTypes: LicenseTypesService, |
|---|
| 24 | 49 | private packs: PacksService, |
|---|
| 25 | 50 | private $L: LocaleService) { |
|---|
| 26 | | - |
|---|
| 51 | + Object.keys(this.fields).forEach(k => this.fields[k] = $L.get(`field.${k}`)); |
|---|
| 52 | + } |
|---|
| 53 | + |
|---|
| 54 | + public getFieldName(fieldId: string) : string { |
|---|
| 55 | + return this.fields[fieldId]; |
|---|
| 27 | 56 | } |
|---|
| 28 | 57 | |
|---|
| 29 | 58 | private loadCombos(): void { |
|---|
| .. | .. |
|---|
| 33 | 62 | data => this.organizations = (<IComboOption[]>data).sort((e1, e2) => e1.label.localeCompare(e2.label)), |
|---|
| 34 | 63 | err => console.error('Error loading orgs') |
|---|
| 35 | 64 | ); |
|---|
| 36 | | - this.http.get('licensetype') |
|---|
| 37 | | - .map(response => response.json().map((lt : any) => <IComboOption>{id: lt.id, label: `(${lt.code}) ${lt.name}`})) |
|---|
| 65 | + this.licenseTypes.get() |
|---|
| 66 | + .map(list => list.map((lt : any) => <IComboOption>{id: lt.id, label: `(${lt.code}) ${lt.name}`})) |
|---|
| 38 | 67 | .subscribe( |
|---|
| 39 | 68 | data => this.licensetypes = (<IComboOption[]>data).sort((e1, e2) => e1.label.localeCompare(e2.label)), |
|---|
| 40 | 69 | err => console.error('Error loading license types') |
|---|
| 41 | 70 | ); |
|---|
| 42 | 71 | } |
|---|
| 43 | 72 | |
|---|
| 44 | | - log(obj: any) { |
|---|
| 45 | | - console.log(obj) |
|---|
| 73 | + save() { |
|---|
| 74 | + var command = this.isNew ? this.packs.create(this.data) : this.packs.modify(this.data.id, this.data); |
|---|
| 75 | + command.subscribe( |
|---|
| 76 | + data => this.toaster.success(this.$L.get('Pack saved sucessfully')), |
|---|
| 77 | + err => { |
|---|
| 78 | + console.error(err); |
|---|
| 79 | + this.toaster.success(this.$L.get('Error saving pack')); |
|---|
| 80 | + } |
|---|
| 81 | + ); |
|---|
| 46 | 82 | } |
|---|
| 83 | + |
|---|
| 84 | + changeLicType(event) { |
|---|
| 85 | + this.licenseTypes.get(this.data.license_type_id) |
|---|
| 86 | + .map(lt_data => lt_data.metadata) |
|---|
| 87 | + .subscribe( |
|---|
| 88 | + metadata => this.data.metadata = metadata, |
|---|
| 89 | + err => { |
|---|
| 90 | + console.error('Error loading license type metadata'); |
|---|
| 91 | + console.error(err); |
|---|
| 92 | + } |
|---|
| 93 | + ); |
|---|
| 94 | + } |
|---|
| 95 | + |
|---|
| 96 | + changeOrg(event) { |
|---|
| 97 | + console.log(event); |
|---|
| 98 | + console.log(this.data.organization_id); |
|---|
| 99 | + } |
|---|
| 47 | 100 | |
|---|
| 48 | 101 | ngOnInit(): void { |
|---|
| 49 | 102 | this.loadCombos(); |
|---|
| 50 | | - this.data = {}; |
|---|
| 103 | + // this.data = {}; |
|---|
| 51 | 104 | this.form_title = this.$L.get('Pack data'); |
|---|
| 52 | | - this.form_subtitle = this.$L.get('Create a new licenses pack'); |
|---|
| 105 | + this.form_subtitle = this.$L.get(this.isNew ? 'Create a new licenses pack': 'Modify the licenses pack data') ; |
|---|
| 53 | 106 | } |
|---|
| 54 | 107 | |
|---|
| 55 | 108 | |
|---|
| .. | .. |
|---|
| 1 | | -<form #packForm="ngForm" class="inset" (keyup.enter)="save()"> |
|---|
| 2 | | - <md-card> |
|---|
| 3 | | - <md-card-title> |
|---|
| 4 | | - {{form_title}} |
|---|
| 5 | | - </md-card-title> |
|---|
| 6 | | - <md-card-subtitle> |
|---|
| 7 | | - {{form_subtitle}} |
|---|
| 8 | | - </md-card-subtitle> |
|---|
| 1 | +<md-toolbar> |
|---|
| 2 | + <span md-dialog-title>{{form_title}}</span> |
|---|
| 3 | + <span flex></span> |
|---|
| 4 | + <button md-icon-button (click)="save()"><md-icon>save</md-icon></button> |
|---|
| 5 | + <button md-icon-button md-dialog-close><md-icon>close</md-icon></button> |
|---|
| 6 | +</md-toolbar> |
|---|
| 7 | +<p class="md-subhead">{{form_subtitle}}</p> |
|---|
| 9 | 8 | <md-divider></md-divider> |
|---|
| 10 | | - <md-card-content> |
|---|
| 11 | | - <div layout="column" layout-align="start center" layout-fill> |
|---|
| 9 | +<form #packForm="ngForm" class="inset" > |
|---|
| 10 | +<div layout="column" > |
|---|
| 11 | +<md-dialog-content> |
|---|
| 12 | + <div layout="column" layout-align="start center"> |
|---|
| 12 | 13 | <div layout="row" layout-fill layout-padding> |
|---|
| 13 | | - <div layout="column" layout-fill flex="50"> |
|---|
| 14 | | - <md-input-container> |
|---|
| 15 | | - <input mdInput maxLength="50" type="text" [(ngModel)]="data.code" name="code" required /> |
|---|
| 16 | | - <md-placeholder> |
|---|
| 17 | | - <span i18n>Code</span> |
|---|
| 18 | | - </md-placeholder> |
|---|
| 19 | | - </md-input-container> |
|---|
| 20 | | - {{log(packForm.controls)}} |
|---|
| 21 | | - <div *ngIf="packForm.controls.code?.touched && packForm.controls.code.invalid" layout="column"> |
|---|
| 22 | | - <span *ngIf="packForm.controls.code.errors.required" align="end">Code is required</span> |
|---|
| 23 | | - <span align="end">Code is ok</span> |
|---|
| 14 | + <div layout="column" layout-fill flex="15" *ngIf="!isNew"> |
|---|
| 15 | + <md-input-container> |
|---|
| 16 | + <input mdInput maxLength="50" type="text" [(ngModel)]="data.id" name="id" required [readonly]="!isNew" /> |
|---|
| 17 | + <md-placeholder> |
|---|
| 18 | + <span i18n="field.id"></span> |
|---|
| 19 | + </md-placeholder> |
|---|
| 20 | + </md-input-container> |
|---|
| 24 | 21 | </div> |
|---|
| 22 | + <div layout="column" layout-fill flex> |
|---|
| 23 | + <md-input-container> |
|---|
| 24 | + <input mdInput maxLength="50" type="text" [(ngModel)]="data.code" name="code" required [readonly]="!isNew" /> |
|---|
| 25 | + <md-placeholder> |
|---|
| 26 | + <span i18n="field.code"></span> |
|---|
| 27 | + </md-placeholder> |
|---|
| 28 | + </md-input-container> |
|---|
| 29 | + <error-checker [fieldName]="getFieldName('code')" [formField]="packForm.controls.code"></error-checker> |
|---|
| 25 | 30 | </div> |
|---|
| 26 | | - <!-- TODO: <div class="alert inline-alert alert-warning" ng-show="packForm.code.$invalid"> |
|---|
| 27 | | - <span class="glyphicon glyphicon-warning-sign"></span> |
|---|
| 28 | | - <span ng-show="packForm.code.$error.maxlength" ng-bind="maxLengthErrorMsg('Code', maxlength.code)" |
|---|
| 29 | | - class="ng-binding ng-hide">Code length is too long (max: 50).</span> |
|---|
| 30 | | - <span ng-show="packForm.code.$error.required" ng-bind="mandatoryFieldErrorMsg('Code')" class="ng-binding">'Code' is required.</span> |
|---|
| 31 | | - </div> --> |
|---|
| 32 | | - <md-input-container flex="50"> |
|---|
| 33 | | - <input mdInput type="number" type="text" [(ngModel)]="data.num_licenses" name="num_licenses" required /> |
|---|
| 34 | | - <md-placeholder> |
|---|
| 35 | | - <span i18n>Num. licenses</span> |
|---|
| 36 | | - </md-placeholder> |
|---|
| 37 | | - </md-input-container> |
|---|
| 38 | | - </div> |
|---|
| 39 | | - <div layout="row" layout-align="start center" layout-fill layout-padding> |
|---|
| 40 | | - <md-input-container flex> |
|---|
| 41 | | - <input mdInput type="date" type="text" [(ngModel)]="data.init_valid_date" name="init_valid_date" required /> |
|---|
| 42 | | - <md-placeholder> |
|---|
| 43 | | - <span i18n>Initial date</span> |
|---|
| 44 | | - </md-placeholder> |
|---|
| 45 | | - <md-hint align="end">YYYY-MM-DD</md-hint> |
|---|
| 46 | | - </md-input-container> |
|---|
| 47 | | - <md-input-container flex> |
|---|
| 48 | | - <input mdInput type="date" type="text" [(ngModel)]="data.end_valid_date" name="end_valid_date" required /> |
|---|
| 49 | | - <md-placeholder> |
|---|
| 50 | | - <span i18n>End date</span> |
|---|
| 51 | | - </md-placeholder> |
|---|
| 52 | | - <md-hint align="end">YYYY-MM-DD</md-hint> |
|---|
| 53 | | - </md-input-container> |
|---|
| 31 | + <div layout="column" layout-fill flex> |
|---|
| 32 | + <md-input-container> |
|---|
| 33 | + <input mdInput type="number" [(ngModel)]="data.num_licenses" name="num_licenses" required /> |
|---|
| 34 | + <md-placeholder> |
|---|
| 35 | + <span i18n="field.num_licenses"></span> |
|---|
| 36 | + </md-placeholder> |
|---|
| 37 | + </md-input-container> |
|---|
| 38 | + <error-checker [fieldName]="getFieldName('num_licenses')" [formField]="packForm.controls.num_licenses"></error-checker> |
|---|
| 39 | + </div> |
|---|
| 54 | 40 | </div> |
|---|
| 55 | 41 | <div layout="row" layout-fill layout-padding> |
|---|
| 56 | | - <md-select flex placeholder="Organization" [(ngModel)]="data.organization_id" name="organization_id"> |
|---|
| 57 | | - <md-option *ngFor="let org of organizations" [value]="org.id"> |
|---|
| 58 | | - {{org.label}} |
|---|
| 59 | | - </md-option> |
|---|
| 60 | | - </md-select> |
|---|
| 61 | | - <md-select flex placeholder="License type" [(ngModel)]="data.license_type_id" name="license_type_id"> |
|---|
| 62 | | - <md-option *ngFor="let lt of licensetypes" [value]="lt.id"> |
|---|
| 63 | | - {{lt.label}} |
|---|
| 64 | | - </md-option> |
|---|
| 65 | | - </md-select> |
|---|
| 42 | + <div layout="column" layout-fill flex> |
|---|
| 43 | + <md-input-container flex> |
|---|
| 44 | + <input mdInput type="date" [(ngModel)]="data.init_valid_date" name="init_valid_date" required /> |
|---|
| 45 | + <md-placeholder> |
|---|
| 46 | + <span i18n="field.end_valid_date"></span> |
|---|
| 47 | + </md-placeholder> |
|---|
| 48 | + </md-input-container> |
|---|
| 49 | + <error-checker [fieldName]="getFieldName('init_valid_date')" [formField]="packForm.controls.init_valid_date"></error-checker> |
|---|
| 50 | + </div> |
|---|
| 51 | + <div layout="column" layout-fill flex> |
|---|
| 52 | + <md-input-container flex> |
|---|
| 53 | + <input mdInput type="date" [(ngModel)]="data.end_valid_date" name="end_valid_date" required /> |
|---|
| 54 | + <md-placeholder> |
|---|
| 55 | + <span i18n="field.end_valid_date"></span> |
|---|
| 56 | + </md-placeholder> |
|---|
| 57 | + </md-input-container> |
|---|
| 58 | + <error-checker [fieldName]="getFieldName('end_valid_date')" [formField]="packForm.controls.end_valid_date"></error-checker> |
|---|
| 59 | + </div> |
|---|
| 60 | + </div> |
|---|
| 61 | + <div layout="row" layout-fill layout-padding *ngIf="isNew"> |
|---|
| 62 | + <div layout="column" layout-fill flex> |
|---|
| 63 | + <md-select [placeholder]="getFieldName('organization_id')" flex [(ngModel)]="data.organization_id" name="organization_id" (change)="changeOrg($event)"> |
|---|
| 64 | + <md-option *ngFor="let org of organizations" [value]="org.id"> |
|---|
| 65 | + {{org.label}} |
|---|
| 66 | + </md-option> |
|---|
| 67 | + </md-select> |
|---|
| 68 | + <error-checker [fieldName]="getFieldName('organization_id')" [formField]="packForm.controls.organization_id"></error-checker> |
|---|
| 69 | + </div> |
|---|
| 70 | + <div layout="column" layout-fill flex> |
|---|
| 71 | + <md-select flex [placeholder]="getFieldName('license_type_id')" [(ngModel)]="data.license_type_id" name="license_type_id" (change)="changeLicType($event)"> |
|---|
| 72 | + <md-option *ngFor="let lt of licensetypes" [value]="lt.id"> |
|---|
| 73 | + {{lt.label}} |
|---|
| 74 | + </md-option> |
|---|
| 75 | + </md-select> |
|---|
| 76 | + <error-checker [fieldName]="getFieldName('license_type_id')" [formField]="packForm.controls.license_type_id"></error-checker> |
|---|
| 77 | + </div> |
|---|
| 78 | + </div> |
|---|
| 79 | + <div layout="row" layout-fill layout-padding *ngIf="!isNew"> |
|---|
| 80 | + <div layout="column" layout-fill flex> |
|---|
| 81 | + <div layout="column" class="mat-input-container" flex> |
|---|
| 82 | + <label class="mat-input-placeholder mat-float"> |
|---|
| 83 | + <span class="placeholder" i18n="field.organization_id"></span> |
|---|
| 84 | + </label> |
|---|
| 85 | + <div class="label-value mat-input-element">{{data.organization_name}}</div> |
|---|
| 86 | + </div> |
|---|
| 87 | + </div> |
|---|
| 88 | + <div layout="column" layout-fill flex> |
|---|
| 89 | + <div layout="column" class="mat-input-container" flex> |
|---|
| 90 | + <label class="mat-input-placeholder mat-float"> |
|---|
| 91 | + <span class="placeholder" i18n="field.license_type_id"></span> |
|---|
| 92 | + </label> |
|---|
| 93 | + <div class="label-value mat-input-element">{{data.licensetype_code}}</div> |
|---|
| 94 | + </div> |
|---|
| 95 | + </div> |
|---|
| 96 | + </div> |
|---|
| 97 | + <div layout="row" layout-fill layout-padding > |
|---|
| 98 | + <div layout="column" layout-fill flex> |
|---|
| 99 | + <md-input-container flex> |
|---|
| 100 | + <input mdInput type="number" [(ngModel)]="data.preactivation_valid_period" name="preactivation_valid_period" required /> |
|---|
| 101 | + <md-placeholder> |
|---|
| 102 | + <span i18n="field.preactivation_valid_period"></span> |
|---|
| 103 | + </md-placeholder> |
|---|
| 104 | + <md-hint align="end">days</md-hint> |
|---|
| 105 | + </md-input-container> |
|---|
| 106 | + <error-checker [fieldName]="getFieldName('preactivation_valid_period')" [formField]="packForm.controls.preactivation_valid_period"></error-checker> |
|---|
| 107 | + </div> |
|---|
| 108 | + <div layout="column" layout-fill flex> |
|---|
| 109 | + <md-input-container flex> |
|---|
| 110 | + <input mdInput type="number"[(ngModel)]="data.renew_valid_period" name="renew_valid_period" required /> |
|---|
| 111 | + <md-placeholder> |
|---|
| 112 | + <span i18n="field.renew_valid_period"></span> |
|---|
| 113 | + </md-placeholder> |
|---|
| 114 | + <md-hint align="end">days</md-hint> |
|---|
| 115 | + </md-input-container> |
|---|
| 116 | + <error-checker [fieldName]="getFieldName('renew_valid_period')" [formField]="packForm.controls.renew_valid_period"></error-checker> |
|---|
| 117 | + </div> |
|---|
| 118 | + </div> |
|---|
| 119 | + <div layout="row" layout-fill layout-padding> |
|---|
| 120 | + <div layout="column" layout-fill flex> |
|---|
| 121 | + <md-input-container flex> |
|---|
| 122 | + <textarea mdInput type="text" type="text" [(ngModel)]="data.comments" name="comments" maxlength="1024" ></textarea> |
|---|
| 123 | + <md-placeholder> |
|---|
| 124 | + <span i18n="field.comments"></span> |
|---|
| 125 | + </md-placeholder> |
|---|
| 126 | + <md-hint align="end">(max 1024)</md-hint> |
|---|
| 127 | + </md-input-container> |
|---|
| 128 | + </div> |
|---|
| 129 | + </div> |
|---|
| 130 | + <div layout="row" layout-fill layout-padding *ngIf="!isNew"> |
|---|
| 131 | + <div layout="column" layout-fill flex> |
|---|
| 132 | + <div layout="column" class="mat-input-container" flex> |
|---|
| 133 | + <label class="mat-input-placeholder mat-float"> |
|---|
| 134 | + <span class="placeholder" i18n="field.created_by_name"></span> |
|---|
| 135 | + </label> |
|---|
| 136 | + <div class="label-value mat-input-element">{{data.created_by_name}}</div> |
|---|
| 137 | + </div> |
|---|
| 138 | + </div> |
|---|
| 139 | + <div layout="column" layout-fill flex> |
|---|
| 140 | + <div layout="column" class="mat-input-container" flex> |
|---|
| 141 | + <label class="mat-input-placeholder mat-float"> |
|---|
| 142 | + <span class="placeholder" i18n="field.creation_timestamp"></span> |
|---|
| 143 | + </label> |
|---|
| 144 | + <div class="label-value mat-input-element">{{data.creation_timestamp | date: 'medium'}}</div> |
|---|
| 145 | + </div> |
|---|
| 146 | + </div> |
|---|
| 147 | + </div> |
|---|
| 148 | + <div layout="column" layout-fill> |
|---|
| 149 | + <span class="md-title" i18n>License metadata</span> |
|---|
| 150 | + <div layout="row" layout-fill layout-padding *ngFor="let pair of data.metadata"> |
|---|
| 151 | + <md-input-container flex="40"> |
|---|
| 152 | + <input mdInput type="text" [ngModelOptions]="{standalone: true}" [(ngModel)]="pair.key" readonly /> |
|---|
| 153 | + <md-placeholder> |
|---|
| 154 | + <span i18n="field.key"></span> |
|---|
| 155 | + </md-placeholder> |
|---|
| 156 | + </md-input-container> |
|---|
| 157 | + <md-input-container flex> |
|---|
| 158 | + <input mdInput type="text" [ngModelOptions]="{standalone: true}" [(ngModel)]="pair.value" [readonly]="pair.readonly" [required]="pair.required" /> |
|---|
| 159 | + <md-placeholder> |
|---|
| 160 | + <span i18n="field.value"></span> |
|---|
| 161 | + </md-placeholder> |
|---|
| 162 | + </md-input-container> |
|---|
| 163 | + </div> |
|---|
| 66 | 164 | </div> |
|---|
| 67 | 165 | </div> |
|---|
| 68 | | -</md-card-content> |
|---|
| 166 | +</md-dialog-content> |
|---|
| 167 | +<div flex></div> |
|---|
| 69 | 168 | <md-divider></md-divider> |
|---|
| 70 | | -<md-card-actions> |
|---|
| 71 | | - <button [disabled]="!packForm.form.valid" md-raised-button color="primary" (click)="save()">Save</button> |
|---|
| 72 | | - <button md-button md-dialog-close>Cancel</button> |
|---|
| 73 | | -</md-card-actions> |
|---|
| 74 | | -</md-card> |
|---|
| 169 | +<md-dialog-actions layout="row" layout-align="end center"> |
|---|
| 170 | + <button [disabled]="!packForm.form.valid" md-raised-button color="primary" (click)="save()">Save</button> |
|---|
| 171 | + <button md-button md-dialog-close>Cancel</button> |
|---|
| 172 | +</md-dialog-actions> |
|---|
| 173 | +</div> |
|---|
| 75 | 174 | </form> |
|---|
| .. | .. |
|---|
| 1 | +<md-toolbar role="toolbar" class="mat-secondary"> |
|---|
| 2 | + <span class="push-left-sm"> |
|---|
| 3 | + <span class="md-title" i18n>License Packs</span> |
|---|
| 4 | + </span> |
|---|
| 5 | + <span class="push-left-sm" *ngIf="filteredItems < data.length"> |
|---|
| 6 | + <span class="md-body-1">{{filteredItems}} of {{data.length}} packs filtered</span> |
|---|
| 7 | + </span> |
|---|
| 8 | + <td-search-box #searchBox class="push-right-sm" placeholder="Search here" (searchDebounce)="search($event)" flex> |
|---|
| 9 | + </td-search-box> |
|---|
| 10 | + <button md-mini-fab color="accent" (click)="createPack()"> |
|---|
| 11 | + <md-icon>add</md-icon> |
|---|
| 12 | + </button> |
|---|
| 13 | +</md-toolbar> |
|---|
| 14 | +<md-divider></md-divider> |
|---|
| 15 | +<div layout="row" layout-align="center center"> |
|---|
| 16 | + <div flex="80" layout="column" layout-align="end center" > |
|---|
| 17 | +<td-data-table [data]="filteredData" [columns]="columns" style="width: 100%"> |
|---|
| 18 | + <template tdDataTableTemplate="used_licenses" let-row="row"> |
|---|
| 19 | + <div layout="row"> |
|---|
| 20 | + <td-notification-count color="secondary" [notifications]="row['num_licenses']"> |
|---|
| 21 | + </td-notification-count> |
|---|
| 22 | + <td-notification-count color="primary" [notifications]="row['num_available']"> |
|---|
| 23 | + </td-notification-count> |
|---|
| 24 | + </div> |
|---|
| 25 | + </template> |
|---|
| 26 | + <template tdDataTableTemplate="code" let-row="row" let-value="value"> |
|---|
| 27 | + <div layout="row" layout-align="start center"> |
|---|
| 28 | + <span style="white-space: nowrap">{{value}}</span> |
|---|
| 29 | + </div> |
|---|
| 30 | + </template> |
|---|
| 31 | + <template tdDataTableTemplate="menu" let-row="row" let-index="index"> |
|---|
| 32 | + <div layout="row" layout-align="end center"> |
|---|
| 33 | + <button md-icon-button (click)="editPack(row)" color="primary"><md-icon>edit</md-icon></button> |
|---|
| 34 | + <button md-icon-button [mdMenuTriggerFor]="packMenu" aria-label="Pack menu"> |
|---|
| 35 | + <md-icon>more_vert</md-icon> |
|---|
| 36 | + </button> |
|---|
| 37 | + |
|---|
| 38 | + <md-menu #packMenu="mdMenu"> |
|---|
| 39 | + <button md-menu-item *ngFor="let action of pack_menu_options" (click)="packAction(action.command, row)" [disabled]="!isActionAvailable(row)"> |
|---|
| 40 | + <md-icon *ngIf="!!action.icon">{{ action.icon }}</md-icon> {{ action.name }} |
|---|
| 41 | + </button> |
|---|
| 42 | + </md-menu> |
|---|
| 43 | + <button md-icon-button (click)="showLicenses(row)" color="accent"><md-icon>arrow_forward</md-icon></button> |
|---|
| 44 | + </div> |
|---|
| 45 | + </template> |
|---|
| 46 | +</td-data-table> |
|---|
| 47 | +<td-paging-bar #pagingBar [pageSizes]="[10, 20, 40]" [total]="filteredTotal" (change)="page($event)" align="end"> |
|---|
| 48 | + <span td-paging-bar-label hide-xs>Rows per page:</span> {{pagingBar.range}} <span hide-xs>of {{pagingBar.total}}</span> |
|---|
| 49 | +</td-paging-bar> |
|---|
| 50 | +</div> |
|---|
| 51 | +</div> |
|---|
| .. | .. |
|---|
| 1 | +import { Router } from '@angular/router'; |
|---|
| 2 | +import { MdDialog } from '@angular/material'; |
|---|
| 3 | +import { TdDataTableService, TdDataTableSortingOrder, ITdDataTableSortChangeEvent, ITdDataTableColumn } from '@covalent/core'; |
|---|
| 4 | +import { IPageChangeEvent } from '@covalent/core'; |
|---|
| 5 | +import { Component, AfterViewInit } from '@angular/core'; |
|---|
| 6 | +import { TdMediaService } from '@covalent/core'; |
|---|
| 7 | +import { LicensesService } from './resources/licenses'; |
|---|
| 8 | +import { LicenseFormComponent } from './forms/license.form.component'; |
|---|
| 9 | + |
|---|
| 10 | +var lic_example = { activation_code: '19fa8d30-29cb-4b59-81b5-3837af8204b6', |
|---|
| 11 | + code: 'CISA02-494-1', |
|---|
| 12 | + code_suffix: 1, |
|---|
| 13 | + created_by_id: '_client', |
|---|
| 14 | + creation_timestamp: 1447848747000, |
|---|
| 15 | + email: 'ccalvo@curisit.net', |
|---|
| 16 | + expiration_date: 1450440747000, |
|---|
| 17 | + full_name: 'César SA', |
|---|
| 18 | + id: 110, |
|---|
| 19 | + licenseData: '{"appCode":"CISA","appName":"CurisIntegrity SA","licenseCode":"CISA02-494-1","activationCode":"19fa8d30-29cb-4b59-81b5-3837af8204b6","expirationDate":1450440746790,"arch":"x86_64","osName":"Mac OS X","macAddresses":["60-03-08-95-AE-D0","B6-2B-33-E9-64-2D"],"crcLogo":"10f6379e0e1c00ebc403160307e3c5d0aba0727c9cae0bf1ac7cd19d84fdc80f","metadata":{"maxWellLifeLines":"50","simulationModes":"A1,A2,N1,QL"},"signature":"Tejun4bNbknxOyEmPaO/fGfGhv4URhVON/7bESxbODFWMJYKQqOPHrDiSUMlf6RbfWSVg2Dry8bY1WX881QGjTkBaHeDJKCy1EaJBwJ2nv9TYSMOiRj0eqMNYWE9/oLpvufHylAkPUpZwXVkSzTxmN+RvWa2Xt4Fu7xN+4PDHV4t7PSq7QwsFlD9ArgYC6Vx+zuL9WZANBtJ2gU/gKOE0CU0KjsB49RGQSFS/G27+H/YuDkCiQq7PC7VdVwYONQ2HO91fyPvInIrzDC5+sWHcUAqSCop//8klMy03hWl6VvAlaSP7kNM3KadyqXIJ3tx4Jwm1W+gBb3tngHzVCpYmw=="}', |
|---|
| 20 | + modification_timestamp: 1447848747000, |
|---|
| 21 | + pack_code: 'CISA02', |
|---|
| 22 | + pack_id: 18, |
|---|
| 23 | + request_data: '{"appCode":"CISA","activationCode":"19fa8d30-29cb-4b59-81b5-3837af8204b6","arch":"x86_64","osName":"Mac OS X","macAddresses":["60-03-08-95-AE-D0","B6-2B-33-E9-64-2D"],"crcLogo":"10f6379e0e1c00ebc403160307e3c5d0aba0727c9cae0bf1ac7cd19d84fdc80f"}', |
|---|
| 24 | + status: 'AC' } |
|---|
| 25 | + |
|---|
| 26 | +@Component({ |
|---|
| 27 | + selector: 'license-list', |
|---|
| 28 | + templateUrl: 'src/app/license.list.component.html' |
|---|
| 29 | +}) |
|---|
| 30 | +export class LicenseListComponent implements AfterViewInit { |
|---|
| 31 | + data: any[] = []; |
|---|
| 32 | + columns: ITdDataTableColumn[] = [ |
|---|
| 33 | + { name: 'code', label: 'Code', tooltip: 'License pack code' }, |
|---|
| 34 | + { name: 'application_name', label: 'App name' }, |
|---|
| 35 | + { name: 'licensetype_code', label: 'License type' }, |
|---|
| 36 | + { name: 'organization_name', label: 'Organization' }, |
|---|
| 37 | + { name: 'used_licenses', label: 'Lics', tooltip: 'Initial/Available pack licenses' }, |
|---|
| 38 | + { name: 'menu', label: '' } |
|---|
| 39 | + ]; |
|---|
| 40 | + |
|---|
| 41 | + filteredData: any[] = this.data; |
|---|
| 42 | + filteredTotal: number = this.data.length; |
|---|
| 43 | + |
|---|
| 44 | + searchTerm: string = ''; |
|---|
| 45 | + fromRow: number = 1; |
|---|
| 46 | + currentPage: number = 1; |
|---|
| 47 | + pageSize: number = 10; |
|---|
| 48 | + sortBy: string = 'application_name'; |
|---|
| 49 | + sortOrder: TdDataTableSortingOrder = TdDataTableSortingOrder.Descending; |
|---|
| 50 | + filteredItems = this.data.length; |
|---|
| 51 | + license_menu_options : any[] = [{ |
|---|
| 52 | + icon: 'edit', |
|---|
| 53 | + command: 'edit', |
|---|
| 54 | + name: 'Edit' |
|---|
| 55 | + },{ |
|---|
| 56 | + icon: 'cancel', |
|---|
| 57 | + command: 'cancel', |
|---|
| 58 | + name: 'Cancel' |
|---|
| 59 | + }] |
|---|
| 60 | + |
|---|
| 61 | + licenseAction(action: any) { |
|---|
| 62 | + console.log(action.command); |
|---|
| 63 | + } |
|---|
| 64 | + |
|---|
| 65 | + isActionAvailable(pack : any) : boolean { |
|---|
| 66 | + return true; |
|---|
| 67 | + } |
|---|
| 68 | + |
|---|
| 69 | + constructor(private _dataTableService: TdDataTableService, |
|---|
| 70 | + private media: TdMediaService, |
|---|
| 71 | + private router: Router, |
|---|
| 72 | + private dialog: MdDialog, |
|---|
| 73 | + private licenseForm: LicenseFormComponent, |
|---|
| 74 | + private licenses: LicensesService) { |
|---|
| 75 | + this.licenses.get().subscribe( |
|---|
| 76 | + list => { |
|---|
| 77 | + this.data = list; |
|---|
| 78 | + this.filter(); |
|---|
| 79 | + }, |
|---|
| 80 | + err => console.error(err) |
|---|
| 81 | + ); |
|---|
| 82 | + } |
|---|
| 83 | + |
|---|
| 84 | + ngOnInit(): void { |
|---|
| 85 | + this.filter(); |
|---|
| 86 | + } |
|---|
| 87 | + |
|---|
| 88 | + createPack() : void { |
|---|
| 89 | + var ref = this.dialog.open(LicenseFormComponent, { |
|---|
| 90 | + height: '50%', // can be px or % |
|---|
| 91 | + width: '40%', // can be px or % |
|---|
| 92 | + }); |
|---|
| 93 | + ref.componentInstance.isNew = true; |
|---|
| 94 | + ref.afterClosed().subscribe(result => { |
|---|
| 95 | + console.log(result); |
|---|
| 96 | + this.filter(); |
|---|
| 97 | + }); |
|---|
| 98 | + } |
|---|
| 99 | + |
|---|
| 100 | + editLicense(lic: any) : void { |
|---|
| 101 | + var ref = this.dialog.open(LicenseFormComponent, { |
|---|
| 102 | + height: '50%', // can be px or % |
|---|
| 103 | + width: '40%', // can be px or % |
|---|
| 104 | + }); |
|---|
| 105 | + ref.componentInstance.isNew = false; |
|---|
| 106 | + ref.componentInstance.data = lic; |
|---|
| 107 | + ref.afterClosed().subscribe(result => { |
|---|
| 108 | + console.log(result); |
|---|
| 109 | + this.filter(); |
|---|
| 110 | + }); |
|---|
| 111 | + } |
|---|
| 112 | + |
|---|
| 113 | + |
|---|
| 114 | + sort(sortEvent: ITdDataTableSortChangeEvent): void { |
|---|
| 115 | + this.sortBy = sortEvent.name; |
|---|
| 116 | + this.sortOrder = sortEvent.order; |
|---|
| 117 | + this.filter(); |
|---|
| 118 | + } |
|---|
| 119 | + |
|---|
| 120 | + search(searchTerm: string): void { |
|---|
| 121 | + this.searchTerm = searchTerm; |
|---|
| 122 | + this.filter(); |
|---|
| 123 | + } |
|---|
| 124 | + |
|---|
| 125 | + page(pagingEvent: IPageChangeEvent): void { |
|---|
| 126 | + this.fromRow = pagingEvent.fromRow; |
|---|
| 127 | + this.currentPage = pagingEvent.page; |
|---|
| 128 | + this.pageSize = pagingEvent.pageSize; |
|---|
| 129 | + this.filter(); |
|---|
| 130 | + } |
|---|
| 131 | + |
|---|
| 132 | + loadData() { |
|---|
| 133 | + |
|---|
| 134 | + } |
|---|
| 135 | + |
|---|
| 136 | + filter(): void { |
|---|
| 137 | + let newData: any[] = this.data; |
|---|
| 138 | + newData = this._dataTableService.filterData(newData, this.searchTerm, true); |
|---|
| 139 | + this.filteredTotal = newData.length; |
|---|
| 140 | + this.filteredItems = newData.length; |
|---|
| 141 | + newData = this._dataTableService.sortData(newData, this.sortBy, this.sortOrder); |
|---|
| 142 | + newData = this._dataTableService.pageData(newData, this.fromRow, this.currentPage * this.pageSize); |
|---|
| 143 | + this.filteredData = newData; |
|---|
| 144 | + } |
|---|
| 145 | + |
|---|
| 146 | + ngAfterViewInit(): void { |
|---|
| 147 | + this.media.broadcast(); |
|---|
| 148 | + |
|---|
| 149 | + } |
|---|
| 150 | +} |
|---|
| 151 | + |
|---|
| .. | .. |
|---|
| 12 | 12 | </button> |
|---|
| 13 | 13 | </md-toolbar> |
|---|
| 14 | 14 | <md-divider></md-divider> |
|---|
| 15 | | -<td-data-table [data]="filteredData" [columns]="columns"> |
|---|
| 16 | | - |
|---|
| 15 | +<div layout="row" layout-align="center center"> |
|---|
| 16 | + <div flex="80" layout="column" layout-align="end center" > |
|---|
| 17 | +<td-data-table [data]="filteredData" [columns]="columns" style="width: 100%"> |
|---|
| 17 | 18 | <template tdDataTableTemplate="used_licenses" let-row="row"> |
|---|
| 18 | 19 | <div layout="row"> |
|---|
| 19 | 20 | <td-notification-count color="secondary" [notifications]="row['num_licenses']"> |
|---|
| 20 | 21 | </td-notification-count> |
|---|
| 21 | | - <td-notification-count color="green" [notifications]="row['num_available']"> |
|---|
| 22 | + <td-notification-count color="primary" [notifications]="row['num_available']"> |
|---|
| 22 | 23 | </td-notification-count> |
|---|
| 23 | 24 | </div> |
|---|
| 24 | 25 | </template> |
|---|
| 25 | | - <template tdDataTableTemplate="lics" let-row="row"> |
|---|
| 26 | | - <button md-icon-button color="primary"><md-icon>arrow_right</md-icon></button> |
|---|
| 26 | + <template tdDataTableTemplate="code" let-row="row" let-value="value"> |
|---|
| 27 | + <div layout="row" layout-align="start center"> |
|---|
| 28 | + <span style="white-space: nowrap">{{value}}</span> |
|---|
| 29 | + </div> |
|---|
| 27 | 30 | </template> |
|---|
| 28 | | - <template tdDataTableTemplate="menu" let-row="row"> |
|---|
| 29 | | - <div layout="row"> |
|---|
| 30 | | - <button md-icon-button color="primary"><md-icon>arrow_right</md-icon></button> |
|---|
| 31 | | - <button md-icon-button><md-icon>edit</md-icon></button> |
|---|
| 32 | | - <button md-icon-button><md-icon>more_vert</md-icon></button> |
|---|
| 31 | + <template tdDataTableTemplate="menu" let-row="row" let-index="index"> |
|---|
| 32 | + <div layout="row" layout-align="end center"> |
|---|
| 33 | + <button md-icon-button (click)="editPack(row)" color="primary"><md-icon>edit</md-icon></button> |
|---|
| 34 | + <button md-icon-button [mdMenuTriggerFor]="packMenu" aria-label="Pack menu"> |
|---|
| 35 | + <md-icon>more_vert</md-icon> |
|---|
| 36 | + </button> |
|---|
| 37 | + |
|---|
| 38 | + <md-menu #packMenu="mdMenu"> |
|---|
| 39 | + <button md-menu-item *ngFor="let action of pack_menu_options" (click)="packAction(action.command, row)" [disabled]="!isActionAvailable(row)"> |
|---|
| 40 | + <md-icon *ngIf="!!action.icon">{{ action.icon }}</md-icon> {{ action.name }} |
|---|
| 41 | + </button> |
|---|
| 42 | + </md-menu> |
|---|
| 43 | + <button md-icon-button (click)="showLicenses(row)" color="accent"><md-icon>arrow_forward</md-icon></button> |
|---|
| 33 | 44 | </div> |
|---|
| 34 | 45 | </template> |
|---|
| 35 | 46 | </td-data-table> |
|---|
| 36 | | -<td-paging-bar #pagingBar [pageSizes]="[10, 20, 40]" [total]="filteredTotal" (change)="page($event)"> |
|---|
| 47 | +<td-paging-bar #pagingBar [pageSizes]="[10, 20, 40]" [total]="filteredTotal" (change)="page($event)" align="end"> |
|---|
| 37 | 48 | <span td-paging-bar-label hide-xs>Rows per page:</span> {{pagingBar.range}} <span hide-xs>of {{pagingBar.total}}</span> |
|---|
| 38 | | -</td-paging-bar> |
|---|
| 49 | +</td-paging-bar> |
|---|
| 50 | +</div> |
|---|
| 51 | +</div> |
|---|
| .. | .. |
|---|
| 1 | +import { Router } from '@angular/router'; |
|---|
| 1 | 2 | import { MdDialog } from '@angular/material'; |
|---|
| 2 | 3 | import { TdDataTableService, TdDataTableSortingOrder, ITdDataTableSortChangeEvent, ITdDataTableColumn } from '@covalent/core'; |
|---|
| 3 | 4 | import { IPageChangeEvent } from '@covalent/core'; |
|---|
| .. | .. |
|---|
| 42 | 43 | export class PackListComponent implements AfterViewInit { |
|---|
| 43 | 44 | data: any[] = []; |
|---|
| 44 | 45 | columns: ITdDataTableColumn[] = [ |
|---|
| 45 | | - { name: 'lics', label: '' }, |
|---|
| 46 | 46 | { name: 'code', label: 'Code', tooltip: 'License pack code' }, |
|---|
| 47 | 47 | { name: 'application_name', label: 'App name' }, |
|---|
| 48 | 48 | { name: 'licensetype_code', label: 'License type' }, |
|---|
| .. | .. |
|---|
| 61 | 61 | sortBy: string = 'application_name'; |
|---|
| 62 | 62 | sortOrder: TdDataTableSortingOrder = TdDataTableSortingOrder.Descending; |
|---|
| 63 | 63 | filteredItems = this.data.length; |
|---|
| 64 | + pack_menu_options : any[] = [{ |
|---|
| 65 | + command: 'edit', |
|---|
| 66 | + name: 'Edit' |
|---|
| 67 | + },{ |
|---|
| 68 | + command: 'cancel', |
|---|
| 69 | + name: 'Cancel' |
|---|
| 70 | + }] |
|---|
| 71 | + |
|---|
| 72 | + packAction(action: any) { |
|---|
| 73 | + console.log(action.command); |
|---|
| 74 | + } |
|---|
| 75 | + |
|---|
| 76 | + isActionAvailable(pack : any) : boolean { |
|---|
| 77 | + return true; |
|---|
| 78 | + } |
|---|
| 64 | 79 | |
|---|
| 65 | 80 | constructor(private _dataTableService: TdDataTableService, |
|---|
| 66 | 81 | private media: TdMediaService, |
|---|
| 82 | + private router: Router, |
|---|
| 67 | 83 | private dialog: MdDialog, |
|---|
| 68 | 84 | private packForm: PackFormComponent, |
|---|
| 69 | 85 | private packs: PacksService) { |
|---|
| .. | .. |
|---|
| 92 | 108 | }); |
|---|
| 93 | 109 | } |
|---|
| 94 | 110 | |
|---|
| 111 | + showLicenses(pack: any) : void { |
|---|
| 112 | + this.router.navigateByUrl('/licenses'); |
|---|
| 113 | + } |
|---|
| 114 | + |
|---|
| 95 | 115 | editPack(pack: any) : void { |
|---|
| 96 | 116 | var ref = this.dialog.open(PackFormComponent, { |
|---|
| 97 | | - height: '50%', // can be px or % |
|---|
| 117 | + height: '70%', // can be px or % |
|---|
| 98 | 118 | width: '40%', // can be px or % |
|---|
| 99 | 119 | }); |
|---|
| 100 | 120 | ref.componentInstance.isNew = false; |
|---|
| .. | .. |
|---|
| 1 | 1 | { |
|---|
| 2 | | -"": "", |
|---|
| 3 | | -"": "" |
|---|
| 2 | + "field.code": "Code", |
|---|
| 3 | + "field.num_licenses": "Num. licenses", |
|---|
| 4 | + "field.pack": "Pack", |
|---|
| 5 | + "field.id": "ID", |
|---|
| 6 | + "field.init_valid_date": "Init valid date", |
|---|
| 7 | + "field.end_valid_date": "End valid date", |
|---|
| 8 | + "field.license_preactivation": "License preactivation", |
|---|
| 9 | + "field.license_type_id": "License type", |
|---|
| 10 | + "field.organization_id": "Organization", |
|---|
| 11 | + "field.licensetype_code": "License type", |
|---|
| 12 | + "field.organization_name": "Organization", |
|---|
| 13 | + "field.preactivation_valid_period": "Preactivation valid period", |
|---|
| 14 | + "field.renew_valid_period": "Renew valid period", |
|---|
| 15 | + "field.application_name": "Application name", |
|---|
| 16 | + "field.status": "Status", |
|---|
| 17 | + "field.metadata": "Metadata", |
|---|
| 18 | + "field.key": "Parameter", |
|---|
| 19 | + "field.value": "Value", |
|---|
| 20 | + "field.comments": "Comments", |
|---|
| 21 | + "": "" |
|---|
| 4 | 22 | } |
|---|