35 changed files with 2269 additions and 295 deletions
@ -0,0 +1,39 @@ |
|||
///
|
|||
/// Copyright © 2016-2019 The Thingsboard Authors
|
|||
///
|
|||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
|||
/// you may not use this file except in compliance with the License.
|
|||
/// You may obtain a copy of the License at
|
|||
///
|
|||
/// http://www.apache.org/licenses/LICENSE-2.0
|
|||
///
|
|||
/// Unless required by applicable law or agreed to in writing, software
|
|||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
|||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||
/// See the License for the specific language governing permissions and
|
|||
/// limitations under the License.
|
|||
///
|
|||
|
|||
import { IAliasController, AliasInfo } from '@core/api/widget-api.models'; |
|||
import { Observable, of, Subject } from 'rxjs'; |
|||
import { Datasource } from '@app/shared/models/widget.models'; |
|||
import { deepClone } from '@core/utils'; |
|||
|
|||
export class DummyAliasController implements IAliasController { |
|||
|
|||
entityAliasesChanged: Observable<Array<string>>; |
|||
|
|||
[key: string]: any | null; |
|||
|
|||
constructor() { |
|||
this.entityAliasesChanged = new Subject<Array<string>>().asObservable(); |
|||
} |
|||
|
|||
getAliasInfo(aliasId): Observable<AliasInfo> { |
|||
return of(null); |
|||
} |
|||
|
|||
resolveDatasources(datasources: Array<Datasource>): Observable<Array<Datasource>> { |
|||
return of(deepClone(datasources)); |
|||
} |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
///
|
|||
/// Copyright © 2016-2019 The Thingsboard Authors
|
|||
///
|
|||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
|||
/// you may not use this file except in compliance with the License.
|
|||
/// You may obtain a copy of the License at
|
|||
///
|
|||
/// http://www.apache.org/licenses/LICENSE-2.0
|
|||
///
|
|||
/// Unless required by applicable law or agreed to in writing, software
|
|||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
|||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||
/// See the License for the specific language governing permissions and
|
|||
/// limitations under the License.
|
|||
///
|
|||
|
|||
import { Injectable } from '@angular/core'; |
|||
import { TelemetryWebsocketService } from '@core/ws/telemetry-websocket.service'; |
|||
import { UtilsService } from '@core/services/utils.service'; |
|||
import { EntityType } from '@app/shared/models/entity-type.models'; |
|||
|
|||
export interface DatasourceListener { |
|||
entityType: EntityType; |
|||
entityId: string; |
|||
} |
|||
|
|||
@Injectable({ |
|||
providedIn: 'root' |
|||
}) |
|||
export class DatasourceService { |
|||
|
|||
constructor(private telemetryService: TelemetryWebsocketService, |
|||
private utils: UtilsService) {} |
|||
|
|||
public subscribeToDatasource(listener: DatasourceListener) { |
|||
// TODO:
|
|||
} |
|||
|
|||
public unsubscribeFromDatasource(listener: DatasourceListener) { |
|||
// TODO:
|
|||
} |
|||
} |
|||
@ -0,0 +1,396 @@ |
|||
///
|
|||
/// Copyright © 2016-2019 The Thingsboard Authors
|
|||
///
|
|||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
|||
/// you may not use this file except in compliance with the License.
|
|||
/// You may obtain a copy of the License at
|
|||
///
|
|||
/// http://www.apache.org/licenses/LICENSE-2.0
|
|||
///
|
|||
/// Unless required by applicable law or agreed to in writing, software
|
|||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
|||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||
/// See the License for the specific language governing permissions and
|
|||
/// limitations under the License.
|
|||
///
|
|||
|
|||
import { |
|||
EntityInfo, |
|||
IWidgetSubscription, |
|||
WidgetSubscriptionCallbacks, |
|||
WidgetSubscriptionContext, |
|||
WidgetSubscriptionOptions |
|||
} from '@core/api/widget-api.models'; |
|||
import { |
|||
DataSet, |
|||
Datasource, |
|||
DatasourceData, |
|||
LegendConfig, |
|||
LegendData, |
|||
LegendKey, |
|||
LegendKeyData, |
|||
widgetType |
|||
} from '@app/shared/models/widget.models'; |
|||
import { HttpErrorResponse } from '@angular/common/http'; |
|||
import { Timewindow } from '@app/shared/models/time/time.models'; |
|||
import { Observable, of, ReplaySubject, Subject } from 'rxjs'; |
|||
import { CancelAnimationFrame } from '@core/services/raf.service'; |
|||
import { EntityType } from '@shared/models/entity-type.models'; |
|||
import { AlarmInfo, AlarmSearchStatus } from '@shared/models/alarm.models'; |
|||
import { deepClone, isDefined } from '@core/utils'; |
|||
import { AlarmSourceListener } from '@core/http/alarm.service'; |
|||
import { DatasourceListener } from '@core/api/datasource.service'; |
|||
|
|||
export class WidgetSubscription implements IWidgetSubscription { |
|||
|
|||
id: string; |
|||
ctx: WidgetSubscriptionContext; |
|||
type: widgetType; |
|||
callbacks: WidgetSubscriptionCallbacks; |
|||
|
|||
timeWindow: Timewindow; |
|||
originalTimewindow: Timewindow; |
|||
timeWindowConfig: Timewindow; |
|||
subscriptionTimewindow: Timewindow; |
|||
useDashboardTimewindow: boolean; |
|||
|
|||
data: Array<DatasourceData>; |
|||
datasources: Array<Datasource>; |
|||
datasourceListeners: Array<DatasourceListener>; |
|||
hiddenData: Array<{ data: DataSet }>; |
|||
legendData: LegendData; |
|||
legendConfig: LegendConfig; |
|||
caulculateLegendData: boolean; |
|||
displayLegend: boolean; |
|||
stateData: boolean; |
|||
decimals: number; |
|||
units: string; |
|||
|
|||
alarms: Array<AlarmInfo>; |
|||
alarmSource: Datasource; |
|||
alarmSearchStatus: AlarmSearchStatus; |
|||
alarmsPollingInterval: number; |
|||
alarmSourceListener: AlarmSourceListener; |
|||
|
|||
loadingData: boolean; |
|||
|
|||
targetDeviceAliasIds?: Array<string>; |
|||
targetDeviceIds?: Array<string>; |
|||
|
|||
executingRpcRequest: boolean; |
|||
rpcEnabled: boolean; |
|||
rpcErrorText: string; |
|||
rpcRejection: HttpErrorResponse; |
|||
|
|||
init$: Observable<IWidgetSubscription>; |
|||
|
|||
cafs: {[cafId: string]: CancelAnimationFrame} = {}; |
|||
|
|||
targetDeviceAliasId: string; |
|||
targetDeviceId: string; |
|||
targetDeviceName: string; |
|||
executingSubjects: Array<Subject<any>>; |
|||
|
|||
constructor(subscriptionContext: WidgetSubscriptionContext, options: WidgetSubscriptionOptions) { |
|||
const subscriptionSubject = new ReplaySubject<IWidgetSubscription>(); |
|||
this.init$ = subscriptionSubject.asObservable(); |
|||
this.ctx = subscriptionContext; |
|||
this.type = options.type; |
|||
this.id = this.ctx.utils.guid(); |
|||
this.callbacks = options.callbacks; |
|||
|
|||
if (this.type === widgetType.rpc) { |
|||
this.callbacks.rpcStateChanged = this.callbacks.rpcStateChanged || (() => {}); |
|||
this.callbacks.onRpcSuccess = this.callbacks.onRpcSuccess || (() => {}); |
|||
this.callbacks.onRpcFailed = this.callbacks.onRpcFailed || (() => {}); |
|||
this.callbacks.onRpcErrorCleared = this.callbacks.onRpcErrorCleared || (() => {}); |
|||
|
|||
this.targetDeviceAliasIds = options.targetDeviceAliasIds; |
|||
this.targetDeviceIds = options.targetDeviceIds; |
|||
|
|||
this.targetDeviceAliasId = null; |
|||
this.targetDeviceId = null; |
|||
|
|||
this.rpcRejection = null; |
|||
this.rpcErrorText = null; |
|||
this.rpcEnabled = false; |
|||
this.executingRpcRequest = false; |
|||
this.executingSubjects = []; |
|||
this.initRpc().subscribe(() => { |
|||
subscriptionSubject.next(this); |
|||
subscriptionSubject.complete(); |
|||
}); |
|||
} else if (this.type === widgetType.alarm) { |
|||
this.callbacks.onDataUpdated = this.callbacks.onDataUpdated || (() => {}); |
|||
this.callbacks.onDataUpdateError = this.callbacks.onDataUpdateError || (() => {}); |
|||
this.callbacks.dataLoading = this.callbacks.dataLoading || (() => {}); |
|||
this.callbacks.timeWindowUpdated = this.callbacks.timeWindowUpdated || (() => {}); |
|||
this.alarmSource = options.alarmSource; |
|||
this.alarmSearchStatus = isDefined(options.alarmSearchStatus) ? |
|||
options.alarmSearchStatus : AlarmSearchStatus.ANY; |
|||
this.alarmsPollingInterval = isDefined(options.alarmsPollingInterval) ? |
|||
options.alarmsPollingInterval : 5000; |
|||
this.alarmSourceListener = null; |
|||
this.alarms = []; |
|||
this.originalTimewindow = null; |
|||
this.timeWindow = {}; |
|||
this.useDashboardTimewindow = options.useDashboardTimewindow; |
|||
if (this.useDashboardTimewindow) { |
|||
this.timeWindowConfig = deepClone(options.dashboardTimewindow); |
|||
} else { |
|||
this.timeWindowConfig = deepClone(options.timeWindowConfig); |
|||
} |
|||
this.subscriptionTimewindow = null; |
|||
this.loadingData = false; |
|||
this.displayLegend = false; |
|||
this.initAlarmSubscription().subscribe(() => { |
|||
subscriptionSubject.next(this); |
|||
subscriptionSubject.complete(); |
|||
}, |
|||
() => { |
|||
subscriptionSubject.error(null); |
|||
}); |
|||
} else { |
|||
this.callbacks.onDataUpdated = this.callbacks.onDataUpdated || (() => {}); |
|||
this.callbacks.onDataUpdateError = this.callbacks.onDataUpdateError || (() => {}); |
|||
this.callbacks.dataLoading = this.callbacks.dataLoading || (() => {}); |
|||
this.callbacks.legendDataUpdated = this.callbacks.legendDataUpdated || (() => {}); |
|||
this.callbacks.timeWindowUpdated = this.callbacks.timeWindowUpdated || (() => {}); |
|||
|
|||
this.datasources = this.ctx.utils.validateDatasources(options.datasources); |
|||
this.datasourceListeners = []; |
|||
this.data = []; |
|||
this.hiddenData = []; |
|||
this.originalTimewindow = null; |
|||
this.timeWindow = {}; |
|||
this.useDashboardTimewindow = options.useDashboardTimewindow; |
|||
this.stateData = options.stateData; |
|||
if (this.useDashboardTimewindow) { |
|||
this.timeWindowConfig = deepClone(options.dashboardTimewindow); |
|||
} else { |
|||
this.timeWindowConfig = deepClone(options.timeWindowConfig); |
|||
} |
|||
|
|||
this.subscriptionTimewindow = null; |
|||
|
|||
this.units = options.units || ''; |
|||
this.decimals = isDefined(options.decimals) ? options.decimals : 2; |
|||
|
|||
this.loadingData = false; |
|||
|
|||
if (options.legendConfig) { |
|||
this.legendConfig = options.legendConfig; |
|||
this.legendData = { |
|||
keys: [], |
|||
data: [] |
|||
}; |
|||
this.displayLegend = true; |
|||
} else { |
|||
this.displayLegend = false; |
|||
} |
|||
this.caulculateLegendData = this.displayLegend && |
|||
this.type === widgetType.timeseries && |
|||
(this.legendConfig.showMin === true || |
|||
this.legendConfig.showMax === true || |
|||
this.legendConfig.showAvg === true || |
|||
this.legendConfig.showTotal === true); |
|||
this.initDataSubscription().subscribe(() => { |
|||
subscriptionSubject.next(this); |
|||
subscriptionSubject.complete(); |
|||
}, |
|||
() => { |
|||
subscriptionSubject.error(null); |
|||
}); |
|||
} |
|||
} |
|||
|
|||
private initRpc(): Observable<any> { |
|||
const initRpcSubject = new ReplaySubject(); |
|||
if (this.targetDeviceAliasIds && this.targetDeviceAliasIds.length > 0) { |
|||
this.targetDeviceAliasId = this.targetDeviceAliasIds[0]; |
|||
this.ctx.aliasController.getAliasInfo(this.targetDeviceAliasId).subscribe( |
|||
(aliasInfo) => { |
|||
if (aliasInfo.currentEntity && aliasInfo.currentEntity.entityType === EntityType.DEVICE) { |
|||
this.targetDeviceId = aliasInfo.currentEntity.id; |
|||
this.targetDeviceName = aliasInfo.currentEntity.name; |
|||
if (this.targetDeviceId) { |
|||
this.rpcEnabled = true; |
|||
} else { |
|||
this.rpcEnabled = this.ctx.utils.widgetEditMode ? true : false; |
|||
} |
|||
this.callbacks.rpcStateChanged(this); |
|||
initRpcSubject.next(); |
|||
initRpcSubject.complete(); |
|||
} else { |
|||
this.rpcEnabled = false; |
|||
this.callbacks.rpcStateChanged(this); |
|||
initRpcSubject.next(); |
|||
initRpcSubject.complete(); |
|||
} |
|||
}, |
|||
() => { |
|||
this.rpcEnabled = false; |
|||
this.callbacks.rpcStateChanged(this); |
|||
initRpcSubject.next(); |
|||
initRpcSubject.complete(); |
|||
} |
|||
); |
|||
} else { |
|||
if (this.targetDeviceIds && this.targetDeviceIds.length > 0) { |
|||
this.targetDeviceId = this.targetDeviceIds[0]; |
|||
} |
|||
if (this.targetDeviceId) { |
|||
this.rpcEnabled = true; |
|||
} else { |
|||
this.rpcEnabled = this.ctx.utils.widgetEditMode ? true : false; |
|||
} |
|||
this.callbacks.rpcStateChanged(this); |
|||
initRpcSubject.next(); |
|||
initRpcSubject.complete(); |
|||
} |
|||
return initRpcSubject.asObservable(); |
|||
} |
|||
|
|||
private initAlarmSubscription(): Observable<any> { |
|||
// TODO:
|
|||
return of(null); |
|||
} |
|||
|
|||
private initDataSubscription(): Observable<any> { |
|||
const initDataSubscriptionSubject = new ReplaySubject(1); |
|||
this.loadStDiff().subscribe(() => { |
|||
if (!this.ctx.aliasController) { |
|||
this.configureData(); |
|||
initDataSubscriptionSubject.next(); |
|||
initDataSubscriptionSubject.complete(); |
|||
} else { |
|||
this.ctx.aliasController.resolveDatasources(this.datasources).subscribe( |
|||
(datasources) => { |
|||
this.datasources = datasources; |
|||
this.configureData(); |
|||
initDataSubscriptionSubject.next(); |
|||
initDataSubscriptionSubject.complete(); |
|||
}, |
|||
() => { |
|||
initDataSubscriptionSubject.error(null); |
|||
} |
|||
); |
|||
} |
|||
}); |
|||
return initDataSubscriptionSubject.asObservable(); |
|||
} |
|||
|
|||
private configureData() { |
|||
let dataIndex = 0; |
|||
this.datasources.forEach((datasource) => { |
|||
datasource.dataKeys.forEach((dataKey) => { |
|||
dataKey.hidden = false; |
|||
dataKey.pattern = dataKey.label; |
|||
const datasourceData: DatasourceData = { |
|||
datasource, |
|||
dataKey, |
|||
data: [] |
|||
}; |
|||
this.data.push(datasourceData); |
|||
this.hiddenData.push({data: []}); |
|||
if (this.displayLegend) { |
|||
const legendKey: LegendKey = { |
|||
dataKey, |
|||
dataIndex: dataIndex++ |
|||
}; |
|||
this.legendData.keys.push(legendKey); |
|||
const legendKeyData: LegendKeyData = { |
|||
min: null, |
|||
max: null, |
|||
avg: null, |
|||
total: null, |
|||
hidden: false |
|||
}; |
|||
this.legendData.data.push(legendKeyData); |
|||
} |
|||
}); |
|||
}); |
|||
if (this.displayLegend) { |
|||
this.legendData.keys = this.legendData.keys.sort((key1, key2) => key1.dataKey.label.localeCompare(key2.dataKey.label)); |
|||
// TODO:
|
|||
} |
|||
if (this.type === widgetType.timeseries) { |
|||
if (this.useDashboardTimewindow) { |
|||
// TODO:
|
|||
} else { |
|||
// TODO:
|
|||
} |
|||
} |
|||
} |
|||
|
|||
getFirstEntityInfo(): EntityInfo { |
|||
return undefined; |
|||
} |
|||
|
|||
updateTimewindowConfig(newTimewindow: Timewindow): void { |
|||
} |
|||
|
|||
onResetTimewindow(): void { |
|||
} |
|||
|
|||
onUpdateTimewindow(startTimeMs: number, endTimeMs: number, interval: number): void { |
|||
} |
|||
|
|||
sendOneWayCommand(method: string, params?: any, timeout?: number): Observable<any> { |
|||
return undefined; |
|||
} |
|||
|
|||
sendTwoWayCommand(method: string, params?: any, timeout?: number): Observable<any> { |
|||
return undefined; |
|||
} |
|||
|
|||
clearRpcError(): void { |
|||
} |
|||
|
|||
subscribe(): void { |
|||
// TODO:
|
|||
this.notifyDataLoaded(); |
|||
} |
|||
|
|||
destroy(): void { |
|||
} |
|||
|
|||
private notifyDataLoading() { |
|||
this.loadingData = true; |
|||
this.callbacks.dataLoading(this); |
|||
} |
|||
|
|||
private notifyDataLoaded() { |
|||
this.loadingData = false; |
|||
this.callbacks.dataLoading(this); |
|||
} |
|||
|
|||
onAliasesChanged(aliasIds: Array<string>): boolean { |
|||
return false; |
|||
} |
|||
|
|||
private loadStDiff(): Observable<any> { |
|||
const loadSubject = new ReplaySubject(1); |
|||
if (this.ctx.getServerTimeDiff && this.timeWindow) { |
|||
this.ctx.getServerTimeDiff().subscribe( |
|||
(stDiff) => { |
|||
this.timeWindow.stDiff = stDiff; |
|||
loadSubject.next(); |
|||
loadSubject.complete(); |
|||
}, |
|||
() => { |
|||
this.timeWindow.stDiff = 0; |
|||
loadSubject.next(); |
|||
loadSubject.complete(); |
|||
} |
|||
); |
|||
} else { |
|||
if (this.timeWindow) { |
|||
this.timeWindow.stDiff = 0; |
|||
} |
|||
loadSubject.next(); |
|||
loadSubject.complete(); |
|||
} |
|||
return loadSubject.asObservable(); |
|||
} |
|||
} |
|||
@ -0,0 +1,68 @@ |
|||
///
|
|||
/// Copyright © 2016-2019 The Thingsboard Authors
|
|||
///
|
|||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
|||
/// you may not use this file except in compliance with the License.
|
|||
/// You may obtain a copy of the License at
|
|||
///
|
|||
/// http://www.apache.org/licenses/LICENSE-2.0
|
|||
///
|
|||
/// Unless required by applicable law or agreed to in writing, software
|
|||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
|||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||
/// See the License for the specific language governing permissions and
|
|||
/// limitations under the License.
|
|||
///
|
|||
|
|||
import { Inject, Injectable, NgZone } from '@angular/core'; |
|||
import { HttpClient } from '@angular/common/http'; |
|||
import { WINDOW } from '@core/services/window.service'; |
|||
|
|||
export type CancelAnimationFrame = () => void; |
|||
|
|||
@Injectable({ |
|||
providedIn: 'root' |
|||
}) |
|||
export class RafService { |
|||
|
|||
private rafFunction: (frameCallback: () => void) => CancelAnimationFrame; |
|||
private rafSupported: boolean; |
|||
|
|||
constructor( |
|||
@Inject(WINDOW) private window: Window, |
|||
private ngZone: NgZone |
|||
) { |
|||
const requestAnimationFrame: (frameCallback: () => void) => number = window.requestAnimationFrame || |
|||
window.webkitRequestAnimationFrame; |
|||
const cancelAnimationFrame = window.cancelAnimationFrame || |
|||
window.webkitCancelAnimationFrame || |
|||
// @ts-ignore
|
|||
window.webkitCancelRequestAnimationFrame; |
|||
|
|||
this.rafSupported = !!requestAnimationFrame; |
|||
|
|||
if (this.rafSupported) { |
|||
this.rafFunction = (frameCallback: () => void) => { |
|||
const id = requestAnimationFrame(frameCallback); |
|||
return () => { |
|||
cancelAnimationFrame(id); |
|||
}; |
|||
}; |
|||
} else { |
|||
this.rafFunction = (frameCallback: () => void) => { |
|||
const timeoutId = setTimeout(frameCallback, 16.66); |
|||
return () => { |
|||
clearTimeout(timeoutId); |
|||
}; |
|||
}; |
|||
} |
|||
} |
|||
|
|||
public raf(frameCallback: () => void, runInZone = false): CancelAnimationFrame { |
|||
if (runInZone) { |
|||
return this.rafFunction(frameCallback); |
|||
} else { |
|||
return this.ngZone.runOutsideAngular(() => this.rafFunction(frameCallback)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,367 @@ |
|||
///
|
|||
/// Copyright © 2016-2019 The Thingsboard Authors
|
|||
///
|
|||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
|||
/// you may not use this file except in compliance with the License.
|
|||
/// You may obtain a copy of the License at
|
|||
///
|
|||
/// http://www.apache.org/licenses/LICENSE-2.0
|
|||
///
|
|||
/// Unless required by applicable law or agreed to in writing, software
|
|||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
|||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||
/// See the License for the specific language governing permissions and
|
|||
/// limitations under the License.
|
|||
///
|
|||
|
|||
import * as tinycolor from 'tinycolor2'; |
|||
|
|||
export interface MaterialColorItem { |
|||
value: string; |
|||
group: string; |
|||
label: string; |
|||
isDark: boolean; |
|||
} |
|||
|
|||
export const materialColorPalette: {[palette: string]: {[spectrum: string]: string}} = { |
|||
red: { |
|||
50: '#ffebee', |
|||
100: '#ffcdd2', |
|||
200: '#ef9a9a', |
|||
300: '#e57373', |
|||
400: '#ef5350', |
|||
500: '#f44336', |
|||
600: '#e53935', |
|||
700: '#d32f2f', |
|||
800: '#c62828', |
|||
900: '#b71c1c', |
|||
A100: '#ff8a80', |
|||
A200: '#ff5252', |
|||
A400: '#ff1744', |
|||
A700: '#d50000' |
|||
}, |
|||
pink: { |
|||
50: '#fce4ec', |
|||
100: '#f8bbd0', |
|||
200: '#f48fb1', |
|||
300: '#f06292', |
|||
400: '#ec407a', |
|||
500: '#e91e63', |
|||
600: '#d81b60', |
|||
700: '#c2185b', |
|||
800: '#ad1457', |
|||
900: '#880e4f', |
|||
A100: '#ff80ab', |
|||
A200: '#ff4081', |
|||
A400: '#f50057', |
|||
A700: '#c51162' |
|||
}, |
|||
purple: { |
|||
50: '#f3e5f5', |
|||
100: '#e1bee7', |
|||
200: '#ce93d8', |
|||
300: '#ba68c8', |
|||
400: '#ab47bc', |
|||
500: '#9c27b0', |
|||
600: '#8e24aa', |
|||
700: '#7b1fa2', |
|||
800: '#6a1b9a', |
|||
900: '#4a148c', |
|||
A100: '#ea80fc', |
|||
A200: '#e040fb', |
|||
A400: '#d500f9', |
|||
A700: '#aa00ff' |
|||
}, |
|||
'deep-purple': { |
|||
50: '#ede7f6', |
|||
100: '#d1c4e9', |
|||
200: '#b39ddb', |
|||
300: '#9575cd', |
|||
400: '#7e57c2', |
|||
500: '#673ab7', |
|||
600: '#5e35b1', |
|||
700: '#512da8', |
|||
800: '#4527a0', |
|||
900: '#311b92', |
|||
A100: '#b388ff', |
|||
A200: '#7c4dff', |
|||
A400: '#651fff', |
|||
A700: '#6200ea' |
|||
}, |
|||
indigo: { |
|||
50: '#e8eaf6', |
|||
100: '#c5cae9', |
|||
200: '#9fa8da', |
|||
300: '#7986cb', |
|||
400: '#5c6bc0', |
|||
500: '#3f51b5', |
|||
600: '#3949ab', |
|||
700: '#303f9f', |
|||
800: '#283593', |
|||
900: '#1a237e', |
|||
A100: '#8c9eff', |
|||
A200: '#536dfe', |
|||
A400: '#3d5afe', |
|||
A700: '#304ffe' |
|||
}, |
|||
blue: { |
|||
50: '#e3f2fd', |
|||
100: '#bbdefb', |
|||
200: '#90caf9', |
|||
300: '#64b5f6', |
|||
400: '#42a5f5', |
|||
500: '#2196f3', |
|||
600: '#1e88e5', |
|||
700: '#1976d2', |
|||
800: '#1565c0', |
|||
900: '#0d47a1', |
|||
A100: '#82b1ff', |
|||
A200: '#448aff', |
|||
A400: '#2979ff', |
|||
A700: '#2962ff' |
|||
}, |
|||
'light-blue': { |
|||
50: '#e1f5fe', |
|||
100: '#b3e5fc', |
|||
200: '#81d4fa', |
|||
300: '#4fc3f7', |
|||
400: '#29b6f6', |
|||
500: '#03a9f4', |
|||
600: '#039be5', |
|||
700: '#0288d1', |
|||
800: '#0277bd', |
|||
900: '#01579b', |
|||
A100: '#80d8ff', |
|||
A200: '#40c4ff', |
|||
A400: '#00b0ff', |
|||
A700: '#0091ea' |
|||
}, |
|||
cyan: { |
|||
50: '#e0f7fa', |
|||
100: '#b2ebf2', |
|||
200: '#80deea', |
|||
300: '#4dd0e1', |
|||
400: '#26c6da', |
|||
500: '#00bcd4', |
|||
600: '#00acc1', |
|||
700: '#0097a7', |
|||
800: '#00838f', |
|||
900: '#006064', |
|||
A100: '#84ffff', |
|||
A200: '#18ffff', |
|||
A400: '#00e5ff', |
|||
A700: '#00b8d4' |
|||
}, |
|||
teal: { |
|||
50: '#e0f2f1', |
|||
100: '#b2dfdb', |
|||
200: '#80cbc4', |
|||
300: '#4db6ac', |
|||
400: '#26a69a', |
|||
500: '#009688', |
|||
600: '#00897b', |
|||
700: '#00796b', |
|||
800: '#00695c', |
|||
900: '#004d40', |
|||
A100: '#a7ffeb', |
|||
A200: '#64ffda', |
|||
A400: '#1de9b6', |
|||
A700: '#00bfa5' |
|||
}, |
|||
green: { |
|||
50: '#e8f5e9', |
|||
100: '#c8e6c9', |
|||
200: '#a5d6a7', |
|||
300: '#81c784', |
|||
400: '#66bb6a', |
|||
500: '#4caf50', |
|||
600: '#43a047', |
|||
700: '#388e3c', |
|||
800: '#2e7d32', |
|||
900: '#1b5e20', |
|||
A100: '#b9f6ca', |
|||
A200: '#69f0ae', |
|||
A400: '#00e676', |
|||
A700: '#00c853' |
|||
}, |
|||
'light-green': { |
|||
50: '#f1f8e9', |
|||
100: '#dcedc8', |
|||
200: '#c5e1a5', |
|||
300: '#aed581', |
|||
400: '#9ccc65', |
|||
500: '#8bc34a', |
|||
600: '#7cb342', |
|||
700: '#689f38', |
|||
800: '#558b2f', |
|||
900: '#33691e', |
|||
A100: '#ccff90', |
|||
A200: '#b2ff59', |
|||
A400: '#76ff03', |
|||
A700: '#64dd17' |
|||
}, |
|||
lime: { |
|||
50: '#f9fbe7', |
|||
100: '#f0f4c3', |
|||
200: '#e6ee9c', |
|||
300: '#dce775', |
|||
400: '#d4e157', |
|||
500: '#cddc39', |
|||
600: '#c0ca33', |
|||
700: '#afb42b', |
|||
800: '#9e9d24', |
|||
900: '#827717', |
|||
A100: '#f4ff81', |
|||
A200: '#eeff41', |
|||
A400: '#c6ff00', |
|||
A700: '#aeea00' |
|||
}, |
|||
yellow: { |
|||
50: '#fffde7', |
|||
100: '#fff9c4', |
|||
200: '#fff59d', |
|||
300: '#fff176', |
|||
400: '#ffee58', |
|||
500: '#ffeb3b', |
|||
600: '#fdd835', |
|||
700: '#fbc02d', |
|||
800: '#f9a825', |
|||
900: '#f57f17', |
|||
A100: '#ffff8d', |
|||
A200: '#ffff00', |
|||
A400: '#ffea00', |
|||
A700: '#ffd600' |
|||
}, |
|||
amber: { |
|||
50: '#fff8e1', |
|||
100: '#ffecb3', |
|||
200: '#ffe082', |
|||
300: '#ffd54f', |
|||
400: '#ffca28', |
|||
500: '#ffc107', |
|||
600: '#ffb300', |
|||
700: '#ffa000', |
|||
800: '#ff8f00', |
|||
900: '#ff6f00', |
|||
A100: '#ffe57f', |
|||
A200: '#ffd740', |
|||
A400: '#ffc400', |
|||
A700: '#ffab00' |
|||
}, |
|||
orange: { |
|||
50: '#fff3e0', |
|||
100: '#ffe0b2', |
|||
200: '#ffcc80', |
|||
300: '#ffb74d', |
|||
400: '#ffa726', |
|||
500: '#ff9800', |
|||
600: '#fb8c00', |
|||
700: '#f57c00', |
|||
800: '#ef6c00', |
|||
900: '#e65100', |
|||
A100: '#ffd180', |
|||
A200: '#ffab40', |
|||
A400: '#ff9100', |
|||
A700: '#ff6d00' |
|||
}, |
|||
'deep-orange': { |
|||
50: '#fbe9e7', |
|||
100: '#ffccbc', |
|||
200: '#ffab91', |
|||
300: '#ff8a65', |
|||
400: '#ff7043', |
|||
500: '#ff5722', |
|||
600: '#f4511e', |
|||
700: '#e64a19', |
|||
800: '#d84315', |
|||
900: '#bf360c', |
|||
A100: '#ff9e80', |
|||
A200: '#ff6e40', |
|||
A400: '#ff3d00', |
|||
A700: '#dd2c00' |
|||
}, |
|||
brown: { |
|||
50: '#efebe9', |
|||
100: '#d7ccc8', |
|||
200: '#bcaaa4', |
|||
300: '#a1887f', |
|||
400: '#8d6e63', |
|||
500: '#795548', |
|||
600: '#6d4c41', |
|||
700: '#5d4037', |
|||
800: '#4e342e', |
|||
900: '#3e2723', |
|||
A100: '#d7ccc8', |
|||
A200: '#bcaaa4', |
|||
A400: '#8d6e63', |
|||
A700: '#5d4037' |
|||
}, |
|||
grey: { |
|||
50: '#fafafa', |
|||
100: '#f5f5f5', |
|||
200: '#eeeeee', |
|||
300: '#e0e0e0', |
|||
400: '#bdbdbd', |
|||
500: '#9e9e9e', |
|||
600: '#757575', |
|||
700: '#616161', |
|||
800: '#424242', |
|||
900: '#212121', |
|||
A100: '#ffffff', |
|||
A200: '#000000', |
|||
A400: '#303030', |
|||
A700: '#616161' |
|||
}, |
|||
'blue-grey': { |
|||
50: '#eceff1', |
|||
100: '#cfd8dc', |
|||
200: '#b0bec5', |
|||
300: '#90a4ae', |
|||
400: '#78909c', |
|||
500: '#607d8b', |
|||
600: '#546e7a', |
|||
700: '#455a64', |
|||
800: '#37474f', |
|||
900: '#263238', |
|||
A100: '#cfd8dc', |
|||
A200: '#b0bec5', |
|||
A400: '#78909c', |
|||
A700: '#455a64' |
|||
} |
|||
}; |
|||
|
|||
export const materialColors = new Array<MaterialColorItem>(); |
|||
|
|||
const colorPalettes = ['blue', 'green', 'red', 'amber', 'blue-grey', 'purple', 'light-green', |
|||
'indigo', 'pink', 'yellow', 'light-blue', 'orange', 'deep-purple', 'lime', 'teal', 'brown', 'cyan', 'deep-orange', 'grey']; |
|||
const colorSpectrum = ['500', 'A700', '600', '700', '800', '900', '300', '400', 'A200', 'A400']; |
|||
|
|||
for (const key of Object.keys(materialColorPalette)) { |
|||
const value = materialColorPalette[key]; |
|||
for (const label of Object.keys(value)) { |
|||
if (colorSpectrum.indexOf(label) > -1) { |
|||
const colorValue = value[label]; |
|||
const color = tinycolor(colorValue); |
|||
const isDark = color.isDark(); |
|||
const colorItem = { |
|||
value: color.toHexString(), |
|||
group: key, |
|||
label, |
|||
isDark |
|||
}; |
|||
materialColors.push(colorItem); |
|||
} |
|||
} |
|||
} |
|||
|
|||
materialColors.sort((colorItem1, colorItem2) => { |
|||
const spectrumIndex1 = colorSpectrum.indexOf(colorItem1.label); |
|||
const spectrumIndex2 = colorSpectrum.indexOf(colorItem2.label); |
|||
let result = spectrumIndex1 - spectrumIndex2; |
|||
if (result === 0) { |
|||
const paletteIndex1 = colorPalettes.indexOf(colorItem1.group); |
|||
const paletteIndex2 = colorPalettes.indexOf(colorItem2.group); |
|||
result = paletteIndex1 - paletteIndex2; |
|||
} |
|||
return result; |
|||
}); |
|||
@ -0,0 +1,19 @@ |
|||
///
|
|||
/// Copyright © 2016-2019 The Thingsboard Authors
|
|||
///
|
|||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
|||
/// you may not use this file except in compliance with the License.
|
|||
/// You may obtain a copy of the License at
|
|||
///
|
|||
/// http://www.apache.org/licenses/LICENSE-2.0
|
|||
///
|
|||
/// Unless required by applicable law or agreed to in writing, software
|
|||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
|||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||
/// See the License for the specific language governing permissions and
|
|||
/// limitations under the License.
|
|||
///
|
|||
|
|||
interface JQuery { |
|||
terminal(options?: any): any; |
|||
} |
|||
Loading…
Reference in new issue