Merge branch 'master' of github.com:thingsboard/thingsboard
This commit is contained in:
commit
fe028a4fe5
@ -391,16 +391,16 @@
|
||||
},
|
||||
{
|
||||
"alias": "web_camera_input",
|
||||
"name": "Web Camera Input",
|
||||
"name": "Photo camera input",
|
||||
"descriptor": {
|
||||
"type": "latest",
|
||||
"sizeX": 7.5,
|
||||
"sizeY": 3,
|
||||
"resources": [],
|
||||
"templateHtml": "<tb-web-camera-widget \n [ctx]=\"ctx\">\n</tb-web-camera-widget>",
|
||||
"templateHtml": "<tb-photo-camera-widget \n [ctx]=\"ctx\">\n</tb-photo-camera-widget>",
|
||||
"templateCss": "",
|
||||
"controllerScript": "self.onInit = function() {\n}\n\nself.onDataUpdated = function() {\n self.ctx.$scope.webCameraInputWidget.onDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true\n }\n}\n\nself.onDestroy = function() {\n}\n",
|
||||
"settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Web Camera\",\n \"properties\": {\n \"widgetTitle\": {\n \"title\": \"Widget title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"imageFormat\": {\n \"title\": \"Image Format\",\n \"type\": \"string\",\n \"default\": \"image/png\"\n },\n \"imageQuality\":{\n \"title\":\"Image quality that use lossy compression such as jpeg and webp\",\n \"type\":\"number\",\n \"default\": 0.92,\n \"min\": 0,\n \"max\": 1\n },\n \"maxWidth\": {\n \"title\": \"The maximal image width\",\n \"type\": \"number\",\n \"default\": 640\n }, \n \"maxHeight\": {\n \"title\": \"The maximal image heigth\",\n \"type\": \"number\",\n \"default\": 480\n }\n },\n \"required\": []\n },\n \"form\": [\n \"widgetTitle\",\n {\n \"key\": \"imageFormat\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"image/jpeg\",\n \"label\": \"JPEG\"\n },\n {\n \"value\": \"image/png\",\n \"label\": \"PNG\"\n },\n {\n \"value\": \"image/webp\",\n \"label\": \"WEBP\"\n }\n ]\n },\n \"imageQuality\",\n \"maxWidth\",\n \"maxHeight\"\n ]\n}",
|
||||
"controllerScript": "self.onInit = function() {\n}\n\nself.onDataUpdated = function() {\n self.ctx.$scope.photoCameraInputWidget.onDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true\n }\n}\n\nself.onDestroy = function() {\n}\n",
|
||||
"settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Photo Camera\",\n \"properties\": {\n \"widgetTitle\": {\n \"title\": \"Widget title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"imageFormat\": {\n \"title\": \"Image Format\",\n \"type\": \"string\",\n \"default\": \"image/png\"\n },\n \"imageQuality\":{\n \"title\":\"Image quality that use lossy compression such as jpeg and webp\",\n \"type\":\"number\",\n \"default\": 0.92,\n \"min\": 0,\n \"max\": 1\n },\n \"maxWidth\": {\n \"title\": \"The maximal image width\",\n \"type\": \"number\",\n \"default\": 640\n }, \n \"maxHeight\": {\n \"title\": \"The maximal image heigth\",\n \"type\": \"number\",\n \"default\": 480\n }\n },\n \"required\": []\n },\n \"form\": [\n \"widgetTitle\",\n {\n \"key\": \"imageFormat\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"image/jpeg\",\n \"label\": \"JPEG\"\n },\n {\n \"value\": \"image/png\",\n \"label\": \"PNG\"\n },\n {\n \"value\": \"image/webp\",\n \"label\": \"WEBP\"\n }\n ]\n },\n \"imageQuality\",\n \"maxWidth\",\n \"maxHeight\"\n ]\n}",
|
||||
"dataKeySettingsSchema": "{}\n",
|
||||
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{},\"title\":\"Web Camera Input\",\"showTitleIcon\":false,\"titleIcon\":\"more_horiz\",\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\",\"titleTooltip\":\"\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"displayTimewindow\":true,\"showLegend\":false,\"actions\":{}}"
|
||||
}
|
||||
|
||||
@ -55,6 +55,7 @@ import org.thingsboard.server.dao.customer.CustomerService;
|
||||
import org.thingsboard.server.dao.device.DeviceProfileService;
|
||||
import org.thingsboard.server.dao.device.DeviceService;
|
||||
import org.thingsboard.server.dao.entityview.EntityViewService;
|
||||
import org.thingsboard.server.dao.exception.IncorrectParameterException;
|
||||
import org.thingsboard.server.dao.rule.RuleChainService;
|
||||
import org.thingsboard.server.dao.tenant.TenantService;
|
||||
import org.thingsboard.server.dao.usagerecord.ApiUsageStateService;
|
||||
@ -158,7 +159,11 @@ public class AccessValidator {
|
||||
new FutureCallback<DeferredResult<ResponseEntity>>() {
|
||||
@Override
|
||||
public void onSuccess(@Nullable DeferredResult<ResponseEntity> result) {
|
||||
onSuccess.accept(response, currentUser.getTenantId(), entityId);
|
||||
try {
|
||||
onSuccess.accept(response, currentUser.getTenantId(), entityId);
|
||||
} catch (Exception e) {
|
||||
onFailure(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -434,9 +439,9 @@ public class AccessValidator {
|
||||
|
||||
public static void handleError(Throwable e, final DeferredResult<ResponseEntity> response, HttpStatus defaultErrorStatus) {
|
||||
ResponseEntity responseEntity;
|
||||
if (e != null && e instanceof ToErrorResponseEntity) {
|
||||
if (e instanceof ToErrorResponseEntity) {
|
||||
responseEntity = ((ToErrorResponseEntity) e).toErrorResponseEntity();
|
||||
} else if (e != null && e instanceof IllegalArgumentException) {
|
||||
} else if (e instanceof IllegalArgumentException || e instanceof IncorrectParameterException) {
|
||||
responseEntity = new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST);
|
||||
} else {
|
||||
responseEntity = new ResponseEntity<>(defaultErrorStatus);
|
||||
|
||||
@ -76,8 +76,8 @@
|
||||
"prettier": "^2.1.2",
|
||||
"prop-types": "^15.7.2",
|
||||
"raphael": "^2.3.0",
|
||||
"rc-select": "^11.3.3",
|
||||
"react": "^16.13.1",
|
||||
"rc-select": "~10.5.1",
|
||||
"react": "~16.14.0",
|
||||
"react-ace": "^9.1.4",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-dropzone": "^11.2.0",
|
||||
@ -92,7 +92,7 @@
|
||||
"tslib": "^2.0.2",
|
||||
"tv4": "^1.3.0",
|
||||
"typeface-roboto": "^1.1.13",
|
||||
"zone.js": "~0.11.1"
|
||||
"zone.js": "~0.10.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-builders/custom-webpack": "^10.0.1",
|
||||
|
||||
@ -52,6 +52,7 @@ export interface AlarmDataSubscriptionOptions {
|
||||
|
||||
export class AlarmDataSubscription {
|
||||
|
||||
private alarmDataSubscriptionOptions = this.listener.alarmDataSubscriptionOptions;
|
||||
private datasourceType: DatasourceType = this.alarmDataSubscriptionOptions.datasourceType;
|
||||
|
||||
private history: boolean;
|
||||
@ -65,8 +66,7 @@ export class AlarmDataSubscription {
|
||||
|
||||
private subsTw: SubscriptionTimewindow;
|
||||
|
||||
constructor(public alarmDataSubscriptionOptions: AlarmDataSubscriptionOptions,
|
||||
private listener: AlarmDataListener,
|
||||
constructor(private listener: AlarmDataListener,
|
||||
private telemetryService: TelemetryService) {
|
||||
}
|
||||
|
||||
|
||||
@ -32,6 +32,7 @@ export interface AlarmDataListener {
|
||||
alarmSource: Datasource;
|
||||
alarmsLoaded: (pageData: PageData<AlarmData>, allowedEntities: number, totalEntities: number) => void;
|
||||
alarmsUpdated: (update: Array<AlarmData>, pageData: PageData<AlarmData>) => void;
|
||||
alarmDataSubscriptionOptions?: AlarmDataSubscriptionOptions;
|
||||
subscription?: AlarmDataSubscription;
|
||||
}
|
||||
|
||||
@ -47,11 +48,11 @@ export class AlarmDataService {
|
||||
pageLink: AlarmDataPageLink,
|
||||
keyFilters: KeyFilter[]) {
|
||||
const alarmSource = listener.alarmSource;
|
||||
listener.alarmDataSubscriptionOptions = this.createAlarmSubscriptionOptions(listener, pageLink, keyFilters);
|
||||
if (alarmSource.type === DatasourceType.entity && (!alarmSource.entityFilter || !pageLink)) {
|
||||
return;
|
||||
}
|
||||
listener.subscription = this.createSubscription(listener,
|
||||
pageLink, alarmSource.keyFilters, keyFilters);
|
||||
listener.subscription = new AlarmDataSubscription(listener, this.telemetryService);
|
||||
return listener.subscription.subscribe();
|
||||
}
|
||||
|
||||
@ -61,10 +62,9 @@ export class AlarmDataService {
|
||||
}
|
||||
}
|
||||
|
||||
private createSubscription(listener: AlarmDataListener,
|
||||
pageLink: AlarmDataPageLink,
|
||||
keyFilters: KeyFilter[],
|
||||
additionalKeyFilters: KeyFilter[]): AlarmDataSubscription {
|
||||
private createAlarmSubscriptionOptions(listener: AlarmDataListener,
|
||||
pageLink: AlarmDataPageLink,
|
||||
additionalKeyFilters: KeyFilter[]): AlarmDataSubscriptionOptions {
|
||||
const alarmSource = listener.alarmSource;
|
||||
const alarmSubscriptionDataKeys: Array<AlarmSubscriptionDataKey> = [];
|
||||
alarmSource.dataKeys.forEach((dataKey) => {
|
||||
@ -82,11 +82,10 @@ export class AlarmDataService {
|
||||
if (alarmDataSubscriptionOptions.datasourceType === DatasourceType.entity) {
|
||||
alarmDataSubscriptionOptions.entityFilter = alarmSource.entityFilter;
|
||||
alarmDataSubscriptionOptions.pageLink = pageLink;
|
||||
alarmDataSubscriptionOptions.keyFilters = keyFilters;
|
||||
alarmDataSubscriptionOptions.keyFilters = alarmSource.keyFilters;
|
||||
alarmDataSubscriptionOptions.additionalKeyFilters = additionalKeyFilters;
|
||||
}
|
||||
return new AlarmDataSubscription(alarmDataSubscriptionOptions,
|
||||
listener, this.telemetryService);
|
||||
return alarmDataSubscriptionOptions;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -960,8 +960,8 @@ export class WidgetSubscription implements IWidgetSubscription {
|
||||
|
||||
private updateAlarmDataSubscription() {
|
||||
if (this.alarmDataListener) {
|
||||
const pageLink = this.alarmDataListener.subscription.alarmDataSubscriptionOptions.pageLink;
|
||||
const keyFilters = this.alarmDataListener.subscription.alarmDataSubscriptionOptions.additionalKeyFilters;
|
||||
const pageLink = this.alarmDataListener.alarmDataSubscriptionOptions.pageLink;
|
||||
const keyFilters = this.alarmDataListener.alarmDataSubscriptionOptions.additionalKeyFilters;
|
||||
this.subscribeForAlarms(pageLink, keyFilters);
|
||||
}
|
||||
}
|
||||
@ -1226,9 +1226,6 @@ export class WidgetSubscription implements IWidgetSubscription {
|
||||
});
|
||||
});
|
||||
}
|
||||
if (this.displayLegend) {
|
||||
this.legendData.keys = this.legendData.keys.sort((key1, key2) => key1.dataKey.label.localeCompare(key2.dataKey.label));
|
||||
}
|
||||
if (this.caulculateLegendData) {
|
||||
this.data.forEach((dataSetHolder, keyIndex) => {
|
||||
this.updateLegend(keyIndex, dataSetHolder.data, false);
|
||||
|
||||
@ -19,8 +19,9 @@ import { defaultHttpOptionsFromConfig, RequestConfig } from './http-utils';
|
||||
import { forkJoin, Observable, of } from 'rxjs';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { EntityId } from '@shared/models/id/entity-id';
|
||||
import { AttributeData, AttributeScope } from '@shared/models/telemetry/telemetry.models';
|
||||
import { AttributeData, AttributeScope, DataSortOrder, TimeseriesData } from '@shared/models/telemetry/telemetry.models';
|
||||
import { isDefinedAndNotNull } from '@core/utils';
|
||||
import { AggregationType } from '@shared/models/time/time.models';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
@ -110,4 +111,28 @@ export class AttributeService {
|
||||
}
|
||||
return forkJoin([saveEntityTimeseriesObservable, deleteEntityTimeseriesObservable]);
|
||||
}
|
||||
|
||||
public getEntityTimeseries(entityId: EntityId, keys: Array<string>, startTs: number, endTs: number,
|
||||
limit: number = 100, agg: AggregationType = AggregationType.NONE, interval?: number,
|
||||
orderBy: DataSortOrder = DataSortOrder.DESC, useStrictDataTypes: boolean = false,
|
||||
config?: RequestConfig): Observable<TimeseriesData> {
|
||||
let url = `/api/plugins/telemetry/${entityId.entityType}/${entityId.id}/values/timeseries?keys=${keys.join(',')}&startTs=${startTs}&endTs=${endTs}`;
|
||||
if (isDefinedAndNotNull(limit)) {
|
||||
url += `&limit=${limit}`;
|
||||
}
|
||||
if (isDefinedAndNotNull(agg)) {
|
||||
url += `&agg=${agg}`;
|
||||
}
|
||||
if (isDefinedAndNotNull(interval)) {
|
||||
url += `&interval=${interval}`;
|
||||
}
|
||||
if (isDefinedAndNotNull(orderBy)) {
|
||||
url += `&orderBy=${orderBy}`;
|
||||
}
|
||||
if (isDefinedAndNotNull(useStrictDataTypes)) {
|
||||
url += `&useStrictDataTypes=${useStrictDataTypes}`;
|
||||
}
|
||||
|
||||
return this.http.get<TimeseriesData>(url, defaultHttpOptionsFromConfig(config));
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,6 +38,9 @@
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-checkbox formControlName="sortDataKeys">
|
||||
{{ 'legend.sort-legend' | translate }}
|
||||
</mat-checkbox>
|
||||
<mat-checkbox formControlName="showMin">
|
||||
{{ 'legend.show-min' | translate }}
|
||||
</mat-checkbox>
|
||||
|
||||
@ -68,6 +68,7 @@ export class LegendConfigPanelComponent extends PageComponent implements OnInit
|
||||
this.legendConfigForm = this.fb.group({
|
||||
direction: [this.data.legendConfig.direction, []],
|
||||
position: [this.data.legendConfig.position, []],
|
||||
sortDataKeys: [this.data.legendConfig.sortDataKeys, []],
|
||||
showMin: [this.data.legendConfig.showMin, []],
|
||||
showMax: [this.data.legendConfig.showMax, []],
|
||||
showAvg: [this.data.legendConfig.showAvg, []],
|
||||
|
||||
@ -60,8 +60,11 @@ export class LegendComponent implements OnInit {
|
||||
}
|
||||
|
||||
legendKeys(): LegendKey[] {
|
||||
return this.legendData.keys
|
||||
.filter(legendKey => this.legendData.keys[legendKey.dataIndex].dataKey.inLegend);
|
||||
let keys = this.legendData.keys;
|
||||
if (this.legendConfig.sortDataKeys) {
|
||||
keys = this.legendData.keys.sort((key1, key2) => key1.dataKey.label.localeCompare(key2.dataKey.label));
|
||||
}
|
||||
return keys.filter(legendKey => this.legendData.keys[legendKey.dataIndex].dataKey.inLegend);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -16,13 +16,13 @@
|
||||
|
||||
-->
|
||||
<div fxLayout="column" fxLayoutAlign="center center" class="tb-web-camera" tb-fullscreen [fullscreen]="isShowCamera">
|
||||
<div *ngIf="isEntityDetected && dataKeyDetected && isCameraSupport && isDeviceDetect" fxFlexFill>
|
||||
<div *ngIf="isEntityDetected && dataKeyDetected && isCameraSupport && isProtocolHttps" class="image-container">
|
||||
<div [fxShow]="!isShowCamera" fxLayout="column" fxLayoutAlign="space-between center" fxFlexFill>
|
||||
<div class="tb-web-camera__last-photo" fxFlex>
|
||||
<span [fxShow]="!lastPhoto" class="tb-web-camera__last-photo_text" translate>widgets.input-widgets.no-image</span>
|
||||
<img [fxShow]="lastPhoto" class="tb-web-camera__last-photo_img" [src]="lastPhoto" alt="last photo"/>
|
||||
</div>
|
||||
<button mat-raised-button color="primary" (click)="takePhoto()">
|
||||
<button mat-raised-button color="primary" (click)="takePhoto()" *ngIf="!textMessage">
|
||||
{{ "widgets.input-widgets.take-photo" | translate }}
|
||||
</button>
|
||||
</div>
|
||||
@ -59,16 +59,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="message-text" *ngIf="!isEntityDetected">
|
||||
{{ 'widgets.input-widgets.no-entity-selected' | translate }}
|
||||
</div>
|
||||
<div class="message-text" *ngIf="isEntityDetected && !dataKeyDetected">
|
||||
{{ 'widgets.input-widgets.no-datakey-selected' | translate }}
|
||||
</div>
|
||||
<div class="message-text" *ngIf="isEntityDetected && dataKeyDetected && !isCameraSupport">
|
||||
{{ 'widgets.input-widgets.no-support-web-camera' | translate }}
|
||||
</div>
|
||||
<div class="message-text" *ngIf="isEntityDetected && dataKeyDetected && isCameraSupport && !isDeviceDetect">
|
||||
{{ 'widgets.input-widgets.no-support-web-camera' | translate }}
|
||||
<div class="message-text" *ngIf="textMessage">
|
||||
{{ textMessage | translate }}
|
||||
</div>
|
||||
</div>
|
||||
@ -18,6 +18,7 @@
|
||||
|
||||
&__last-photo {
|
||||
width: 100%;
|
||||
min-height: 0;
|
||||
margin: 5px 0;
|
||||
text-align: center;
|
||||
border: solid 1px;
|
||||
@ -71,4 +72,11 @@
|
||||
color: #a0a0a0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.image-container{
|
||||
height: 100%;
|
||||
min-height: 0;
|
||||
width: 100%;
|
||||
min-width: 100%;
|
||||
}
|
||||
}
|
||||
@ -40,7 +40,7 @@ import { Observable } from 'rxjs';
|
||||
import { isString } from '@core/utils';
|
||||
import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
|
||||
|
||||
interface WebCameraInputWidgetSettings {
|
||||
interface PhotoCameraInputWidgetSettings {
|
||||
widgetTitle: string;
|
||||
imageQuality: number;
|
||||
imageFormat: string;
|
||||
@ -50,12 +50,12 @@ interface WebCameraInputWidgetSettings {
|
||||
|
||||
// @dynamic
|
||||
@Component({
|
||||
selector: 'tb-web-camera-widget',
|
||||
templateUrl: './web-camera-input.component.html',
|
||||
styleUrls: ['./web-camera-input.component.scss'],
|
||||
selector: 'tb-photo-camera-widget',
|
||||
templateUrl: './photo-camera-input.component.html',
|
||||
styleUrls: ['./photo-camera-input.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class WebCameraInputWidgetComponent extends PageComponent implements OnInit, OnDestroy {
|
||||
export class PhotoCameraInputWidgetComponent extends PageComponent implements OnInit, OnDestroy {
|
||||
|
||||
constructor(@Inject(WINDOW) private window: Window,
|
||||
protected store: Store<AppState>,
|
||||
@ -93,11 +93,11 @@ export class WebCameraInputWidgetComponent extends PageComponent implements OnIn
|
||||
@Input()
|
||||
ctx: WidgetContext;
|
||||
|
||||
@ViewChild('videoStream', {static: true}) videoStreamRef: ElementRef<HTMLVideoElement>;
|
||||
@ViewChild('canvas', {static: true}) canvasRef: ElementRef<HTMLCanvasElement>;
|
||||
@ViewChild('videoStream', {static: false}) videoStreamRef: ElementRef<HTMLVideoElement>;
|
||||
@ViewChild('canvas', {static: false}) canvasRef: ElementRef<HTMLCanvasElement>;
|
||||
|
||||
private videoInputsIndex = 0;
|
||||
private settings: WebCameraInputWidgetSettings;
|
||||
private settings: PhotoCameraInputWidgetSettings;
|
||||
private datasource: Datasource;
|
||||
private width = 640;
|
||||
private height = 480;
|
||||
@ -106,10 +106,13 @@ export class WebCameraInputWidgetComponent extends PageComponent implements OnIn
|
||||
|
||||
isEntityDetected = false;
|
||||
dataKeyDetected = false;
|
||||
isProtocolHttps = false;
|
||||
isCameraSupport = false;
|
||||
isDeviceDetect = false;
|
||||
isShowCamera = false;
|
||||
isPreviewPhoto = false;
|
||||
isHavePermissionCamera = true;
|
||||
isLoading = false;
|
||||
singleDevice = true;
|
||||
updatePhoto = false;
|
||||
previewPhoto: SafeUrl;
|
||||
@ -132,7 +135,8 @@ export class WebCameraInputWidgetComponent extends PageComponent implements OnIn
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.ctx.$scope.webCameraInputWidget = this;
|
||||
this.ctx.$scope.photoCameraInputWidget = this;
|
||||
this.isLoading = true;
|
||||
this.settings = this.ctx.settings;
|
||||
this.datasource = this.ctx.datasources[0];
|
||||
|
||||
@ -168,25 +172,33 @@ export class WebCameraInputWidgetComponent extends PageComponent implements OnIn
|
||||
}
|
||||
|
||||
public onDataUpdated() {
|
||||
this.ngZone.run(() => {
|
||||
this.updateWidgetData(this.ctx.defaultSubscription.data);
|
||||
this.ctx.detectChanges();
|
||||
});
|
||||
this.updateWidgetData(this.ctx.defaultSubscription.data);
|
||||
this.ctx.detectChanges();
|
||||
}
|
||||
|
||||
|
||||
private detectAvailableDevices(): void {
|
||||
if (WebCameraInputWidgetComponent.hasGetUserMedia()) {
|
||||
this.isCameraSupport = true;
|
||||
WebCameraInputWidgetComponent.getAvailableVideoInputs().then((devices) => {
|
||||
this.isDeviceDetect = !!devices.length;
|
||||
this.singleDevice = devices.length < 2;
|
||||
this.availableVideoInputs = devices;
|
||||
this.ctx.detectChanges();
|
||||
}, () => {
|
||||
this.availableVideoInputs = [];
|
||||
}
|
||||
)
|
||||
if (this.window.location.protocol === 'https:' || this.window.location.hostname === 'localhost') {
|
||||
this.isProtocolHttps = true;
|
||||
|
||||
if (PhotoCameraInputWidgetComponent.hasGetUserMedia()) {
|
||||
this.isCameraSupport = true;
|
||||
PhotoCameraInputWidgetComponent.getAvailableVideoInputs().then((devices) => {
|
||||
this.isLoading = false;
|
||||
this.isDeviceDetect = !!devices.length;
|
||||
this.singleDevice = devices.length < 2;
|
||||
this.availableVideoInputs = devices;
|
||||
this.ctx.detectChanges();
|
||||
}, () => {
|
||||
this.isLoading = false;
|
||||
this.availableVideoInputs = [];
|
||||
}
|
||||
);
|
||||
} else {
|
||||
this.isLoading = false;
|
||||
}
|
||||
} else {
|
||||
this.isLoading = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -206,8 +218,7 @@ export class WebCameraInputWidgetComponent extends PageComponent implements OnIn
|
||||
}
|
||||
|
||||
takePhoto() {
|
||||
this.isShowCamera = true;
|
||||
this.initWebCamera(this.availableVideoInputs[this.videoInputsIndex].deviceId);
|
||||
this.inititedVideoStream(this.availableVideoInputs[this.videoInputsIndex].deviceId, true);
|
||||
}
|
||||
|
||||
closeCamera() {
|
||||
@ -243,13 +254,13 @@ export class WebCameraInputWidgetComponent extends PageComponent implements OnIn
|
||||
this.closeCamera();
|
||||
}, () => {
|
||||
this.updatePhoto = false;
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
switchWebCamera() {
|
||||
this.videoInputsIndex = (this.videoInputsIndex + 1) % this.availableVideoInputs.length;
|
||||
this.stopMediaTracks();
|
||||
this.initWebCamera(this.availableVideoInputs[this.videoInputsIndex].deviceId)
|
||||
this.inititedVideoStream(this.availableVideoInputs[this.videoInputsIndex].deviceId);
|
||||
}
|
||||
|
||||
createPhoto() {
|
||||
@ -257,22 +268,53 @@ export class WebCameraInputWidgetComponent extends PageComponent implements OnIn
|
||||
this.canvasElement.height = this.videoHeight;
|
||||
this.canvasElement.getContext('2d').drawImage(this.videoElement, 0, 0, this.videoWidth, this.videoHeight);
|
||||
|
||||
const mimeType: string = this.settings.imageFormat ? this.settings.imageFormat : WebCameraInputWidgetComponent.DEFAULT_IMAGE_TYPE;
|
||||
const quality: number = this.settings.imageQuality ? this.settings.imageQuality : WebCameraInputWidgetComponent.DEFAULT_IMAGE_QUALITY;
|
||||
this.previewPhoto = this.sanitizer.bypassSecurityTrustUrl(this.canvasElement.toDataURL(mimeType, quality));
|
||||
const mimeType: string = this.settings.imageFormat ? this.settings.imageFormat : PhotoCameraInputWidgetComponent.DEFAULT_IMAGE_TYPE;
|
||||
const quality: number = this.settings.imageQuality ? this.settings.imageQuality : PhotoCameraInputWidgetComponent.DEFAULT_IMAGE_QUALITY;
|
||||
this.previewPhoto = this.canvasElement.toDataURL(mimeType, quality);
|
||||
this.isPreviewPhoto = true;
|
||||
}
|
||||
|
||||
private initWebCamera(deviceId?: string) {
|
||||
private inititedVideoStream(deviceId?: string, init = false) {
|
||||
if (window.navigator.mediaDevices && window.navigator.mediaDevices.getUserMedia) {
|
||||
const videoTrackConstraints = {
|
||||
video: {deviceId: deviceId !== '' ? {exact: deviceId} : undefined}
|
||||
};
|
||||
|
||||
window.navigator.mediaDevices.getUserMedia(videoTrackConstraints).then((stream: MediaStream) => {
|
||||
if (init) {
|
||||
this.isShowCamera = true;
|
||||
}
|
||||
this.mediaStream = stream;
|
||||
this.videoElement.srcObject = stream;
|
||||
})
|
||||
this.ctx.detectChanges();
|
||||
}, () => {
|
||||
this.isHavePermissionCamera = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
get textMessage() {
|
||||
if (this.isLoading) {
|
||||
return '';
|
||||
}
|
||||
if (!this.isProtocolHttps) {
|
||||
return 'widgets.input-widgets.enable-https-use-widget';
|
||||
}
|
||||
if (!this.isCameraSupport) {
|
||||
return 'widgets.input-widgets.no-support-web-camera';
|
||||
}
|
||||
if (!this.isEntityDetected) {
|
||||
return 'widgets.input-widgets.no-entity-selected';
|
||||
}
|
||||
if (!this.dataKeyDetected) {
|
||||
return 'widgets.input-widgets.no-datakey-selected';
|
||||
}
|
||||
if (!this.isDeviceDetect) {
|
||||
return 'widgets.input-widgets.no-found-your-camera';
|
||||
}
|
||||
if (!this.isHavePermissionCamera) {
|
||||
return 'widgets.input-widgets.no-permission-camera';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -32,7 +32,7 @@ import {
|
||||
} from '@home/components/widget/lib/date-range-navigator/date-range-navigator.component';
|
||||
import { MultipleInputWidgetComponent } from './lib/multiple-input-widget.component';
|
||||
import { TripAnimationComponent } from './trip-animation/trip-animation.component';
|
||||
import { WebCameraInputWidgetComponent } from './lib/web-camera-input.component';
|
||||
import { PhotoCameraInputWidgetComponent } from './lib/photo-camera-input.component';
|
||||
import { GatewayFormComponent } from './lib/gateway/gateway-form.component';
|
||||
import { ImportExportService } from '@home/components/import-export/import-export.service';
|
||||
|
||||
@ -49,7 +49,7 @@ import { ImportExportService } from '@home/components/import-export/import-expor
|
||||
DateRangeNavigatorPanelComponent,
|
||||
MultipleInputWidgetComponent,
|
||||
TripAnimationComponent,
|
||||
WebCameraInputWidgetComponent,
|
||||
PhotoCameraInputWidgetComponent,
|
||||
GatewayFormComponent
|
||||
],
|
||||
imports: [
|
||||
@ -67,7 +67,7 @@ import { ImportExportService } from '@home/components/import-export/import-expor
|
||||
DateRangeNavigatorWidgetComponent,
|
||||
MultipleInputWidgetComponent,
|
||||
TripAnimationComponent,
|
||||
WebCameraInputWidgetComponent,
|
||||
PhotoCameraInputWidgetComponent,
|
||||
GatewayFormComponent
|
||||
],
|
||||
providers: [
|
||||
|
||||
@ -76,13 +76,15 @@
|
||||
[required]="!createProfile"
|
||||
[transportType]="deviceWizardFormGroup.get('transportType').value"
|
||||
formControlName="deviceProfileId"
|
||||
[ngClass]="{invisible: deviceWizardFormGroup.get('addProfileType').value !== 0}"
|
||||
(deviceProfileChanged)="$event?.transportType ? deviceWizardFormGroup.get('transportType').patchValue($event?.transportType) : {}"
|
||||
[addNewProfile]="false"
|
||||
[selectDefaultProfile]="true"
|
||||
[selectFirstProfile]="true"
|
||||
[editProfileEnabled]="false">
|
||||
</tb-device-profile-autocomplete>
|
||||
<mat-form-field fxFlex class="mat-block">
|
||||
<mat-form-field fxFlex class="mat-block"
|
||||
[ngClass]="{invisible: deviceWizardFormGroup.get('addProfileType').value !== 1}">
|
||||
<mat-label translate>device-profile.new-device-profile-name</mat-label>
|
||||
<input matInput formControlName="newDeviceProfileTitle"
|
||||
[required]="createProfile">
|
||||
@ -93,12 +95,14 @@
|
||||
</div>
|
||||
<div fxLayout="column" fxLayoutAlign="flex-end start">
|
||||
<tb-rule-chain-autocomplete
|
||||
[ngClass]="{invisible: deviceWizardFormGroup.get('addProfileType').value !== 1}"
|
||||
labelText="device-profile.default-rule-chain"
|
||||
formControlName="defaultRuleChainId">
|
||||
</tb-rule-chain-autocomplete>
|
||||
</div>
|
||||
<div fxLayout="column" fxLayoutAlign="flex-end start">
|
||||
<tb-queue-type-list
|
||||
[ngClass]="{invisible: deviceWizardFormGroup.get('addProfileType').value !== 1}"
|
||||
[queueType]="serviceType"
|
||||
formControlName="defaultQueueName">
|
||||
</tb-queue-type-list>
|
||||
|
||||
@ -22,6 +22,10 @@
|
||||
max-height: 75vh;
|
||||
}
|
||||
}
|
||||
|
||||
.invisible{
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
:host ::ng-deep {
|
||||
@ -60,6 +64,12 @@
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
tb-device-profile-autocomplete, tb-queue-type-list{
|
||||
.mat-form-field-wrapper{
|
||||
width: 180px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,6 +37,7 @@
|
||||
.tb-nav-header-toolbar {
|
||||
min-height: 64px;
|
||||
height: inherit;
|
||||
padding: 0;
|
||||
z-index: 2;
|
||||
flex-shrink: 0;
|
||||
white-space: nowrap;
|
||||
@ -45,7 +46,9 @@
|
||||
height: 64px;
|
||||
.tb-logo-title {
|
||||
width: auto;
|
||||
max-width: 100%;
|
||||
height: 36px;
|
||||
max-height: 100%;
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,7 +26,7 @@ import { EntityInfoData } from '@shared/models/entity.models';
|
||||
import { KeyFilter } from '@shared/models/query/query.models';
|
||||
import { TimeUnit } from '@shared/models/time/time.models';
|
||||
import * as _moment from 'moment-timezone';
|
||||
import { AbstractControl, FormGroup, ValidationErrors } from '@angular/forms';
|
||||
import { AbstractControl, ValidationErrors } from '@angular/forms';
|
||||
|
||||
export enum DeviceProfileType {
|
||||
DEFAULT = 'DEFAULT'
|
||||
@ -513,7 +513,7 @@ export function timeOfDayToUTCTimestamp(date: Date | number): number {
|
||||
}
|
||||
|
||||
export function utcTimestampToTimeOfDay(time = 0): Date {
|
||||
return new Date(time + new Date().getTimezoneOffset() * 60 * 1000);
|
||||
return new Date(time + new Date(time).getTimezoneOffset() * 60 * 1000);
|
||||
}
|
||||
|
||||
function timeOfDayToMoment(date: Date | number): _moment.Moment {
|
||||
|
||||
@ -21,7 +21,14 @@ import { Observable, ReplaySubject, Subject } from 'rxjs';
|
||||
import { EntityId } from '@shared/models/id/entity-id';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { NgZone } from '@angular/core';
|
||||
import { AlarmData, AlarmDataQuery, EntityData, EntityDataQuery, EntityKey } from '@shared/models/query/query.models';
|
||||
import {
|
||||
AlarmData,
|
||||
AlarmDataQuery,
|
||||
EntityData,
|
||||
EntityDataQuery,
|
||||
EntityKey,
|
||||
TsValue
|
||||
} from '@shared/models/query/query.models';
|
||||
import { PageData } from '@shared/models/page/page-data';
|
||||
|
||||
export enum DataKeyType {
|
||||
@ -81,6 +88,15 @@ export interface AttributeData {
|
||||
value: any;
|
||||
}
|
||||
|
||||
export interface TimeseriesData {
|
||||
[key: string]: Array<TsValue>;
|
||||
}
|
||||
|
||||
export enum DataSortOrder {
|
||||
ASC = 'ASC',
|
||||
DESC = 'DESC'
|
||||
}
|
||||
|
||||
export interface WebsocketCmd {
|
||||
cmdId: number;
|
||||
}
|
||||
|
||||
@ -203,6 +203,7 @@ export const legendPositionTranslationMap = new Map<LegendPosition, string>(
|
||||
export interface LegendConfig {
|
||||
position: LegendPosition;
|
||||
direction?: LegendDirection;
|
||||
sortDataKeys: boolean;
|
||||
showMin: boolean;
|
||||
showMax: boolean;
|
||||
showAvg: boolean;
|
||||
@ -213,6 +214,7 @@ export function defaultLegendConfig(wType: widgetType): LegendConfig {
|
||||
return {
|
||||
direction: LegendDirection.column,
|
||||
position: LegendPosition.bottom,
|
||||
sortDataKeys: false,
|
||||
showMin: false,
|
||||
showMax: false,
|
||||
showAvg: wType === widgetType.timeseries,
|
||||
|
||||
@ -875,7 +875,7 @@
|
||||
"profile-configuration": "Profile configuration",
|
||||
"transport-configuration": "Transport configuration",
|
||||
"default-rule-chain": "Default rule chain",
|
||||
"select-queue-hint": "The queue name can be selected from a drop-down list or add a custom name.",
|
||||
"select-queue-hint": "Select from a drop-down list or add a custom name.",
|
||||
"delete-device-profile-title": "Are you sure you want to delete the device profile '{{deviceProfileName}}'?",
|
||||
"delete-device-profile-text": "Be careful, after the confirmation the device profile and all related data will become unrecoverable.",
|
||||
"delete-device-profiles-title": "Are you sure you want to delete { count, plural, 1 {1 device profile} other {# device profiles} }?",
|
||||
@ -1668,6 +1668,7 @@
|
||||
"legend": {
|
||||
"direction": "Legend direction",
|
||||
"position": "Legend position",
|
||||
"sort-legend": "Sort datakeys in legend",
|
||||
"show-max": "Show max value",
|
||||
"show-min": "Show min value",
|
||||
"show-avg": "Show average value",
|
||||
@ -2318,7 +2319,10 @@
|
||||
"no-entity-selected": "No entity selected",
|
||||
"no-image": "No image",
|
||||
"no-support-geolocation": "Your browser doesn't support geolocation",
|
||||
"no-support-web-camera": "No supported web camera",
|
||||
"no-support-web-camera": "Your browser does not support cameras",
|
||||
"enable-https-use-widget": "Please enable HTTPS to use this widget",
|
||||
"no-found-your-camera": "Can't find your camera",
|
||||
"no-permission-camera": "Permission was denied by the user / This site doesn't have permission to use the camera",
|
||||
"no-timeseries-selected": "No timeseries selected",
|
||||
"secret-key": "Secret key",
|
||||
"secret-key-required": "Secret key is required",
|
||||
|
||||
126
ui-ngx/yarn.lock
126
ui-ngx/yarn.lock
@ -272,6 +272,11 @@
|
||||
dependencies:
|
||||
tslib "^2.0.0"
|
||||
|
||||
"@ant-design/css-animation@^1.7.2":
|
||||
version "1.7.3"
|
||||
resolved "https://registry.yarnpkg.com/@ant-design/css-animation/-/css-animation-1.7.3.tgz#60a1c970014e86b28f940510d69e503e428f1136"
|
||||
integrity sha512-LrX0OGZtW+W6iLnTAqnTaoIsRelYeuLZWsrmBJFUXDALQphPsN8cE5DCsmoSlL0QYb94BQxINiuS70Ar/8BNgA==
|
||||
|
||||
"@auth0/angular-jwt@^5.0.1":
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@auth0/angular-jwt/-/angular-jwt-5.0.1.tgz#37851d3ca2a0e88b3e673afd7dd2891f0c61bdf5"
|
||||
@ -1787,6 +1792,13 @@ acorn@^6.4.1:
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6"
|
||||
integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==
|
||||
|
||||
add-dom-event-listener@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/add-dom-event-listener/-/add-dom-event-listener-1.1.0.tgz#6a92db3a0dd0abc254e095c0f1dc14acbbaae310"
|
||||
integrity sha512-WCxx1ixHT0GQU9hb0KI/mhgRQhnU+U3GvwY6ZvVjYq8rsihIGoaIOUbY0yMPBxLH5MDtr0kz3fisWGNcbWW7Jw==
|
||||
dependencies:
|
||||
object-assign "4.x"
|
||||
|
||||
adjust-sourcemap-loader@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/adjust-sourcemap-loader/-/adjust-sourcemap-loader-2.0.0.tgz#6471143af75ec02334b219f54bc7970c52fb29a4"
|
||||
@ -6752,7 +6764,7 @@ oauth-sign@~0.9.0:
|
||||
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
|
||||
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
|
||||
|
||||
object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
|
||||
object-assign@4.x, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
|
||||
@ -7645,7 +7657,7 @@ promise-retry@^1.1.1:
|
||||
err-code "^1.0.0"
|
||||
retry "^0.10.0"
|
||||
|
||||
prop-types@^15.6.2, prop-types@^15.7.2:
|
||||
prop-types@^15.5.10, prop-types@^15.6.2, prop-types@^15.7.2:
|
||||
version "15.7.2"
|
||||
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
|
||||
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
|
||||
@ -7810,6 +7822,13 @@ querystringify@^2.1.1:
|
||||
resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6"
|
||||
integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==
|
||||
|
||||
raf@^3.4.0, raf@^3.4.1:
|
||||
version "3.4.1"
|
||||
resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39"
|
||||
integrity sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==
|
||||
dependencies:
|
||||
performance-now "^2.1.0"
|
||||
|
||||
randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
|
||||
@ -7866,50 +7885,63 @@ rc-align@^4.0.0:
|
||||
rc-util "^5.3.0"
|
||||
resize-observer-polyfill "^1.5.1"
|
||||
|
||||
rc-motion@^2.0.0, rc-motion@^2.0.1:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/rc-motion/-/rc-motion-2.3.1.tgz#a0c9f402c267bd03543ef80a970297a6ba77c503"
|
||||
integrity sha512-UAB2gwS9c1DuCFKVCimAkL2JUEGCwzgCbb+VslhIMFg6vY7oyMxYIQ6hkoji1PzgDEw0tHIhP+a17R6Y5DGMrQ==
|
||||
rc-animate@^3.0.0:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/rc-animate/-/rc-animate-3.1.1.tgz#defdd863f56816c222534e4dc68feddecd081386"
|
||||
integrity sha512-8wg2Zg3EETy0k/9kYuis30NJNQg1D6/WSQwnCiz6SvyxQXNet/rVraRz3bPngwY6rcU2nlRvoShiYOorXyF7Sg==
|
||||
dependencies:
|
||||
"@ant-design/css-animation" "^1.7.2"
|
||||
classnames "^2.2.6"
|
||||
raf "^3.4.0"
|
||||
rc-util "^4.15.3"
|
||||
|
||||
rc-motion@^1.0.0:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/rc-motion/-/rc-motion-1.1.2.tgz#07212f1b96c715b8245ec121339146c4a9b0968c"
|
||||
integrity sha512-YC/E7SSWKBFakYg4PENhSRWD4ZLDqkI7FKmutJcrMewZ91/ZIWfoZSDvPaBdKO0hsFrrzWepFhXQIq0FNnCMWA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.11.1"
|
||||
classnames "^2.2.1"
|
||||
rc-util "^5.2.1"
|
||||
raf "^3.4.1"
|
||||
rc-util "^5.0.6"
|
||||
|
||||
rc-resize-observer@^0.2.3:
|
||||
version "0.2.5"
|
||||
resolved "https://registry.yarnpkg.com/rc-resize-observer/-/rc-resize-observer-0.2.5.tgz#03e3a5c3dfccd6c996a547e4f82721e4f20f6156"
|
||||
integrity sha512-cc4sOI722MVoCkGf/ZZybDVsjxvnH0giyDdA7wBJLTiMSFJ0eyxBMnr0JLYoClxftjnr75Xzl/VUB3HDrAx04Q==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.10.1"
|
||||
classnames "^2.2.1"
|
||||
rc-util "^5.0.0"
|
||||
resize-observer-polyfill "^1.5.1"
|
||||
|
||||
rc-select@^11.3.3:
|
||||
version "11.3.3"
|
||||
resolved "https://registry.yarnpkg.com/rc-select/-/rc-select-11.3.3.tgz#ba445ac4d2d933dd1f80b796c1de28ce6c81bbf8"
|
||||
integrity sha512-YMsGVEZxXctj15nIZKlFCkiOxMe0PNBeACN6nHqDozDYKR/aqP8J3XZqZ5Gw/fcgS4bI50zPVMieJKlY8/6Wfw==
|
||||
rc-select@~10.5.1:
|
||||
version "10.5.1"
|
||||
resolved "https://registry.yarnpkg.com/rc-select/-/rc-select-10.5.1.tgz#4d4c5d4f8d2fd3b7e3dccf74e4c43142b2979247"
|
||||
integrity sha512-fZraoNNhjUmDJccfk6VYgrgHBWFmHWh/NJZh2Xttcm/usOolYI1RjO9ikP4QGhzlJBFtnTLH2pE2nchjn3TCXA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.10.1"
|
||||
classnames "2.x"
|
||||
rc-motion "^2.0.1"
|
||||
rc-trigger "^5.0.4"
|
||||
rc-animate "^3.0.0"
|
||||
rc-trigger "^4.3.0"
|
||||
rc-util "^5.0.1"
|
||||
rc-virtual-list "^3.0.3"
|
||||
rc-virtual-list "^1.1.2"
|
||||
warning "^4.0.3"
|
||||
|
||||
rc-trigger@^5.0.4:
|
||||
version "5.0.6"
|
||||
resolved "https://registry.yarnpkg.com/rc-trigger/-/rc-trigger-5.0.6.tgz#7e84717525871a7923a671edb5a290e9e616525b"
|
||||
integrity sha512-L/xIX5OO7a/bdTH0yYT9mwAsV6oM1inAqAbLjoUzpcIW+UUE3jjVOjm5VaKDfHd41rzDzOfN05URmhet5QzXKQ==
|
||||
rc-trigger@^4.3.0:
|
||||
version "4.4.3"
|
||||
resolved "https://registry.yarnpkg.com/rc-trigger/-/rc-trigger-4.4.3.tgz#ed449cd6cce446555bc57f4394229c5c7154f4b0"
|
||||
integrity sha512-yq/WyuiPwxd2q6jy+VPyy0GUCRFJ2eFqAaCwPE27AOftXeIupOcJ/2t1wakSq63cfk7qtzev5DKHUAjb8LOJCw==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.11.2"
|
||||
classnames "^2.2.6"
|
||||
raf "^3.4.1"
|
||||
rc-align "^4.0.0"
|
||||
rc-motion "^2.0.0"
|
||||
rc-util "^5.3.4"
|
||||
rc-motion "^1.0.0"
|
||||
rc-util "^5.0.1"
|
||||
|
||||
rc-util@^5.0.0, rc-util@^5.0.1, rc-util@^5.0.7, rc-util@^5.2.1, rc-util@^5.3.0, rc-util@^5.3.4:
|
||||
rc-util@^4.15.3:
|
||||
version "4.21.1"
|
||||
resolved "https://registry.yarnpkg.com/rc-util/-/rc-util-4.21.1.tgz#88602d0c3185020aa1053d9a1e70eac161becb05"
|
||||
integrity sha512-Z+vlkSQVc1l8O2UjR3WQ+XdWlhj5q9BMQNLk2iOBch75CqPfrJyGtcWMcnhRlNuDu0Ndtt4kLVO8JI8BrABobg==
|
||||
dependencies:
|
||||
add-dom-event-listener "^1.1.0"
|
||||
prop-types "^15.5.10"
|
||||
react-is "^16.12.0"
|
||||
react-lifecycles-compat "^3.0.4"
|
||||
shallowequal "^1.1.0"
|
||||
|
||||
rc-util@^5.0.0, rc-util@^5.0.1, rc-util@^5.0.6, rc-util@^5.3.0:
|
||||
version "5.4.0"
|
||||
resolved "https://registry.yarnpkg.com/rc-util/-/rc-util-5.4.0.tgz#688eaeecfdae9dae2bfdf10bedbe884591dba004"
|
||||
integrity sha512-kXDn1JyLJTAWLBFt+fjkTcUtXhxKkipQCobQmxIEVrX62iXgo24z8YKoWehWfMxPZFPE+RXqrmEu9j5kHz/Lrg==
|
||||
@ -7917,14 +7949,14 @@ rc-util@^5.0.0, rc-util@^5.0.1, rc-util@^5.0.7, rc-util@^5.2.1, rc-util@^5.3.0,
|
||||
react-is "^16.12.0"
|
||||
shallowequal "^1.1.0"
|
||||
|
||||
rc-virtual-list@^3.0.3:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/rc-virtual-list/-/rc-virtual-list-3.1.0.tgz#ca7ddbb291dace89c00cc4198ca7ef6e5e2034f7"
|
||||
integrity sha512-DYU3wOjVuQo4hzYvmmpnoNtxrd8OIcutazA90x374ZFGGm4xYoSjCdh6UhBLi47IJI2BRry4l583nuoi7+06GA==
|
||||
rc-virtual-list@^1.1.2:
|
||||
version "1.1.6"
|
||||
resolved "https://registry.yarnpkg.com/rc-virtual-list/-/rc-virtual-list-1.1.6.tgz#b255baf9aacde149a8893324e6307214094f4c0a"
|
||||
integrity sha512-u3+izqWL8p8bQy8nYH48qWpiGyxR/ye8D2k0zJlXmfYeL55/xh83YrzHqiDzO78uj0Ewag3nXDA0JTVrYO7ygQ==
|
||||
dependencies:
|
||||
classnames "^2.2.6"
|
||||
rc-resize-observer "^0.2.3"
|
||||
rc-util "^5.0.7"
|
||||
raf "^3.4.1"
|
||||
rc-util "^5.0.0"
|
||||
|
||||
react-ace@^9.1.4:
|
||||
version "9.1.4"
|
||||
@ -7961,6 +7993,11 @@ react-is@^16.12.0, react-is@^16.7.0, react-is@^16.8.0, react-is@^16.8.1:
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
||||
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
|
||||
|
||||
react-lifecycles-compat@^3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
|
||||
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
|
||||
|
||||
react-transition-group@^4.0.0, react-transition-group@^4.4.0:
|
||||
version "4.4.1"
|
||||
resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.1.tgz#63868f9325a38ea5ee9535d828327f85773345c9"
|
||||
@ -7971,10 +8008,10 @@ react-transition-group@^4.0.0, react-transition-group@^4.4.0:
|
||||
loose-envify "^1.4.0"
|
||||
prop-types "^15.6.2"
|
||||
|
||||
react@^16.13.1:
|
||||
version "16.13.1"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e"
|
||||
integrity sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w==
|
||||
react@~16.14.0:
|
||||
version "16.14.0"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-16.14.0.tgz#94d776ddd0aaa37da3eda8fc5b6b18a4c9a3114d"
|
||||
integrity sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
@ -10206,10 +10243,3 @@ zone.js@~0.10.3:
|
||||
version "0.10.3"
|
||||
resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.10.3.tgz#3e5e4da03c607c9dcd92e37dd35687a14a140c16"
|
||||
integrity sha512-LXVLVEq0NNOqK/fLJo3d0kfzd4sxwn2/h67/02pjCjfKDxgx1i9QqpvtHD8CrBnSSwMw5+dy11O7FRX5mkO7Cg==
|
||||
|
||||
zone.js@~0.11.1:
|
||||
version "0.11.1"
|
||||
resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.11.1.tgz#0301d00d26febb2722f074c46aac4a948698ce39"
|
||||
integrity sha512-KcZawpmVgS+3U2rzKTM6fLKaCX1QDv3//NxiSOOsqpQY/r5hl+xpYikPwY93Sp7CAB+J5mZJpb/YubxEYLGK5g==
|
||||
dependencies:
|
||||
tslib "^2.0.0"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user