#3527 fix - Changes on licenses list and routes
| .. | .. |
|---|
| 24 | 24 | import { HeroDetailComponent } from './detail.component'; |
|---|
| 25 | 25 | import { LoginFormComponent } from './login.form.component'; |
|---|
| 26 | 26 | import { LicenseListComponent } from './license.list.component'; |
|---|
| 27 | +import { LicenseFormComponent } from './forms/license.form.component'; |
|---|
| 28 | + |
|---|
| 27 | 29 | |
|---|
| 28 | 30 | import { appRoutes, appRoutingProviders } from './app.routes'; |
|---|
| 29 | 31 | import { requestOptionsProvider, requestBackendProvider } from './common/default.requests.options'; |
|---|
| .. | .. |
|---|
| 54 | 56 | LoginFormComponent, |
|---|
| 55 | 57 | ErrorCheckerComponent, |
|---|
| 56 | 58 | LicenseListComponent, |
|---|
| 59 | + LicenseFormComponent, |
|---|
| 57 | 60 | I18nDirective, |
|---|
| 58 | 61 | HomeComponent |
|---|
| 59 | 62 | ], |
|---|
| 60 | 63 | bootstrap: [ HomeComponent ], |
|---|
| 61 | | - entryComponents: [ PackFormComponent ], |
|---|
| 64 | + entryComponents: [ PackFormComponent, LicenseFormComponent ], |
|---|
| 62 | 65 | providers: [ |
|---|
| 63 | 66 | SeCurisSession, |
|---|
| 64 | 67 | UserService, |
|---|
| 65 | 68 | PacksService, |
|---|
| 66 | 69 | LicensesService, |
|---|
| 67 | 70 | PackFormComponent, |
|---|
| 71 | + LicenseFormComponent, |
|---|
| 68 | 72 | ApplicationsService, |
|---|
| 69 | 73 | OrganizationsService, |
|---|
| 70 | 74 | LicenseTypesService, |
|---|
| .. | .. |
|---|
| 1 | 1 | <md-toolbar role="toolbar" class="mat-secondary"> |
|---|
| 2 | 2 | <span class="push-left-sm"> |
|---|
| 3 | | - <span class="md-title" i18n>License Packs</span> |
|---|
| 3 | + <button md-icon-button (click)="goBack" color="accent"> |
|---|
| 4 | + <md-icon class="md-36">arrow_back</md-icon> |
|---|
| 5 | + </button> |
|---|
| 6 | + <span class="md-title" i18n>Licenses for pack</span>: {{pack?.code}} |
|---|
| 4 | 7 | </span> |
|---|
| 5 | 8 | <span class="push-left-sm" *ngIf="filteredItems < data.length"> |
|---|
| 6 | 9 | <span class="md-body-1">{{filteredItems}} of {{data.length}} packs filtered</span> |
|---|
| 7 | 10 | </span> |
|---|
| 8 | 11 | <td-search-box #searchBox class="push-right-sm" placeholder="Search here" (searchDebounce)="search($event)" flex> |
|---|
| 9 | 12 | </td-search-box> |
|---|
| 10 | | - <button md-mini-fab color="accent" (click)="createPack()"> |
|---|
| 13 | + <button md-mini-fab color="accent" (click)="createLicense()"> |
|---|
| 11 | 14 | <md-icon>add</md-icon> |
|---|
| 12 | 15 | </button> |
|---|
| 16 | + <md-toolbar-row *ngIf="!!pack"> |
|---|
| 17 | + <md-chip-list flex="80" style="margin-left: 70px;"> |
|---|
| 18 | + <md-chip selected [mdTooltip]="$L.get('field.application_name')" color="primary">{{pack.application_name}} </md-chip> |
|---|
| 19 | + <md-chip selected [mdTooltip]="$L.get('field.organization_id')" color="accent">{{pack.organization_name}} </md-chip> |
|---|
| 20 | + <md-chip selected [mdTooltip]="$L.get('field.license_type_id')" color="accent">{{pack.licensetype_code}} </md-chip> |
|---|
| 21 | + <md-chip selected [mdTooltip]="$L.get('field.num_available')" color="accent">{{pack.num_available}} </md-chip> |
|---|
| 22 | + </md-chip-list> |
|---|
| 23 | + </md-toolbar-row> |
|---|
| 13 | 24 | </md-toolbar> |
|---|
| 14 | 25 | <md-divider></md-divider> |
|---|
| 15 | 26 | <div layout="row" layout-align="center center"> |
|---|
| 16 | 27 | <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"> |
|---|
| 28 | +<td-data-table |
|---|
| 29 | + [data]="filteredData" |
|---|
| 30 | + [columns]="columns" |
|---|
| 31 | + [sortable]="true" |
|---|
| 32 | + [sortBy]="sortBy" |
|---|
| 33 | + (sortChange)="sort($event)" |
|---|
| 34 | + style="width: 100%"> |
|---|
| 35 | + <template tdDataTableTemplate="status" let-row="row"> |
|---|
| 19 | 36 | <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> |
|---|
| 37 | + <md-chip-list> |
|---|
| 38 | + <md-icon [style]="'color: ' + licenses.getStatusColor(row.status)">brightness_1</md-icon> <span>{{licenses.getStatusName(row.status)}}</span> |
|---|
| 39 | + </md-chip-list> |
|---|
| 24 | 40 | </div> |
|---|
| 25 | 41 | </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> |
|---|
| 42 | + <template tdDataTableTemplate="email" let-row="row"> |
|---|
| 43 | + <div layout="row"> |
|---|
| 44 | + <a [href]="'mailto:' + row.email + '?subject=SeCuris'">{{row.email}}</a> |
|---|
| 29 | 45 | </div> |
|---|
| 30 | 46 | </template> |
|---|
| 47 | + <template tdDataTableTemplate="expiration_date" let-row="row"> |
|---|
| 48 | + <div layout="row"> |
|---|
| 49 | + <span [class]="isLicenseExpired(row) ? 'warn' : ''" >{{row.expiration_date | date: 'short'}}</span> |
|---|
| 50 | + </div> |
|---|
| 51 | + </template> |
|---|
| 52 | + |
|---|
| 31 | 53 | <template tdDataTableTemplate="menu" let-row="row" let-index="index"> |
|---|
| 32 | 54 | <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"> |
|---|
| 55 | + <button md-icon-button (click)="editLicense(row)" color="primary"><md-icon>edit</md-icon></button> |
|---|
| 56 | + <button md-icon-button [mdMenuTriggerFor]="licenseMenu" aria-label="License menu"> |
|---|
| 35 | 57 | <md-icon>more_vert</md-icon> |
|---|
| 36 | 58 | </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)"> |
|---|
| 59 | + <md-menu #licenseMenu="mdMenu"> |
|---|
| 60 | + <button md-menu-item *ngFor="let action of license_menu_options" (click)="licenseAction(action.command, row)" [disabled]="!isActionAvailable(row)"> |
|---|
| 40 | 61 | <md-icon *ngIf="!!action.icon">{{ action.icon }}</md-icon> {{ action.name }} |
|---|
| 41 | 62 | </button> |
|---|
| 42 | 63 | </md-menu> |
|---|
| 43 | | - <button md-icon-button (click)="showLicenses(row)" color="accent"><md-icon>arrow_forward</md-icon></button> |
|---|
| 44 | 64 | </div> |
|---|
| 45 | 65 | </template> |
|---|
| 46 | 66 | </td-data-table> |
|---|
| .. | .. |
|---|
| 1 | | -import { Router } from '@angular/router'; |
|---|
| 1 | +import { LocaleService } from './common/i18n'; |
|---|
| 2 | +import { ActivatedRoute, Router } from '@angular/router'; |
|---|
| 2 | 3 | import { MdDialog, MdDialogConfig } from '@angular/material'; |
|---|
| 3 | 4 | import { TdDataTableService, TdDataTableSortingOrder, ITdDataTableSortChangeEvent, ITdDataTableColumn } from '@covalent/core'; |
|---|
| 4 | 5 | import { IPageChangeEvent } from '@covalent/core'; |
|---|
| 5 | 6 | import { Component, AfterViewInit } from '@angular/core'; |
|---|
| 6 | 7 | import { TdMediaService } from '@covalent/core'; |
|---|
| 7 | 8 | import { LicensesService } from './resources/licenses'; |
|---|
| 9 | +import { PacksService } from './resources/packs'; |
|---|
| 10 | + |
|---|
| 8 | 11 | import { LicenseFormComponent } from './forms/license.form.component'; |
|---|
| 9 | 12 | |
|---|
| 10 | 13 | var lic_example = { activation_code: '19fa8d30-29cb-4b59-81b5-3837af8204b6', |
|---|
| .. | .. |
|---|
| 34 | 37 | }) |
|---|
| 35 | 38 | export class LicenseListComponent implements AfterViewInit { |
|---|
| 36 | 39 | data: any[] = []; |
|---|
| 40 | + pack: any = null; |
|---|
| 37 | 41 | columns: ITdDataTableColumn[] = [ |
|---|
| 38 | | - { name: 'code', label: 'Code', tooltip: 'License pack code' }, |
|---|
| 39 | | - { name: 'application_name', label: 'App name' }, |
|---|
| 40 | | - { name: 'licensetype_code', label: 'License type' }, |
|---|
| 41 | | - { name: 'organization_name', label: 'Organization' }, |
|---|
| 42 | | - { name: 'used_licenses', label: 'Lics', tooltip: 'Initial/Available pack licenses' }, |
|---|
| 42 | + { name: 'code', label: 'Code', tooltip: 'License code' }, |
|---|
| 43 | + { name: 'full_name', label: 'User name' }, |
|---|
| 44 | + { name: 'email', label: 'User email' }, |
|---|
| 45 | + { name: 'expiration_date', label: 'Expiration date' }, |
|---|
| 46 | + { name: 'status', label: 'Status' }, |
|---|
| 43 | 47 | { name: 'menu', label: '' } |
|---|
| 44 | 48 | ]; |
|---|
| 45 | 49 | |
|---|
| .. | .. |
|---|
| 50 | 54 | fromRow: number = 1; |
|---|
| 51 | 55 | currentPage: number = 1; |
|---|
| 52 | 56 | pageSize: number = 10; |
|---|
| 53 | | - sortBy: string = 'application_name'; |
|---|
| 57 | + sortBy: string = 'expiration_date'; |
|---|
| 54 | 58 | sortOrder: TdDataTableSortingOrder = TdDataTableSortingOrder.Descending; |
|---|
| 55 | 59 | filteredItems = this.data.length; |
|---|
| 56 | 60 | license_menu_options : any[] = [{ |
|---|
| .. | .. |
|---|
| 73 | 77 | |
|---|
| 74 | 78 | constructor(private _dataTableService: TdDataTableService, |
|---|
| 75 | 79 | private media: TdMediaService, |
|---|
| 80 | + private $L: LocaleService, |
|---|
| 76 | 81 | private router: Router, |
|---|
| 82 | + private route: ActivatedRoute, |
|---|
| 77 | 83 | private dialog: MdDialog, |
|---|
| 78 | 84 | private licenseForm: LicenseFormComponent, |
|---|
| 79 | | - private licenses: LicensesService) { |
|---|
| 80 | | - this.licenses.get().subscribe( |
|---|
| 81 | | - list => { |
|---|
| 82 | | - this.data = list; |
|---|
| 83 | | - this.filter(); |
|---|
| 84 | | - }, |
|---|
| 85 | | - err => console.error(err) |
|---|
| 86 | | - ); |
|---|
| 85 | + private licenses: LicensesService, |
|---|
| 86 | + private packs: PacksService) { |
|---|
| 87 | 87 | } |
|---|
| 88 | 88 | |
|---|
| 89 | 89 | ngOnInit(): void { |
|---|
| 90 | | - this.filter(); |
|---|
| 90 | + this.route.params.subscribe(params => { |
|---|
| 91 | + var packId = +params['id']; // (+) converts string 'id' to a number |
|---|
| 92 | + this.licenses.getByPack(packId).subscribe( |
|---|
| 93 | + list => { |
|---|
| 94 | + this.data = list; |
|---|
| 95 | + this.filter(); |
|---|
| 96 | + }, |
|---|
| 97 | + err => console.error(err) |
|---|
| 98 | + ); |
|---|
| 99 | + this.packs.get(packId).subscribe( |
|---|
| 100 | + packData => { |
|---|
| 101 | + this.pack = packData; |
|---|
| 102 | + }, |
|---|
| 103 | + err => console.error(err) |
|---|
| 104 | + ); |
|---|
| 105 | + }); |
|---|
| 106 | + } |
|---|
| 107 | + |
|---|
| 108 | + isLicenseExpired(lic: any): boolean { |
|---|
| 109 | + return lic.expiration_date < (new Date().getTime()); |
|---|
| 91 | 110 | } |
|---|
| 92 | 111 | |
|---|
| 93 | 112 | createLicense() : void { |
|---|
| .. | .. |
|---|
| 1 | | -import { Router } from '@angular/router'; |
|---|
| 1 | +import { Router, ActivatedRoute } from '@angular/router'; |
|---|
| 2 | 2 | import { MdDialog, MdDialogConfig } from '@angular/material'; |
|---|
| 3 | 3 | import { TdDataTableService, TdDataTableSortingOrder, ITdDataTableSortChangeEvent, ITdDataTableColumn } from '@covalent/core'; |
|---|
| 4 | 4 | import { IPageChangeEvent } from '@covalent/core'; |
|---|
| .. | .. |
|---|
| 54 | 54 | { name: 'application_name', label: 'App name' }, |
|---|
| 55 | 55 | { name: 'licensetype_code', label: 'License type' }, |
|---|
| 56 | 56 | { name: 'organization_name', label: 'Organization' }, |
|---|
| 57 | | - { name: 'used_licenses', label: 'Lics', tooltip: 'Initial/Available pack licenses' }, |
|---|
| 57 | + { name: 'used_licenses', label: 'Licenses', tooltip: 'Initial/Available pack licenses' }, |
|---|
| 58 | 58 | { name: 'menu', label: '' } |
|---|
| 59 | 59 | ]; |
|---|
| 60 | 60 | |
|---|
| .. | .. |
|---|
| 87 | 87 | constructor(private _dataTableService: TdDataTableService, |
|---|
| 88 | 88 | private media: TdMediaService, |
|---|
| 89 | 89 | private router: Router, |
|---|
| 90 | + private route: ActivatedRoute, |
|---|
| 90 | 91 | private dialog: MdDialog, |
|---|
| 91 | 92 | private $L: LocaleService, |
|---|
| 92 | 93 | private packForm: PackFormComponent, |
|---|
| .. | .. |
|---|
| 114 | 115 | } |
|---|
| 115 | 116 | |
|---|
| 116 | 117 | showLicenses(pack: any) : void { |
|---|
| 117 | | - this.router.navigateByUrl('/licenses'); |
|---|
| 118 | + this.router.navigate([`${pack.id}/licenses`], {relativeTo: this.route}); |
|---|
| 118 | 119 | } |
|---|
| 119 | 120 | |
|---|
| 120 | 121 | editPack(pack: any) : void { |
|---|
| .. | .. |
|---|
| 1 | +import { LocaleService } from '../common/i18n'; |
|---|
| 1 | 2 | import { Observable } from 'rxjs/Rx'; |
|---|
| 2 | 3 | import { Injectable } from '@angular/core'; |
|---|
| 3 | 4 | import { Http, RequestOptions } from '@angular/http'; |
|---|
| .. | .. |
|---|
| 21 | 22 | status: 'AC' |
|---|
| 22 | 23 | } |
|---|
| 23 | 24 | |
|---|
| 24 | | -export const PACK_STATUS = { |
|---|
| 25 | | - CREATED: 'CR', |
|---|
| 26 | | - ACTIVE: 'AC', |
|---|
| 27 | | - ONHOLD: 'OH', |
|---|
| 28 | | - EXPIRED: 'EX', |
|---|
| 29 | | - CANCELLED: 'CA' |
|---|
| 30 | | -} |
|---|
| 31 | | - |
|---|
| 32 | 25 | export const LIC_STATUS = { |
|---|
| 33 | 26 | CREATED: 'CR', |
|---|
| 34 | 27 | ACTIVE: 'AC', |
|---|
| .. | .. |
|---|
| 38 | 31 | BLOCKED: 'BL', |
|---|
| 39 | 32 | CANCELLED: 'CA' |
|---|
| 40 | 33 | } |
|---|
| 34 | + |
|---|
| 35 | +export const COLORS_BY_STATUS = { |
|---|
| 36 | + 'CR': '#808080', |
|---|
| 37 | + 'AC': '#329e5a', |
|---|
| 38 | + 'RE': '#2981d4', |
|---|
| 39 | + 'EX': '#ea7824', |
|---|
| 40 | + 'BL': '#ff0000', |
|---|
| 41 | + 'CA': '#a21717' |
|---|
| 42 | +}; |
|---|
| 41 | 43 | |
|---|
| 42 | 44 | /** |
|---|
| 43 | 45 | * These transitions could be get from server, class License.Status, but |
|---|
| .. | .. |
|---|
| 55 | 57 | 'delete': [LIC_STATUS.CREATED, LIC_STATUS.CANCELLED, LIC_STATUS.BLOCKED] |
|---|
| 56 | 58 | } |
|---|
| 57 | 59 | |
|---|
| 58 | | - |
|---|
| 59 | | - |
|---|
| 60 | 60 | @Injectable() |
|---|
| 61 | 61 | export class LicensesService extends SeCurisResourceServices { |
|---|
| 62 | | - constructor(http: Http) { |
|---|
| 62 | + constructor(http: Http, |
|---|
| 63 | + private $L: LocaleService) { |
|---|
| 63 | 64 | super(http, 'license'); |
|---|
| 64 | 65 | } |
|---|
| 65 | 66 | |
|---|
| .. | .. |
|---|
| 84 | 85 | var validStatuses = LIC_ACTIONS_BY_STATUS[action]; |
|---|
| 85 | 86 | return lic && validStatuses && validStatuses.indexOf(lic.status) !== -1; |
|---|
| 86 | 87 | } |
|---|
| 88 | + |
|---|
| 89 | + |
|---|
| 90 | + getStatusName(statusCode: string): string { |
|---|
| 91 | + return this.$L.get(`pack.status.${statusCode}`, this.$L.get('Unknown')); |
|---|
| 92 | + } |
|---|
| 93 | + |
|---|
| 94 | + getStatusColor(statusCode: string): string { |
|---|
| 95 | + return COLORS_BY_STATUS[statusCode] || '#cccccc'; |
|---|
| 96 | + } |
|---|
| 87 | 97 | } |
|---|
| 88 | 98 | |
|---|
| .. | .. |
|---|
| 82 | 82 | } |
|---|
| 83 | 83 | |
|---|
| 84 | 84 | getStatusName(statusCode: string): string { |
|---|
| 85 | | - return this.$L.get(`pack.status.${statusCode}`, this.$L.get('Unknown')); |
|---|
| 85 | + return this.$L.get(`pack.status.${statusCode}`, this.$L.get('Unknown')); |
|---|
| 86 | + } |
|---|
| 87 | + |
|---|
| 88 | + getStatusColor(statusCode: string): string { |
|---|
| 89 | + return COLORS_BY_STATUS[statusCode] || '#cccccc'; |
|---|
| 86 | 90 | } |
|---|
| 87 | 91 | |
|---|
| 88 | 92 | } |
|---|