Merge pull request #3626 from vvlladd28/improvement/camera-widget
UI: Improvement photo camera input widget
This commit is contained in:
commit
130bbc51ad
@ -391,16 +391,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": "web_camera_input",
|
"alias": "web_camera_input",
|
||||||
"name": "Web Camera Input",
|
"name": "Photo camera input",
|
||||||
"descriptor": {
|
"descriptor": {
|
||||||
"type": "latest",
|
"type": "latest",
|
||||||
"sizeX": 7.5,
|
"sizeX": 7.5,
|
||||||
"sizeY": 3,
|
"sizeY": 3,
|
||||||
"resources": [],
|
"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": "",
|
"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",
|
"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\": \"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}",
|
"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",
|
"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\":{}}"
|
"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\":{}}"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,13 +16,13 @@
|
|||||||
|
|
||||||
-->
|
-->
|
||||||
<div fxLayout="column" fxLayoutAlign="center center" class="tb-web-camera" tb-fullscreen [fullscreen]="isShowCamera">
|
<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 [fxShow]="!isShowCamera" fxLayout="column" fxLayoutAlign="space-between center" fxFlexFill>
|
||||||
<div class="tb-web-camera__last-photo" fxFlex>
|
<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>
|
<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"/>
|
<img [fxShow]="lastPhoto" class="tb-web-camera__last-photo_img" [src]="lastPhoto" alt="last photo"/>
|
||||||
</div>
|
</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 }}
|
{{ "widgets.input-widgets.take-photo" | translate }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@ -59,16 +59,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="message-text" *ngIf="!isEntityDetected">
|
<div class="message-text" *ngIf="textMessage">
|
||||||
{{ 'widgets.input-widgets.no-entity-selected' | translate }}
|
{{ textMessage | 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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
&__last-photo {
|
&__last-photo {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
min-height: 0;
|
||||||
margin: 5px 0;
|
margin: 5px 0;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border: solid 1px;
|
border: solid 1px;
|
||||||
@ -71,4 +72,11 @@
|
|||||||
color: #a0a0a0;
|
color: #a0a0a0;
|
||||||
text-align: center;
|
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 { isString } from '@core/utils';
|
||||||
import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
|
import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
|
||||||
|
|
||||||
interface WebCameraInputWidgetSettings {
|
interface PhotoCameraInputWidgetSettings {
|
||||||
widgetTitle: string;
|
widgetTitle: string;
|
||||||
imageQuality: number;
|
imageQuality: number;
|
||||||
imageFormat: string;
|
imageFormat: string;
|
||||||
@ -50,12 +50,12 @@ interface WebCameraInputWidgetSettings {
|
|||||||
|
|
||||||
// @dynamic
|
// @dynamic
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'tb-web-camera-widget',
|
selector: 'tb-photo-camera-widget',
|
||||||
templateUrl: './web-camera-input.component.html',
|
templateUrl: './photo-camera-input.component.html',
|
||||||
styleUrls: ['./web-camera-input.component.scss'],
|
styleUrls: ['./photo-camera-input.component.scss'],
|
||||||
encapsulation: ViewEncapsulation.None
|
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,
|
constructor(@Inject(WINDOW) private window: Window,
|
||||||
protected store: Store<AppState>,
|
protected store: Store<AppState>,
|
||||||
@ -93,11 +93,11 @@ export class WebCameraInputWidgetComponent extends PageComponent implements OnIn
|
|||||||
@Input()
|
@Input()
|
||||||
ctx: WidgetContext;
|
ctx: WidgetContext;
|
||||||
|
|
||||||
@ViewChild('videoStream', {static: true}) videoStreamRef: ElementRef<HTMLVideoElement>;
|
@ViewChild('videoStream', {static: false}) videoStreamRef: ElementRef<HTMLVideoElement>;
|
||||||
@ViewChild('canvas', {static: true}) canvasRef: ElementRef<HTMLCanvasElement>;
|
@ViewChild('canvas', {static: false}) canvasRef: ElementRef<HTMLCanvasElement>;
|
||||||
|
|
||||||
private videoInputsIndex = 0;
|
private videoInputsIndex = 0;
|
||||||
private settings: WebCameraInputWidgetSettings;
|
private settings: PhotoCameraInputWidgetSettings;
|
||||||
private datasource: Datasource;
|
private datasource: Datasource;
|
||||||
private width = 640;
|
private width = 640;
|
||||||
private height = 480;
|
private height = 480;
|
||||||
@ -106,10 +106,13 @@ export class WebCameraInputWidgetComponent extends PageComponent implements OnIn
|
|||||||
|
|
||||||
isEntityDetected = false;
|
isEntityDetected = false;
|
||||||
dataKeyDetected = false;
|
dataKeyDetected = false;
|
||||||
|
isProtocolHttps = false;
|
||||||
isCameraSupport = false;
|
isCameraSupport = false;
|
||||||
isDeviceDetect = false;
|
isDeviceDetect = false;
|
||||||
isShowCamera = false;
|
isShowCamera = false;
|
||||||
isPreviewPhoto = false;
|
isPreviewPhoto = false;
|
||||||
|
isHavePermissionCamera = true;
|
||||||
|
isLoading = false;
|
||||||
singleDevice = true;
|
singleDevice = true;
|
||||||
updatePhoto = false;
|
updatePhoto = false;
|
||||||
previewPhoto: SafeUrl;
|
previewPhoto: SafeUrl;
|
||||||
@ -132,7 +135,8 @@ export class WebCameraInputWidgetComponent extends PageComponent implements OnIn
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.ctx.$scope.webCameraInputWidget = this;
|
this.ctx.$scope.photoCameraInputWidget = this;
|
||||||
|
this.isLoading = true;
|
||||||
this.settings = this.ctx.settings;
|
this.settings = this.ctx.settings;
|
||||||
this.datasource = this.ctx.datasources[0];
|
this.datasource = this.ctx.datasources[0];
|
||||||
|
|
||||||
@ -168,25 +172,33 @@ export class WebCameraInputWidgetComponent extends PageComponent implements OnIn
|
|||||||
}
|
}
|
||||||
|
|
||||||
public onDataUpdated() {
|
public onDataUpdated() {
|
||||||
this.ngZone.run(() => {
|
|
||||||
this.updateWidgetData(this.ctx.defaultSubscription.data);
|
this.updateWidgetData(this.ctx.defaultSubscription.data);
|
||||||
this.ctx.detectChanges();
|
this.ctx.detectChanges();
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private detectAvailableDevices(): void {
|
private detectAvailableDevices(): void {
|
||||||
if (WebCameraInputWidgetComponent.hasGetUserMedia()) {
|
if (this.window.location.protocol === 'https:' || this.window.location.hostname === 'localhost') {
|
||||||
|
this.isProtocolHttps = true;
|
||||||
|
|
||||||
|
if (PhotoCameraInputWidgetComponent.hasGetUserMedia()) {
|
||||||
this.isCameraSupport = true;
|
this.isCameraSupport = true;
|
||||||
WebCameraInputWidgetComponent.getAvailableVideoInputs().then((devices) => {
|
PhotoCameraInputWidgetComponent.getAvailableVideoInputs().then((devices) => {
|
||||||
|
this.isLoading = false;
|
||||||
this.isDeviceDetect = !!devices.length;
|
this.isDeviceDetect = !!devices.length;
|
||||||
this.singleDevice = devices.length < 2;
|
this.singleDevice = devices.length < 2;
|
||||||
this.availableVideoInputs = devices;
|
this.availableVideoInputs = devices;
|
||||||
this.ctx.detectChanges();
|
this.ctx.detectChanges();
|
||||||
}, () => {
|
}, () => {
|
||||||
|
this.isLoading = false;
|
||||||
this.availableVideoInputs = [];
|
this.availableVideoInputs = [];
|
||||||
}
|
}
|
||||||
)
|
);
|
||||||
|
} else {
|
||||||
|
this.isLoading = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.isLoading = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,8 +218,7 @@ export class WebCameraInputWidgetComponent extends PageComponent implements OnIn
|
|||||||
}
|
}
|
||||||
|
|
||||||
takePhoto() {
|
takePhoto() {
|
||||||
this.isShowCamera = true;
|
this.inititedVideoStream(this.availableVideoInputs[this.videoInputsIndex].deviceId, true);
|
||||||
this.initWebCamera(this.availableVideoInputs[this.videoInputsIndex].deviceId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
closeCamera() {
|
closeCamera() {
|
||||||
@ -243,13 +254,13 @@ export class WebCameraInputWidgetComponent extends PageComponent implements OnIn
|
|||||||
this.closeCamera();
|
this.closeCamera();
|
||||||
}, () => {
|
}, () => {
|
||||||
this.updatePhoto = false;
|
this.updatePhoto = false;
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
switchWebCamera() {
|
switchWebCamera() {
|
||||||
this.videoInputsIndex = (this.videoInputsIndex + 1) % this.availableVideoInputs.length;
|
this.videoInputsIndex = (this.videoInputsIndex + 1) % this.availableVideoInputs.length;
|
||||||
this.stopMediaTracks();
|
this.stopMediaTracks();
|
||||||
this.initWebCamera(this.availableVideoInputs[this.videoInputsIndex].deviceId)
|
this.inititedVideoStream(this.availableVideoInputs[this.videoInputsIndex].deviceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
createPhoto() {
|
createPhoto() {
|
||||||
@ -257,22 +268,53 @@ export class WebCameraInputWidgetComponent extends PageComponent implements OnIn
|
|||||||
this.canvasElement.height = this.videoHeight;
|
this.canvasElement.height = this.videoHeight;
|
||||||
this.canvasElement.getContext('2d').drawImage(this.videoElement, 0, 0, this.videoWidth, 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 mimeType: string = this.settings.imageFormat ? this.settings.imageFormat : PhotoCameraInputWidgetComponent.DEFAULT_IMAGE_TYPE;
|
||||||
const quality: number = this.settings.imageQuality ? this.settings.imageQuality : WebCameraInputWidgetComponent.DEFAULT_IMAGE_QUALITY;
|
const quality: number = this.settings.imageQuality ? this.settings.imageQuality : PhotoCameraInputWidgetComponent.DEFAULT_IMAGE_QUALITY;
|
||||||
this.previewPhoto = this.sanitizer.bypassSecurityTrustUrl(this.canvasElement.toDataURL(mimeType, quality));
|
this.previewPhoto = this.canvasElement.toDataURL(mimeType, quality);
|
||||||
this.isPreviewPhoto = true;
|
this.isPreviewPhoto = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private initWebCamera(deviceId?: string) {
|
private inititedVideoStream(deviceId?: string, init = false) {
|
||||||
if (window.navigator.mediaDevices && window.navigator.mediaDevices.getUserMedia) {
|
if (window.navigator.mediaDevices && window.navigator.mediaDevices.getUserMedia) {
|
||||||
const videoTrackConstraints = {
|
const videoTrackConstraints = {
|
||||||
video: {deviceId: deviceId !== '' ? {exact: deviceId} : undefined}
|
video: {deviceId: deviceId !== '' ? {exact: deviceId} : undefined}
|
||||||
};
|
};
|
||||||
|
|
||||||
window.navigator.mediaDevices.getUserMedia(videoTrackConstraints).then((stream: MediaStream) => {
|
window.navigator.mediaDevices.getUserMedia(videoTrackConstraints).then((stream: MediaStream) => {
|
||||||
|
if (init) {
|
||||||
|
this.isShowCamera = true;
|
||||||
|
}
|
||||||
this.mediaStream = stream;
|
this.mediaStream = stream;
|
||||||
this.videoElement.srcObject = 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';
|
} from '@home/components/widget/lib/date-range-navigator/date-range-navigator.component';
|
||||||
import { MultipleInputWidgetComponent } from './lib/multiple-input-widget.component';
|
import { MultipleInputWidgetComponent } from './lib/multiple-input-widget.component';
|
||||||
import { TripAnimationComponent } from './trip-animation/trip-animation.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 { GatewayFormComponent } from './lib/gateway/gateway-form.component';
|
||||||
import { ImportExportService } from '@home/components/import-export/import-export.service';
|
import { ImportExportService } from '@home/components/import-export/import-export.service';
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ import { ImportExportService } from '@home/components/import-export/import-expor
|
|||||||
DateRangeNavigatorPanelComponent,
|
DateRangeNavigatorPanelComponent,
|
||||||
MultipleInputWidgetComponent,
|
MultipleInputWidgetComponent,
|
||||||
TripAnimationComponent,
|
TripAnimationComponent,
|
||||||
WebCameraInputWidgetComponent,
|
PhotoCameraInputWidgetComponent,
|
||||||
GatewayFormComponent
|
GatewayFormComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
@ -67,7 +67,7 @@ import { ImportExportService } from '@home/components/import-export/import-expor
|
|||||||
DateRangeNavigatorWidgetComponent,
|
DateRangeNavigatorWidgetComponent,
|
||||||
MultipleInputWidgetComponent,
|
MultipleInputWidgetComponent,
|
||||||
TripAnimationComponent,
|
TripAnimationComponent,
|
||||||
WebCameraInputWidgetComponent,
|
PhotoCameraInputWidgetComponent,
|
||||||
GatewayFormComponent
|
GatewayFormComponent
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
|
|||||||
@ -2318,7 +2318,10 @@
|
|||||||
"no-entity-selected": "No entity selected",
|
"no-entity-selected": "No entity selected",
|
||||||
"no-image": "No image",
|
"no-image": "No image",
|
||||||
"no-support-geolocation": "Your browser doesn't support geolocation",
|
"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",
|
"no-timeseries-selected": "No timeseries selected",
|
||||||
"secret-key": "Secret key",
|
"secret-key": "Secret key",
|
||||||
"secret-key-required": "Secret key is required",
|
"secret-key-required": "Secret key is required",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user