before frontend login
This commit is contained in:
Generated
+143
-3
@@ -1382,6 +1382,14 @@
|
||||
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
|
||||
"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="
|
||||
},
|
||||
"define-properties": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
|
||||
"integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
|
||||
"requires": {
|
||||
"object-keys": "^1.0.12"
|
||||
}
|
||||
},
|
||||
"define-property": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
|
||||
@@ -1571,6 +1579,33 @@
|
||||
"prr": "~1.0.1"
|
||||
}
|
||||
},
|
||||
"es-abstract": {
|
||||
"version": "1.16.0",
|
||||
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.16.0.tgz",
|
||||
"integrity": "sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg==",
|
||||
"requires": {
|
||||
"es-to-primitive": "^1.2.0",
|
||||
"function-bind": "^1.1.1",
|
||||
"has": "^1.0.3",
|
||||
"has-symbols": "^1.0.0",
|
||||
"is-callable": "^1.1.4",
|
||||
"is-regex": "^1.0.4",
|
||||
"object-inspect": "^1.6.0",
|
||||
"object-keys": "^1.1.1",
|
||||
"string.prototype.trimleft": "^2.1.0",
|
||||
"string.prototype.trimright": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"es-to-primitive": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz",
|
||||
"integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==",
|
||||
"requires": {
|
||||
"is-callable": "^1.1.4",
|
||||
"is-date-object": "^1.0.1",
|
||||
"is-symbol": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"escape-html": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
||||
@@ -2764,6 +2799,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"function-bind": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
|
||||
},
|
||||
"gauge": {
|
||||
"version": "2.7.4",
|
||||
"resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
|
||||
@@ -2982,12 +3022,25 @@
|
||||
"har-schema": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"has": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
|
||||
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
|
||||
"requires": {
|
||||
"function-bind": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
|
||||
"dev": true
|
||||
},
|
||||
"has-symbols": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz",
|
||||
"integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q="
|
||||
},
|
||||
"has-unicode": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
|
||||
@@ -3235,6 +3288,11 @@
|
||||
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
|
||||
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
|
||||
},
|
||||
"is-callable": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz",
|
||||
"integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA=="
|
||||
},
|
||||
"is-data-descriptor": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
|
||||
@@ -3253,6 +3311,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"is-date-object": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
|
||||
"integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY="
|
||||
},
|
||||
"is-descriptor": {
|
||||
"version": "0.1.6",
|
||||
"resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
|
||||
@@ -3340,6 +3403,14 @@
|
||||
"resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
|
||||
"integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o="
|
||||
},
|
||||
"is-regex": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
|
||||
"integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
|
||||
"requires": {
|
||||
"has": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"is-relative": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz",
|
||||
@@ -3354,6 +3425,14 @@
|
||||
"integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
|
||||
"dev": true
|
||||
},
|
||||
"is-symbol": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz",
|
||||
"integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==",
|
||||
"requires": {
|
||||
"has-symbols": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"is-typedarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
|
||||
@@ -4182,6 +4261,16 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"object-inspect": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz",
|
||||
"integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ=="
|
||||
},
|
||||
"object-keys": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
|
||||
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="
|
||||
},
|
||||
"object-visit": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
|
||||
@@ -4201,6 +4290,15 @@
|
||||
"isobject": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"object.getownpropertydescriptors": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz",
|
||||
"integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=",
|
||||
"requires": {
|
||||
"define-properties": "^1.1.2",
|
||||
"es-abstract": "^1.5.1"
|
||||
}
|
||||
},
|
||||
"object.map": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz",
|
||||
@@ -4863,9 +4961,9 @@
|
||||
}
|
||||
},
|
||||
"rpclibrary": {
|
||||
"version": "1.3.17",
|
||||
"resolved": "https://registry.npmjs.org/rpclibrary/-/rpclibrary-1.3.17.tgz",
|
||||
"integrity": "sha512-ZdhZ1TSDO+bcz5kCJ7Ol+YAAyYpwg7YI/hETS4vv3RYerUEQVZSZjcm22J5a91RnQVN2SRiXzdoXbbFb/Renog==",
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/rpclibrary/-/rpclibrary-1.4.0.tgz",
|
||||
"integrity": "sha512-JUU7+HymV2ZTI+NrIVOiIr5LGFoRsPq4k/ffdUonqIpd9fjOHBQ2/PFLVXx9z94+dKxdqN8/D9ZXPwU03ovZrg==",
|
||||
"requires": {
|
||||
"bsock": "^0.1.9",
|
||||
"http": "0.0.0",
|
||||
@@ -5403,6 +5501,24 @@
|
||||
"strip-ansi": "^5.1.0"
|
||||
}
|
||||
},
|
||||
"string.prototype.trimleft": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz",
|
||||
"integrity": "sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==",
|
||||
"requires": {
|
||||
"define-properties": "^1.1.3",
|
||||
"function-bind": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"string.prototype.trimright": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz",
|
||||
"integrity": "sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==",
|
||||
"requires": {
|
||||
"define-properties": "^1.1.3",
|
||||
"function-bind": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||
@@ -5842,6 +5958,15 @@
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
|
||||
},
|
||||
"util.promisify": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz",
|
||||
"integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==",
|
||||
"requires": {
|
||||
"define-properties": "^1.1.2",
|
||||
"object.getownpropertydescriptors": "^2.0.3"
|
||||
}
|
||||
},
|
||||
"utils-merge": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
|
||||
@@ -6080,6 +6205,21 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"xml2js": {
|
||||
"version": "0.4.22",
|
||||
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.22.tgz",
|
||||
"integrity": "sha512-MWTbxAQqclRSTnehWWe5nMKzI3VmJ8ltiJEco8akcC6j3miOhjjfzKum5sId+CWhfxdOs/1xauYr8/ZDBtQiRw==",
|
||||
"requires": {
|
||||
"sax": ">=0.6.0",
|
||||
"util.promisify": "~1.0.0",
|
||||
"xmlbuilder": "~11.0.0"
|
||||
}
|
||||
},
|
||||
"xmlbuilder": {
|
||||
"version": "11.0.1",
|
||||
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
|
||||
"integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA=="
|
||||
},
|
||||
"xtend": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||
|
||||
+4
-3
@@ -9,7 +9,7 @@
|
||||
"build-backend": "tsc; npm run webpack",
|
||||
"build-frontend": "npm run build-dashboard; cp node_modules/rpclibrary/js/browser/rpclibrary.browser.js ./dist/static/FrontblockLib.js",
|
||||
"build-dashboard": "cd src/frontend; npm i && npm run build; mkdir ../../dist/static; cp -r dist/* ../../dist/static",
|
||||
"clean": "rm -rf lib static plugins conf dist widget .rpt2_cache *.js *.ts src/frontend/dist data",
|
||||
"clean": "rm -rf lib static plugins conf dist/static widget .rpt2_cache *.js *.ts src/frontend/dist data",
|
||||
"update-frontblock": "npm remove frontblock frontblock-generic; npm install frontblock-generic@latest frontblock@latest",
|
||||
"webpack": "webpack --config src/backend/webpack.prod.js --progress --colors"
|
||||
},
|
||||
@@ -37,13 +37,14 @@
|
||||
"node-fetch": "^2.6.0",
|
||||
"path": "^0.12.7",
|
||||
"rimraf": "^3.0.0",
|
||||
"rpclibrary": "^1.3.17",
|
||||
"rpclibrary": "^1.4.0",
|
||||
"simple-git": "^1.124.0",
|
||||
"spawn-sync": "^2.0.0",
|
||||
"sqlite3": "^4.1.0",
|
||||
"trash": "^6.0.0",
|
||||
"upgiter": "^1.0.4",
|
||||
"uuid": "^3.3.3"
|
||||
"uuid": "^3.3.3",
|
||||
"xml2js": "^0.4.22"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/express": "^4.17.0",
|
||||
|
||||
@@ -3,52 +3,26 @@
|
||||
import { getLogger } from 'frontblock-generic/Types';
|
||||
import { promises as fs, mkdirSync } from "fs"
|
||||
import { RPCServer } from 'rpclibrary'
|
||||
import { AdminConf, TableDefiniton } from './Types';
|
||||
import { RPCConfigLoader } from './RPCConfigLoader';
|
||||
import { RPCPluginLoader } from './PluginLoader';
|
||||
import { AdminConf, TableDefiniton } from '../Types/Types';
|
||||
import { RPCConfigLoader } from '../Components/RPCConfigLoader';
|
||||
import * as Path from 'path'
|
||||
import Knex = require('knex');
|
||||
import http = require('http');
|
||||
import express = require('express');
|
||||
import { TableDefinitionExporter } from './Interfaces';
|
||||
import { FrontworkEventBus } from './Eventbus';
|
||||
import * as Knex from 'knex';
|
||||
import * as http from 'http';
|
||||
import * as express from 'express';
|
||||
import { TableDefinitionExporter } from '../Types/Interfaces';
|
||||
import { FrontworkComponent } from '../Types/FrontworkComponent';
|
||||
|
||||
const logger = getLogger("admin", 'debug')
|
||||
|
||||
export class FrontworkAdmin
|
||||
implements TableDefinitionExporter {
|
||||
knex:Knex
|
||||
config: RPCConfigLoader<AdminConf>
|
||||
|
||||
private express
|
||||
private httpServer
|
||||
private pluginLoader:RPCPluginLoader = new RPCPluginLoader(this)
|
||||
private eventBus:FrontworkEventBus = new FrontworkEventBus(this)
|
||||
config: RPCConfigLoader<AdminConf>
|
||||
knex:Knex
|
||||
|
||||
constructor(){}
|
||||
|
||||
async start(){
|
||||
this.initConfig()
|
||||
await this.makeKnex()
|
||||
this.startWebsocket()
|
||||
this.startWebserver()
|
||||
}
|
||||
|
||||
protected configChangeHandler = (conf:AdminConf, key?:string) => {
|
||||
if(key === 'dbConf'){
|
||||
this.makeKnex()
|
||||
}
|
||||
}
|
||||
|
||||
getConfigKey(key:string){
|
||||
return this.config.getConfigKey(key)
|
||||
}
|
||||
|
||||
setConfigKey(key:string, value:any){
|
||||
return this.config.setConfigKey(key, value)
|
||||
}
|
||||
|
||||
private initConfig(){
|
||||
constructor(private components: FrontworkComponent[]){
|
||||
this.config = new RPCConfigLoader<AdminConf>({
|
||||
name: "FrontworkAdminConf",
|
||||
getDefaultConfig: () => {
|
||||
@@ -65,20 +39,44 @@ implements TableDefinitionExporter {
|
||||
}
|
||||
}
|
||||
}, './config', this.configChangeHandler)
|
||||
|
||||
components.forEach(c => {
|
||||
c.admin = this
|
||||
if(c.onSetAdmin) c.onSetAdmin(this)
|
||||
})
|
||||
}
|
||||
|
||||
async start(){
|
||||
await this.makeKnex()
|
||||
this.startWebsocket()
|
||||
await Promise.all( this.components.map(c => c.initialize?c.initialize():undefined ))
|
||||
this.startWebserver()
|
||||
|
||||
}
|
||||
|
||||
protected configChangeHandler = (conf:AdminConf, key?:string) => {
|
||||
if(key === 'dbConf'){
|
||||
this.makeKnex()
|
||||
}
|
||||
}
|
||||
|
||||
getConfigKey(key:string){
|
||||
return this.config.getConfigKey(key)
|
||||
}
|
||||
|
||||
setConfigKey(key:string, value:any){
|
||||
return this.config.setConfigKey(key, value)
|
||||
}
|
||||
|
||||
getTableDefinitions(): TableDefiniton[]{
|
||||
return [
|
||||
this.eventBus,
|
||||
...this.pluginLoader.getPlugins()
|
||||
...this.components
|
||||
].flatMap(exporter => exporter.getTableDefinitions())
|
||||
}
|
||||
|
||||
private startWebsocket(){
|
||||
new RPCServer(20000, [
|
||||
this.config,
|
||||
this.pluginLoader,
|
||||
this.eventBus
|
||||
...this.components,
|
||||
])
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import { RPCExporter } from "rpclibrary"
|
||||
import { FrontworkAdmin } from "../../Admin/Admin"
|
||||
import { TableDefiniton } from "../../Types/Types"
|
||||
import { PrivilegedRPCExporter } from "../../Types/PrivilegedRPCExporter"
|
||||
import { FrontworkComponent } from "../../Types/FrontworkComponent"
|
||||
|
||||
export class Debugger
|
||||
implements FrontworkComponent<any,any>{
|
||||
public admin: FrontworkAdmin
|
||||
name = "Debugger"
|
||||
|
||||
|
||||
constructor(private exporters: PrivilegedRPCExporter[]){
|
||||
}
|
||||
|
||||
exportRPCs(){
|
||||
|
||||
return [{
|
||||
name: 'getTable',
|
||||
call: async(table:string) => this.admin.knex.select('*').from(table)
|
||||
},
|
||||
...this.exporters.flatMap(e => e.exportRPCs()),
|
||||
...this.exporters.flatMap(e => e.exportRPCFeatures().flatMap(e => e.exportRPCs()))]
|
||||
}
|
||||
|
||||
exportRPCFeatures(): RPCExporter<any, any, {}>[] {
|
||||
return []
|
||||
}
|
||||
|
||||
getTableDefinitions(): TableDefiniton[] {
|
||||
return []
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
import { RPCExporter, SubscriptionResponse, ErrorResponse, SuccessResponse } from "rpclibrary";
|
||||
import { FrontworkAdmin } from "./Admin";
|
||||
import { TableDefinitionExporter } from "./Interfaces";
|
||||
import { FrontworkAdmin } from "../Admin/Admin";
|
||||
import { TableDefinitionExporter } from "../Types/Interfaces";
|
||||
import { getLogger } from 'frontblock-generic/Types';
|
||||
|
||||
import * as uuid from 'uuid/v4'
|
||||
import { TableDefiniton } from "../Types/Types";
|
||||
|
||||
export type NotificationSeverity = 'Info' | 'Important' | 'Error'
|
||||
|
||||
@@ -84,11 +85,11 @@ implements RPCExporter<EventbusIfc, "Eventbus">, TableDefinitionExporter {
|
||||
}]
|
||||
}
|
||||
|
||||
getTableDefinitions(){
|
||||
getTableDefinitions(): TableDefiniton[]{
|
||||
return [{
|
||||
name: 'notifications',
|
||||
tableBuilder: (table) => {
|
||||
table.increments('ID');
|
||||
table.increments('ID').primary();
|
||||
table.string('severity');
|
||||
table.string('topic');
|
||||
table.string('message');
|
||||
@@ -0,0 +1,107 @@
|
||||
import { TableDefinitionExporter } from "../../Types/Interfaces";
|
||||
import { TableDefiniton, _Rank } from "../../Types/Types";
|
||||
import { FrontworkAdmin } from "../../Admin/Admin";
|
||||
import { T1 } from "../../Types/Items";
|
||||
import { FrontworkComponent } from "../../Types/FrontworkComponent";
|
||||
import { RPC } from "rpclibrary";
|
||||
const fetch = require('node-fetch')
|
||||
const xml2js = require('xml2js');
|
||||
const parser = new xml2js.Parser(/* options */);
|
||||
|
||||
|
||||
export type ItemManagerFeatureIfc = any
|
||||
|
||||
export type Item = {
|
||||
id?:number
|
||||
name:string
|
||||
iconname:string
|
||||
url:string
|
||||
quality:string
|
||||
hidden:boolean
|
||||
}
|
||||
|
||||
export class ItemManager
|
||||
implements FrontworkComponent<ItemManagerFeatureIfc>, TableDefinitionExporter{
|
||||
|
||||
admin:FrontworkAdmin
|
||||
name = "ItemManager";
|
||||
|
||||
exportRPCs(): RPC<any, any>[]{
|
||||
return [{
|
||||
name: 'getItems',
|
||||
call: async () => await this.getItems()
|
||||
},{
|
||||
name: 'getItem',
|
||||
call: async (name:string) => await this.getItem(name)
|
||||
}]
|
||||
}
|
||||
|
||||
exportRPCFeatures() {
|
||||
return []
|
||||
}
|
||||
|
||||
getItems = async () :Promise<Item[]> => await this.admin.knex.select('*').from('items')
|
||||
|
||||
getItem = async (name:string):Promise<Item> => {
|
||||
const res = await fetch('https://classic.wowhead.com/item='+name+'&xml');
|
||||
const txt = await res.text();
|
||||
const r = await parser.parseStringPromise(txt);
|
||||
|
||||
try{
|
||||
return <Item>{
|
||||
name: r.wowhead.item[0].name[0],
|
||||
iconname: r.wowhead.item[0].icon[0]._,
|
||||
url: r.wowhead.item[0].link[0],
|
||||
quality: r.wowhead.item[0].quality[0]._,
|
||||
}
|
||||
}catch (e){
|
||||
console.log(name)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
getTableDefinitions(): TableDefiniton[] {
|
||||
return [
|
||||
{
|
||||
name: 'reservations',
|
||||
tableBuilder: (table) => {
|
||||
table.integer("user_id").primary()
|
||||
table.foreign("user_id").references("id").inTable('users')
|
||||
table.integer("item_id").primary()
|
||||
table.foreign("item_id").references("id").inTable('items')
|
||||
table.integer("raid_id").primary()
|
||||
table.foreign("raid_id").references("id").inTable('raids')
|
||||
}
|
||||
},{
|
||||
name: 'items',
|
||||
tableBuilder: (table) => {
|
||||
table.increments("id").primary()
|
||||
table.string('name').unique().notNullable()
|
||||
table.string('iconname').notNullable()
|
||||
table.string('url').notNullable()
|
||||
table.string('quality').defaultTo('Epic').notNullable()
|
||||
table.boolean('hidden').defaultTo(false).notNullable()
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
||||
countItems = async() :Promise<number> => {
|
||||
const count = await this.admin.knex('items').count('*');
|
||||
return <number>count[0]['count(*)']
|
||||
}
|
||||
|
||||
initialize = async() => {
|
||||
const allItems = [...T1]
|
||||
const countCache = await this.countItems()
|
||||
if(countCache != allItems.length){
|
||||
const items:Item[] = await Promise.all(allItems.map(async (i) => this.getItem(i)))
|
||||
try{
|
||||
await this.admin
|
||||
.knex('items')
|
||||
.insert(items)
|
||||
}catch(e){
|
||||
console.error(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
import { RPCServer } from "rpclibrary";
|
||||
import { TableDefiniton, AnyRPCExporter, User, RPCPermission, _Rank, Token, Auth } from "../../Types/Types";
|
||||
import { FrontworkAdmin } from "../../Admin/Admin";
|
||||
import { PrivilegedRPCExporter } from "../../Types/PrivilegedRPCExporter";
|
||||
import { FrontworkComponent } from "../../Types/FrontworkComponent";
|
||||
const uuid = require('uuid/v4')
|
||||
|
||||
|
||||
export class LoginManager
|
||||
implements FrontworkComponent{
|
||||
name = "Authenticator" as "Authenticator";
|
||||
admin:FrontworkAdmin
|
||||
|
||||
constructor(private exporters: PrivilegedRPCExporter[]){}
|
||||
|
||||
exportRPCs() {
|
||||
return [
|
||||
{
|
||||
name: 'login' as 'login',
|
||||
call: async (username:string, pwHash:string) => await this.login(username, pwHash)
|
||||
},{
|
||||
name: 'authenticate' as 'authenticate',
|
||||
call: async (tokenValue:string | Token) => await this.authenticate(tokenValue)
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
onSetAdmin(admin:FrontworkAdmin){
|
||||
this.exporters.forEach(e => e['admin'] = admin)
|
||||
}
|
||||
|
||||
exportRPCFeatures() {
|
||||
return [{
|
||||
name: 'createUser' as 'createUser',
|
||||
exportRPCs: () => [{
|
||||
name: 'createUser' as 'createUser',
|
||||
call: async (user:User) => {
|
||||
return await this.createUser(user)
|
||||
}
|
||||
}]
|
||||
},{
|
||||
name: 'modifyPermissions' as 'modifyPermissions',
|
||||
exportRPCs: () => [{
|
||||
name: 'getPermissions' as 'getPermissions',
|
||||
call: async () => await this.getPermissions()
|
||||
},{
|
||||
name: 'setPermission' as 'setPermission',
|
||||
call: async (perm: RPCPermission) => await this.setPermission(perm)
|
||||
}]
|
||||
}]
|
||||
}
|
||||
|
||||
getTableDefinitions(): TableDefiniton[] {
|
||||
return [
|
||||
{
|
||||
name: 'users',
|
||||
tableBuilder: (table) => {
|
||||
table.increments("id").primary()
|
||||
table.string("name").notNullable().unique()
|
||||
table.string("pwhash").notNullable()
|
||||
table.string("rank").notNullable()
|
||||
table.string("class").notNullable()
|
||||
table.string("email").nullable().unique()
|
||||
}
|
||||
},{
|
||||
name: 'rpcpermissions',
|
||||
tableBuilder: (table) => {
|
||||
table.string("rpcName").primary().notNullable()
|
||||
table.boolean("ADMIN").defaultTo(true).notNullable()
|
||||
_Rank.forEach(r => table.boolean(r).defaultTo(false).notNullable())
|
||||
}
|
||||
},{
|
||||
name: 'tokens',
|
||||
tableBuilder: (table) => {
|
||||
table.string('value').primary()
|
||||
table.integer('user_id').notNullable()
|
||||
table.foreign('user_id').references('users')
|
||||
table.dateTime('created').defaultTo(this.admin.knex.fn.now())
|
||||
}
|
||||
}
|
||||
,...this.exporters.flatMap(exp => exp['getTableDefinitions']?exp['getTableDefinitions']():undefined)]
|
||||
}
|
||||
|
||||
async initialize(){
|
||||
await Promise.all(
|
||||
[this, ...this.exporters].flatMap(exp => exp.exportRPCFeatures().map(async (rpc) => {
|
||||
try{
|
||||
await this.admin.knex.insert({ rpcname: rpc.name }).into('rpcpermissions')
|
||||
}catch(e){}
|
||||
})))
|
||||
|
||||
await Promise.all(this.exporters.map(ex => ex['initialize']?ex['initialize']():undefined))
|
||||
}
|
||||
|
||||
async setPermission(permission: RPCPermission){
|
||||
await this.admin.knex('rpcpermissions')
|
||||
.where('rpcname', '=', permission.name)
|
||||
.update(permission)
|
||||
}
|
||||
|
||||
getPermissions = async () : Promise<RPCPermission[]> => {
|
||||
return await this.admin.knex.select('*').from('rpcpermissions')
|
||||
}
|
||||
|
||||
getRPCForUser = async (user:User): Promise<AnyRPCExporter[]> => {
|
||||
return [...this.exportRPCFeatures(), ...this.exporters.flatMap((exp) => exp.exportRPCFeatures())]
|
||||
}
|
||||
|
||||
createUser = async(user:User): Promise<User> => {
|
||||
await this.admin.knex('users')
|
||||
.insert(user)
|
||||
|
||||
const users = await this.admin.knex
|
||||
.select("*")
|
||||
.from('users')
|
||||
.where(user)
|
||||
return users[0]
|
||||
}
|
||||
|
||||
login = async(username:string, pwHash:string) : Promise<Token> => {
|
||||
const res:User[] = await this.admin.knex
|
||||
.select("*")
|
||||
.from('users')
|
||||
.where({ name: username })
|
||||
|
||||
if(res.length > 0 && pwHash === res[0].pwhash){
|
||||
return await this.createToken(res[0])
|
||||
}
|
||||
|
||||
throw new Error('login failed')
|
||||
}
|
||||
|
||||
authenticate = async(tokenValue: string | Token) : Promise<Auth> => {
|
||||
if(typeof tokenValue !== 'string') tokenValue = tokenValue.value
|
||||
|
||||
const res : User[] = await this.admin.knex
|
||||
.select('users.id', 'name', 'class', 'rank', 'email')
|
||||
.from('tokens')
|
||||
.join('users', function(){
|
||||
this.on('users.id', '=', 'tokens.user_id')
|
||||
})
|
||||
.where({ value: tokenValue})
|
||||
|
||||
if(res.length === 0)
|
||||
throw new Error('authentication failed')
|
||||
|
||||
const allowedRPCs = await this.getRPCForUser(res[0])
|
||||
const randomPort = 20000 + Math.floor(Math.random() * 10000)
|
||||
while(true){
|
||||
try{
|
||||
let commSock = new RPCServer(randomPort, allowedRPCs, {
|
||||
closeHandler: () => {
|
||||
console.log(res[0].name, 'disconnected')
|
||||
commSock.destroy()
|
||||
},
|
||||
connectionHandler: () => {
|
||||
console.log(res[0].name, 'connected')
|
||||
cancelTimeout()
|
||||
},
|
||||
sesame: tokenValue
|
||||
})
|
||||
const timeout = setTimeout(() => {
|
||||
console.log(res[0].name, 'timeout')
|
||||
commSock.destroy()
|
||||
}, 10000)
|
||||
const cancelTimeout = () => { clearTimeout(timeout) }
|
||||
break;
|
||||
}catch(e){
|
||||
//retry
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
port: randomPort,
|
||||
user: res[0],
|
||||
token: {
|
||||
value: tokenValue,
|
||||
user_id: res[0].id!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
createToken = async(user:User): Promise<Token> => {
|
||||
const old = await this.admin.knex.select('*').from('tokens').where({user_id: user.id})
|
||||
if(old.length === 0){
|
||||
const token:Token = {
|
||||
value: uuid(),
|
||||
user_id: user.id!
|
||||
}
|
||||
await this.admin.knex('tokens').insert(token)
|
||||
return token
|
||||
}else{
|
||||
return old[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
import { RPCExporter } from "rpclibrary";
|
||||
import { Git } from "upgiter"
|
||||
import { FolderStatus } from "upgiter/js/src/Types";
|
||||
import { Plugin } from "./Plugin";
|
||||
import { FrontworkAdmin } from "./Admin";
|
||||
import { Plugin } from "../Types/Plugin";
|
||||
import { FrontworkAdmin } from "../Admin/Admin";
|
||||
|
||||
class PluginLoader {
|
||||
private runningPlugins: Plugin[] = []
|
||||
@@ -0,0 +1,95 @@
|
||||
import { TableDefiniton, User, _Rank, Raid, Signup, RaidManagerFeatureIfc } from "../../Types/Types";
|
||||
import { FrontworkAdmin } from "../../Admin/Admin";
|
||||
import { FrontworkComponent } from "../../Types/FrontworkComponent";
|
||||
|
||||
|
||||
export class RaidManager
|
||||
implements FrontworkComponent<RaidManagerFeatureIfc>{
|
||||
name = "RaidManager";
|
||||
admin: FrontworkAdmin
|
||||
|
||||
exportRPCs = () => []
|
||||
|
||||
exportRPCFeatures() {
|
||||
return [{
|
||||
name: 'manageRaid' as 'manageRaid',
|
||||
exportRPCs: () => [{
|
||||
name: 'createRaid' as 'createRaid',
|
||||
call: async (raid:Raid) => await this.createRaid(raid)
|
||||
},{
|
||||
name: 'addSignup' as 'addSignup',
|
||||
call: async(signup: Signup) => await this.addSignup(signup)
|
||||
},{
|
||||
name: 'removeSignup' as 'removeSignup',
|
||||
call: async(signup: Signup) => await this.removeSignup(signup)
|
||||
}]
|
||||
},{
|
||||
name: 'signup' as 'signup',
|
||||
exportRPCs: () => [{
|
||||
name: 'getRaids' as 'getRaids',
|
||||
call: async () => await this.getRaids()
|
||||
},{
|
||||
name: 'getSingups' as 'getSingups',
|
||||
call: async(raid: Raid) => await this.getSignups(raid)
|
||||
},{
|
||||
name: 'sign' as 'sign',
|
||||
call: async(user:User, raid:Raid) => await this.sign(user, raid)
|
||||
}]
|
||||
},]
|
||||
}
|
||||
|
||||
getTableDefinitions(): TableDefiniton[] {
|
||||
return [
|
||||
{
|
||||
name: 'raids',
|
||||
tableBuilder: (table) => {
|
||||
table.increments('id').primary()
|
||||
table.dateTime('start').notNullable()
|
||||
table.string('description').notNullable()
|
||||
table.string('title').notNullable()
|
||||
table.integer('minrank').notNullable()
|
||||
}
|
||||
},{
|
||||
name: 'signups',
|
||||
tableBuilder: (table) => {
|
||||
table.integer('raid_id').primary()
|
||||
table.foreign('raid_id').references('id').inTable('raids')
|
||||
table.integer('user_id').primary()
|
||||
table.foreign('user_id').references('id').inTable('users')
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
createRaid = async (raid:Raid) => await this.admin
|
||||
.knex('raids')
|
||||
.insert(raid)
|
||||
|
||||
addSignup = async (signup: Signup) => await this.admin
|
||||
.knex('signups')
|
||||
.insert(signup)
|
||||
|
||||
removeSignup = async (signup: Signup) => await this.admin
|
||||
.knex('signups')
|
||||
.where({
|
||||
raid_id: signup.raid_id,
|
||||
user_id: signup.user_id
|
||||
})
|
||||
.delete()
|
||||
|
||||
getRaids = async () => await this.admin.knex
|
||||
.select('*')
|
||||
.from('raids')
|
||||
|
||||
getSignups = async (raid:Raid) => await this.admin.knex
|
||||
.select('*')
|
||||
.from('signups')
|
||||
.where('raid_id', '=', raid.id!)
|
||||
|
||||
sign = async (user:User, raid:Raid) => await this.admin
|
||||
.knex('signups')
|
||||
.insert({
|
||||
raid_id: raid.id!,
|
||||
user_id: user.id!
|
||||
})
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
import { Plugin } from "./Plugin"
|
||||
import { getLogger } from "frontblock-generic/Types"
|
||||
import { FrontworkAdmin } from "./Admin";
|
||||
var exec = require('child-process-promise').exec;
|
||||
|
||||
const logger = getLogger("installer", 'info')
|
||||
|
||||
export type NPMPkgName = string
|
||||
export type NPMVersion = string
|
||||
|
||||
export const installAdmin = (plugins: Plugin[] = []) => {
|
||||
|
||||
const npmPkgs:[NPMPkgName, NPMVersion][] = [['sqlite3', '4.1.0'], ['knex', '0.19.2']]
|
||||
const deps = npmPkgs.map(tuple => tuple.join('@') ).join(" ")
|
||||
logger.info("Installing plaform dependencies: "+deps)
|
||||
|
||||
exec("npm i " + deps).then(async process => {
|
||||
logger.debug(process.stdout)
|
||||
const Admin = require("./Admin").FrontworkAdmin
|
||||
const fbAdmin:FrontworkAdmin = new Admin(plugins)
|
||||
fbAdmin.start()
|
||||
})
|
||||
|
||||
}
|
||||
+20
-2
@@ -1,2 +1,20 @@
|
||||
import { installAdmin } from "./Installer";
|
||||
installAdmin()
|
||||
import { FrontworkAdmin } from './Admin/Admin'
|
||||
import { RaidManager } from "./Components/Raid/RaidManager";
|
||||
import { ItemManager } from "./Components/Item/ItemManager";
|
||||
import { LoginManager } from "./Components/Login/LoginManager";
|
||||
import { Debugger } from './Components/Debugger/Debugger';
|
||||
import { FrontworkComponent } from './Types/FrontworkComponent';
|
||||
require('events').EventEmitter.defaultMaxListeners = 0;
|
||||
|
||||
let raidManager = new RaidManager()
|
||||
let itemManager = new ItemManager()
|
||||
let loginManager = new LoginManager([
|
||||
raidManager,
|
||||
itemManager
|
||||
])
|
||||
|
||||
let components:FrontworkComponent[] = [ raidManager, itemManager, loginManager ]
|
||||
let dbg = new Debugger(components)
|
||||
|
||||
|
||||
new FrontworkAdmin([dbg, ...components]).start()
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
import Knex = require("knex")
|
||||
|
||||
export declare type NotificationSeverity = 'Info' | 'Important' | 'Error';
|
||||
|
||||
export type AdminConf = {
|
||||
httpPort: number,
|
||||
dbConf:Knex.Config,
|
||||
eventBusConf: { [topic in string]: NotificationSeverity}
|
||||
}
|
||||
|
||||
export type TableDefiniton = {
|
||||
name: string,
|
||||
tableBuilder: (table: Knex.CreateTableBuilder) => void
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { PrivilegedRPCExporter } from "./PrivilegedRPCExporter";
|
||||
import { RPCInterface, RPC, AnyFunction, RPCExporter } from "rpclibrary";
|
||||
import { TableDefinitionExporter } from "./Interfaces";
|
||||
import { FrontworkAdmin } from "../Admin/Admin";
|
||||
import { TableDefiniton } from "./Types";
|
||||
|
||||
export interface FrontworkComponent<
|
||||
Ifc extends RPCInterface = RPCInterface,
|
||||
Name extends keyof Ifc = keyof Ifc,
|
||||
SubresT = {}
|
||||
> extends
|
||||
PrivilegedRPCExporter<Ifc, Name, SubresT>,
|
||||
TableDefinitionExporter
|
||||
{
|
||||
admin:FrontworkAdmin
|
||||
name: string;
|
||||
|
||||
exportRPCFeatures(): RPCExporter<Ifc, Name, SubresT>[]
|
||||
exportRPCs(): RPC<string, AnyFunction, {}>[]
|
||||
getTableDefinitions(): TableDefiniton[]
|
||||
|
||||
initialize?(): Promise<any>
|
||||
onSetAdmin?(admin:FrontworkAdmin): void
|
||||
}
|
||||
@@ -2,4 +2,4 @@ import { TableDefiniton } from "./Types";
|
||||
|
||||
export interface TableDefinitionExporter{
|
||||
getTableDefinitions(): TableDefiniton[]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
export const T1 = [
|
||||
"Robe of Volatile Power",
|
||||
"Salamander Scale Pants",
|
||||
"Heavy Dark Iron Ring",
|
||||
"Ring of Spell Power",
|
||||
"Sorcerous Dagger",
|
||||
"Wristguards of Stability",
|
||||
"Helm of the Lifegiver",
|
||||
"Fire Runed Grimoire",
|
||||
"Crimson Shocker",
|
||||
"Mana Igniting Cord",
|
||||
"Quick Strike Ring",
|
||||
"Seal of the Archmagus",
|
||||
"Talisman of Ephemeral Power",
|
||||
"Flameguard Gauntlets",
|
||||
"Magma Tempered Boots",
|
||||
"Obsidian Edged Blade",
|
||||
"Aged Core Leather Gloves",
|
||||
"Sabatons of the Flamewalker",
|
||||
"Striker's Mark",
|
||||
"Medallion of Steadfast Might",
|
||||
"Earthshaker",
|
||||
"Brutality Blade",
|
||||
"Aurastone Hammer",
|
||||
"Gutgore Ripper",
|
||||
"Drillborer Disk",
|
||||
"Azuresong Mageblade",
|
||||
"Staff of Dominance",
|
||||
"Blastershot Launcher",
|
||||
"The Eye of Divinity",
|
||||
"Ancient Petrified Leaf",
|
||||
"Finkle's Lava Dredger",
|
||||
"Core Hound Tooth",
|
||||
"Core Forged Greaves",
|
||||
"Gloves of the Hypnotic Flame",
|
||||
"Sash of Whispered Secrets",
|
||||
"Wild Growth Spaulders",
|
||||
"Fireproof Cloak",
|
||||
"Wristguards of True Flight",
|
||||
"Fireguard Shoulders",
|
||||
"Cauterizing Band",
|
||||
"Onslaught Girdle",
|
||||
"Perdition's Blade",
|
||||
"Cloak of the Shrouded Mists",
|
||||
"Band of Accuria",
|
||||
"Crown of Destruction",
|
||||
"Choker of the Fire Lord",
|
||||
"Band of Sulfuras",
|
||||
"Dragon's Blood Cape",
|
||||
"Malistar's Defender",
|
||||
"Spinal Reaper",
|
||||
"Bonereaver's Edge",
|
||||
"Shard of the Flame",
|
||||
"Essence of the Pure Flame",
|
||||
"Eye of Sulfuras",
|
||||
"Deathbringer",
|
||||
"Vis'kag the Bloodletter",
|
||||
"Sapphiron Drape",
|
||||
"Ancient Cornerstone Grimoire",
|
||||
"Eskhandar's Collar",
|
||||
"Ring of Binding",
|
||||
"Shard of the Scale",
|
||||
"Head of Onyxia",
|
||||
"Bindings of the Windseeker"]
|
||||
@@ -1,4 +1,4 @@
|
||||
import { FrontworkAdmin } from "./Admin"
|
||||
import { FrontworkAdmin } from "../Admin/Admin"
|
||||
import { RPC, RPCExporter } from "rpclibrary"
|
||||
import { TableDefiniton } from "./Types"
|
||||
import { TableDefinitionExporter } from "./Interfaces"
|
||||
@@ -0,0 +1,7 @@
|
||||
import { RPCExporter, RPCInterface, RPC, RPCInterfaceArray } from "rpclibrary";
|
||||
|
||||
export interface PrivilegedRPCExporter <Ifc extends RPCInterface = RPCInterface, Name extends keyof Ifc = keyof Ifc, SubresT = {}>
|
||||
extends RPCExporter<any,any>{
|
||||
|
||||
exportRPCFeatures() : RPCExporter<Ifc, Name, SubresT>[]
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
import * as Knex from "knex"
|
||||
import { RPCExporter } from "rpclibrary";
|
||||
|
||||
export declare type NotificationSeverity = 'Info' | 'Important' | 'Error';
|
||||
|
||||
export type AdminConf = {
|
||||
httpPort: number,
|
||||
dbConf:Knex.Config,
|
||||
eventBusConf: { [topic in string]: NotificationSeverity}
|
||||
}
|
||||
|
||||
export type TableDefiniton = {
|
||||
name: string,
|
||||
tableBuilder: (table: Knex.CreateTableBuilder) => void
|
||||
}
|
||||
|
||||
export type Rank = "ADMIN" | "Guildmaster" | "Officer" | "Classleader" | "Raider" | "Trial" | "Social" | "Guest"
|
||||
export const _Rank : Rank[] = ["Guildmaster" , "Officer" , "Classleader" , "Raider" , "Trial" , "Social" , "Guest"]
|
||||
export type Class = "Warrior" | "Rogue" | "Hunter" | "Mage" | "Warlock" | "Priest" | "Shaman" | "Paladin" | "Druid"
|
||||
export const _Class : Class[] = ["Warrior" , "Rogue" , "Hunter" , "Mage" , "Warlock" , "Priest" , "Shaman" , "Paladin" , "Druid"]
|
||||
|
||||
export type AnyRPCExporter = RPCExporter<any,any>
|
||||
|
||||
export type RPCPermission = {
|
||||
name: string
|
||||
} & {
|
||||
[rank in Rank] : boolean
|
||||
}
|
||||
|
||||
export type User = {
|
||||
id?: number
|
||||
name: string
|
||||
pwhash: string
|
||||
class: Class
|
||||
rank: Rank
|
||||
email?: string
|
||||
}
|
||||
|
||||
export type Raid = {
|
||||
id?: number
|
||||
title: string
|
||||
description: string
|
||||
start: string
|
||||
minrank: Rank
|
||||
}
|
||||
|
||||
export type Signup = {
|
||||
raid_id: number
|
||||
user_id: number
|
||||
}
|
||||
|
||||
export type Token = {
|
||||
value: string
|
||||
user_id: number
|
||||
created?: number
|
||||
}
|
||||
|
||||
export type Auth = {port: number, user: User, token: Token}
|
||||
|
||||
export type FrontcraftFeatureIfc = RaidManagerFeatureIfc & LoginManagerFeatureIfc
|
||||
|
||||
|
||||
export type LoginManagerIfc = {
|
||||
Authenticator: {
|
||||
login: (username:string, pwHash:string) => Promise<Token>
|
||||
authenticate: (token:string | Token) => Promise<Auth>
|
||||
}
|
||||
}
|
||||
|
||||
export type LoginManagerFeatureIfc = {
|
||||
createUser: {
|
||||
createUser: (user:User) => Promise<User>
|
||||
}
|
||||
modifyPermissions: {
|
||||
setPermission: (perm: RPCPermission) => Promise<void>
|
||||
getPermissions: () => Promise<RPCPermission[]>
|
||||
}
|
||||
}
|
||||
|
||||
export type RaidManagerFeatureIfc = {
|
||||
manageRaid: {
|
||||
createRaid: (raid:Raid) => Promise<any>
|
||||
addSignup: (signup: Signup) => Promise<any>
|
||||
removeSignup: (signup: Signup) => Promise<any>
|
||||
}
|
||||
signup: {
|
||||
getRaids: () => Promise<Raid[]>
|
||||
getSingups: (raid:Raid) => Promise<Signup[]>
|
||||
sign: (user:User, raid:Raid, attending:boolean) => Promise<any>
|
||||
}
|
||||
}
|
||||
@@ -9,8 +9,12 @@
|
||||
"projectType": "application",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:browser",
|
||||
"builder": "@angular-builders/custom-webpack:browser",
|
||||
"options": {
|
||||
"customWebpackConfig": {
|
||||
"path": "./custom-webpack.config.js",
|
||||
"replaceDuplicatePlugins": true
|
||||
},
|
||||
"preserveSymlinks": true,
|
||||
"rebaseRootRelativeCssUrls": true,
|
||||
"outputPath": "dist",
|
||||
@@ -75,7 +79,7 @@
|
||||
}
|
||||
},
|
||||
"serve": {
|
||||
"builder": "@angular-devkit/build-angular:dev-server",
|
||||
"builder": "@angular-builders/custom-webpack:dev-server",
|
||||
"options": {
|
||||
"browserTarget": "ngx-admin-demo:build"
|
||||
},
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
module.exports = {
|
||||
externals: ['http'],
|
||||
node: {global: true, fs: 'empty'}
|
||||
}
|
||||
Generated
+24
-4
@@ -9,6 +9,22 @@
|
||||
"resolved": "https://registry.npmjs.org/@agm/core/-/core-1.0.0-beta.5.tgz",
|
||||
"integrity": "sha512-LVENJqtBZEWpX+uJkGI0zgg+Xkm2KkktQm4ojZozArbeNvQkVL6pqVc04Mme6vvOzwJpD1cET5w4byC8Xaq1QQ=="
|
||||
},
|
||||
"@angular-builders/custom-webpack": {
|
||||
"version": "8.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@angular-builders/custom-webpack/-/custom-webpack-8.2.0.tgz",
|
||||
"integrity": "sha512-6654RfyqhTGhCI0edC9YU/iMn1UJnzX01bxYJbDWFgvReCqXdlgy+Fe9tp1MeqKweX6BQ1d0gRroR/WjY1aX0A==",
|
||||
"requires": {
|
||||
"lodash": "^4.17.10",
|
||||
"webpack-merge": "^4.2.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"lodash": {
|
||||
"version": "4.17.15",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
|
||||
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@angular-devkit/architect": {
|
||||
"version": "0.800.2",
|
||||
"resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.800.2.tgz",
|
||||
@@ -11695,6 +11711,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"ngx-cookie-service": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ngx-cookie-service/-/ngx-cookie-service-2.2.0.tgz",
|
||||
"integrity": "sha512-2kaC1itlEMxiMAPJ320hOpcwU9vhvjbKQCZ1Go6bGhYjJtqG7eYvhNP7mM9IhFz1/afG2tBryJPySWmFUGhRpA=="
|
||||
},
|
||||
"ngx-echarts": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ngx-echarts/-/ngx-echarts-4.0.1.tgz",
|
||||
@@ -14314,9 +14335,9 @@
|
||||
"integrity": "sha512-ZYzRkETgBrdEGzL5JSKimvjI2CX7ioyZCkX2BpcfyjqI+079W0wHAyj5W4rIZMcDSOHgLZtgz1IdDi/vU77KEQ=="
|
||||
},
|
||||
"rpclibrary": {
|
||||
"version": "1.3.17",
|
||||
"resolved": "https://registry.npmjs.org/rpclibrary/-/rpclibrary-1.3.17.tgz",
|
||||
"integrity": "sha512-ZdhZ1TSDO+bcz5kCJ7Ol+YAAyYpwg7YI/hETS4vv3RYerUEQVZSZjcm22J5a91RnQVN2SRiXzdoXbbFb/Renog==",
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/rpclibrary/-/rpclibrary-1.4.0.tgz",
|
||||
"integrity": "sha512-JUU7+HymV2ZTI+NrIVOiIr5LGFoRsPq4k/ffdUonqIpd9fjOHBQ2/PFLVXx9z94+dKxdqN8/D9ZXPwU03ovZrg==",
|
||||
"requires": {
|
||||
"bsock": "^0.1.9",
|
||||
"http": "0.0.0",
|
||||
@@ -20446,7 +20467,6 @@
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.1.tgz",
|
||||
"integrity": "sha512-4p8WQyS98bUJcCvFMbdGZyZmsKuWjWVnVHnAS3FFg0HDaRVrPbkivx2RYCre8UiemD67RsiFFLfn4JhLAin8Vw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lodash": "^4.17.5"
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@agm/core": "^1.0.0-beta.5",
|
||||
"@angular-builders/custom-webpack": "^8.2.0",
|
||||
"@angular/animations": "^8.0.0",
|
||||
"@angular/cdk": "^8.0.0",
|
||||
"@angular/common": "^8.0.0",
|
||||
@@ -62,12 +63,13 @@
|
||||
"ng2-ckeditor": "^1.2.2",
|
||||
"ng2-completer": "2.0.8",
|
||||
"ng2-smart-table": "1.3.5",
|
||||
"ngx-cookie-service": "^2.2.0",
|
||||
"ngx-echarts": "^4.0.1",
|
||||
"node-sass": "^4.12.0",
|
||||
"normalize.css": "6.0.0",
|
||||
"pace-js": "1.0.2",
|
||||
"roboto-fontface": "0.8.0",
|
||||
"rpclibrary": "^1.3.17",
|
||||
"rpclibrary": "^1.4.0",
|
||||
"rxjs": "6.5.2",
|
||||
"rxjs-compat": "6.3.0",
|
||||
"socicon": "3.0.5",
|
||||
|
||||
@@ -1,146 +1,35 @@
|
||||
import { ModuleWithProviders, NgModule, Optional, SkipSelf } from '@angular/core';
|
||||
import { ModuleWithProviders, NgModule, Optional, SkipSelf, APP_INITIALIZER } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NbAuthModule, NbDummyAuthStrategy } from '@nebular/auth';
|
||||
import { NbSecurityModule, NbRoleProvider } from '@nebular/security';
|
||||
import { of as observableOf } from 'rxjs';
|
||||
|
||||
import { throwIfAlreadyLoaded } from './module-import-guard';
|
||||
import { CookieService } from 'ngx-cookie-service';
|
||||
|
||||
import {
|
||||
AnalyticsService,
|
||||
LayoutService,
|
||||
PlayerService,
|
||||
StateService,
|
||||
} from './utils';
|
||||
import { UserData } from './data/users';
|
||||
import { ElectricityData } from './data/electricity';
|
||||
import { SmartTableData } from './data/smart-table';
|
||||
import { UserActivityData } from './data/user-activity';
|
||||
import { OrdersChartData } from './data/orders-chart';
|
||||
import { ProfitChartData } from './data/profit-chart';
|
||||
import { TrafficListData } from './data/traffic-list';
|
||||
import { EarningData } from './data/earning';
|
||||
import { OrdersProfitChartData } from './data/orders-profit-chart';
|
||||
import { TrafficBarData } from './data/traffic-bar';
|
||||
import { ProfitBarAnimationChartData } from './data/profit-bar-animation-chart';
|
||||
import { TemperatureHumidityData } from './data/temperature-humidity';
|
||||
import { SolarData } from './data/solar';
|
||||
import { TrafficChartData } from './data/traffic-chart';
|
||||
import { StatsBarData } from './data/stats-bar';
|
||||
import { CountryOrderData } from './data/country-order';
|
||||
import { StatsProgressBarData } from './data/stats-progress-bar';
|
||||
import { VisitorsAnalyticsData } from './data/visitors-analytics';
|
||||
import { SecurityCamerasData } from './data/security-cameras';
|
||||
import { LoginApiService, initializeLoginSvc } from '../frontcraft/login-api';
|
||||
|
||||
import { UserService } from './mock/users.service';
|
||||
import { ElectricityService } from './mock/electricity.service';
|
||||
import { SmartTableService } from './mock/smart-table.service';
|
||||
import { UserActivityService } from './mock/user-activity.service';
|
||||
import { OrdersChartService } from './mock/orders-chart.service';
|
||||
import { ProfitChartService } from './mock/profit-chart.service';
|
||||
import { TrafficListService } from './mock/traffic-list.service';
|
||||
import { EarningService } from './mock/earning.service';
|
||||
import { OrdersProfitChartService } from './mock/orders-profit-chart.service';
|
||||
import { TrafficBarService } from './mock/traffic-bar.service';
|
||||
import { ProfitBarAnimationChartService } from './mock/profit-bar-animation-chart.service';
|
||||
import { TemperatureHumidityService } from './mock/temperature-humidity.service';
|
||||
import { SolarService } from './mock/solar.service';
|
||||
import { TrafficChartService } from './mock/traffic-chart.service';
|
||||
import { StatsBarService } from './mock/stats-bar.service';
|
||||
import { CountryOrderService } from './mock/country-order.service';
|
||||
import { StatsProgressBarService } from './mock/stats-progress-bar.service';
|
||||
import { VisitorsAnalyticsService } from './mock/visitors-analytics.service';
|
||||
import { SecurityCamerasService } from './mock/security-cameras.service';
|
||||
import { MockDataModule } from './mock/mock-data.module';
|
||||
|
||||
const socialLinks = [
|
||||
const DATA_SERVICES = [
|
||||
{provide: LoginApiService, useClass: LoginApiService},
|
||||
{provide: CookieService, useClass: CookieService},
|
||||
{
|
||||
url: 'https://github.com/akveo/nebular',
|
||||
target: '_blank',
|
||||
icon: 'github',
|
||||
},
|
||||
{
|
||||
url: 'https://www.facebook.com/akveo/',
|
||||
target: '_blank',
|
||||
icon: 'facebook',
|
||||
},
|
||||
{
|
||||
url: 'https://twitter.com/akveo_inc',
|
||||
target: '_blank',
|
||||
icon: 'twitter',
|
||||
},
|
||||
];
|
||||
|
||||
const DATA_SERVICES = [
|
||||
{ provide: UserData, useClass: UserService },
|
||||
{ provide: ElectricityData, useClass: ElectricityService },
|
||||
{ provide: SmartTableData, useClass: SmartTableService },
|
||||
{ provide: UserActivityData, useClass: UserActivityService },
|
||||
{ provide: OrdersChartData, useClass: OrdersChartService },
|
||||
{ provide: ProfitChartData, useClass: ProfitChartService },
|
||||
{ provide: TrafficListData, useClass: TrafficListService },
|
||||
{ provide: EarningData, useClass: EarningService },
|
||||
{ provide: OrdersProfitChartData, useClass: OrdersProfitChartService },
|
||||
{ provide: TrafficBarData, useClass: TrafficBarService },
|
||||
{ provide: ProfitBarAnimationChartData, useClass: ProfitBarAnimationChartService },
|
||||
{ provide: TemperatureHumidityData, useClass: TemperatureHumidityService },
|
||||
{ provide: SolarData, useClass: SolarService },
|
||||
{ provide: TrafficChartData, useClass: TrafficChartService },
|
||||
{ provide: StatsBarData, useClass: StatsBarService },
|
||||
{ provide: CountryOrderData, useClass: CountryOrderService },
|
||||
{ provide: StatsProgressBarData, useClass: StatsProgressBarService },
|
||||
{ provide: VisitorsAnalyticsData, useClass: VisitorsAnalyticsService },
|
||||
{ provide: SecurityCamerasData, useClass: SecurityCamerasService },
|
||||
];
|
||||
|
||||
export class NbSimpleRoleProvider extends NbRoleProvider {
|
||||
getRole() {
|
||||
// here you could provide any role based on any auth flow
|
||||
return observableOf('guest');
|
||||
provide: APP_INITIALIZER,
|
||||
useFactory: initializeLoginSvc,
|
||||
deps: [LoginApiService, CookieService],
|
||||
multi: true
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
export const NB_CORE_PROVIDERS = [
|
||||
...MockDataModule.forRoot().providers,
|
||||
...DATA_SERVICES,
|
||||
...NbAuthModule.forRoot({
|
||||
|
||||
strategies: [
|
||||
NbDummyAuthStrategy.setup({
|
||||
name: 'email',
|
||||
delay: 3000,
|
||||
}),
|
||||
],
|
||||
forms: {
|
||||
login: {
|
||||
socialLinks: socialLinks,
|
||||
},
|
||||
register: {
|
||||
socialLinks: socialLinks,
|
||||
},
|
||||
},
|
||||
}).providers,
|
||||
|
||||
NbSecurityModule.forRoot({
|
||||
accessControl: {
|
||||
guest: {
|
||||
view: '*',
|
||||
},
|
||||
user: {
|
||||
parent: 'guest',
|
||||
create: '*',
|
||||
edit: '*',
|
||||
remove: '*',
|
||||
},
|
||||
},
|
||||
}).providers,
|
||||
|
||||
{
|
||||
provide: NbRoleProvider, useClass: NbSimpleRoleProvider,
|
||||
},
|
||||
AnalyticsService,
|
||||
LayoutService,
|
||||
PlayerService,
|
||||
StateService,
|
||||
CookieService,
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
@@ -148,7 +37,6 @@ export const NB_CORE_PROVIDERS = [
|
||||
CommonModule,
|
||||
],
|
||||
exports: [
|
||||
NbAuthModule,
|
||||
],
|
||||
declarations: [],
|
||||
})
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
Application-wise data providers.
|
||||
@@ -1,29 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { of as observableOf, Observable } from 'rxjs';
|
||||
import { CountryOrderData } from '../data/country-order';
|
||||
|
||||
@Injectable()
|
||||
export class CountryOrderService extends CountryOrderData {
|
||||
|
||||
private countriesCategories = [
|
||||
'Sofas',
|
||||
'Furniture',
|
||||
'Lighting',
|
||||
'Tables',
|
||||
'Textiles',
|
||||
];
|
||||
private countriesCategoriesLength = this.countriesCategories.length;
|
||||
private generateRandomData(nPoints: number): number[] {
|
||||
return Array.from(Array(nPoints)).map(() => {
|
||||
return Math.round(Math.random() * 20);
|
||||
});
|
||||
}
|
||||
|
||||
getCountriesCategories(): Observable<string[]> {
|
||||
return observableOf(this.countriesCategories);
|
||||
}
|
||||
|
||||
getCountriesCategoriesData(country: string): Observable<number[]> {
|
||||
return observableOf(this.generateRandomData(this.countriesCategoriesLength));
|
||||
}
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { of as observableOf, Observable } from 'rxjs';
|
||||
import { LiveUpdateChart, PieChart, EarningData } from '../data/earning';
|
||||
|
||||
@Injectable()
|
||||
export class EarningService extends EarningData {
|
||||
|
||||
private currentDate: Date = new Date();
|
||||
private currentValue = Math.random() * 1000;
|
||||
private ONE_DAY = 24 * 3600 * 1000;
|
||||
|
||||
private pieChartData = [
|
||||
{
|
||||
value: 50,
|
||||
name: 'Bitcoin',
|
||||
},
|
||||
{
|
||||
value: 25,
|
||||
name: 'Tether',
|
||||
},
|
||||
{
|
||||
value: 25,
|
||||
name: 'Ethereum',
|
||||
},
|
||||
];
|
||||
|
||||
private liveUpdateChartData = {
|
||||
bitcoin: {
|
||||
liveChart: [],
|
||||
delta: {
|
||||
up: true,
|
||||
value: 4,
|
||||
},
|
||||
dailyIncome: 45895,
|
||||
},
|
||||
tether: {
|
||||
liveChart: [],
|
||||
delta: {
|
||||
up: false,
|
||||
value: 9,
|
||||
},
|
||||
dailyIncome: 5862,
|
||||
},
|
||||
ethereum: {
|
||||
liveChart: [],
|
||||
delta: {
|
||||
up: false,
|
||||
value: 21,
|
||||
},
|
||||
dailyIncome: 584,
|
||||
},
|
||||
};
|
||||
|
||||
getDefaultLiveChartData(elementsNumber: number) {
|
||||
this.currentDate = new Date();
|
||||
this.currentValue = Math.random() * 1000;
|
||||
|
||||
return Array.from(Array(elementsNumber))
|
||||
.map(item => this.generateRandomLiveChartData());
|
||||
}
|
||||
|
||||
generateRandomLiveChartData() {
|
||||
this.currentDate = new Date(+this.currentDate + this.ONE_DAY);
|
||||
this.currentValue = this.currentValue + Math.random() * 20 - 11;
|
||||
|
||||
if (this.currentValue < 0) {
|
||||
this.currentValue = Math.random() * 100;
|
||||
}
|
||||
|
||||
return {
|
||||
value: [
|
||||
[
|
||||
this.currentDate.getFullYear(),
|
||||
this.currentDate.getMonth(),
|
||||
this.currentDate.getDate(),
|
||||
].join('/'),
|
||||
Math.round(this.currentValue),
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
getEarningLiveUpdateCardData(currency): Observable<any[]> {
|
||||
const data = this.liveUpdateChartData[currency.toLowerCase()];
|
||||
const newValue = this.generateRandomLiveChartData();
|
||||
|
||||
data.liveChart.shift();
|
||||
data.liveChart.push(newValue);
|
||||
|
||||
return observableOf(data.liveChart);
|
||||
}
|
||||
|
||||
getEarningCardData(currency: string): Observable<LiveUpdateChart> {
|
||||
const data = this.liveUpdateChartData[currency.toLowerCase()];
|
||||
|
||||
data.liveChart = this.getDefaultLiveChartData(150);
|
||||
|
||||
return observableOf(data);
|
||||
}
|
||||
|
||||
getEarningPieChartData(): Observable<PieChart[]> {
|
||||
return observableOf(this.pieChartData);
|
||||
}
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { of as observableOf, Observable } from 'rxjs';
|
||||
import { Electricity, ElectricityChart, ElectricityData } from '../data/electricity';
|
||||
|
||||
@Injectable()
|
||||
export class ElectricityService extends ElectricityData {
|
||||
|
||||
private listData: Electricity[] = [
|
||||
{
|
||||
title: '2015',
|
||||
months: [
|
||||
{ month: 'Jan', delta: '0.97', down: true, kWatts: '816', cost: '97' },
|
||||
{ month: 'Feb', delta: '1.83', down: true, kWatts: '806', cost: '95' },
|
||||
{ month: 'Mar', delta: '0.64', down: true, kWatts: '803', cost: '94' },
|
||||
{ month: 'Apr', delta: '2.17', down: false, kWatts: '818', cost: '98' },
|
||||
{ month: 'May', delta: '1.32', down: true, kWatts: '809', cost: '96' },
|
||||
{ month: 'Jun', delta: '0.05', down: true, kWatts: '808', cost: '96' },
|
||||
{ month: 'Jul', delta: '1.39', down: false, kWatts: '815', cost: '97' },
|
||||
{ month: 'Aug', delta: '0.73', down: true, kWatts: '807', cost: '95' },
|
||||
{ month: 'Sept', delta: '2.61', down: true, kWatts: '792', cost: '92' },
|
||||
{ month: 'Oct', delta: '0.16', down: true, kWatts: '791', cost: '92' },
|
||||
{ month: 'Nov', delta: '1.71', down: true, kWatts: '786', cost: '89' },
|
||||
{ month: 'Dec', delta: '0.37', down: false, kWatts: '789', cost: '91' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '2016',
|
||||
active: true,
|
||||
months: [
|
||||
{ month: 'Jan', delta: '1.56', down: true, kWatts: '789', cost: '91' },
|
||||
{ month: 'Feb', delta: '0.33', down: false, kWatts: '791', cost: '92' },
|
||||
{ month: 'Mar', delta: '0.62', down: true, kWatts: '790', cost: '92' },
|
||||
{ month: 'Apr', delta: '1.93', down: true, kWatts: '783', cost: '87' },
|
||||
{ month: 'May', delta: '2.52', down: true, kWatts: '771', cost: '83' },
|
||||
{ month: 'Jun', delta: '0.39', down: false, kWatts: '774', cost: '85' },
|
||||
{ month: 'Jul', delta: '1.61', down: true, kWatts: '767', cost: '81' },
|
||||
{ month: 'Aug', delta: '1.41', down: true, kWatts: '759', cost: '76' },
|
||||
{ month: 'Sept', delta: '1.03', down: true, kWatts: '752', cost: '74' },
|
||||
{ month: 'Oct', delta: '2.94', down: false, kWatts: '769', cost: '82' },
|
||||
{ month: 'Nov', delta: '0.26', down: true, kWatts: '767', cost: '81' },
|
||||
{ month: 'Dec', delta: '1.62', down: true, kWatts: '760', cost: '76' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '2017',
|
||||
months: [
|
||||
{ month: 'Jan', delta: '1.34', down: false, kWatts: '789', cost: '91' },
|
||||
{ month: 'Feb', delta: '0.95', down: false, kWatts: '793', cost: '93' },
|
||||
{ month: 'Mar', delta: '0.25', down: true, kWatts: '791', cost: '92' },
|
||||
{ month: 'Apr', delta: '1.72', down: false, kWatts: '797', cost: '95' },
|
||||
{ month: 'May', delta: '2.62', down: true, kWatts: '786', cost: '90' },
|
||||
{ month: 'Jun', delta: '0.72', down: false, kWatts: '789', cost: '91' },
|
||||
{ month: 'Jul', delta: '0.78', down: true, kWatts: '784', cost: '89' },
|
||||
{ month: 'Aug', delta: '0.36', down: true, kWatts: '782', cost: '88' },
|
||||
{ month: 'Sept', delta: '0.55', down: false, kWatts: '787', cost: '90' },
|
||||
{ month: 'Oct', delta: '1.81', down: true, kWatts: '779', cost: '86' },
|
||||
{ month: 'Nov', delta: '1.12', down: true, kWatts: '774', cost: '84' },
|
||||
{ month: 'Dec', delta: '0.52', down: false, kWatts: '776', cost: '95' },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
private chartPoints = [
|
||||
490, 490, 495, 500,
|
||||
505, 510, 520, 530,
|
||||
550, 580, 630, 720,
|
||||
800, 840, 860, 870,
|
||||
870, 860, 840, 800,
|
||||
720, 200, 145, 130,
|
||||
130, 145, 200, 570,
|
||||
635, 660, 670, 670,
|
||||
660, 630, 580, 460,
|
||||
380, 350, 340, 340,
|
||||
340, 340, 340, 340,
|
||||
340, 340, 340,
|
||||
];
|
||||
|
||||
chartData: ElectricityChart[];
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.chartData = this.chartPoints.map((p, index) => ({
|
||||
label: (index % 5 === 3) ? `${Math.round(index / 5)}` : '',
|
||||
value: p,
|
||||
}));
|
||||
}
|
||||
|
||||
getListData(): Observable<Electricity[]> {
|
||||
return observableOf(this.listData);
|
||||
}
|
||||
|
||||
getChartData(): Observable<ElectricityChart[]> {
|
||||
return observableOf(this.chartData);
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
import { NgModule, ModuleWithProviders } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { UserService } from './users.service';
|
||||
import { ElectricityService } from './electricity.service';
|
||||
import { SmartTableService } from './smart-table.service';
|
||||
import { UserActivityService } from './user-activity.service';
|
||||
import { OrdersChartService } from './orders-chart.service';
|
||||
import { ProfitChartService } from './profit-chart.service';
|
||||
import { TrafficListService } from './traffic-list.service';
|
||||
import { PeriodsService } from './periods.service';
|
||||
import { EarningService } from './earning.service';
|
||||
import { OrdersProfitChartService } from './orders-profit-chart.service';
|
||||
import { TrafficBarService } from './traffic-bar.service';
|
||||
import { ProfitBarAnimationChartService } from './profit-bar-animation-chart.service';
|
||||
import { TemperatureHumidityService } from './temperature-humidity.service';
|
||||
import { SolarService } from './solar.service';
|
||||
import { TrafficChartService } from './traffic-chart.service';
|
||||
import { StatsBarService } from './stats-bar.service';
|
||||
import { CountryOrderService } from './country-order.service';
|
||||
import { StatsProgressBarService } from './stats-progress-bar.service';
|
||||
import { VisitorsAnalyticsService } from './visitors-analytics.service';
|
||||
import { SecurityCamerasService } from './security-cameras.service';
|
||||
|
||||
const SERVICES = [
|
||||
UserService,
|
||||
ElectricityService,
|
||||
SmartTableService,
|
||||
UserActivityService,
|
||||
OrdersChartService,
|
||||
ProfitChartService,
|
||||
TrafficListService,
|
||||
PeriodsService,
|
||||
EarningService,
|
||||
OrdersProfitChartService,
|
||||
TrafficBarService,
|
||||
ProfitBarAnimationChartService,
|
||||
TemperatureHumidityService,
|
||||
SolarService,
|
||||
TrafficChartService,
|
||||
StatsBarService,
|
||||
CountryOrderService,
|
||||
StatsProgressBarService,
|
||||
VisitorsAnalyticsService,
|
||||
SecurityCamerasService,
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
],
|
||||
providers: [
|
||||
...SERVICES,
|
||||
],
|
||||
})
|
||||
export class MockDataModule {
|
||||
static forRoot(): ModuleWithProviders {
|
||||
return <ModuleWithProviders>{
|
||||
ngModule: MockDataModule,
|
||||
providers: [
|
||||
...SERVICES,
|
||||
],
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,155 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { PeriodsService } from './periods.service';
|
||||
import { OrdersChart, OrdersChartData } from '../data/orders-chart';
|
||||
|
||||
@Injectable()
|
||||
export class OrdersChartService extends OrdersChartData {
|
||||
|
||||
private year = [
|
||||
'2012',
|
||||
'2013',
|
||||
'2014',
|
||||
'2015',
|
||||
'2016',
|
||||
'2017',
|
||||
'2018',
|
||||
];
|
||||
|
||||
private data = { };
|
||||
|
||||
constructor(private period: PeriodsService) {
|
||||
super();
|
||||
this.data = {
|
||||
week: this.getDataForWeekPeriod(),
|
||||
month: this.getDataForMonthPeriod(),
|
||||
year: this.getDataForYearPeriod(),
|
||||
};
|
||||
}
|
||||
|
||||
private getDataForWeekPeriod(): OrdersChart {
|
||||
return {
|
||||
chartLabel: this.getDataLabels(42, this.period.getWeeks()),
|
||||
linesData: [
|
||||
[
|
||||
184, 267, 326, 366, 389, 399,
|
||||
392, 371, 340, 304, 265, 227,
|
||||
191, 158, 130, 108, 95, 91, 97,
|
||||
109, 125, 144, 166, 189, 212,
|
||||
236, 259, 280, 300, 316, 329,
|
||||
338, 342, 339, 329, 312, 288,
|
||||
258, 221, 178, 128, 71,
|
||||
],
|
||||
[
|
||||
158, 178, 193, 205, 212, 213,
|
||||
204, 190, 180, 173, 168, 164,
|
||||
162, 160, 159, 158, 159, 166,
|
||||
179, 195, 215, 236, 257, 276,
|
||||
292, 301, 304, 303, 300, 293,
|
||||
284, 273, 262, 251, 241, 234,
|
||||
232, 232, 232, 232, 232, 232,
|
||||
],
|
||||
[
|
||||
58, 137, 202, 251, 288, 312,
|
||||
323, 324, 311, 288, 257, 222,
|
||||
187, 154, 124, 100, 81, 68, 61,
|
||||
58, 61, 69, 80, 96, 115, 137,
|
||||
161, 186, 210, 233, 254, 271,
|
||||
284, 293, 297, 297, 297, 297,
|
||||
297, 297, 297, 297, 297,
|
||||
],
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
private getDataForMonthPeriod(): OrdersChart {
|
||||
return {
|
||||
chartLabel: this.getDataLabels(47, this.period.getMonths()),
|
||||
linesData: [
|
||||
[
|
||||
5, 63, 113, 156, 194, 225,
|
||||
250, 270, 283, 289, 290,
|
||||
286, 277, 264, 244, 220,
|
||||
194, 171, 157, 151, 150,
|
||||
152, 155, 160, 166, 170,
|
||||
167, 153, 135, 115, 97,
|
||||
82, 71, 64, 63, 62, 61,
|
||||
62, 65, 73, 84, 102,
|
||||
127, 159, 203, 259, 333,
|
||||
],
|
||||
[
|
||||
6, 83, 148, 200, 240,
|
||||
265, 273, 259, 211,
|
||||
122, 55, 30, 28, 36,
|
||||
50, 68, 88, 109, 129,
|
||||
146, 158, 163, 165,
|
||||
173, 187, 208, 236,
|
||||
271, 310, 346, 375,
|
||||
393, 400, 398, 387,
|
||||
368, 341, 309, 275,
|
||||
243, 220, 206, 202,
|
||||
207, 222, 247, 286, 348,
|
||||
],
|
||||
[
|
||||
398, 348, 315, 292, 274,
|
||||
261, 251, 243, 237, 231,
|
||||
222, 209, 192, 172, 152,
|
||||
132, 116, 102, 90, 80, 71,
|
||||
64, 58, 53, 49, 48, 54, 66,
|
||||
84, 104, 125, 142, 156, 166,
|
||||
172, 174, 172, 167, 159, 149,
|
||||
136, 121, 105, 86, 67, 45, 22,
|
||||
],
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
private getDataForYearPeriod(): OrdersChart {
|
||||
return {
|
||||
chartLabel: this.getDataLabels(42, this.year),
|
||||
linesData: [
|
||||
[
|
||||
190, 269, 327, 366, 389, 398,
|
||||
396, 387, 375, 359, 343, 327,
|
||||
312, 298, 286, 276, 270, 268,
|
||||
265, 258, 247, 234, 220, 204,
|
||||
188, 172, 157, 142, 128, 116,
|
||||
106, 99, 95, 94, 92, 89, 84,
|
||||
77, 69, 60, 49, 36, 22,
|
||||
],
|
||||
[
|
||||
265, 307, 337, 359, 375, 386,
|
||||
393, 397, 399, 397, 390, 379,
|
||||
365, 347, 326, 305, 282, 261,
|
||||
241, 223, 208, 197, 190, 187,
|
||||
185, 181, 172, 160, 145, 126,
|
||||
105, 82, 60, 40, 26, 19, 22,
|
||||
43, 82, 141, 220, 321,
|
||||
],
|
||||
[
|
||||
9, 165, 236, 258, 244, 206,
|
||||
186, 189, 209, 239, 273, 307,
|
||||
339, 365, 385, 396, 398, 385,
|
||||
351, 300, 255, 221, 197, 181,
|
||||
170, 164, 162, 161, 159, 154,
|
||||
146, 135, 122, 108, 96, 87,
|
||||
83, 82, 82, 82, 82, 82, 82,
|
||||
],
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
getDataLabels(nPoints: number, labelsArray: string[]): string[] {
|
||||
const labelsArrayLength = labelsArray.length;
|
||||
const step = Math.round(nPoints / labelsArrayLength);
|
||||
|
||||
return Array.from(Array(nPoints)).map((item, index) => {
|
||||
const dataIndex = Math.round(index / step);
|
||||
|
||||
return index % step === 0 ? labelsArray[dataIndex] : '';
|
||||
});
|
||||
}
|
||||
|
||||
getOrdersChartData(period: string): OrdersChart {
|
||||
return this.data[period];
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
import { of as observableOf, Observable } from 'rxjs';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { OrdersChart, OrdersChartData } from '../data/orders-chart';
|
||||
import { OrderProfitChartSummary, OrdersProfitChartData } from '../data/orders-profit-chart';
|
||||
import { ProfitChart, ProfitChartData } from '../data/profit-chart';
|
||||
|
||||
@Injectable()
|
||||
export class OrdersProfitChartService extends OrdersProfitChartData {
|
||||
|
||||
private summary = [
|
||||
{
|
||||
title: 'Marketplace',
|
||||
value: 3654,
|
||||
},
|
||||
{
|
||||
title: 'Last Month',
|
||||
value: 946,
|
||||
},
|
||||
{
|
||||
title: 'Last Week',
|
||||
value: 654,
|
||||
},
|
||||
{
|
||||
title: 'Today',
|
||||
value: 230,
|
||||
},
|
||||
];
|
||||
|
||||
constructor(private ordersChartService: OrdersChartData,
|
||||
private profitChartService: ProfitChartData) {
|
||||
super();
|
||||
}
|
||||
|
||||
getOrderProfitChartSummary(): Observable<OrderProfitChartSummary[]> {
|
||||
return observableOf(this.summary);
|
||||
}
|
||||
|
||||
getOrdersChartData(period: string): Observable<OrdersChart> {
|
||||
return observableOf(this.ordersChartService.getOrdersChartData(period));
|
||||
}
|
||||
|
||||
getProfitChartData(period: string): Observable<ProfitChart> {
|
||||
return observableOf(this.profitChartService.getProfitChartData(period));
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable()
|
||||
export class PeriodsService {
|
||||
getYears() {
|
||||
return [
|
||||
'2010', '2011', '2012',
|
||||
'2013', '2014', '2015',
|
||||
'2016', '2017', '2018',
|
||||
];
|
||||
}
|
||||
|
||||
getMonths() {
|
||||
return [
|
||||
'Jan', 'Feb', 'Mar',
|
||||
'Apr', 'May', 'Jun',
|
||||
'Jul', 'Aug', 'Sep',
|
||||
'Oct', 'Nov', 'Dec',
|
||||
];
|
||||
}
|
||||
|
||||
getWeeks() {
|
||||
return [
|
||||
'Mon',
|
||||
'Tue',
|
||||
'Wed',
|
||||
'Thu',
|
||||
'Fri',
|
||||
'Sat',
|
||||
'Sun',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { of as observableOf, Observable } from 'rxjs';
|
||||
import { ProfitBarAnimationChartData } from '../data/profit-bar-animation-chart';
|
||||
|
||||
@Injectable()
|
||||
export class ProfitBarAnimationChartService extends ProfitBarAnimationChartData {
|
||||
|
||||
private data: any;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.data = {
|
||||
firstLine: this.getDataForFirstLine(),
|
||||
secondLine: this.getDataForSecondLine(),
|
||||
};
|
||||
}
|
||||
|
||||
getDataForFirstLine(): number[] {
|
||||
return this.createEmptyArray(100)
|
||||
.map((_, index) => {
|
||||
const oneFifth = index / 5;
|
||||
|
||||
return (Math.sin(oneFifth) * (oneFifth - 10) + index / 6) * 5;
|
||||
});
|
||||
}
|
||||
|
||||
getDataForSecondLine(): number[] {
|
||||
return this.createEmptyArray(100)
|
||||
.map((_, index) => {
|
||||
const oneFifth = index / 5;
|
||||
|
||||
return (Math.cos(oneFifth) * (oneFifth - 10) + index / 6) * 5;
|
||||
});
|
||||
}
|
||||
|
||||
createEmptyArray(nPoints: number) {
|
||||
return Array.from(Array(nPoints));
|
||||
}
|
||||
|
||||
getChartData(): Observable<{ firstLine: number[]; secondLine: number[]; }> {
|
||||
return observableOf(this.data);
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { PeriodsService } from './periods.service';
|
||||
import { ProfitChart, ProfitChartData } from '../data/profit-chart';
|
||||
|
||||
@Injectable()
|
||||
export class ProfitChartService extends ProfitChartData {
|
||||
|
||||
private year = [
|
||||
'2012',
|
||||
'2013',
|
||||
'2014',
|
||||
'2015',
|
||||
'2016',
|
||||
'2017',
|
||||
'2018',
|
||||
];
|
||||
|
||||
private data = { };
|
||||
|
||||
constructor(private period: PeriodsService) {
|
||||
super();
|
||||
this.data = {
|
||||
week: this.getDataForWeekPeriod(),
|
||||
month: this.getDataForMonthPeriod(),
|
||||
year: this.getDataForYearPeriod(),
|
||||
};
|
||||
}
|
||||
|
||||
private getDataForWeekPeriod(): ProfitChart {
|
||||
const nPoint = this.period.getWeeks().length;
|
||||
|
||||
return {
|
||||
chartLabel: this.period.getWeeks(),
|
||||
data: [
|
||||
this.getRandomData(nPoint),
|
||||
this.getRandomData(nPoint),
|
||||
this.getRandomData(nPoint),
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
private getDataForMonthPeriod(): ProfitChart {
|
||||
const nPoint = this.period.getMonths().length;
|
||||
|
||||
return {
|
||||
chartLabel: this.period.getMonths(),
|
||||
data: [
|
||||
this.getRandomData(nPoint),
|
||||
this.getRandomData(nPoint),
|
||||
this.getRandomData(nPoint),
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
private getDataForYearPeriod(): ProfitChart {
|
||||
const nPoint = this.year.length;
|
||||
|
||||
return {
|
||||
chartLabel: this.year,
|
||||
data: [
|
||||
this.getRandomData(nPoint),
|
||||
this.getRandomData(nPoint),
|
||||
this.getRandomData(nPoint),
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
private getRandomData(nPoints: number): number[] {
|
||||
return Array.from(Array(nPoints)).map(() => {
|
||||
return Math.round(Math.random() * 500);
|
||||
});
|
||||
}
|
||||
|
||||
getProfitChartData(period: string): ProfitChart {
|
||||
return this.data[period];
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { of as observableOf, Observable } from 'rxjs';
|
||||
import { Camera, SecurityCamerasData } from '../data/security-cameras';
|
||||
|
||||
@Injectable()
|
||||
export class SecurityCamerasService extends SecurityCamerasData {
|
||||
|
||||
private cameras: Camera[] = [
|
||||
{
|
||||
title: 'Camera #1',
|
||||
source: 'assets/images/camera1.jpg',
|
||||
},
|
||||
{
|
||||
title: 'Camera #2',
|
||||
source: 'assets/images/camera2.jpg',
|
||||
},
|
||||
{
|
||||
title: 'Camera #3',
|
||||
source: 'assets/images/camera3.jpg',
|
||||
},
|
||||
{
|
||||
title: 'Camera #4',
|
||||
source: 'assets/images/camera4.jpg',
|
||||
},
|
||||
];
|
||||
|
||||
getCamerasData(): Observable<Camera[]> {
|
||||
return observableOf(this.cameras);
|
||||
}
|
||||
}
|
||||
@@ -1,432 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { SmartTableData } from '../data/smart-table';
|
||||
|
||||
@Injectable()
|
||||
export class SmartTableService extends SmartTableData {
|
||||
|
||||
data = [{
|
||||
id: 1,
|
||||
firstName: 'Mark',
|
||||
lastName: 'Otto',
|
||||
username: '@mdo',
|
||||
email: 'mdo@gmail.com',
|
||||
age: '28',
|
||||
}, {
|
||||
id: 2,
|
||||
firstName: 'Jacob',
|
||||
lastName: 'Thornton',
|
||||
username: '@fat',
|
||||
email: 'fat@yandex.ru',
|
||||
age: '45',
|
||||
}, {
|
||||
id: 3,
|
||||
firstName: 'Larry',
|
||||
lastName: 'Bird',
|
||||
username: '@twitter',
|
||||
email: 'twitter@outlook.com',
|
||||
age: '18',
|
||||
}, {
|
||||
id: 4,
|
||||
firstName: 'John',
|
||||
lastName: 'Snow',
|
||||
username: '@snow',
|
||||
email: 'snow@gmail.com',
|
||||
age: '20',
|
||||
}, {
|
||||
id: 5,
|
||||
firstName: 'Jack',
|
||||
lastName: 'Sparrow',
|
||||
username: '@jack',
|
||||
email: 'jack@yandex.ru',
|
||||
age: '30',
|
||||
}, {
|
||||
id: 6,
|
||||
firstName: 'Ann',
|
||||
lastName: 'Smith',
|
||||
username: '@ann',
|
||||
email: 'ann@gmail.com',
|
||||
age: '21',
|
||||
}, {
|
||||
id: 7,
|
||||
firstName: 'Barbara',
|
||||
lastName: 'Black',
|
||||
username: '@barbara',
|
||||
email: 'barbara@yandex.ru',
|
||||
age: '43',
|
||||
}, {
|
||||
id: 8,
|
||||
firstName: 'Sevan',
|
||||
lastName: 'Bagrat',
|
||||
username: '@sevan',
|
||||
email: 'sevan@outlook.com',
|
||||
age: '13',
|
||||
}, {
|
||||
id: 9,
|
||||
firstName: 'Ruben',
|
||||
lastName: 'Vardan',
|
||||
username: '@ruben',
|
||||
email: 'ruben@gmail.com',
|
||||
age: '22',
|
||||
}, {
|
||||
id: 10,
|
||||
firstName: 'Karen',
|
||||
lastName: 'Sevan',
|
||||
username: '@karen',
|
||||
email: 'karen@yandex.ru',
|
||||
age: '33',
|
||||
}, {
|
||||
id: 11,
|
||||
firstName: 'Mark',
|
||||
lastName: 'Otto',
|
||||
username: '@mark',
|
||||
email: 'mark@gmail.com',
|
||||
age: '38',
|
||||
}, {
|
||||
id: 12,
|
||||
firstName: 'Jacob',
|
||||
lastName: 'Thornton',
|
||||
username: '@jacob',
|
||||
email: 'jacob@yandex.ru',
|
||||
age: '48',
|
||||
}, {
|
||||
id: 13,
|
||||
firstName: 'Haik',
|
||||
lastName: 'Hakob',
|
||||
username: '@haik',
|
||||
email: 'haik@outlook.com',
|
||||
age: '48',
|
||||
}, {
|
||||
id: 14,
|
||||
firstName: 'Garegin',
|
||||
lastName: 'Jirair',
|
||||
username: '@garegin',
|
||||
email: 'garegin@gmail.com',
|
||||
age: '40',
|
||||
}, {
|
||||
id: 15,
|
||||
firstName: 'Krikor',
|
||||
lastName: 'Bedros',
|
||||
username: '@krikor',
|
||||
email: 'krikor@yandex.ru',
|
||||
age: '32',
|
||||
}, {
|
||||
'id': 16,
|
||||
'firstName': 'Francisca',
|
||||
'lastName': 'Brady',
|
||||
'username': '@Gibson',
|
||||
'email': 'franciscagibson@comtours.com',
|
||||
'age': 11,
|
||||
}, {
|
||||
'id': 17,
|
||||
'firstName': 'Tillman',
|
||||
'lastName': 'Figueroa',
|
||||
'username': '@Snow',
|
||||
'email': 'tillmansnow@comtours.com',
|
||||
'age': 34,
|
||||
}, {
|
||||
'id': 18,
|
||||
'firstName': 'Jimenez',
|
||||
'lastName': 'Morris',
|
||||
'username': '@Bryant',
|
||||
'email': 'jimenezbryant@comtours.com',
|
||||
'age': 45,
|
||||
}, {
|
||||
'id': 19,
|
||||
'firstName': 'Sandoval',
|
||||
'lastName': 'Jacobson',
|
||||
'username': '@Mcbride',
|
||||
'email': 'sandovalmcbride@comtours.com',
|
||||
'age': 32,
|
||||
}, {
|
||||
'id': 20,
|
||||
'firstName': 'Griffin',
|
||||
'lastName': 'Torres',
|
||||
'username': '@Charles',
|
||||
'email': 'griffincharles@comtours.com',
|
||||
'age': 19,
|
||||
}, {
|
||||
'id': 21,
|
||||
'firstName': 'Cora',
|
||||
'lastName': 'Parker',
|
||||
'username': '@Caldwell',
|
||||
'email': 'coracaldwell@comtours.com',
|
||||
'age': 27,
|
||||
}, {
|
||||
'id': 22,
|
||||
'firstName': 'Cindy',
|
||||
'lastName': 'Bond',
|
||||
'username': '@Velez',
|
||||
'email': 'cindyvelez@comtours.com',
|
||||
'age': 24,
|
||||
}, {
|
||||
'id': 23,
|
||||
'firstName': 'Frieda',
|
||||
'lastName': 'Tyson',
|
||||
'username': '@Craig',
|
||||
'email': 'friedacraig@comtours.com',
|
||||
'age': 45,
|
||||
}, {
|
||||
'id': 24,
|
||||
'firstName': 'Cote',
|
||||
'lastName': 'Holcomb',
|
||||
'username': '@Rowe',
|
||||
'email': 'coterowe@comtours.com',
|
||||
'age': 20,
|
||||
}, {
|
||||
'id': 25,
|
||||
'firstName': 'Trujillo',
|
||||
'lastName': 'Mejia',
|
||||
'username': '@Valenzuela',
|
||||
'email': 'trujillovalenzuela@comtours.com',
|
||||
'age': 16,
|
||||
}, {
|
||||
'id': 26,
|
||||
'firstName': 'Pruitt',
|
||||
'lastName': 'Shepard',
|
||||
'username': '@Sloan',
|
||||
'email': 'pruittsloan@comtours.com',
|
||||
'age': 44,
|
||||
}, {
|
||||
'id': 27,
|
||||
'firstName': 'Sutton',
|
||||
'lastName': 'Ortega',
|
||||
'username': '@Black',
|
||||
'email': 'suttonblack@comtours.com',
|
||||
'age': 42,
|
||||
}, {
|
||||
'id': 28,
|
||||
'firstName': 'Marion',
|
||||
'lastName': 'Heath',
|
||||
'username': '@Espinoza',
|
||||
'email': 'marionespinoza@comtours.com',
|
||||
'age': 47,
|
||||
}, {
|
||||
'id': 29,
|
||||
'firstName': 'Newman',
|
||||
'lastName': 'Hicks',
|
||||
'username': '@Keith',
|
||||
'email': 'newmankeith@comtours.com',
|
||||
'age': 15,
|
||||
}, {
|
||||
'id': 30,
|
||||
'firstName': 'Boyle',
|
||||
'lastName': 'Larson',
|
||||
'username': '@Summers',
|
||||
'email': 'boylesummers@comtours.com',
|
||||
'age': 32,
|
||||
}, {
|
||||
'id': 31,
|
||||
'firstName': 'Haynes',
|
||||
'lastName': 'Vinson',
|
||||
'username': '@Mckenzie',
|
||||
'email': 'haynesmckenzie@comtours.com',
|
||||
'age': 15,
|
||||
}, {
|
||||
'id': 32,
|
||||
'firstName': 'Miller',
|
||||
'lastName': 'Acosta',
|
||||
'username': '@Young',
|
||||
'email': 'milleryoung@comtours.com',
|
||||
'age': 55,
|
||||
}, {
|
||||
'id': 33,
|
||||
'firstName': 'Johnston',
|
||||
'lastName': 'Brown',
|
||||
'username': '@Knight',
|
||||
'email': 'johnstonknight@comtours.com',
|
||||
'age': 29,
|
||||
}, {
|
||||
'id': 34,
|
||||
'firstName': 'Lena',
|
||||
'lastName': 'Pitts',
|
||||
'username': '@Forbes',
|
||||
'email': 'lenaforbes@comtours.com',
|
||||
'age': 25,
|
||||
}, {
|
||||
'id': 35,
|
||||
'firstName': 'Terrie',
|
||||
'lastName': 'Kennedy',
|
||||
'username': '@Branch',
|
||||
'email': 'terriebranch@comtours.com',
|
||||
'age': 37,
|
||||
}, {
|
||||
'id': 36,
|
||||
'firstName': 'Louise',
|
||||
'lastName': 'Aguirre',
|
||||
'username': '@Kirby',
|
||||
'email': 'louisekirby@comtours.com',
|
||||
'age': 44,
|
||||
}, {
|
||||
'id': 37,
|
||||
'firstName': 'David',
|
||||
'lastName': 'Patton',
|
||||
'username': '@Sanders',
|
||||
'email': 'davidsanders@comtours.com',
|
||||
'age': 26,
|
||||
}, {
|
||||
'id': 38,
|
||||
'firstName': 'Holden',
|
||||
'lastName': 'Barlow',
|
||||
'username': '@Mckinney',
|
||||
'email': 'holdenmckinney@comtours.com',
|
||||
'age': 11,
|
||||
}, {
|
||||
'id': 39,
|
||||
'firstName': 'Baker',
|
||||
'lastName': 'Rivera',
|
||||
'username': '@Montoya',
|
||||
'email': 'bakermontoya@comtours.com',
|
||||
'age': 47,
|
||||
}, {
|
||||
'id': 40,
|
||||
'firstName': 'Belinda',
|
||||
'lastName': 'Lloyd',
|
||||
'username': '@Calderon',
|
||||
'email': 'belindacalderon@comtours.com',
|
||||
'age': 21,
|
||||
}, {
|
||||
'id': 41,
|
||||
'firstName': 'Pearson',
|
||||
'lastName': 'Patrick',
|
||||
'username': '@Clements',
|
||||
'email': 'pearsonclements@comtours.com',
|
||||
'age': 42,
|
||||
}, {
|
||||
'id': 42,
|
||||
'firstName': 'Alyce',
|
||||
'lastName': 'Mckee',
|
||||
'username': '@Daugherty',
|
||||
'email': 'alycedaugherty@comtours.com',
|
||||
'age': 55,
|
||||
}, {
|
||||
'id': 43,
|
||||
'firstName': 'Valencia',
|
||||
'lastName': 'Spence',
|
||||
'username': '@Olsen',
|
||||
'email': 'valenciaolsen@comtours.com',
|
||||
'age': 20,
|
||||
}, {
|
||||
'id': 44,
|
||||
'firstName': 'Leach',
|
||||
'lastName': 'Holcomb',
|
||||
'username': '@Humphrey',
|
||||
'email': 'leachhumphrey@comtours.com',
|
||||
'age': 28,
|
||||
}, {
|
||||
'id': 45,
|
||||
'firstName': 'Moss',
|
||||
'lastName': 'Baxter',
|
||||
'username': '@Fitzpatrick',
|
||||
'email': 'mossfitzpatrick@comtours.com',
|
||||
'age': 51,
|
||||
}, {
|
||||
'id': 46,
|
||||
'firstName': 'Jeanne',
|
||||
'lastName': 'Cooke',
|
||||
'username': '@Ward',
|
||||
'email': 'jeanneward@comtours.com',
|
||||
'age': 59,
|
||||
}, {
|
||||
'id': 47,
|
||||
'firstName': 'Wilma',
|
||||
'lastName': 'Briggs',
|
||||
'username': '@Kidd',
|
||||
'email': 'wilmakidd@comtours.com',
|
||||
'age': 53,
|
||||
}, {
|
||||
'id': 48,
|
||||
'firstName': 'Beatrice',
|
||||
'lastName': 'Perry',
|
||||
'username': '@Gilbert',
|
||||
'email': 'beatricegilbert@comtours.com',
|
||||
'age': 39,
|
||||
}, {
|
||||
'id': 49,
|
||||
'firstName': 'Whitaker',
|
||||
'lastName': 'Hyde',
|
||||
'username': '@Mcdonald',
|
||||
'email': 'whitakermcdonald@comtours.com',
|
||||
'age': 35,
|
||||
}, {
|
||||
'id': 50,
|
||||
'firstName': 'Rebekah',
|
||||
'lastName': 'Duran',
|
||||
'username': '@Gross',
|
||||
'email': 'rebekahgross@comtours.com',
|
||||
'age': 40,
|
||||
}, {
|
||||
'id': 51,
|
||||
'firstName': 'Earline',
|
||||
'lastName': 'Mayer',
|
||||
'username': '@Woodward',
|
||||
'email': 'earlinewoodward@comtours.com',
|
||||
'age': 52,
|
||||
}, {
|
||||
'id': 52,
|
||||
'firstName': 'Moran',
|
||||
'lastName': 'Baxter',
|
||||
'username': '@Johns',
|
||||
'email': 'moranjohns@comtours.com',
|
||||
'age': 20,
|
||||
}, {
|
||||
'id': 53,
|
||||
'firstName': 'Nanette',
|
||||
'lastName': 'Hubbard',
|
||||
'username': '@Cooke',
|
||||
'email': 'nanettecooke@comtours.com',
|
||||
'age': 55,
|
||||
}, {
|
||||
'id': 54,
|
||||
'firstName': 'Dalton',
|
||||
'lastName': 'Walker',
|
||||
'username': '@Hendricks',
|
||||
'email': 'daltonhendricks@comtours.com',
|
||||
'age': 25,
|
||||
}, {
|
||||
'id': 55,
|
||||
'firstName': 'Bennett',
|
||||
'lastName': 'Blake',
|
||||
'username': '@Pena',
|
||||
'email': 'bennettpena@comtours.com',
|
||||
'age': 13,
|
||||
}, {
|
||||
'id': 56,
|
||||
'firstName': 'Kellie',
|
||||
'lastName': 'Horton',
|
||||
'username': '@Weiss',
|
||||
'email': 'kellieweiss@comtours.com',
|
||||
'age': 48,
|
||||
}, {
|
||||
'id': 57,
|
||||
'firstName': 'Hobbs',
|
||||
'lastName': 'Talley',
|
||||
'username': '@Sanford',
|
||||
'email': 'hobbssanford@comtours.com',
|
||||
'age': 28,
|
||||
}, {
|
||||
'id': 58,
|
||||
'firstName': 'Mcguire',
|
||||
'lastName': 'Donaldson',
|
||||
'username': '@Roman',
|
||||
'email': 'mcguireroman@comtours.com',
|
||||
'age': 38,
|
||||
}, {
|
||||
'id': 59,
|
||||
'firstName': 'Rodriquez',
|
||||
'lastName': 'Saunders',
|
||||
'username': '@Harper',
|
||||
'email': 'rodriquezharper@comtours.com',
|
||||
'age': 20,
|
||||
}, {
|
||||
'id': 60,
|
||||
'firstName': 'Lou',
|
||||
'lastName': 'Conner',
|
||||
'username': '@Sanchez',
|
||||
'email': 'lousanchez@comtours.com',
|
||||
'age': 16,
|
||||
}];
|
||||
|
||||
getData() {
|
||||
return this.data;
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { of as observableOf, Observable } from 'rxjs';
|
||||
import { SolarData } from '../data/solar';
|
||||
|
||||
@Injectable()
|
||||
export class SolarService extends SolarData {
|
||||
private value = 42;
|
||||
|
||||
getSolarData(): Observable<number> {
|
||||
return observableOf(this.value);
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { of as observableOf, Observable } from 'rxjs';
|
||||
import { StatsBarData } from '../data/stats-bar';
|
||||
|
||||
@Injectable()
|
||||
export class StatsBarService extends StatsBarData {
|
||||
|
||||
private statsBarData: number[] = [
|
||||
300, 520, 435, 530,
|
||||
730, 620, 660, 860,
|
||||
];
|
||||
|
||||
getStatsBarData(): Observable<number[]> {
|
||||
return observableOf(this.statsBarData);
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { of as observableOf, Observable } from 'rxjs';
|
||||
import { ProgressInfo, StatsProgressBarData } from '../data/stats-progress-bar';
|
||||
|
||||
@Injectable()
|
||||
export class StatsProgressBarService extends StatsProgressBarData {
|
||||
private progressInfoData: ProgressInfo[] = [
|
||||
{
|
||||
title: 'Today’s Profit',
|
||||
value: 572900,
|
||||
activeProgress: 70,
|
||||
description: 'Better than last week (70%)',
|
||||
},
|
||||
{
|
||||
title: 'New Orders',
|
||||
value: 6378,
|
||||
activeProgress: 30,
|
||||
description: 'Better than last week (30%)',
|
||||
},
|
||||
{
|
||||
title: 'New Comments',
|
||||
value: 200,
|
||||
activeProgress: 55,
|
||||
description: 'Better than last week (55%)',
|
||||
},
|
||||
];
|
||||
|
||||
getProgressInfoData(): Observable<ProgressInfo[]> {
|
||||
return observableOf(this.progressInfoData);
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { of as observableOf, Observable } from 'rxjs';
|
||||
import { TemperatureHumidityData, Temperature } from '../data/temperature-humidity';
|
||||
|
||||
@Injectable()
|
||||
export class TemperatureHumidityService extends TemperatureHumidityData {
|
||||
|
||||
private temperatureDate: Temperature = {
|
||||
value: 24,
|
||||
min: 12,
|
||||
max: 30,
|
||||
};
|
||||
|
||||
private humidityDate: Temperature = {
|
||||
value: 87,
|
||||
min: 0,
|
||||
max: 100,
|
||||
};
|
||||
|
||||
getTemperatureData(): Observable<Temperature> {
|
||||
return observableOf(this.temperatureDate);
|
||||
}
|
||||
|
||||
getHumidityData(): Observable<Temperature> {
|
||||
return observableOf(this.humidityDate);
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { of as observableOf, Observable } from 'rxjs';
|
||||
import { PeriodsService } from './periods.service';
|
||||
import { TrafficBarData, TrafficBar } from '../data/traffic-bar';
|
||||
|
||||
@Injectable()
|
||||
export class TrafficBarService extends TrafficBarData {
|
||||
|
||||
private data = { };
|
||||
|
||||
constructor(private period: PeriodsService) {
|
||||
super();
|
||||
this.data = {
|
||||
week: this.getDataForWeekPeriod(),
|
||||
month: this.getDataForMonthPeriod(),
|
||||
year: this.getDataForYearPeriod(),
|
||||
};
|
||||
}
|
||||
|
||||
getDataForWeekPeriod(): TrafficBar {
|
||||
return {
|
||||
data: [10, 15, 19, 7, 20, 13, 15],
|
||||
labels: this.period.getWeeks(),
|
||||
formatter: '{c0} MB',
|
||||
};
|
||||
}
|
||||
|
||||
getDataForMonthPeriod(): TrafficBar {
|
||||
return {
|
||||
data: [0.5, 0.3, 0.8, 0.2, 0.3, 0.7, 0.8, 1, 0.7, 0.8, 0.6, 0.7],
|
||||
labels: this.period.getMonths(),
|
||||
formatter: '{c0} GB',
|
||||
};
|
||||
}
|
||||
|
||||
getDataForYearPeriod(): TrafficBar {
|
||||
return {
|
||||
data: [10, 15, 19, 7, 20, 13, 15, 19, 11],
|
||||
labels: this.period.getYears(),
|
||||
formatter: '{c0} GB',
|
||||
};
|
||||
}
|
||||
|
||||
getTrafficBarData(period: string): Observable<TrafficBar> {
|
||||
return observableOf(this.data[period]);
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { of as observableOf, Observable } from 'rxjs';
|
||||
import { TrafficChartData } from '../data/traffic-chart';
|
||||
|
||||
@Injectable()
|
||||
export class TrafficChartService extends TrafficChartData {
|
||||
|
||||
private data: number[] = [
|
||||
300, 520, 435, 530,
|
||||
730, 620, 660, 860,
|
||||
];
|
||||
|
||||
getTrafficChartData(): Observable<number[]> {
|
||||
return observableOf(this.data);
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { of as observableOf, Observable } from 'rxjs';
|
||||
import { PeriodsService } from './periods.service';
|
||||
import { TrafficList, TrafficListData } from '../data/traffic-list';
|
||||
|
||||
@Injectable()
|
||||
export class TrafficListService extends TrafficListData {
|
||||
|
||||
private getRandom = (roundTo: number) => Math.round(Math.random() * roundTo);
|
||||
private data = {};
|
||||
|
||||
constructor(private period: PeriodsService) {
|
||||
super();
|
||||
this.data = {
|
||||
week: this.getDataWeek(),
|
||||
month: this.getDataMonth(),
|
||||
year: this.getDataYear(),
|
||||
};
|
||||
}
|
||||
|
||||
private getDataWeek(): TrafficList[] {
|
||||
const getFirstDateInPeriod = () => {
|
||||
const weeks = this.period.getWeeks();
|
||||
|
||||
return weeks[weeks.length - 1];
|
||||
};
|
||||
|
||||
return this.reduceData(this.period.getWeeks(), getFirstDateInPeriod);
|
||||
}
|
||||
|
||||
private getDataMonth(): TrafficList[] {
|
||||
const getFirstDateInPeriod = () => {
|
||||
const months = this.period.getMonths();
|
||||
|
||||
return months[months.length - 1];
|
||||
};
|
||||
|
||||
return this.reduceData(this.period.getMonths(), getFirstDateInPeriod);
|
||||
}
|
||||
|
||||
private getDataYear(): TrafficList[] {
|
||||
const getFirstDateInPeriod = () => {
|
||||
const years = this.period.getYears();
|
||||
|
||||
return `${parseInt(years[0], 10) - 1}`;
|
||||
};
|
||||
|
||||
return this.reduceData(this.period.getYears(), getFirstDateInPeriod);
|
||||
}
|
||||
|
||||
private reduceData(timePeriods: string[], getFirstDateInPeriod: () => string): TrafficList[] {
|
||||
return timePeriods.reduce((result, timePeriod, index) => {
|
||||
const hasResult = result[index - 1];
|
||||
const prevDate = hasResult ?
|
||||
result[index - 1].comparison.nextDate :
|
||||
getFirstDateInPeriod();
|
||||
const prevValue = hasResult ?
|
||||
result[index - 1].comparison.nextValue :
|
||||
this.getRandom(100);
|
||||
const nextValue = this.getRandom(100);
|
||||
const deltaValue = prevValue - nextValue;
|
||||
|
||||
const item = {
|
||||
date: timePeriod,
|
||||
value: this.getRandom(1000),
|
||||
delta: {
|
||||
up: deltaValue <= 0,
|
||||
value: Math.abs(deltaValue),
|
||||
},
|
||||
comparison: {
|
||||
prevDate,
|
||||
prevValue,
|
||||
nextDate: timePeriod,
|
||||
nextValue,
|
||||
},
|
||||
};
|
||||
|
||||
return [...result, item];
|
||||
}, []);
|
||||
}
|
||||
|
||||
getTrafficListData(period: string): Observable<TrafficList> {
|
||||
return observableOf(this.data[period]);
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { of as observableOf, Observable } from 'rxjs';
|
||||
import { PeriodsService } from './periods.service';
|
||||
import { UserActive, UserActivityData } from '../data/user-activity';
|
||||
|
||||
@Injectable()
|
||||
export class UserActivityService extends UserActivityData {
|
||||
|
||||
private getRandom = (roundTo: number) => Math.round(Math.random() * roundTo);
|
||||
private generateUserActivityRandomData(date) {
|
||||
return {
|
||||
date,
|
||||
pagesVisitCount: this.getRandom(1000),
|
||||
deltaUp: this.getRandom(1) % 2 === 0,
|
||||
newVisits: this.getRandom(100),
|
||||
};
|
||||
}
|
||||
|
||||
data = {};
|
||||
|
||||
constructor(private periods: PeriodsService) {
|
||||
super();
|
||||
this.data = {
|
||||
week: this.getDataWeek(),
|
||||
month: this.getDataMonth(),
|
||||
year: this.getDataYear(),
|
||||
};
|
||||
}
|
||||
|
||||
private getDataWeek(): UserActive[] {
|
||||
return this.periods.getWeeks().map((week) => {
|
||||
return this.generateUserActivityRandomData(week);
|
||||
});
|
||||
}
|
||||
|
||||
private getDataMonth(): UserActive[] {
|
||||
const currentDate = new Date();
|
||||
const days = currentDate.getDate();
|
||||
const month = this.periods.getMonths()[currentDate.getMonth()];
|
||||
|
||||
return Array.from(Array(days)).map((_, index) => {
|
||||
const date = `${index + 1} ${month}`;
|
||||
|
||||
return this.generateUserActivityRandomData(date);
|
||||
});
|
||||
}
|
||||
|
||||
private getDataYear(): UserActive[] {
|
||||
return this.periods.getYears().map((year) => {
|
||||
return this.generateUserActivityRandomData(year);
|
||||
});
|
||||
}
|
||||
|
||||
getUserActivityData(period: string): Observable<UserActive[]> {
|
||||
return observableOf(this.data[period]);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { of as observableOf, Observable } from 'rxjs';
|
||||
import { PeriodsService } from './periods.service';
|
||||
import { OutlineData, VisitorsAnalyticsData } from '../data/visitors-analytics';
|
||||
|
||||
@Injectable()
|
||||
export class VisitorsAnalyticsService extends VisitorsAnalyticsData {
|
||||
|
||||
constructor(private periodService: PeriodsService) {
|
||||
super();
|
||||
}
|
||||
|
||||
private pieChartValue = 75;
|
||||
private innerLinePoints: number[] = [
|
||||
94, 188, 225, 244, 253, 254, 249, 235, 208,
|
||||
173, 141, 118, 105, 97, 94, 96, 104, 121, 147,
|
||||
183, 224, 265, 302, 333, 358, 375, 388, 395,
|
||||
400, 400, 397, 390, 377, 360, 338, 310, 278,
|
||||
241, 204, 166, 130, 98, 71, 49, 32, 20, 13, 9,
|
||||
];
|
||||
private outerLinePoints: number[] = [
|
||||
85, 71, 59, 50, 45, 42, 41, 44 , 58, 88,
|
||||
136 , 199, 267, 326, 367, 391, 400, 397,
|
||||
376, 319, 200, 104, 60, 41, 36, 37, 44,
|
||||
55, 74, 100 , 131, 159, 180, 193, 199, 200,
|
||||
195, 184, 164, 135, 103, 73, 50, 33, 22, 15, 11,
|
||||
];
|
||||
private generateOutlineLineData(): OutlineData[] {
|
||||
const months = this.periodService.getMonths();
|
||||
const outerLinePointsLength = this.outerLinePoints.length;
|
||||
const monthsLength = months.length;
|
||||
|
||||
return this.outerLinePoints.map((p, index) => {
|
||||
const monthIndex = Math.round(index / 4);
|
||||
const label = (index % Math.round(outerLinePointsLength / monthsLength) === 0)
|
||||
? months[monthIndex]
|
||||
: '';
|
||||
|
||||
return {
|
||||
label,
|
||||
value: p,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
getInnerLineChartData(): Observable<number[]> {
|
||||
return observableOf(this.innerLinePoints);
|
||||
}
|
||||
|
||||
getOutlineLineChartData(): Observable<OutlineData[]> {
|
||||
return observableOf(this.generateOutlineLineData());
|
||||
}
|
||||
|
||||
getPieChartData(): Observable<number> {
|
||||
return observableOf(this.pieChartValue);
|
||||
}
|
||||
}
|
||||
@@ -6,10 +6,7 @@ import { Component } from '@angular/core';
|
||||
template: `
|
||||
<span class="created-by">Created with ♥ by <b><a href="https://akveo.com" target="_blank">Akveo</a></b> 2019</span>
|
||||
<div class="socials">
|
||||
<a href="#" target="_blank" class="ion ion-social-github"></a>
|
||||
<a href="#" target="_blank" class="ion ion-social-facebook"></a>
|
||||
<a href="#" target="_blank" class="ion ion-social-twitter"></a>
|
||||
<a href="#" target="_blank" class="ion ion-social-linkedin"></a>
|
||||
<a href="http://www.versioncontrol.me/" target="_blank" class="ion ion-social-github"></a>
|
||||
</div>
|
||||
`,
|
||||
})
|
||||
|
||||
@@ -3,11 +3,8 @@
|
||||
<a (click)="toggleSidebar()" href="#" class="sidebar-toggle">
|
||||
<nb-icon icon="menu-2-outline"></nb-icon>
|
||||
</a>
|
||||
<a class="logo" href="#" (click)="navigateHome()">ngx-<span>admin</span></a>
|
||||
<a class="logo" href="#" (click)="navigateHome()">Frontcraft</a>
|
||||
</div>
|
||||
<nb-select [selected]="currentTheme" (selectedChange)="changeTheme($event)" status="primary">
|
||||
<nb-option *ngFor="let theme of themes" [value]="theme.value"> {{ theme.name }}</nb-option>
|
||||
</nb-select>
|
||||
</div>
|
||||
|
||||
<div class="header-container">
|
||||
@@ -18,7 +15,7 @@
|
||||
</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="user-action" *nbIsGranted="['view', 'user']" >
|
||||
<nb-action class="user-action">
|
||||
<nb-user [nbContextMenu]="userMenu"
|
||||
[onlyPicture]="userPictureOnly"
|
||||
[name]="user?.name"
|
||||
|
||||
@@ -36,14 +36,13 @@ export class HeaderComponent implements OnInit, OnDestroy {
|
||||
},
|
||||
];
|
||||
|
||||
currentTheme = 'default';
|
||||
currentTheme = 'dark';
|
||||
|
||||
userMenu = [ { title: 'Profile' }, { title: 'Log out' } ];
|
||||
|
||||
constructor(private sidebarService: NbSidebarService,
|
||||
private menuService: NbMenuService,
|
||||
private themeService: NbThemeService,
|
||||
private userService: UserData,
|
||||
private layoutService: LayoutService,
|
||||
private breakpointService: NbMediaBreakpointsService) {
|
||||
}
|
||||
@@ -51,10 +50,12 @@ export class HeaderComponent implements OnInit, OnDestroy {
|
||||
ngOnInit() {
|
||||
this.currentTheme = this.themeService.currentTheme;
|
||||
|
||||
/*
|
||||
this.userService.getUsers()
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe((users: any) => this.user = users.nick);
|
||||
|
||||
.subscribe((users: any) => this.user = users.lee);
|
||||
*/
|
||||
|
||||
const { xl } = this.breakpointService.getBreakpointsMap();
|
||||
this.themeService.onMediaQueryChange()
|
||||
.pipe(
|
||||
|
||||
@@ -82,7 +82,7 @@ export class ThemeModule {
|
||||
providers: [
|
||||
...NbThemeModule.forRoot(
|
||||
{
|
||||
name: 'default',
|
||||
name: 'dark',
|
||||
},
|
||||
[ DEFAULT_THEME, COSMIC_THEME, CORPORATE_THEME, DARK_THEME ],
|
||||
).providers,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { ExtraOptions, RouterModule, Routes } from '@angular/router';
|
||||
import { NgModule } from '@angular/core';
|
||||
import {
|
||||
NbAuthComponent,
|
||||
NbLoginComponent,
|
||||
NbLogoutComponent,
|
||||
NbRegisterComponent,
|
||||
@@ -12,39 +11,10 @@ import {
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: 'pages',
|
||||
loadChildren: () => import('app/pages/pages.module')
|
||||
loadChildren: () => import('./pages/pages.module')
|
||||
.then(m => m.PagesModule),
|
||||
},
|
||||
{
|
||||
path: 'auth',
|
||||
component: NbAuthComponent,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
component: NbLoginComponent,
|
||||
},
|
||||
{
|
||||
path: 'login',
|
||||
component: NbLoginComponent,
|
||||
},
|
||||
{
|
||||
path: 'register',
|
||||
component: NbRegisterComponent,
|
||||
},
|
||||
{
|
||||
path: 'logout',
|
||||
component: NbLogoutComponent,
|
||||
},
|
||||
{
|
||||
path: 'request-password',
|
||||
component: NbRequestPasswordComponent,
|
||||
},
|
||||
{
|
||||
path: 'reset-password',
|
||||
component: NbResetPasswordComponent,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{ path: '', redirectTo: 'pages', pathMatch: 'full' },
|
||||
{ path: '**', redirectTo: 'pages' },
|
||||
];
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { AnalyticsService } from './@core/utils/analytics.service';
|
||||
import { LoginApiService } from './frontcraft/login-api';
|
||||
|
||||
@Component({
|
||||
selector: 'ngx-app',
|
||||
@@ -12,11 +13,12 @@ import { AnalyticsService } from './@core/utils/analytics.service';
|
||||
})
|
||||
export class AppComponent implements OnInit {
|
||||
|
||||
constructor(private analytics: AnalyticsService) {
|
||||
constructor(private loginSvc: LoginApiService, private analytics: AnalyticsService) {
|
||||
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.analytics.trackPageViews();
|
||||
window['s'] = this.loginSvc
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
import {RPCSocket} from 'rpclibrary/js/src/Frontend'
|
||||
|
||||
import { Token, Auth, User, _Rank, _Class, FrontcraftFeatureIfc, LoginManagerIfc, } from '../../../../backend/Types/Types'
|
||||
import { CookieService } from 'ngx-cookie-service';
|
||||
|
||||
@Injectable()
|
||||
export class LoginApiService{
|
||||
private socket:RPCSocket & LoginManagerIfc;
|
||||
private auth:Auth
|
||||
private privSocket: RPCSocket & FrontcraftFeatureIfc
|
||||
|
||||
constructor(
|
||||
private cookieSvc : CookieService
|
||||
){}
|
||||
|
||||
getUnprivilegedSocket = () : RPCSocket & LoginManagerIfc => this.socket
|
||||
|
||||
private getPrivilegedSocket = async (auth:Auth) : Promise<RPCSocket & FrontcraftFeatureIfc> => {
|
||||
if(this.privSocket) return this.privSocket
|
||||
try{
|
||||
const sock: RPCSocket & FrontcraftFeatureIfc = await new RPCSocket(auth.port, window.location.hostname).connect(auth.token.value)
|
||||
//login success
|
||||
this.auth = auth
|
||||
this.privSocket = sock
|
||||
this.setCookie(auth.token)
|
||||
return sock
|
||||
}catch(e){
|
||||
//login failed
|
||||
throw new Error('login failed')
|
||||
}
|
||||
}
|
||||
|
||||
getCurrentUser = () : User => this.auth
|
||||
? this.auth.user
|
||||
: {
|
||||
name: 'Guest',
|
||||
class: _Class[Math.floor(_Class.length * Math.random())],
|
||||
pwhash: '',
|
||||
rank: 'Guest'
|
||||
}
|
||||
|
||||
authenticate = async (token : Token | string) : Promise<RPCSocket & FrontcraftFeatureIfc> => {
|
||||
const auth = await this.socket.Authenticator.authenticate(token)
|
||||
return await this.getPrivilegedSocket(auth)
|
||||
}
|
||||
|
||||
login = async (username, password) => {
|
||||
const buf = str2arraybuf(password)
|
||||
const pwHash = await crypto.subtle.digest('SHA-256', buf);
|
||||
const token = await this.socket.Authenticator.login(username, buf2hex(pwHash))
|
||||
return await this.authenticate(token)
|
||||
}
|
||||
|
||||
logout = () => {
|
||||
this.cookieSvc.deleteAll()
|
||||
this.auth = null
|
||||
if(this.privSocket) this.privSocket.destroy()
|
||||
this.privSocket = null
|
||||
}
|
||||
|
||||
private setCookie = (token: string | Token) => {
|
||||
token = 'string' === typeof token? token : token.value
|
||||
this.cookieSvc.set('token', token)
|
||||
}
|
||||
|
||||
private getCookie = () : string | Token | undefined => {
|
||||
return this.cookieSvc.get('token')
|
||||
}
|
||||
|
||||
initialize = async () : Promise<RPCSocket> => {
|
||||
const sock : RPCSocket & LoginManagerIfc = await new RPCSocket(20000, window.location.hostname).connect()
|
||||
this.socket = sock
|
||||
|
||||
const cookie = this.getCookie()
|
||||
if(cookie) {
|
||||
return await this.authenticate(cookie)
|
||||
}
|
||||
|
||||
return sock
|
||||
}
|
||||
}
|
||||
|
||||
function str2arraybuf(str:string): ArrayBuffer {
|
||||
return new Buffer(str)
|
||||
}
|
||||
|
||||
function buf2hex(buffer) { // buffer is an ArrayBuffer
|
||||
return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join('');
|
||||
}
|
||||
|
||||
|
||||
export function initializeLoginSvc(svc: LoginApiService): () => Promise<RPCSocket> {
|
||||
return svc.initialize
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
import {RPCSocket} from 'rpclibrary'
|
||||
var crypto = require('crypto');
|
||||
|
||||
import { User, } from '../../../../backend/Types/Types'
|
||||
|
||||
@Injectable()
|
||||
export class UserService{
|
||||
|
||||
private loginSocket = new RPCSocket(20000, window.location.hostname).connect()
|
||||
|
||||
constructor(){}
|
||||
|
||||
login = async (username:string, password:string) => {
|
||||
const pwHash = crypto.createHash('sha256').update(password).digest('hex');
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,247 +1,4 @@
|
||||
import { NbMenuItem } from '@nebular/theme';
|
||||
|
||||
export const MENU_ITEMS: NbMenuItem[] = [
|
||||
{
|
||||
title: 'E-commerce',
|
||||
icon: 'shopping-cart-outline',
|
||||
link: '/pages/dashboard',
|
||||
home: true,
|
||||
},
|
||||
{
|
||||
title: 'IoT Dashboard',
|
||||
icon: 'home-outline',
|
||||
link: '/pages/iot-dashboard',
|
||||
},
|
||||
{
|
||||
title: 'FEATURES',
|
||||
group: true,
|
||||
},
|
||||
{
|
||||
title: 'Layout',
|
||||
icon: 'layout-outline',
|
||||
children: [
|
||||
{
|
||||
title: 'Stepper',
|
||||
link: '/pages/layout/stepper',
|
||||
},
|
||||
{
|
||||
title: 'List',
|
||||
link: '/pages/layout/list',
|
||||
},
|
||||
{
|
||||
title: 'Infinite List',
|
||||
link: '/pages/layout/infinite-list',
|
||||
},
|
||||
{
|
||||
title: 'Accordion',
|
||||
link: '/pages/layout/accordion',
|
||||
},
|
||||
{
|
||||
title: 'Tabs',
|
||||
pathMatch: 'prefix',
|
||||
link: '/pages/layout/tabs',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Forms',
|
||||
icon: 'edit-2-outline',
|
||||
children: [
|
||||
{
|
||||
title: 'Form Inputs',
|
||||
link: '/pages/forms/inputs',
|
||||
},
|
||||
{
|
||||
title: 'Form Layouts',
|
||||
link: '/pages/forms/layouts',
|
||||
},
|
||||
{
|
||||
title: 'Buttons',
|
||||
link: '/pages/forms/buttons',
|
||||
},
|
||||
{
|
||||
title: 'Datepicker',
|
||||
link: '/pages/forms/datepicker',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'UI Features',
|
||||
icon: 'keypad-outline',
|
||||
link: '/pages/ui-features',
|
||||
children: [
|
||||
{
|
||||
title: 'Grid',
|
||||
link: '/pages/ui-features/grid',
|
||||
},
|
||||
{
|
||||
title: 'Icons',
|
||||
link: '/pages/ui-features/icons',
|
||||
},
|
||||
{
|
||||
title: 'Typography',
|
||||
link: '/pages/ui-features/typography',
|
||||
},
|
||||
{
|
||||
title: 'Animated Searches',
|
||||
link: '/pages/ui-features/search-fields',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Modal & Overlays',
|
||||
icon: 'browser-outline',
|
||||
children: [
|
||||
{
|
||||
title: 'Dialog',
|
||||
link: '/pages/modal-overlays/dialog',
|
||||
},
|
||||
{
|
||||
title: 'Window',
|
||||
link: '/pages/modal-overlays/window',
|
||||
},
|
||||
{
|
||||
title: 'Popover',
|
||||
link: '/pages/modal-overlays/popover',
|
||||
},
|
||||
{
|
||||
title: 'Toastr',
|
||||
link: '/pages/modal-overlays/toastr',
|
||||
},
|
||||
{
|
||||
title: 'Tooltip',
|
||||
link: '/pages/modal-overlays/tooltip',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Extra Components',
|
||||
icon: 'message-circle-outline',
|
||||
children: [
|
||||
{
|
||||
title: 'Calendar',
|
||||
link: '/pages/extra-components/calendar',
|
||||
},
|
||||
{
|
||||
title: 'Progress Bar',
|
||||
link: '/pages/extra-components/progress-bar',
|
||||
},
|
||||
{
|
||||
title: 'Spinner',
|
||||
link: '/pages/extra-components/spinner',
|
||||
},
|
||||
{
|
||||
title: 'Alert',
|
||||
link: '/pages/extra-components/alert',
|
||||
},
|
||||
{
|
||||
title: 'Calendar Kit',
|
||||
link: '/pages/extra-components/calendar-kit',
|
||||
},
|
||||
{
|
||||
title: 'Chat',
|
||||
link: '/pages/extra-components/chat',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Maps',
|
||||
icon: 'map-outline',
|
||||
children: [
|
||||
{
|
||||
title: 'Google Maps',
|
||||
link: '/pages/maps/gmaps',
|
||||
},
|
||||
{
|
||||
title: 'Leaflet Maps',
|
||||
link: '/pages/maps/leaflet',
|
||||
},
|
||||
{
|
||||
title: 'Bubble Maps',
|
||||
link: '/pages/maps/bubble',
|
||||
},
|
||||
{
|
||||
title: 'Search Maps',
|
||||
link: '/pages/maps/searchmap',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Charts',
|
||||
icon: 'pie-chart-outline',
|
||||
children: [
|
||||
{
|
||||
title: 'Echarts',
|
||||
link: '/pages/charts/echarts',
|
||||
},
|
||||
{
|
||||
title: 'Charts.js',
|
||||
link: '/pages/charts/chartjs',
|
||||
},
|
||||
{
|
||||
title: 'D3',
|
||||
link: '/pages/charts/d3',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Editors',
|
||||
icon: 'text-outline',
|
||||
children: [
|
||||
{
|
||||
title: 'TinyMCE',
|
||||
link: '/pages/editors/tinymce',
|
||||
},
|
||||
{
|
||||
title: 'CKEditor',
|
||||
link: '/pages/editors/ckeditor',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Tables & Data',
|
||||
icon: 'grid-outline',
|
||||
children: [
|
||||
{
|
||||
title: 'Smart Table',
|
||||
link: '/pages/tables/smart-table',
|
||||
},
|
||||
{
|
||||
title: 'Tree Grid',
|
||||
link: '/pages/tables/tree-grid',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Miscellaneous',
|
||||
icon: 'shuffle-2-outline',
|
||||
children: [
|
||||
{
|
||||
title: '404',
|
||||
link: '/pages/miscellaneous/404',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Auth',
|
||||
icon: 'lock-outline',
|
||||
children: [
|
||||
{
|
||||
title: 'Login',
|
||||
link: '/auth/login',
|
||||
},
|
||||
{
|
||||
title: 'Register',
|
||||
link: '/auth/register',
|
||||
},
|
||||
{
|
||||
title: 'Request Password',
|
||||
link: '/auth/request-password',
|
||||
},
|
||||
{
|
||||
title: 'Reset Password',
|
||||
link: '/auth/reset-password',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
@@ -10,64 +10,7 @@ const routes: Routes = [{
|
||||
path: '',
|
||||
component: PagesComponent,
|
||||
children: [
|
||||
{
|
||||
path: 'dashboard',
|
||||
component: ECommerceComponent,
|
||||
},
|
||||
{
|
||||
path: 'iot-dashboard',
|
||||
component: DashboardComponent,
|
||||
},
|
||||
{
|
||||
path: 'layout',
|
||||
loadChildren: () => import('./layout/layout.module')
|
||||
.then(m => m.LayoutModule),
|
||||
},
|
||||
{
|
||||
path: 'forms',
|
||||
loadChildren: () => import('./forms/forms.module')
|
||||
.then(m => m.FormsModule),
|
||||
},
|
||||
{
|
||||
path: 'ui-features',
|
||||
loadChildren: () => import('./ui-features/ui-features.module')
|
||||
.then(m => m.UiFeaturesModule),
|
||||
},
|
||||
{
|
||||
path: 'modal-overlays',
|
||||
loadChildren: () => import('./modal-overlays/modal-overlays.module')
|
||||
.then(m => m.ModalOverlaysModule),
|
||||
},
|
||||
{
|
||||
path: 'extra-components',
|
||||
loadChildren: () => import('./extra-components/extra-components.module')
|
||||
.then(m => m.ExtraComponentsModule),
|
||||
},
|
||||
{
|
||||
path: 'maps',
|
||||
loadChildren: () => import('./maps/maps.module')
|
||||
.then(m => m.MapsModule),
|
||||
},
|
||||
{
|
||||
path: 'charts',
|
||||
loadChildren: () => import('./charts/charts.module')
|
||||
.then(m => m.ChartsModule),
|
||||
},
|
||||
{
|
||||
path: 'editors',
|
||||
loadChildren: () => import('./editors/editors.module')
|
||||
.then(m => m.EditorsModule),
|
||||
},
|
||||
{
|
||||
path: 'tables',
|
||||
loadChildren: () => import('./tables/tables.module')
|
||||
.then(m => m.TablesModule),
|
||||
},
|
||||
{
|
||||
path: 'miscellaneous',
|
||||
loadChildren: () => import('./miscellaneous/miscellaneous.module')
|
||||
.then(m => m.MiscellaneousModule),
|
||||
},
|
||||
|
||||
{
|
||||
path: '',
|
||||
redirectTo: 'dashboard',
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
"exclude": [
|
||||
"test.ts",
|
||||
"**/*.spec.ts",
|
||||
"../node_modules/@nebular/**/*.spec.ts"
|
||||
"../node_modules/@nebular/**/*.spec.ts",
|
||||
"../node_modules/rpclibrary/js/**/*"
|
||||
],
|
||||
"include": [
|
||||
"../src/*.ts",
|
||||
|
||||
Reference in New Issue
Block a user