mirror of
https://github.com/akveo/ngx-admin.git
synced 2025-12-16 23:40:14 +01:00
Final state from MSSE692
This commit is contained in:
parent
5f18537bd5
commit
43c7198f22
41 changed files with 816 additions and 218 deletions
36
package-lock.json
generated
36
package-lock.json
generated
|
|
@ -49,6 +49,7 @@
|
||||||
"rxjs-compat": "6.3.0",
|
"rxjs-compat": "6.3.0",
|
||||||
"socicon": "3.0.5",
|
"socicon": "3.0.5",
|
||||||
"style-loader": "^1.1.3",
|
"style-loader": "^1.1.3",
|
||||||
|
"thingbook-api": "^1.0.14",
|
||||||
"tinymce": "4.5.7",
|
"tinymce": "4.5.7",
|
||||||
"tslib": "^2.0.0",
|
"tslib": "^2.0.0",
|
||||||
"typeface-exo": "0.0.22",
|
"typeface-exo": "0.0.22",
|
||||||
|
|
@ -649,6 +650,7 @@
|
||||||
"resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-11.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-11.0.4.tgz",
|
||||||
"integrity": "sha512-suhAhsZEv+lLwm8dc524cMvO7gHPi+z2+4tueNS+zDiIObdZc4fs+KoOlnRMdYwba++X/V8mHXuDEQetl3GFcw==",
|
"integrity": "sha512-suhAhsZEv+lLwm8dc524cMvO7gHPi+z2+4tueNS+zDiIObdZc4fs+KoOlnRMdYwba++X/V8mHXuDEQetl3GFcw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"parse5": "^5.0.0",
|
||||||
"tslib": "^2.0.0"
|
"tslib": "^2.0.0"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
|
|
@ -911,6 +913,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"anymatch": "~3.1.1",
|
"anymatch": "~3.1.1",
|
||||||
"braces": "~3.0.2",
|
"braces": "~3.0.2",
|
||||||
|
"fsevents": "~2.3.1",
|
||||||
"glob-parent": "~5.1.0",
|
"glob-parent": "~5.1.0",
|
||||||
"is-binary-path": "~2.1.0",
|
"is-binary-path": "~2.1.0",
|
||||||
"is-glob": "~4.0.1",
|
"is-glob": "~4.0.1",
|
||||||
|
|
@ -4780,6 +4783,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"anymatch": "^1.3.0",
|
"anymatch": "^1.3.0",
|
||||||
"async-each": "^1.0.0",
|
"async-each": "^1.0.0",
|
||||||
|
"fsevents": "^1.0.0",
|
||||||
"glob-parent": "^2.0.0",
|
"glob-parent": "^2.0.0",
|
||||||
"inherits": "^2.0.1",
|
"inherits": "^2.0.1",
|
||||||
"is-binary-path": "^1.0.0",
|
"is-binary-path": "^1.0.0",
|
||||||
|
|
@ -10966,7 +10970,8 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"async": "^1.4.0",
|
"async": "^1.4.0",
|
||||||
"optimist": "^0.6.1",
|
"optimist": "^0.6.1",
|
||||||
"source-map": "^0.4.4"
|
"source-map": "^0.4.4",
|
||||||
|
"uglify-js": "^2.6"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"handlebars": "bin/handlebars"
|
"handlebars": "bin/handlebars"
|
||||||
|
|
@ -13695,6 +13700,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"anymatch": "~3.1.1",
|
"anymatch": "~3.1.1",
|
||||||
"braces": "~3.0.2",
|
"braces": "~3.0.2",
|
||||||
|
"fsevents": "~2.3.1",
|
||||||
"glob-parent": "~5.1.0",
|
"glob-parent": "~5.1.0",
|
||||||
"is-binary-path": "~2.1.0",
|
"is-binary-path": "~2.1.0",
|
||||||
"is-glob": "~4.0.1",
|
"is-glob": "~4.0.1",
|
||||||
|
|
@ -14220,8 +14226,11 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"errno": "^0.1.1",
|
"errno": "^0.1.1",
|
||||||
"graceful-fs": "^4.1.2",
|
"graceful-fs": "^4.1.2",
|
||||||
|
"image-size": "~0.5.0",
|
||||||
"make-dir": "^2.1.0",
|
"make-dir": "^2.1.0",
|
||||||
"mime": "^1.4.1",
|
"mime": "^1.4.1",
|
||||||
|
"native-request": "^1.0.5",
|
||||||
|
"source-map": "~0.6.0",
|
||||||
"tslib": "^1.10.0"
|
"tslib": "^1.10.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
@ -21141,6 +21150,9 @@
|
||||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.32.1.tgz",
|
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.32.1.tgz",
|
||||||
"integrity": "sha512-Op2vWTpvK7t6/Qnm1TTh7VjEZZkN8RWgf0DHbkKzQBwNf748YhXbozHVefqpPp/Fuyk/PQPAnYsBxAEtlMvpUw==",
|
"integrity": "sha512-Op2vWTpvK7t6/Qnm1TTh7VjEZZkN8RWgf0DHbkKzQBwNf748YhXbozHVefqpPp/Fuyk/PQPAnYsBxAEtlMvpUw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"fsevents": "~2.1.2"
|
||||||
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"rollup": "dist/bin/rollup"
|
"rollup": "dist/bin/rollup"
|
||||||
},
|
},
|
||||||
|
|
@ -21493,6 +21505,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"anymatch": "~3.1.1",
|
"anymatch": "~3.1.1",
|
||||||
"braces": "~3.0.2",
|
"braces": "~3.0.2",
|
||||||
|
"fsevents": "~2.3.1",
|
||||||
"glob-parent": "~5.1.0",
|
"glob-parent": "~5.1.0",
|
||||||
"is-binary-path": "~2.1.0",
|
"is-binary-path": "~2.1.0",
|
||||||
"is-glob": "~4.0.1",
|
"is-glob": "~4.0.1",
|
||||||
|
|
@ -22832,8 +22845,12 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"asn1": "~0.2.3",
|
"asn1": "~0.2.3",
|
||||||
"assert-plus": "^1.0.0",
|
"assert-plus": "^1.0.0",
|
||||||
|
"bcrypt-pbkdf": "^1.0.0",
|
||||||
"dashdash": "^1.12.0",
|
"dashdash": "^1.12.0",
|
||||||
"getpass": "^0.1.1"
|
"ecc-jsbn": "~0.1.1",
|
||||||
|
"getpass": "^0.1.1",
|
||||||
|
"jsbn": "~0.1.0",
|
||||||
|
"tweetnacl": "~0.14.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
|
|
@ -24353,6 +24370,11 @@
|
||||||
"integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
|
"integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/thingbook-api": {
|
||||||
|
"version": "1.0.14",
|
||||||
|
"resolved": "https://registry.npmjs.org/thingbook-api/-/thingbook-api-1.0.14.tgz",
|
||||||
|
"integrity": "sha512-nX72Sa2SM13Hg1W8PTbJ+IIvoynCNDwTcTEXNScQLrw16b6QcgCRaVJ69W4tzxb0sFffzDN7+xcPoewl//syxg=="
|
||||||
|
},
|
||||||
"node_modules/through": {
|
"node_modules/through": {
|
||||||
"version": "2.3.8",
|
"version": "2.3.8",
|
||||||
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
||||||
|
|
@ -25412,8 +25434,10 @@
|
||||||
"integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==",
|
"integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"chokidar": "^3.4.1",
|
||||||
"graceful-fs": "^4.1.2",
|
"graceful-fs": "^4.1.2",
|
||||||
"neo-async": "^2.5.0"
|
"neo-async": "^2.5.0",
|
||||||
|
"watchpack-chokidar2": "^2.0.1"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"chokidar": "^3.4.1",
|
"chokidar": "^3.4.1",
|
||||||
|
|
@ -26366,6 +26390,7 @@
|
||||||
"anymatch": "^2.0.0",
|
"anymatch": "^2.0.0",
|
||||||
"async-each": "^1.0.1",
|
"async-each": "^1.0.1",
|
||||||
"braces": "^2.3.2",
|
"braces": "^2.3.2",
|
||||||
|
"fsevents": "^1.2.7",
|
||||||
"glob-parent": "^3.1.0",
|
"glob-parent": "^3.1.0",
|
||||||
"inherits": "^2.0.3",
|
"inherits": "^2.0.3",
|
||||||
"is-binary-path": "^1.0.0",
|
"is-binary-path": "^1.0.0",
|
||||||
|
|
@ -48529,6 +48554,11 @@
|
||||||
"integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
|
"integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"thingbook-api": {
|
||||||
|
"version": "1.0.14",
|
||||||
|
"resolved": "https://registry.npmjs.org/thingbook-api/-/thingbook-api-1.0.14.tgz",
|
||||||
|
"integrity": "sha512-nX72Sa2SM13Hg1W8PTbJ+IIvoynCNDwTcTEXNScQLrw16b6QcgCRaVJ69W4tzxb0sFffzDN7+xcPoewl//syxg=="
|
||||||
|
},
|
||||||
"through": {
|
"through": {
|
||||||
"version": "2.3.8",
|
"version": "2.3.8",
|
||||||
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
||||||
|
|
|
||||||
|
|
@ -4,15 +4,15 @@
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://github.com/akveo/ngx-admin.git"
|
"url": "git+https://github.com/kerry-t-johnson/thingbook-ui"
|
||||||
},
|
},
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/akveo/ngx-admin/issues"
|
"url": "https://github.com/kerry-t-johnson/thingbook-ui/issues"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"ng": "ng",
|
"ng": "ng",
|
||||||
"conventional-changelog": "conventional-changelog",
|
"conventional-changelog": "conventional-changelog",
|
||||||
"start": "ng serve",
|
"start": "ng serve --host 0.0.0.0",
|
||||||
"build": "ng build",
|
"build": "ng build",
|
||||||
"build:prod": "npm run build -- --prod --aot",
|
"build:prod": "npm run build -- --prod --aot",
|
||||||
"test": "ng test",
|
"test": "ng test",
|
||||||
|
|
@ -70,6 +70,7 @@
|
||||||
"rxjs-compat": "6.3.0",
|
"rxjs-compat": "6.3.0",
|
||||||
"socicon": "3.0.5",
|
"socicon": "3.0.5",
|
||||||
"style-loader": "^1.1.3",
|
"style-loader": "^1.1.3",
|
||||||
|
"thingbook-api": "^1.0.14",
|
||||||
"tinymce": "4.5.7",
|
"tinymce": "4.5.7",
|
||||||
"tslib": "^2.0.0",
|
"tslib": "^2.0.0",
|
||||||
"typeface-exo": "0.0.22",
|
"typeface-exo": "0.0.22",
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@ import {
|
||||||
SeoService,
|
SeoService,
|
||||||
StateService,
|
StateService,
|
||||||
} from './utils';
|
} from './utils';
|
||||||
import { UserData } from './data/users';
|
|
||||||
import { ElectricityData } from './data/electricity';
|
import { ElectricityData } from './data/electricity';
|
||||||
import { SmartTableData } from './data/smart-table';
|
import { SmartTableData } from './data/smart-table';
|
||||||
import { UserActivityData } from './data/user-activity';
|
import { UserActivityData } from './data/user-activity';
|
||||||
|
|
@ -32,7 +31,6 @@ import { StatsProgressBarData } from './data/stats-progress-bar';
|
||||||
import { VisitorsAnalyticsData } from './data/visitors-analytics';
|
import { VisitorsAnalyticsData } from './data/visitors-analytics';
|
||||||
import { SecurityCamerasData } from './data/security-cameras';
|
import { SecurityCamerasData } from './data/security-cameras';
|
||||||
|
|
||||||
import { UserService } from './mock/users.service';
|
|
||||||
import { ElectricityService } from './mock/electricity.service';
|
import { ElectricityService } from './mock/electricity.service';
|
||||||
import { SmartTableService } from './mock/smart-table.service';
|
import { SmartTableService } from './mock/smart-table.service';
|
||||||
import { UserActivityService } from './mock/user-activity.service';
|
import { UserActivityService } from './mock/user-activity.service';
|
||||||
|
|
@ -72,7 +70,6 @@ const socialLinks = [
|
||||||
];
|
];
|
||||||
|
|
||||||
const DATA_SERVICES = [
|
const DATA_SERVICES = [
|
||||||
{ provide: UserData, useClass: UserService },
|
|
||||||
{ provide: ElectricityData, useClass: ElectricityService },
|
{ provide: ElectricityData, useClass: ElectricityService },
|
||||||
{ provide: SmartTableData, useClass: SmartTableService },
|
{ provide: SmartTableData, useClass: SmartTableService },
|
||||||
{ provide: UserActivityData, useClass: UserActivityService },
|
{ provide: UserActivityData, useClass: UserActivityService },
|
||||||
|
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
import { Observable } from 'rxjs';
|
|
||||||
|
|
||||||
export interface User {
|
|
||||||
name: string;
|
|
||||||
picture: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Contacts {
|
|
||||||
user: User;
|
|
||||||
type: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RecentUsers extends Contacts {
|
|
||||||
time: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export abstract class UserData {
|
|
||||||
abstract getUsers(): Observable<User[]>;
|
|
||||||
abstract getContacts(): Observable<Contacts[]>;
|
|
||||||
abstract getRecentUsers(): Observable<RecentUsers[]>;
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import { NgModule, ModuleWithProviders } from '@angular/core';
|
import { NgModule, ModuleWithProviders } from '@angular/core';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
|
|
||||||
import { UserService } from './users.service';
|
|
||||||
import { ElectricityService } from './electricity.service';
|
import { ElectricityService } from './electricity.service';
|
||||||
import { SmartTableService } from './smart-table.service';
|
import { SmartTableService } from './smart-table.service';
|
||||||
import { UserActivityService } from './user-activity.service';
|
import { UserActivityService } from './user-activity.service';
|
||||||
|
|
@ -23,7 +22,6 @@ import { VisitorsAnalyticsService } from './visitors-analytics.service';
|
||||||
import { SecurityCamerasService } from './security-cameras.service';
|
import { SecurityCamerasService } from './security-cameras.service';
|
||||||
|
|
||||||
const SERVICES = [
|
const SERVICES = [
|
||||||
UserService,
|
|
||||||
ElectricityService,
|
ElectricityService,
|
||||||
SmartTableService,
|
SmartTableService,
|
||||||
UserActivityService,
|
UserActivityService,
|
||||||
|
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
import { of as observableOf, Observable } from 'rxjs';
|
|
||||||
import { Injectable } from '@angular/core';
|
|
||||||
import { Contacts, RecentUsers, UserData } from '../data/users';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class UserService extends UserData {
|
|
||||||
|
|
||||||
private time: Date = new Date;
|
|
||||||
|
|
||||||
private users = {
|
|
||||||
nick: { name: 'Nick Jones', picture: 'assets/images/nick.png' },
|
|
||||||
eva: { name: 'Eva Moor', picture: 'assets/images/eva.png' },
|
|
||||||
jack: { name: 'Jack Williams', picture: 'assets/images/jack.png' },
|
|
||||||
lee: { name: 'Lee Wong', picture: 'assets/images/lee.png' },
|
|
||||||
alan: { name: 'Alan Thompson', picture: 'assets/images/alan.png' },
|
|
||||||
kate: { name: 'Kate Martinez', picture: 'assets/images/kate.png' },
|
|
||||||
};
|
|
||||||
private types = {
|
|
||||||
mobile: 'mobile',
|
|
||||||
home: 'home',
|
|
||||||
work: 'work',
|
|
||||||
};
|
|
||||||
private contacts: Contacts[] = [
|
|
||||||
{ user: this.users.nick, type: this.types.mobile },
|
|
||||||
{ user: this.users.eva, type: this.types.home },
|
|
||||||
{ user: this.users.jack, type: this.types.mobile },
|
|
||||||
{ user: this.users.lee, type: this.types.mobile },
|
|
||||||
{ user: this.users.alan, type: this.types.home },
|
|
||||||
{ user: this.users.kate, type: this.types.work },
|
|
||||||
];
|
|
||||||
private recentUsers: RecentUsers[] = [
|
|
||||||
{ user: this.users.alan, type: this.types.home, time: this.time.setHours(21, 12)},
|
|
||||||
{ user: this.users.eva, type: this.types.home, time: this.time.setHours(17, 45)},
|
|
||||||
{ user: this.users.nick, type: this.types.mobile, time: this.time.setHours(5, 29)},
|
|
||||||
{ user: this.users.lee, type: this.types.mobile, time: this.time.setHours(11, 24)},
|
|
||||||
{ user: this.users.jack, type: this.types.mobile, time: this.time.setHours(10, 45)},
|
|
||||||
{ user: this.users.kate, type: this.types.work, time: this.time.setHours(9, 42)},
|
|
||||||
{ user: this.users.kate, type: this.types.work, time: this.time.setHours(9, 31)},
|
|
||||||
{ user: this.users.jack, type: this.types.mobile, time: this.time.setHours(8, 0)},
|
|
||||||
];
|
|
||||||
|
|
||||||
getUsers(): Observable<any> {
|
|
||||||
return observableOf(this.users);
|
|
||||||
}
|
|
||||||
|
|
||||||
getContacts(): Observable<Contacts[]> {
|
|
||||||
return observableOf(this.contacts);
|
|
||||||
}
|
|
||||||
|
|
||||||
getRecentUsers(): Observable<RecentUsers[]> {
|
|
||||||
return observableOf(this.recentUsers);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<a (click)="toggleSidebar()" href="#" class="sidebar-toggle">
|
<a (click)="toggleSidebar()" href="#" class="sidebar-toggle">
|
||||||
<nb-icon icon="menu-2-outline"></nb-icon>
|
<nb-icon icon="menu-2-outline"></nb-icon>
|
||||||
</a>
|
</a>
|
||||||
<a class="logo" href="#" (click)="navigateHome()">ngx-<span>admin</span></a>
|
<a class="logo" href="#" (click)="navigateHome()">Thing<span>Book</span></a>
|
||||||
</div>
|
</div>
|
||||||
<nb-select [selected]="currentTheme" (selectedChange)="changeTheme($event)" status="primary">
|
<nb-select [selected]="currentTheme" (selectedChange)="changeTheme($event)" status="primary">
|
||||||
<nb-option *ngFor="let theme of themes" [value]="theme.value"> {{ theme.name }}</nb-option>
|
<nb-option *ngFor="let theme of themes" [value]="theme.value"> {{ theme.name }}</nb-option>
|
||||||
|
|
@ -18,12 +18,10 @@
|
||||||
</nb-action>
|
</nb-action>
|
||||||
<nb-action class="control-item" icon="email-outline"></nb-action>
|
<nb-action class="control-item" icon="email-outline"></nb-action>
|
||||||
<nb-action class="control-item" icon="bell-outline"></nb-action>
|
<nb-action class="control-item" icon="bell-outline"></nb-action>
|
||||||
<nb-action class="user-action" *nbIsGranted="['view', 'user']" >
|
<nb-action class="user-action" *nbIsGranted="['view', 'user']">
|
||||||
<nb-user [nbContextMenu]="userMenu"
|
<nb-user [nbContextMenu]="userMenu" [onlyPicture]="userPictureOnly" [name]="displayName"
|
||||||
[onlyPicture]="userPictureOnly"
|
[picture]="user?.picture">
|
||||||
[name]="user?.name"
|
|
||||||
[picture]="user?.picture">
|
|
||||||
</nb-user>
|
</nb-user>
|
||||||
</nb-action>
|
</nb-action>
|
||||||
</nb-actions>
|
</nb-actions>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||||
import { NbMediaBreakpointsService, NbMenuService, NbSidebarService, NbThemeService } from '@nebular/theme';
|
import { NbMediaBreakpointsService, NbMenuService, NbSidebarService, NbThemeService } from '@nebular/theme';
|
||||||
|
|
||||||
import { UserData } from '../../../@core/data/users';
|
|
||||||
import { LayoutService } from '../../../@core/utils';
|
import { LayoutService } from '../../../@core/utils';
|
||||||
import { map, takeUntil } from 'rxjs/operators';
|
import { map, takeUntil } from 'rxjs/operators';
|
||||||
import { Subject } from 'rxjs';
|
import { Subject } from 'rxjs';
|
||||||
|
import { UserService, User } from '../../../modules/user/user.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ngx-header',
|
selector: 'ngx-header',
|
||||||
|
|
@ -15,45 +15,40 @@ export class HeaderComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
private destroy$: Subject<void> = new Subject<void>();
|
private destroy$: Subject<void> = new Subject<void>();
|
||||||
userPictureOnly: boolean = false;
|
userPictureOnly: boolean = false;
|
||||||
user: any;
|
user: User;
|
||||||
|
displayName: string;
|
||||||
|
|
||||||
themes = [
|
themes = [
|
||||||
{
|
{ value: 'default', name: 'Light', },
|
||||||
value: 'default',
|
{ value: 'dark', name: 'Dark', },
|
||||||
name: 'Light',
|
{ value: 'cosmic', name: 'Cosmic', },
|
||||||
},
|
{ value: 'corporate', name: 'Corporate', },
|
||||||
{
|
|
||||||
value: 'dark',
|
|
||||||
name: 'Dark',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'cosmic',
|
|
||||||
name: 'Cosmic',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'corporate',
|
|
||||||
name: 'Corporate',
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
currentTheme = 'default';
|
currentTheme = 'default';
|
||||||
|
|
||||||
userMenu = [ { title: 'Profile' }, { title: 'Log out' } ];
|
userMenu = [
|
||||||
|
{ title: 'Profile', icon: 'person-outline', link: 'pages/user/profile', },
|
||||||
|
{ title: 'Log out' }
|
||||||
|
];
|
||||||
|
|
||||||
constructor(private sidebarService: NbSidebarService,
|
constructor(private sidebarService: NbSidebarService,
|
||||||
private menuService: NbMenuService,
|
private menuService: NbMenuService,
|
||||||
private themeService: NbThemeService,
|
private themeService: NbThemeService,
|
||||||
private userService: UserData,
|
private userService: UserService,
|
||||||
private layoutService: LayoutService,
|
private layoutService: LayoutService,
|
||||||
private breakpointService: NbMediaBreakpointsService) {
|
private breakpointService: NbMediaBreakpointsService) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.currentTheme = this.themeService.currentTheme;
|
this.currentTheme = this.themeService.currentTheme;
|
||||||
|
|
||||||
this.userService.getUsers()
|
this.userService.onUserStatus()
|
||||||
.pipe(takeUntil(this.destroy$))
|
.pipe(takeUntil(this.destroy$))
|
||||||
.subscribe((users: any) => this.user = users.nick);
|
.subscribe((user: any) => {
|
||||||
|
this.user = user;
|
||||||
|
this.displayName = user?.first ?? user?.email;
|
||||||
|
});
|
||||||
|
|
||||||
const { xl } = this.breakpointService.getBreakpointsMap();
|
const { xl } = this.breakpointService.getBreakpointsMap();
|
||||||
this.themeService.onMediaQueryChange()
|
this.themeService.onMediaQueryChange()
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { HttpClientModule } from '@angular/common/http';
|
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
|
||||||
import { CoreModule } from './@core/core.module';
|
import { CoreModule } from './@core/core.module';
|
||||||
import { ThemeModule } from './@theme/theme.module';
|
import { ThemeModule } from './@theme/theme.module';
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
|
|
@ -15,14 +15,19 @@ import {
|
||||||
NbChatModule,
|
NbChatModule,
|
||||||
NbDatepickerModule,
|
NbDatepickerModule,
|
||||||
NbDialogModule,
|
NbDialogModule,
|
||||||
|
NbIconModule,
|
||||||
NbMenuModule,
|
NbMenuModule,
|
||||||
NbSidebarModule,
|
NbSidebarModule,
|
||||||
NbToastrModule,
|
NbToastrModule,
|
||||||
NbWindowModule,
|
NbWindowModule,
|
||||||
} from '@nebular/theme';
|
} from '@nebular/theme';
|
||||||
|
|
||||||
|
import { UserModule } from './modules/user/user.module';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [AppComponent],
|
declarations: [
|
||||||
|
AppComponent,
|
||||||
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
BrowserAnimationsModule,
|
BrowserAnimationsModule,
|
||||||
|
|
@ -32,6 +37,7 @@ import {
|
||||||
NbMenuModule.forRoot(),
|
NbMenuModule.forRoot(),
|
||||||
NbDatepickerModule.forRoot(),
|
NbDatepickerModule.forRoot(),
|
||||||
NbDialogModule.forRoot(),
|
NbDialogModule.forRoot(),
|
||||||
|
NbIconModule,
|
||||||
NbWindowModule.forRoot(),
|
NbWindowModule.forRoot(),
|
||||||
NbToastrModule.forRoot(),
|
NbToastrModule.forRoot(),
|
||||||
NbChatModule.forRoot({
|
NbChatModule.forRoot({
|
||||||
|
|
@ -39,8 +45,11 @@ import {
|
||||||
}),
|
}),
|
||||||
CoreModule.forRoot(),
|
CoreModule.forRoot(),
|
||||||
ThemeModule.forRoot(),
|
ThemeModule.forRoot(),
|
||||||
|
UserModule.forRoot(),
|
||||||
|
|
||||||
],
|
],
|
||||||
bootstrap: [AppComponent],
|
bootstrap: [AppComponent],
|
||||||
|
providers: []
|
||||||
})
|
})
|
||||||
export class AppModule {
|
export class AppModule {
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
<nb-card>
|
||||||
|
<nb-card-header>
|
||||||
|
<span class="col-lg-10">{{agreement?.name}}</span>
|
||||||
|
<span class="col-lg-1">
|
||||||
|
<nb-icon icon="activity" [status]='agreement?.state == "ACTIVE" ? "success" : "danger" '>
|
||||||
|
</nb-icon>
|
||||||
|
</span>
|
||||||
|
</nb-card-header>
|
||||||
|
<nb-card-body>
|
||||||
|
<div>
|
||||||
|
<span>{{agreement?.producer.name}}<nb-icon icon="arrowhead-right"></nb-icon>
|
||||||
|
{{agreement?.consumer.name}}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<app-date-calendar [date]="agreement?.commenceDate"></app-date-calendar>
|
||||||
|
<app-date-calendar [date]="agreement?.expirationDate"></app-date-calendar>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<nb-accordion>
|
||||||
|
<nb-accordion-item *ngFor="let fragment of agreement.template.template.fragments">
|
||||||
|
<nb-accordion-item-header>
|
||||||
|
{{ fragment.name }}
|
||||||
|
<span style="justify-content: flex-end;">
|
||||||
|
{{ fragment.type | titlecase}}
|
||||||
|
</span>
|
||||||
|
</nb-accordion-item-header>
|
||||||
|
<nb-accordion-item-body>
|
||||||
|
{{fragment.text}}
|
||||||
|
</nb-accordion-item-body>
|
||||||
|
</nb-accordion-item>
|
||||||
|
</nb-accordion>
|
||||||
|
</div>
|
||||||
|
</nb-card-body>
|
||||||
|
</nb-card>
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
import { Component, Input, OnInit } from "@angular/core";
|
||||||
|
import { OrganizationDataSharingAgreement } from "thingbook-api/lib";
|
||||||
|
import { OrganizationService } from "../../organization.service";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'org-data-sharing-agreement',
|
||||||
|
templateUrl: './data-sharing-agreement.component.html',
|
||||||
|
styleUrls: ['./data-sharing-agreement.component.scss']
|
||||||
|
})
|
||||||
|
export class DataSharingAgreementComponent implements OnInit {
|
||||||
|
|
||||||
|
@Input() agreement: OrganizationDataSharingAgreement;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
<h3>{{org?.name}}</h3>
|
||||||
|
<nb-tabset fullWidth="true">
|
||||||
|
<nb-tab tabTitle="Data Sharing Agreements ({{ agreements?.length }})" class="container">
|
||||||
|
<ng-container *ngIf="agreements?.length > 0; else loading">
|
||||||
|
<nb-list class="col-lg-12">
|
||||||
|
<nb-list-item *ngFor="let a of agreements; odd as odd; even as even;"
|
||||||
|
[ngClass]="{row: true, odd: odd, even: even}">
|
||||||
|
<org-data-sharing-agreement [agreement]="a"></org-data-sharing-agreement>
|
||||||
|
</nb-list-item>
|
||||||
|
</nb-list>
|
||||||
|
</ng-container>
|
||||||
|
<ng-template #loading>
|
||||||
|
<div>Loading...</div>
|
||||||
|
</ng-template>
|
||||||
|
</nb-tab>
|
||||||
|
<nb-tab tabTitle="Data Sharing Templates">
|
||||||
|
<span>TBD</span>
|
||||||
|
</nb-tab>
|
||||||
|
</nb-tabset>
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
import { Component, OnInit } from "@angular/core";
|
||||||
|
import { ActivatedRoute, ParamMap } from "@angular/router";
|
||||||
|
import { switchMap } from "rxjs/operators";
|
||||||
|
import { Organization, OrganizationDataSharingAgreement } from "thingbook-api/lib";
|
||||||
|
import { OrganizationService } from "../../organization.service";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'org-detail',
|
||||||
|
templateUrl: './detail-page.component.html',
|
||||||
|
styleUrls: ['./detail-page.component.scss'],
|
||||||
|
})
|
||||||
|
export class OrganizationDetailPageComponent implements OnInit {
|
||||||
|
|
||||||
|
org: Organization;
|
||||||
|
agreements: OrganizationDataSharingAgreement[] = [];
|
||||||
|
|
||||||
|
constructor(private route: ActivatedRoute, private orgSvc: OrganizationService) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.route.paramMap.pipe(
|
||||||
|
switchMap((params: ParamMap) => {
|
||||||
|
return this.orgSvc.getOrganization(params.get('id'));
|
||||||
|
})
|
||||||
|
).subscribe(org => this.org = org);
|
||||||
|
|
||||||
|
this.route.paramMap.pipe(
|
||||||
|
switchMap((params: ParamMap) => {
|
||||||
|
return this.orgSvc.getOrganizationAgreements(params.get('id'));
|
||||||
|
})
|
||||||
|
).subscribe(agreements => {
|
||||||
|
this.agreements = agreements;
|
||||||
|
console.log(agreements);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
<div class="lists row">
|
||||||
|
<div class="col-md-12 col-lg-12 col-xxxl-12">
|
||||||
|
<nb-card class="list-card">
|
||||||
|
<nb-card-header>Organizations</nb-card-header>
|
||||||
|
<nb-card-body>
|
||||||
|
<nb-list>
|
||||||
|
<nb-list-item *ngFor="let o of orgs">
|
||||||
|
<span class="col-sm-6">{{o.name}}</span>
|
||||||
|
<span class="col-sm-3">{{o.domainName}}</span>
|
||||||
|
<app-verification-icon [value]=o?.verification?.verified></app-verification-icon>
|
||||||
|
<a [routerLink]="['/pages/org', o._id]"><span class="col-sm-2">Details...</span></a>
|
||||||
|
</nb-list-item>
|
||||||
|
</nb-list>
|
||||||
|
</nb-card-body>
|
||||||
|
</nb-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
@import '../../../../@theme/styles/themes';
|
||||||
|
|
||||||
|
@include nb-install-component() {
|
||||||
|
.list-card {
|
||||||
|
nb-card-header {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
nb-card-body {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { Component, OnInit } from "@angular/core";
|
||||||
|
import { Organization } from "thingbook-api/lib";
|
||||||
|
import { OrganizationService } from "../../organization.service";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'organization-list',
|
||||||
|
templateUrl: './list-page.component.html',
|
||||||
|
styleUrls: ['./list-page.component.scss']
|
||||||
|
})
|
||||||
|
export class OrganizationListPageComponent implements OnInit {
|
||||||
|
|
||||||
|
orgs: Organization[];
|
||||||
|
|
||||||
|
constructor(private orgSvc: OrganizationService) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.orgSvc.getOrganizations()
|
||||||
|
.subscribe(orgs => {
|
||||||
|
this.orgs = orgs;
|
||||||
|
console.log(this.orgs);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
34
src/app/modules/organization/organization.module.ts
Normal file
34
src/app/modules/organization/organization.module.ts
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { RouterModule } from '@angular/router';
|
||||||
|
import { OrganizationListPageComponent } from './components/list-page/list-page.component';
|
||||||
|
import { NbAccordionModule, NbCardModule, NbIconModule, NbListModule, NbTabsetModule } from '@nebular/theme';
|
||||||
|
import { ThemeModule } from '../../@theme/theme.module';
|
||||||
|
import { OrganizationDetailPageComponent } from './components/detail-page/detail-page.component';
|
||||||
|
import { DataSharingAgreementComponent } from './components/data-sharing-agreement/data-sharing-agreement.component';
|
||||||
|
import { WidgetsModule } from '../../widgets/widgets.module';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [
|
||||||
|
OrganizationListPageComponent,
|
||||||
|
OrganizationDetailPageComponent,
|
||||||
|
DataSharingAgreementComponent,
|
||||||
|
],
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
ThemeModule,
|
||||||
|
NbAccordionModule,
|
||||||
|
NbCardModule,
|
||||||
|
NbIconModule,
|
||||||
|
NbListModule,
|
||||||
|
NbTabsetModule,
|
||||||
|
RouterModule.forChild([
|
||||||
|
{ path: 'list', component: OrganizationListPageComponent },
|
||||||
|
{ path: ':id', component: OrganizationDetailPageComponent }
|
||||||
|
]),
|
||||||
|
WidgetsModule,
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class OrganizationModule { }
|
||||||
51
src/app/modules/organization/organization.service.ts
Normal file
51
src/app/modules/organization/organization.service.ts
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
import { HttpClient } from "@angular/common/http";
|
||||||
|
import { Injectable } from "@angular/core";
|
||||||
|
import { Observable, of } from "rxjs";
|
||||||
|
import { catchError, tap } from "rxjs/operators";
|
||||||
|
import { Organization, OrganizationDataSharingAgreement } from 'thingbook-api';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class OrganizationService {
|
||||||
|
|
||||||
|
constructor(private http: HttpClient) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
getOrganization(id): Observable<Organization> {
|
||||||
|
return this.http.get<Organization>(`http://localhost:3000/api/v1/organization/${id}`)
|
||||||
|
.pipe(
|
||||||
|
catchError(this.handleError<Organization>('getOrganization', null))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
getOrganizationAgreements(id): Observable<OrganizationDataSharingAgreement[]> {
|
||||||
|
return this.http.get<OrganizationDataSharingAgreement[]>(`http://localhost:3000/api/v1/organization/${id}/agreement`)
|
||||||
|
.pipe(
|
||||||
|
catchError(this.handleError<OrganizationDataSharingAgreement[]>('getOrganizationAgreements', []))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
getOrganizations(): Observable<Organization[]> {
|
||||||
|
return this.http.get<Organization[]>('http://localhost:3000/api/v1/organization')
|
||||||
|
.pipe(
|
||||||
|
catchError(this.handleError<Organization[]>('getOrganizations', []))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleError<T>(operation = 'operation', result?: T) {
|
||||||
|
return (error: any): Observable<T> => {
|
||||||
|
|
||||||
|
// TODO: send the error to remote logging infrastructure
|
||||||
|
console.error(error); // log to console instead
|
||||||
|
|
||||||
|
// TODO: better job of transforming error for user consumption
|
||||||
|
console.log(`${operation} failed: ${error.message}`);
|
||||||
|
|
||||||
|
// Let the app keep running by returning an empty result.
|
||||||
|
return of(result as T);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
17
src/app/modules/user/pages/profile.component.html
Normal file
17
src/app/modules/user/pages/profile.component.html
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
<nb-card>
|
||||||
|
<nb-card-header>{{user?.email}}</nb-card-header>
|
||||||
|
<nb-card-body>
|
||||||
|
<form>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="inputFirst" class="label">First name</label>
|
||||||
|
<input nbInput fullWidth id="inputFirst" ngModel [(ngModel)]="first"
|
||||||
|
placeholder="First name">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="inputLast" class="label">Last name</label>
|
||||||
|
<input type="text" nbInput fullWidth id="inputLast" placeholder="Last name">
|
||||||
|
</div>
|
||||||
|
<button type="submit" nbButton hero status="primary">Update</button>
|
||||||
|
</form>
|
||||||
|
</nb-card-body>
|
||||||
|
</nb-card>
|
||||||
15
src/app/modules/user/pages/profile.component.scss
Normal file
15
src/app/modules/user/pages/profile.component.scss
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
nb-checkbox {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-inline [fullWidth] {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-inline > * {
|
||||||
|
margin: 0 1.5rem 1.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
nb-card.inline-form-card nb-card-body {
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
38
src/app/modules/user/pages/profile.component.ts
Normal file
38
src/app/modules/user/pages/profile.component.ts
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
import { Component, OnDestroy, OnInit } from "@angular/core";
|
||||||
|
import { Subject } from "rxjs";
|
||||||
|
import { takeUntil } from "rxjs/operators";
|
||||||
|
import { User, UserService } from "../user.service";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'user-profile',
|
||||||
|
templateUrl: './profile.component.html',
|
||||||
|
styleUrls: ['./profile.component.scss']
|
||||||
|
})
|
||||||
|
export class UserProfileComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
|
private destroy$: Subject<void> = new Subject<void>();
|
||||||
|
public user: User;
|
||||||
|
public first: string = "Blah";
|
||||||
|
public last: string;
|
||||||
|
|
||||||
|
constructor(private userService: UserService) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.userService.onUserStatus()
|
||||||
|
.pipe(takeUntil(this.destroy$))
|
||||||
|
.subscribe((user: any) => {
|
||||||
|
this.user = user;
|
||||||
|
this.user.first = 'Blargle';
|
||||||
|
this.first = user?.first || 'Foo!';
|
||||||
|
this.last = user?.last || 'Bar!';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.destroy$.next();
|
||||||
|
this.destroy$.complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
67
src/app/modules/user/user.module.ts
Normal file
67
src/app/modules/user/user.module.ts
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
import { ModuleWithProviders, NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { NbPasswordAuthStrategy, NbAuthModule } from '@nebular/auth';
|
||||||
|
import { HTTP_INTERCEPTORS } from '@angular/common/http';
|
||||||
|
import { LoginInterceptor } from '../../user.interceptors';
|
||||||
|
import { RouterModule } from '@angular/router';
|
||||||
|
import { UserProfileComponent } from './pages/profile.component';
|
||||||
|
import { ThemeModule } from '../../@theme/theme.module';
|
||||||
|
import { NbCardModule, NbCheckboxComponent, NbCheckboxModule, NbInputModule, NbMenuModule } from '@nebular/theme';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [
|
||||||
|
UserProfileComponent,
|
||||||
|
],
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
ThemeModule,
|
||||||
|
NbMenuModule,
|
||||||
|
NbCardModule,
|
||||||
|
NbCheckboxModule,
|
||||||
|
NbInputModule,
|
||||||
|
FormsModule,
|
||||||
|
RouterModule.forChild([
|
||||||
|
{ path: 'profile', component: UserProfileComponent }
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
exports: [
|
||||||
|
UserProfileComponent,
|
||||||
|
RouterModule,
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class UserModule {
|
||||||
|
|
||||||
|
static forRoot(): ModuleWithProviders<UserModule>[] {
|
||||||
|
return [{
|
||||||
|
ngModule: UserModule,
|
||||||
|
providers: [
|
||||||
|
{ provide: HTTP_INTERCEPTORS, useClass: LoginInterceptor, multi: true }
|
||||||
|
],
|
||||||
|
},
|
||||||
|
NbAuthModule.forRoot({
|
||||||
|
strategies: [
|
||||||
|
NbPasswordAuthStrategy.setup({
|
||||||
|
name: 'email',
|
||||||
|
baseEndpoint: 'http://localhost:3000/api/v1/user',
|
||||||
|
login: {
|
||||||
|
endpoint: '/login',
|
||||||
|
requireValidToken: false,
|
||||||
|
},
|
||||||
|
register: {
|
||||||
|
endpoint: '/register',
|
||||||
|
requireValidToken: false,
|
||||||
|
},
|
||||||
|
logout: {
|
||||||
|
method: 'get',
|
||||||
|
endpoint: '/logout',
|
||||||
|
requireValidToken: false,
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
forms: {},
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
16
src/app/modules/user/user.service.spec.ts
Normal file
16
src/app/modules/user/user.service.spec.ts
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { UserServiceImpl } from './user.service.impl';
|
||||||
|
|
||||||
|
describe('UserService', () => {
|
||||||
|
let service: UserServiceImpl;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
service = TestBed.inject(UserServiceImpl);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
27
src/app/modules/user/user.service.ts
Normal file
27
src/app/modules/user/user.service.ts
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Observable, of as ObservableOf } from 'rxjs';
|
||||||
|
import { User } from 'thingbook-api';
|
||||||
|
import { LoginInterceptor } from '../../user.interceptors';
|
||||||
|
|
||||||
|
export { User };
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class UserService {
|
||||||
|
|
||||||
|
private user: User = undefined;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
LoginInterceptor.s.subscribe({
|
||||||
|
next: (v) => {
|
||||||
|
this.user = v;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public onUserStatus(): Observable<User> {
|
||||||
|
return ObservableOf(this.user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
<nb-card size="giant">
|
|
||||||
<nb-tabset fullWidth>
|
|
||||||
|
|
||||||
<nb-tab tabTitle="Contacts">
|
|
||||||
<nb-list>
|
|
||||||
<nb-list-item class="contact" *ngFor="let c of contacts">
|
|
||||||
<nb-user [picture]="c.user.picture" [name]="c.user.name" [title]="c.type" size="large"></nb-user>
|
|
||||||
<nb-icon icon="phone-outline" pack="eva"></nb-icon>
|
|
||||||
</nb-list-item>
|
|
||||||
</nb-list>
|
|
||||||
</nb-tab>
|
|
||||||
|
|
||||||
<nb-tab tabTitle="Recent">
|
|
||||||
<nb-list>
|
|
||||||
<nb-list-item class="contact" *ngFor="let c of recent">
|
|
||||||
<nb-user [picture]="c.user.picture" [name]="c.user.name" [title]="c.type" size="large"></nb-user>
|
|
||||||
<span class="caption">{{ c.time | date: 'shortTime' }}</span>
|
|
||||||
</nb-list-item>
|
|
||||||
</nb-list>
|
|
||||||
</nb-tab>
|
|
||||||
|
|
||||||
</nb-tabset>
|
|
||||||
</nb-card>
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
@import '../../../@theme/styles/themes';
|
|
||||||
|
|
||||||
@include nb-install-component() {
|
|
||||||
nb-card {
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
nb-tabset {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
::ng-deep ul {
|
|
||||||
// make same size as card header
|
|
||||||
padding-bottom: 1px;
|
|
||||||
::ng-deep .tab-link {
|
|
||||||
padding: 1.25rem 2rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nb-tab {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contact {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
&:first-child {
|
|
||||||
border-top: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
import { Component, OnDestroy } from '@angular/core';
|
|
||||||
import { takeWhile } from 'rxjs/operators';
|
|
||||||
import { forkJoin } from 'rxjs';
|
|
||||||
|
|
||||||
import { Contacts, RecentUsers, UserData } from '../../../@core/data/users';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'ngx-contacts',
|
|
||||||
styleUrls: ['./contacts.component.scss'],
|
|
||||||
templateUrl: './contacts.component.html',
|
|
||||||
})
|
|
||||||
export class ContactsComponent implements OnDestroy {
|
|
||||||
|
|
||||||
private alive = true;
|
|
||||||
|
|
||||||
contacts: any[];
|
|
||||||
recent: any[];
|
|
||||||
|
|
||||||
constructor(private userService: UserData) {
|
|
||||||
forkJoin(
|
|
||||||
this.userService.getContacts(),
|
|
||||||
this.userService.getRecentUsers(),
|
|
||||||
)
|
|
||||||
.pipe(takeWhile(() => this.alive))
|
|
||||||
.subscribe(([contacts, recent]: [Contacts[], RecentUsers[]]) => {
|
|
||||||
this.contacts = contacts;
|
|
||||||
this.recent = recent;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnDestroy() {
|
|
||||||
this.alive = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -21,10 +21,6 @@
|
||||||
<ngx-rooms></ngx-rooms>
|
<ngx-rooms></ngx-rooms>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-xxxl-3 col-xxl-4 col-lg-7 col-md-6">
|
|
||||||
<ngx-contacts></ngx-contacts>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-xxxl-3 col-xxl-4 col-lg-5 col-md-6">
|
<div class="col-xxxl-3 col-xxl-4 col-lg-5 col-md-6">
|
||||||
<ngx-solar [chartValue]="solarValue"></ngx-solar>
|
<ngx-solar [chartValue]="solarValue"></ngx-solar>
|
||||||
|
|
||||||
|
|
@ -39,4 +35,4 @@
|
||||||
<div class="col-xxxl-6 col-xxl-12 col-md-7">
|
<div class="col-xxxl-6 col-xxl-12 col-md-7">
|
||||||
<ngx-security-cameras></ngx-security-cameras>
|
<ngx-security-cameras></ngx-security-cameras>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -15,7 +15,6 @@ import { NgxEchartsModule } from 'ngx-echarts';
|
||||||
import { ThemeModule } from '../../@theme/theme.module';
|
import { ThemeModule } from '../../@theme/theme.module';
|
||||||
import { DashboardComponent } from './dashboard.component';
|
import { DashboardComponent } from './dashboard.component';
|
||||||
import { StatusCardComponent } from './status-card/status-card.component';
|
import { StatusCardComponent } from './status-card/status-card.component';
|
||||||
import { ContactsComponent } from './contacts/contacts.component';
|
|
||||||
import { RoomsComponent } from './rooms/rooms.component';
|
import { RoomsComponent } from './rooms/rooms.component';
|
||||||
import { RoomSelectorComponent } from './rooms/room-selector/room-selector.component';
|
import { RoomSelectorComponent } from './rooms/room-selector/room-selector.component';
|
||||||
import { TemperatureComponent } from './temperature/temperature.component';
|
import { TemperatureComponent } from './temperature/temperature.component';
|
||||||
|
|
@ -51,7 +50,6 @@ import { FormsModule } from '@angular/forms';
|
||||||
DashboardComponent,
|
DashboardComponent,
|
||||||
StatusCardComponent,
|
StatusCardComponent,
|
||||||
TemperatureDraggerComponent,
|
TemperatureDraggerComponent,
|
||||||
ContactsComponent,
|
|
||||||
RoomSelectorComponent,
|
RoomSelectorComponent,
|
||||||
TemperatureComponent,
|
TemperatureComponent,
|
||||||
RoomsComponent,
|
RoomsComponent,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,11 @@
|
||||||
import { NbMenuItem } from '@nebular/theme';
|
import { NbMenuItem } from '@nebular/theme';
|
||||||
|
|
||||||
export const MENU_ITEMS: NbMenuItem[] = [
|
export const MENU_ITEMS: NbMenuItem[] = [
|
||||||
|
{
|
||||||
|
title: 'Organizations',
|
||||||
|
icon: 'keypad-outline',
|
||||||
|
link: '/pages/org/list',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: 'E-commerce',
|
title: 'E-commerce',
|
||||||
icon: 'shopping-cart-outline',
|
icon: 'shopping-cart-outline',
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,16 @@ const routes: Routes = [{
|
||||||
path: 'dashboard',
|
path: 'dashboard',
|
||||||
component: ECommerceComponent,
|
component: ECommerceComponent,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'user',
|
||||||
|
loadChildren: () => import('../modules/user/user.module')
|
||||||
|
.then(m => m.UserModule)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'org',
|
||||||
|
loadChildren: () => import('../modules/organization/organization.module')
|
||||||
|
.then(m => m.OrganizationModule)
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'iot-dashboard',
|
path: 'iot-dashboard',
|
||||||
component: DashboardComponent,
|
component: DashboardComponent,
|
||||||
|
|
|
||||||
22
src/app/user.interceptors.ts
Normal file
22
src/app/user.interceptors.ts
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse } from "@angular/common/http";
|
||||||
|
import { Injectable } from "@angular/core";
|
||||||
|
import { BehaviorSubject, Observable, Subject } from "rxjs";
|
||||||
|
import { filter, tap } from "rxjs/operators";
|
||||||
|
import * as api from 'thingbook-api';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class LoginInterceptor implements HttpInterceptor {
|
||||||
|
|
||||||
|
public static s: BehaviorSubject<api.User> = new BehaviorSubject<api.User>(undefined);
|
||||||
|
|
||||||
|
intercept(httpRequest: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
||||||
|
return next.handle(httpRequest).pipe(
|
||||||
|
tap((event: HttpResponse<any>) => {
|
||||||
|
if (event instanceof HttpResponse && event.url.endsWith('/user/login')) {
|
||||||
|
LoginInterceptor.s.next(<api.User>event.body);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
6
src/app/widgets/date/date-calendar.component.html
Normal file
6
src/app/widgets/date/date-calendar.component.html
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
<time datetime="datestr" class="date-as-calendar inline-flex {{size}}">
|
||||||
|
<span class="weekday">{{weekday}}</span>
|
||||||
|
<span class="day">{{day}}</span>
|
||||||
|
<span class="month">{{month}}</span>
|
||||||
|
<span class="year">{{year}}</span>
|
||||||
|
</time>
|
||||||
175
src/app/widgets/date/date-calendar.component.scss
Normal file
175
src/app/widgets/date/date-calendar.component.scss
Normal file
|
|
@ -0,0 +1,175 @@
|
||||||
|
/****************************************/
|
||||||
|
/* Styling rules, such as font and colors */
|
||||||
|
.date-as-calendar {
|
||||||
|
font-variant: normal;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: normal;
|
||||||
|
font-family: "Helvetica", "Arial", sans-serif;
|
||||||
|
|
||||||
|
/* It seems vertical-align: baseline does not work correctly with display: inline-flex. */
|
||||||
|
vertical-align: top;
|
||||||
|
|
||||||
|
/* margin: 1ex; */
|
||||||
|
|
||||||
|
color: black;
|
||||||
|
background: white;
|
||||||
|
background : linear-gradient(to bottom right, #FFF 0%, #EEE 100%);
|
||||||
|
|
||||||
|
border: 1px solid #888;
|
||||||
|
border-radius: 3px;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
box-shadow: 2px 2px 2px -2px black;
|
||||||
|
}
|
||||||
|
.date-as-calendar .weekday,
|
||||||
|
.date-as-calendar .day,
|
||||||
|
.date-as-calendar .month,
|
||||||
|
.date-as-calendar .year {
|
||||||
|
text-align: center;
|
||||||
|
line-height: 1.0;
|
||||||
|
}
|
||||||
|
.date-as-calendar .month {
|
||||||
|
font-family: "Oswald", sans-serif;
|
||||||
|
text-transform: uppercase;
|
||||||
|
background: #B11;
|
||||||
|
background : linear-gradient(to bottom right, #D66 0%, #A00 100%);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************/
|
||||||
|
/* Layout rules using position: absolute and pixels. */
|
||||||
|
.position-pixels.date-as-calendar {
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
}
|
||||||
|
.position-pixels.date-as-calendar .weekday,
|
||||||
|
.position-pixels.date-as-calendar .day,
|
||||||
|
.position-pixels.date-as-calendar .month,
|
||||||
|
.position-pixels.date-as-calendar .year {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 1em;
|
||||||
|
}
|
||||||
|
.position-pixels.date-as-calendar .month {
|
||||||
|
top: 0px;
|
||||||
|
font-size: 12px;
|
||||||
|
padding: 2px 0;
|
||||||
|
}
|
||||||
|
.position-pixels.date-as-calendar .weekday {
|
||||||
|
top: 16px;
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
.position-pixels.date-as-calendar .day {
|
||||||
|
top: 26px;
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
.position-pixels.date-as-calendar .year {
|
||||||
|
top: 50px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************/
|
||||||
|
/* Layout rules using position: absolute and relative dimensions using em. */
|
||||||
|
.position-em.date-as-calendar {
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
width: 4em;
|
||||||
|
height: 4em;
|
||||||
|
}
|
||||||
|
.position-em.date-as-calendar .weekday,
|
||||||
|
.position-em.date-as-calendar .day,
|
||||||
|
.position-em.date-as-calendar .month,
|
||||||
|
.position-em.date-as-calendar .year {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 1em;
|
||||||
|
}
|
||||||
|
.position-em.date-as-calendar .month {
|
||||||
|
top: 0px;
|
||||||
|
font-size: 0.75em;
|
||||||
|
padding: 0.1em 0;
|
||||||
|
}
|
||||||
|
.position-em.date-as-calendar .weekday {
|
||||||
|
top: 1.6em;
|
||||||
|
font-size: 0.6125em;
|
||||||
|
}
|
||||||
|
.position-em.date-as-calendar .day {
|
||||||
|
top: 1.1em;
|
||||||
|
font-size: 1.5em
|
||||||
|
}
|
||||||
|
.position-em.date-as-calendar .year {
|
||||||
|
bottom: 0px;
|
||||||
|
font-size: 0.87750em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************/
|
||||||
|
/* Layout rules using display: inline-flex and relative dimensions using em. */
|
||||||
|
.inline-flex.date-as-calendar {
|
||||||
|
display: inline-flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
width: 4em;
|
||||||
|
height: 4em;
|
||||||
|
}
|
||||||
|
.inline-flex.date-as-calendar .weekday,
|
||||||
|
.inline-flex.date-as-calendar .day,
|
||||||
|
.inline-flex.date-as-calendar .month,
|
||||||
|
.inline-flex.date-as-calendar .year {
|
||||||
|
display: block;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
}
|
||||||
|
.inline-flex.date-as-calendar .month {
|
||||||
|
order: 1;
|
||||||
|
font-size: 0.75em;
|
||||||
|
padding: 0.1em 0;
|
||||||
|
}
|
||||||
|
.inline-flex.date-as-calendar .weekday {
|
||||||
|
order: 2;
|
||||||
|
font-size: 0.6125em;
|
||||||
|
}
|
||||||
|
.inline-flex.date-as-calendar .day {
|
||||||
|
order: 3;
|
||||||
|
font-size: 1.5em;
|
||||||
|
}
|
||||||
|
.inline-flex.date-as-calendar .year {
|
||||||
|
order: 4;
|
||||||
|
font-size: 0.87750em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************/
|
||||||
|
/* Multiple sizes. */
|
||||||
|
.date-as-calendar.size0_5x {
|
||||||
|
font-size: 8px;
|
||||||
|
}
|
||||||
|
.date-as-calendar.size0_75x {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
.date-as-calendar.size1x {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
.date-as-calendar.size1_25x {
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
.date-as-calendar.size1_5x {
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
.date-as-calendar.size1_75x {
|
||||||
|
font-size: 28px;
|
||||||
|
}
|
||||||
|
.date-as-calendar.size2x {
|
||||||
|
font-size: 32px;
|
||||||
|
}
|
||||||
|
.date-as-calendar.size3x {
|
||||||
|
font-size: 48px;
|
||||||
|
}
|
||||||
58
src/app/widgets/date/date-calendar.component.ts
Normal file
58
src/app/widgets/date/date-calendar.component.ts
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
import { getLocaleDateTimeFormat } from "@angular/common";
|
||||||
|
import { Component, Input, OnInit } from "@angular/core";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-date-calendar',
|
||||||
|
templateUrl: './date-calendar.component.html',
|
||||||
|
styleUrls: ['./date-calendar.component.scss']
|
||||||
|
})
|
||||||
|
export class DateCalendarComponent implements OnInit {
|
||||||
|
@Input() date: Date | string;
|
||||||
|
@Input() size: string = "size1x";
|
||||||
|
|
||||||
|
datestr: string;
|
||||||
|
weekday: string;
|
||||||
|
day: string;
|
||||||
|
month: string;
|
||||||
|
year: string;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
if (typeof this.date === 'string') {
|
||||||
|
this.date = new Date(this.date);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.datestr = this.date.toISOString();
|
||||||
|
|
||||||
|
const dateParts: any = this.extract(this.date);
|
||||||
|
|
||||||
|
this.weekday = dateParts.weekday;
|
||||||
|
this.day = dateParts.day;
|
||||||
|
this.month = dateParts.month;
|
||||||
|
this.year = dateParts.year;
|
||||||
|
}
|
||||||
|
|
||||||
|
private extract(date: Date): object {
|
||||||
|
const formatter: Intl.DateTimeFormat = new Intl.DateTimeFormat(navigator.language, {
|
||||||
|
weekday: 'long',
|
||||||
|
year: 'numeric',
|
||||||
|
month: 'short',
|
||||||
|
day: 'numeric',
|
||||||
|
hour: 'numeric',
|
||||||
|
minute: 'numeric',
|
||||||
|
second: 'numeric',
|
||||||
|
hour12: true,
|
||||||
|
timeZone: 'UTC'
|
||||||
|
});
|
||||||
|
const parts: Intl.DateTimeFormatPart[] = formatter.formatToParts(date);
|
||||||
|
|
||||||
|
let result = {}
|
||||||
|
for (let p of parts) {
|
||||||
|
result[p.type] = p.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
<nb-icon [icon]='value ? "shield-outline" : "shield-off-outline"' [status]='value ? "success" : "danger"'>
|
||||||
|
</nb-icon>
|
||||||
12
src/app/widgets/verification/verification-icon.component.ts
Normal file
12
src/app/widgets/verification/verification-icon.component.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { Component, Input } from "@angular/core";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-verification-icon',
|
||||||
|
templateUrl: './verification-icon.component.html',
|
||||||
|
styleUrls: ['./verification-icon.component.scss']
|
||||||
|
})
|
||||||
|
export class VerificationIconComponent {
|
||||||
|
|
||||||
|
@Input() value: boolean;
|
||||||
|
|
||||||
|
}
|
||||||
19
src/app/widgets/widgets.module.ts
Normal file
19
src/app/widgets/widgets.module.ts
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
import { NgModule } from "@angular/core";
|
||||||
|
import { NbIconModule } from "@nebular/theme";
|
||||||
|
import { DateCalendarComponent } from "./date/date-calendar.component";
|
||||||
|
import { VerificationIconComponent } from "./verification/verification-icon.component";
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [
|
||||||
|
VerificationIconComponent,
|
||||||
|
DateCalendarComponent,
|
||||||
|
],
|
||||||
|
exports: [
|
||||||
|
VerificationIconComponent,
|
||||||
|
DateCalendarComponent,
|
||||||
|
],
|
||||||
|
imports: [
|
||||||
|
NbIconModule,
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class WidgetsModule { }
|
||||||
Loading…
Add table
Add a link
Reference in a new issue