diff --git a/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js b/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js index 48530a9d28..e821549e09 100644 --- a/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js +++ b/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js @@ -13,4 +13,4 @@ See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. ***************************************************************************** */var g=function(e,t){return(g=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)};function y(e,t){function r(){this.constructor=e}g(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)}function b(e,t,r,n){var a,o=arguments.length,i=o<3?t:null===n?n=Object.getOwnPropertyDescriptor(t,r):n;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)i=Reflect.decorate(e,t,r,n);else for(var l=e.length-1;l>=0;l--)(a=e[l])&&(i=(o<3?a(i):o>3?a(t,r,i):a(t,r))||i);return o>3&&i&&Object.defineProperty(t,r,i),i}function h(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}function C(e){var t="function"==typeof Symbol&&e[Symbol.iterator],r=0;return t?t.call(e):{next:function(){return e&&r>=e.length&&(e=void 0),{value:e&&e[r++],done:!e}}}}var v,F=function(e){function r(t,r){var n=e.call(this,t)||this;return n.store=t,n.fb=r,n}return y(r,e),r.prototype.configForm=function(){return this.emptyConfigForm},r.prototype.onConfigurationSet=function(e){this.emptyConfigForm=this.fb.group({})},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder}]},r=b([t.Component({selector:"tb-node-empty-config",template:"
"}),h("design:paramtypes",[o.Store,i.FormBuilder])],r)}(a.RuleNodeConfigurationComponent),T=function(e){function r(t,r){var n=e.call(this,t)||this;return n.store=t,n.fb=r,n.attributeScopes=Object.keys(a.AttributeScope),n.telemetryTypeTranslationsMap=a.telemetryTypeTranslations,n}return y(r,e),r.prototype.configForm=function(){return this.attributesConfigForm},r.prototype.onConfigurationSet=function(e){this.attributesConfigForm=this.fb.group({scope:[e?e.scope:null,[i.Validators.required]]})},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder}]},r=b([t.Component({selector:"tb-action-node-attributes-config",template:'
\n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
\n'}),h("design:paramtypes",[o.Store,i.FormBuilder])],r)}(a.RuleNodeConfigurationComponent),x=function(e){function r(t,r){var n=e.call(this,t)||this;return n.store=t,n.fb=r,n}return y(r,e),r.prototype.configForm=function(){return this.timeseriesConfigForm},r.prototype.onConfigurationSet=function(e){this.timeseriesConfigForm=this.fb.group({defaultTTL:[e?e.defaultTTL:null,[i.Validators.required,i.Validators.min(0)]]})},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder}]},r=b([t.Component({selector:"tb-action-node-timeseries-config",template:'
\n \n tb.rulenode.default-ttl\n \n \n {{ \'tb.rulenode.default-ttl-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-default-ttl-message\' | translate }}\n \n \n
\n'}),h("design:paramtypes",[o.Store,i.FormBuilder])],r)}(a.RuleNodeConfigurationComponent),q=function(e){function r(t,r){var n=e.call(this,t)||this;return n.store=t,n.fb=r,n}return y(r,e),r.prototype.configForm=function(){return this.rpcRequestConfigForm},r.prototype.onConfigurationSet=function(e){this.rpcRequestConfigForm=this.fb.group({timeoutInSeconds:[e?e.timeoutInSeconds:null,[i.Validators.required,i.Validators.min(0)]]})},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder}]},r=b([t.Component({selector:"tb-action-node-rpc-request-config",template:'
\n \n tb.rulenode.timeout-sec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-message\' | translate }}\n \n \n
\n'}),h("design:paramtypes",[o.Store,i.FormBuilder])],r)}(a.RuleNodeConfigurationComponent),S=function(e){function r(t,r,n,a){var o=e.call(this,t)||this;return o.store=t,o.fb=r,o.nodeScriptTestService=n,o.translate=a,o}return y(r,e),r.prototype.configForm=function(){return this.logConfigForm},r.prototype.onConfigurationSet=function(e){this.logConfigForm=this.fb.group({jsScript:[e?e.jsScript:null,[i.Validators.required]]})},r.prototype.testScript=function(){var e=this,t=this.logConfigForm.get("jsScript").value;this.nodeScriptTestService.testNodeScript(t,"string",this.translate.instant("tb.rulenode.to-string"),"ToString",["msg","metadata","msgType"],this.ruleNodeId).subscribe((function(t){t&&e.logConfigForm.get("jsScript").setValue(t)}))},r.prototype.onValidate=function(){this.jsFuncComponent.validateOnSubmit()},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder},{type:l.NodeScriptTestService},{type:n.TranslateService}]},b([t.ViewChild("jsFuncComponent",{static:!0}),h("design:type",a.JsFuncComponent)],r.prototype,"jsFuncComponent",void 0),r=b([t.Component({selector:"tb-action-node-log-config",template:'
\n \n \n \n
\n \n
\n
\n'}),h("design:paramtypes",[o.Store,i.FormBuilder,l.NodeScriptTestService,n.TranslateService])],r)}(a.RuleNodeConfigurationComponent),I=function(e){function r(t,r){var n=e.call(this,t)||this;return n.store=t,n.fb=r,n}return y(r,e),r.prototype.configForm=function(){return this.assignCustomerConfigForm},r.prototype.onConfigurationSet=function(e){this.assignCustomerConfigForm=this.fb.group({customerNamePattern:[e?e.customerNamePattern:null,[i.Validators.required]],createCustomerIfNotExists:[!!e&&e.createCustomerIfNotExists,[]],customerCacheExpiration:[e?e.customerCacheExpiration:null,[i.Validators.required,i.Validators.min(0)]]})},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder}]},r=b([t.Component({selector:"tb-action-node-assign-to-customer-config",template:'
\n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n \n \n \n {{ \'tb.rulenode.create-customer-if-not-exists\' | translate }}\n \n \n tb.rulenode.customer-cache-expiration\n \n \n {{ \'tb.rulenode.customer-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.customer-cache-expiration-range\' | translate }}\n \n \n \n
\n'}),h("design:paramtypes",[o.Store,i.FormBuilder])],r)}(a.RuleNodeConfigurationComponent),k=function(e){function r(t,r,n,a){var o=e.call(this,t)||this;return o.store=t,o.fb=r,o.nodeScriptTestService=n,o.translate=a,o}return y(r,e),r.prototype.configForm=function(){return this.clearAlarmConfigForm},r.prototype.onConfigurationSet=function(e){this.clearAlarmConfigForm=this.fb.group({alarmDetailsBuildJs:[e?e.alarmDetailsBuildJs:null,[i.Validators.required]],alarmType:[e?e.alarmType:null,[i.Validators.required]]})},r.prototype.testScript=function(){var e=this,t=this.clearAlarmConfigForm.get("alarmDetailsBuildJs").value;this.nodeScriptTestService.testNodeScript(t,"json",this.translate.instant("tb.rulenode.details"),"Details",["msg","metadata","msgType"],this.ruleNodeId).subscribe((function(t){t&&e.clearAlarmConfigForm.get("alarmDetailsBuildJs").setValue(t)}))},r.prototype.onValidate=function(){this.jsFuncComponent.validateOnSubmit()},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder},{type:l.NodeScriptTestService},{type:n.TranslateService}]},b([t.ViewChild("jsFuncComponent",{static:!0}),h("design:type",a.JsFuncComponent)],r.prototype,"jsFuncComponent",void 0),r=b([t.Component({selector:"tb-action-node-clear-alarm-config",template:'
\n \n \n \n
\n \n
\n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n \n \n
\n'}),h("design:paramtypes",[o.Store,i.FormBuilder,l.NodeScriptTestService,n.TranslateService])],r)}(a.RuleNodeConfigurationComponent),N=function(e){function r(t,r,n,o){var i=e.call(this,t)||this;return i.store=t,i.fb=r,i.nodeScriptTestService=n,i.translate=o,i.alarmSeverities=Object.keys(a.AlarmSeverity),i.alarmSeverityTranslationMap=a.alarmSeverityTranslations,i.separatorKeysCodes=[s.ENTER,s.COMMA,s.SEMICOLON],i}return y(r,e),r.prototype.configForm=function(){return this.createAlarmConfigForm},r.prototype.onConfigurationSet=function(e){this.createAlarmConfigForm=this.fb.group({alarmDetailsBuildJs:[e?e.alarmDetailsBuildJs:null,[i.Validators.required]],useMessageAlarmData:[!!e&&e.useMessageAlarmData,[]],alarmType:[e?e.alarmType:null,[]],severity:[e?e.severity:null,[]],propagate:[!!e&&e.propagate,[]],relationTypes:[e?e.relationTypes:null,[]]})},r.prototype.validatorTriggers=function(){return["useMessageAlarmData"]},r.prototype.updateValidators=function(e){this.createAlarmConfigForm.get("useMessageAlarmData").value?(this.createAlarmConfigForm.get("alarmType").setValidators([]),this.createAlarmConfigForm.get("severity").setValidators([])):(this.createAlarmConfigForm.get("alarmType").setValidators([i.Validators.required]),this.createAlarmConfigForm.get("severity").setValidators([i.Validators.required])),this.createAlarmConfigForm.get("alarmType").updateValueAndValidity({emitEvent:e}),this.createAlarmConfigForm.get("severity").updateValueAndValidity({emitEvent:e})},r.prototype.testScript=function(){var e=this,t=this.createAlarmConfigForm.get("alarmDetailsBuildJs").value;this.nodeScriptTestService.testNodeScript(t,"json",this.translate.instant("tb.rulenode.details"),"Details",["msg","metadata","msgType"],this.ruleNodeId).subscribe((function(t){t&&e.createAlarmConfigForm.get("alarmDetailsBuildJs").setValue(t)}))},r.prototype.removeKey=function(e,t){var r=this.createAlarmConfigForm.get(t).value,n=r.indexOf(e);n>=0&&(r.splice(n,1),this.createAlarmConfigForm.get(t).setValue(r,{emitEvent:!0}))},r.prototype.addKey=function(e,t){var r=e.input,n=e.value;if((n||"").trim()){n=n.trim();var a=this.createAlarmConfigForm.get(t).value;a&&-1!==a.indexOf(n)||(a||(a=[]),a.push(n),this.createAlarmConfigForm.get(t).setValue(a,{emitEvent:!0}))}r&&(r.value="")},r.prototype.onValidate=function(){this.jsFuncComponent.validateOnSubmit()},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder},{type:l.NodeScriptTestService},{type:n.TranslateService}]},b([t.ViewChild("jsFuncComponent",{static:!0}),h("design:type",a.JsFuncComponent)],r.prototype,"jsFuncComponent",void 0),r=b([t.Component({selector:"tb-action-node-create-alarm-config",template:'
\n \n \n \n
\n \n
\n \n {{ \'tb.rulenode.use-message-alarm-data\' | translate }}\n \n
\n
\n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n \n \n \n tb.rulenode.alarm-severity\n \n \n {{ alarmSeverityTranslationMap.get(severity) | translate }}\n \n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n
\n \n {{ \'tb.rulenode.propagate\' | translate }}\n \n
\n \n tb.rulenode.relation-types-list\n \n \n {{key}}\n close\n \n \n \n \n \n
\n
\n
\n'}),h("design:paramtypes",[o.Store,i.FormBuilder,l.NodeScriptTestService,n.TranslateService])],r)}(a.RuleNodeConfigurationComponent),V=function(e){function r(t,r){var n=e.call(this,t)||this;return n.store=t,n.fb=r,n.directionTypes=Object.keys(a.EntitySearchDirection),n.directionTypeTranslations=a.entitySearchDirectionTranslations,n.entityType=a.EntityType,n}return y(r,e),r.prototype.configForm=function(){return this.createRelationConfigForm},r.prototype.onConfigurationSet=function(e){this.createRelationConfigForm=this.fb.group({direction:[e?e.direction:null,[i.Validators.required]],entityType:[e?e.entityType:null,[i.Validators.required]],entityNamePattern:[e?e.entityNamePattern:null,[]],entityTypePattern:[e?e.entityTypePattern:null,[]],relationType:[e?e.relationType:null,[i.Validators.required]],createEntityIfNotExists:[!!e&&e.createEntityIfNotExists,[]],removeCurrentRelations:[!!e&&e.removeCurrentRelations,[]],changeOriginatorToRelatedEntity:[!!e&&e.changeOriginatorToRelatedEntity,[]],entityCacheExpiration:[e?e.entityCacheExpiration:null,[i.Validators.required,i.Validators.min(0)]]})},r.prototype.validatorTriggers=function(){return["entityType"]},r.prototype.updateValidators=function(e){var t=this.createRelationConfigForm.get("entityType").value;t?this.createRelationConfigForm.get("entityNamePattern").setValidators([i.Validators.required]):this.createRelationConfigForm.get("entityNamePattern").setValidators([]),!t||t!==a.EntityType.DEVICE&&t!==a.EntityType.ASSET?this.createRelationConfigForm.get("entityTypePattern").setValidators([]):this.createRelationConfigForm.get("entityTypePattern").setValidators([i.Validators.required]),this.createRelationConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e}),this.createRelationConfigForm.get("entityTypePattern").updateValueAndValidity({emitEvent:e})},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder}]},r=b([t.Component({selector:"tb-action-node-create-relation-config",template:'
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n
\n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n \n \n \n tb.rulenode.entity-type-pattern\n \n \n {{ \'tb.rulenode.entity-type-pattern-required\' | translate }}\n \n \n \n
\n \n tb.rulenode.relation-type-pattern\n \n \n {{ \'tb.rulenode.relation-type-pattern-required\' | translate }}\n \n \n \n
\n \n {{ \'tb.rulenode.create-entity-if-not-exists\' | translate }}\n \n
tb.rulenode.create-entity-if-not-exists-hint
\n
\n \n {{ \'tb.rulenode.remove-current-relations\' | translate }}\n \n
tb.rulenode.remove-current-relations-hint
\n \n {{ \'tb.rulenode.change-originator-to-related-entity\' | translate }}\n \n
tb.rulenode.change-originator-to-related-entity-hint
\n \n tb.rulenode.entity-cache-expiration\n \n \n {{ \'tb.rulenode.entity-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.entity-cache-expiration-range\' | translate }}\n \n \n \n
\n'}),h("design:paramtypes",[o.Store,i.FormBuilder])],r)}(a.RuleNodeConfigurationComponent),E=function(e){function r(t,r){var n=e.call(this,t)||this;return n.store=t,n.fb=r,n}return y(r,e),r.prototype.configForm=function(){return this.msgDelayConfigForm},r.prototype.onConfigurationSet=function(e){this.msgDelayConfigForm=this.fb.group({useMetadataPeriodInSecondsPatterns:[!!e&&e.useMetadataPeriodInSecondsPatterns,[]],periodInSeconds:[e?e.periodInSeconds:null,[]],periodInSecondsPattern:[e?e.periodInSecondsPattern:null,[]],maxPendingMsgs:[e?e.maxPendingMsgs:null,[i.Validators.required,i.Validators.min(1),i.Validators.max(1e5)]]})},r.prototype.validatorTriggers=function(){return["useMetadataPeriodInSecondsPatterns"]},r.prototype.updateValidators=function(e){this.msgDelayConfigForm.get("useMetadataPeriodInSecondsPatterns").value?(this.msgDelayConfigForm.get("periodInSecondsPattern").setValidators([i.Validators.required]),this.msgDelayConfigForm.get("periodInSeconds").setValidators([])):(this.msgDelayConfigForm.get("periodInSecondsPattern").setValidators([]),this.msgDelayConfigForm.get("periodInSeconds").setValidators([i.Validators.required,i.Validators.min(0)])),this.msgDelayConfigForm.get("periodInSecondsPattern").updateValueAndValidity({emitEvent:e}),this.msgDelayConfigForm.get("periodInSeconds").updateValueAndValidity({emitEvent:e})},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder}]},r=b([t.Component({selector:"tb-action-node-msg-delay-config",template:'
\n \n {{ \'tb.rulenode.use-metadata-period-in-seconds-patterns\' | translate }}\n \n
tb.rulenode.use-metadata-period-in-seconds-patterns-hint
\n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-0-seconds-message\' | translate }}\n \n \n \n \n tb.rulenode.period-in-seconds-pattern\n \n \n {{ \'tb.rulenode.period-in-seconds-pattern-required\' | translate }}\n \n \n \n \n \n tb.rulenode.max-pending-messages\n \n \n {{ \'tb.rulenode.max-pending-messages-required\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n
\n'}),h("design:paramtypes",[o.Store,i.FormBuilder])],r)}(a.RuleNodeConfigurationComponent),A=function(e){function r(t,r){var n=e.call(this,t)||this;return n.store=t,n.fb=r,n.directionTypes=Object.keys(a.EntitySearchDirection),n.directionTypeTranslations=a.entitySearchDirectionTranslations,n.entityType=a.EntityType,n}return y(r,e),r.prototype.configForm=function(){return this.deleteRelationConfigForm},r.prototype.onConfigurationSet=function(e){this.deleteRelationConfigForm=this.fb.group({deleteForSingleEntity:[!!e&&e.deleteForSingleEntity,[]],direction:[e?e.direction:null,[i.Validators.required]],entityType:[e?e.entityType:null,[]],entityNamePattern:[e?e.entityNamePattern:null,[]],relationType:[e?e.relationType:null,[i.Validators.required]],entityCacheExpiration:[e?e.entityCacheExpiration:null,[i.Validators.required,i.Validators.min(0)]]})},r.prototype.validatorTriggers=function(){return["deleteForSingleEntity","entityType"]},r.prototype.updateValidators=function(e){var t=this.deleteRelationConfigForm.get("deleteForSingleEntity").value,r=this.deleteRelationConfigForm.get("entityType").value;t?this.deleteRelationConfigForm.get("entityType").setValidators([i.Validators.required]):this.deleteRelationConfigForm.get("entityType").setValidators([]),t&&r?this.deleteRelationConfigForm.get("entityNamePattern").setValidators([i.Validators.required]):this.deleteRelationConfigForm.get("entityNamePattern").setValidators([]),this.deleteRelationConfigForm.get("entityType").updateValueAndValidity({emitEvent:!1}),this.deleteRelationConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e})},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder}]},r=b([t.Component({selector:"tb-action-node-delete-relation-config",template:'
\n \n {{ \'tb.rulenode.delete-relation-to-specific-entity\' | translate }}\n \n
tb.rulenode.delete-relation-hint
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n
\n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n \n \n
\n \n tb.rulenode.relation-type-pattern\n \n \n {{ \'tb.rulenode.relation-type-pattern-required\' | translate }}\n \n \n \n \n tb.rulenode.entity-cache-expiration\n \n \n {{ \'tb.rulenode.entity-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.entity-cache-expiration-range\' | translate }}\n \n \n \n
\n'}),h("design:paramtypes",[o.Store,i.FormBuilder])],r)}(a.RuleNodeConfigurationComponent),L=function(e){function r(t,r,n,a){var o=e.call(this,t)||this;return o.store=t,o.fb=r,o.nodeScriptTestService=n,o.translate=a,o}return y(r,e),r.prototype.configForm=function(){return this.generatorConfigForm},r.prototype.onConfigurationSet=function(e){this.generatorConfigForm=this.fb.group({msgCount:[e?e.msgCount:null,[i.Validators.required,i.Validators.min(0)]],periodInSeconds:[e?e.periodInSeconds:null,[i.Validators.required,i.Validators.min(1)]],originator:[e?e.originator:null,[]],jsScript:[e?e.jsScript:null,[i.Validators.required]]})},r.prototype.prepareInputConfig=function(e){return e&&(e.originatorId&&e.originatorType?e.originator={id:e.originatorId,entityType:e.originatorType}:e.originator=null,delete e.originatorId,delete e.originatorType),e},r.prototype.prepareOutputConfig=function(e){return e.originator?(e.originatorId=e.originator.id,e.originatorType=e.originator.entityType):(e.originatorId=null,e.originatorType=null),delete e.originator,e},r.prototype.testScript=function(){var e=this,t=this.generatorConfigForm.get("jsScript").value;this.nodeScriptTestService.testNodeScript(t,"generate",this.translate.instant("tb.rulenode.generator"),"Generate",["prevMsg","prevMetadata","prevMsgType"],this.ruleNodeId).subscribe((function(t){t&&e.generatorConfigForm.get("jsScript").setValue(t)}))},r.prototype.onValidate=function(){this.jsFuncComponent.validateOnSubmit()},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder},{type:l.NodeScriptTestService},{type:n.TranslateService}]},b([t.ViewChild("jsFuncComponent",{static:!0}),h("design:type",a.JsFuncComponent)],r.prototype,"jsFuncComponent",void 0),r=b([t.Component({selector:"tb-action-node-generator-config",template:'
\n \n tb.rulenode.message-count\n \n \n {{ \'tb.rulenode.message-count-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-message-count-message\' | translate }}\n \n \n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-seconds-message\' | translate }}\n \n \n
\n \n \n \n
\n \n \n \n
\n \n
\n
\n'}),h("design:paramtypes",[o.Store,i.FormBuilder,l.NodeScriptTestService,n.TranslateService])],r)}(a.RuleNodeConfigurationComponent);!function(e){e.CUSTOMER="CUSTOMER",e.TENANT="TENANT",e.RELATED="RELATED",e.ALARM_ORIGINATOR="ALARM_ORIGINATOR"}(v||(v={}));var M,P=new Map([[v.CUSTOMER,"tb.rulenode.originator-customer"],[v.TENANT,"tb.rulenode.originator-tenant"],[v.RELATED,"tb.rulenode.originator-related"],[v.ALARM_ORIGINATOR,"tb.rulenode.originator-alarm-originator"]]);!function(e){e.CIRCLE="CIRCLE",e.POLYGON="POLYGON"}(M||(M={}));var R,w=new Map([[M.CIRCLE,"tb.rulenode.perimeter-circle"],[M.POLYGON,"tb.rulenode.perimeter-polygon"]]);!function(e){e.MILLISECONDS="MILLISECONDS",e.SECONDS="SECONDS",e.MINUTES="MINUTES",e.HOURS="HOURS",e.DAYS="DAYS"}(R||(R={}));var D,O=new Map([[R.MILLISECONDS,"tb.rulenode.time-unit-milliseconds"],[R.SECONDS,"tb.rulenode.time-unit-seconds"],[R.MINUTES,"tb.rulenode.time-unit-minutes"],[R.HOURS,"tb.rulenode.time-unit-hours"],[R.DAYS,"tb.rulenode.time-unit-days"]]);!function(e){e.METER="METER",e.KILOMETER="KILOMETER",e.FOOT="FOOT",e.MILE="MILE",e.NAUTICAL_MILE="NAUTICAL_MILE"}(D||(D={}));var K,B=new Map([[D.METER,"tb.rulenode.range-unit-meter"],[D.KILOMETER,"tb.rulenode.range-unit-kilometer"],[D.FOOT,"tb.rulenode.range-unit-foot"],[D.MILE,"tb.rulenode.range-unit-mile"],[D.NAUTICAL_MILE,"tb.rulenode.range-unit-nautical-mile"]]);!function(e){e.TITLE="TITLE",e.COUNTRY="COUNTRY",e.STATE="STATE",e.ZIP="ZIP",e.ADDRESS="ADDRESS",e.ADDRESS2="ADDRESS2",e.PHONE="PHONE",e.EMAIL="EMAIL",e.ADDITIONAL_INFO="ADDITIONAL_INFO"}(K||(K={}));var j,U,G,H=new Map([[K.TITLE,"tb.rulenode.entity-details-title"],[K.COUNTRY,"tb.rulenode.entity-details-country"],[K.STATE,"tb.rulenode.entity-details-state"],[K.ZIP,"tb.rulenode.entity-details-zip"],[K.ADDRESS,"tb.rulenode.entity-details-address"],[K.ADDRESS2,"tb.rulenode.entity-details-address2"],[K.PHONE,"tb.rulenode.entity-details-phone"],[K.EMAIL,"tb.rulenode.entity-details-email"],[K.ADDITIONAL_INFO,"tb.rulenode.entity-details-additional_info"]]);!function(e){e.FIRST="FIRST",e.LAST="LAST",e.ALL="ALL"}(j||(j={})),function(e){e.ASC="ASC",e.DESC="DESC"}(U||(U={})),function(e){e.STANDARD="STANDARD",e.FIFO="FIFO"}(G||(G={}));var Q,z=new Map([[G.STANDARD,"tb.rulenode.sqs-queue-standard"],[G.FIFO,"tb.rulenode.sqs-queue-fifo"]]),$=["anonymous","basic","cert.PEM"],_=new Map([["anonymous","tb.rulenode.credentials-anonymous"],["basic","tb.rulenode.credentials-basic"],["cert.PEM","tb.rulenode.credentials-pem"]]);!function(e){e.GET="GET",e.POST="POST",e.PUT="PUT",e.DELETE="DELETE"}(Q||(Q={}));var W=function(e){function r(t,r){var n=e.call(this,t)||this;return n.store=t,n.fb=r,n.perimeterType=M,n.perimeterTypes=Object.keys(M),n.perimeterTypeTranslationMap=w,n.rangeUnits=Object.keys(D),n.rangeUnitTranslationMap=B,n.timeUnits=Object.keys(R),n.timeUnitsTranslationMap=O,n}return y(r,e),r.prototype.configForm=function(){return this.geoActionConfigForm},r.prototype.onConfigurationSet=function(e){this.geoActionConfigForm=this.fb.group({latitudeKeyName:[e?e.latitudeKeyName:null,[i.Validators.required]],longitudeKeyName:[e?e.longitudeKeyName:null,[i.Validators.required]],fetchPerimeterInfoFromMessageMetadata:[!!e&&e.fetchPerimeterInfoFromMessageMetadata,[]],perimeterType:[e?e.perimeterType:null,[]],centerLatitude:[e?e.centerLatitude:null,[]],centerLongitude:[e?e.centerLatitude:null,[]],range:[e?e.range:null,[]],rangeUnit:[e?e.rangeUnit:null,[]],polygonsDefinition:[e?e.polygonsDefinition:null,[]],minInsideDuration:[e?e.minInsideDuration:null,[i.Validators.required,i.Validators.min(1),i.Validators.max(2147483647)]],minInsideDurationTimeUnit:[e?e.minInsideDurationTimeUnit:null,[i.Validators.required]],minOutsideDuration:[e?e.minOutsideDuration:null,[i.Validators.required,i.Validators.min(1),i.Validators.max(2147483647)]],minOutsideDurationTimeUnit:[e?e.minOutsideDurationTimeUnit:null,[i.Validators.required]]})},r.prototype.validatorTriggers=function(){return["fetchPerimeterInfoFromMessageMetadata","perimeterType"]},r.prototype.updateValidators=function(e){var t=this.geoActionConfigForm.get("fetchPerimeterInfoFromMessageMetadata").value,r=this.geoActionConfigForm.get("perimeterType").value;t?this.geoActionConfigForm.get("perimeterType").setValidators([]):this.geoActionConfigForm.get("perimeterType").setValidators([i.Validators.required]),t||r!==M.CIRCLE?(this.geoActionConfigForm.get("centerLatitude").setValidators([]),this.geoActionConfigForm.get("centerLongitude").setValidators([]),this.geoActionConfigForm.get("range").setValidators([]),this.geoActionConfigForm.get("rangeUnit").setValidators([])):(this.geoActionConfigForm.get("centerLatitude").setValidators([i.Validators.required,i.Validators.min(-90),i.Validators.max(90)]),this.geoActionConfigForm.get("centerLongitude").setValidators([i.Validators.required,i.Validators.min(-180),i.Validators.max(180)]),this.geoActionConfigForm.get("range").setValidators([i.Validators.required,i.Validators.min(0)]),this.geoActionConfigForm.get("rangeUnit").setValidators([i.Validators.required])),t||r!==M.POLYGON?this.geoActionConfigForm.get("polygonsDefinition").setValidators([]):this.geoActionConfigForm.get("polygonsDefinition").setValidators([i.Validators.required]),this.geoActionConfigForm.get("perimeterType").updateValueAndValidity({emitEvent:!1}),this.geoActionConfigForm.get("centerLatitude").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("centerLongitude").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("range").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("rangeUnit").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("polygonsDefinition").updateValueAndValidity({emitEvent:e})},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder}]},r=b([t.Component({selector:"tb-action-node-gps-geofencing-config",template:'
\n \n tb.rulenode.latitude-key-name\n \n \n {{ \'tb.rulenode.latitude-key-name-required\' | translate }}\n \n \n \n tb.rulenode.longitude-key-name\n \n \n {{ \'tb.rulenode.longitude-key-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.fetch-perimeter-info-from-message-metadata\' | translate }}\n \n
\n \n tb.rulenode.perimeter-type\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
\n
\n
\n \n tb.rulenode.circle-center-latitude\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n tb.rulenode.circle-center-longitude\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
\n
\n \n tb.rulenode.range\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n tb.rulenode.range-units\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n
\n
\n
\n \n tb.rulenode.polygon-definition\n \n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
\n
\n \n tb.rulenode.min-inside-duration\n \n \n {{ \'tb.rulenode.min-inside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-inside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n \n tb.rulenode.min-outside-duration\n \n \n {{ \'tb.rulenode.min-outside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-outside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n'}),h("design:paramtypes",[o.Store,i.FormBuilder])],r)}(a.RuleNodeConfigurationComponent),J=function(e){function r(t,r){var n=e.call(this,t)||this;return n.store=t,n.fb=r,n}return y(r,e),r.prototype.configForm=function(){return this.msgCountConfigForm},r.prototype.onConfigurationSet=function(e){this.msgCountConfigForm=this.fb.group({interval:[e?e.interval:null,[i.Validators.required,i.Validators.min(1)]],telemetryPrefix:[e?e.telemetryPrefix:null,[i.Validators.required]]})},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder}]},r=b([t.Component({selector:"tb-action-node-msg-count-config",template:'
\n \n tb.rulenode.interval-seconds\n \n \n {{ \'tb.rulenode.interval-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-interval-seconds-message\' | translate }}\n \n \n \n tb.rulenode.output-timeseries-key-prefix\n \n \n {{ \'tb.rulenode.output-timeseries-key-prefix-required\' | translate }}\n \n \n
\n'}),h("design:paramtypes",[o.Store,i.FormBuilder])],r)}(a.RuleNodeConfigurationComponent),Y=function(e){function r(t,r){var n=e.call(this,t)||this;return n.store=t,n.fb=r,n}return y(r,e),r.prototype.configForm=function(){return this.rpcReplyConfigForm},r.prototype.onConfigurationSet=function(e){this.rpcReplyConfigForm=this.fb.group({requestIdMetaDataAttribute:[e?e.requestIdMetaDataAttribute:null,[]]})},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder}]},r=b([t.Component({selector:"tb-action-node-rpc-reply-config",template:'
\n \n tb.rulenode.request-id-metadata-attribute\n \n \n
\n'}),h("design:paramtypes",[o.Store,i.FormBuilder])],r)}(a.RuleNodeConfigurationComponent),Z=function(e){function r(t,r){var n=e.call(this,t)||this;return n.store=t,n.fb=r,n}return y(r,e),r.prototype.configForm=function(){return this.saveToCustomTableConfigForm},r.prototype.onConfigurationSet=function(e){this.saveToCustomTableConfigForm=this.fb.group({tableName:[e?e.tableName:null,[i.Validators.required]],fieldsMapping:[e?e.fieldsMapping:null,[i.Validators.required]]})},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder}]},r=b([t.Component({selector:"tb-action-node-custom-table-config",template:'
\n \n tb.rulenode.custom-table-name\n \n \n {{ \'tb.rulenode.custom-table-name-required\' | translate }}\n \n \n \n \n \n \n
\n'}),h("design:paramtypes",[o.Store,i.FormBuilder])],r)}(a.RuleNodeConfigurationComponent),X=function(e){function r(t,r,n,a){var o=e.call(this,t)||this;return o.store=t,o.translate=r,o.injector=n,o.fb=a,o.propagateChange=null,o.valueChangeSubscription=null,o}var a;return y(r,e),a=r,Object.defineProperty(r.prototype,"required",{get:function(){return this.requiredValue},set:function(e){this.requiredValue=u.coerceBooleanProperty(e)},enumerable:!0,configurable:!0}),r.prototype.ngOnInit=function(){this.ngControl=this.injector.get(i.NgControl),null!=this.ngControl&&(this.ngControl.valueAccessor=this),this.kvListFormGroup=this.fb.group({}),this.kvListFormGroup.addControl("keyVals",this.fb.array([]))},r.prototype.keyValsFormArray=function(){return this.kvListFormGroup.get("keyVals")},r.prototype.registerOnChange=function(e){this.propagateChange=e},r.prototype.registerOnTouched=function(e){},r.prototype.setDisabledState=function(e){this.disabled=e,this.disabled?this.kvListFormGroup.disable({emitEvent:!1}):this.kvListFormGroup.enable({emitEvent:!1})},r.prototype.writeValue=function(e){var t,r,n=this;this.valueChangeSubscription&&this.valueChangeSubscription.unsubscribe();var a=[];if(e)try{for(var o=C(Object.keys(e)),l=o.next();!l.done;l=o.next()){var s=l.value;Object.prototype.hasOwnProperty.call(e,s)&&a.push(this.fb.group({key:[s,[i.Validators.required]],value:[e[s],[i.Validators.required]]}))}}catch(e){t={error:e}}finally{try{l&&!l.done&&(r=o.return)&&r.call(o)}finally{if(t)throw t.error}}this.kvListFormGroup.setControl("keyVals",this.fb.array(a)),this.valueChangeSubscription=this.kvListFormGroup.valueChanges.subscribe((function(){n.updateModel()}))},r.prototype.removeKeyVal=function(e){this.kvListFormGroup.get("keyVals").removeAt(e)},r.prototype.addKeyVal=function(){this.kvListFormGroup.get("keyVals").push(this.fb.group({key:["",[i.Validators.required]],value:["",[i.Validators.required]]}))},r.prototype.validate=function(e){return!this.kvListFormGroup.get("keyVals").value.length&&this.required?{kvMapRequired:!0}:this.kvListFormGroup.valid?null:{kvFieldsRequired:!0}},r.prototype.updateModel=function(){var e=this.kvListFormGroup.get("keyVals").value;if(this.required&&!e.length||!this.kvListFormGroup.valid)this.propagateChange(null);else{var t={};e.forEach((function(e){t[e.key]=e.value})),this.propagateChange(t)}},r.ctorParameters=function(){return[{type:o.Store},{type:n.TranslateService},{type:t.Injector},{type:i.FormBuilder}]},b([t.Input(),h("design:type",Boolean)],r.prototype,"disabled",void 0),b([t.Input(),h("design:type",String)],r.prototype,"requiredText",void 0),b([t.Input(),h("design:type",String)],r.prototype,"keyText",void 0),b([t.Input(),h("design:type",String)],r.prototype,"keyRequiredText",void 0),b([t.Input(),h("design:type",String)],r.prototype,"valText",void 0),b([t.Input(),h("design:type",String)],r.prototype,"valRequiredText",void 0),b([t.Input(),h("design:type",Boolean),h("design:paramtypes",[Boolean])],r.prototype,"required",null),r=a=b([t.Component({selector:"tb-kv-map-config",template:'
\n
\n {{ keyText }}\n {{ valText }}\n \n
\n
\n
\n \n \n \n \n {{ keyRequiredText | translate }}\n \n \n \n \n \n \n {{ valRequiredText | translate }}\n \n \n \n
\n
\n \n
\n \n
\n
\n',providers:[{provide:i.NG_VALUE_ACCESSOR,useExisting:t.forwardRef((function(){return a})),multi:!0},{provide:i.NG_VALIDATORS,useExisting:t.forwardRef((function(){return a})),multi:!0}],styles:[":host .tb-kv-map-config{margin-bottom:16px}:host .tb-kv-map-config .header{padding-left:5px;padding-right:5px;padding-bottom:5px}:host .tb-kv-map-config .header .cell{padding-left:5px;padding-right:5px;color:rgba(0,0,0,.54);font-size:12px;font-weight:700;white-space:nowrap}:host .tb-kv-map-config .body{padding-left:5px;padding-right:5px;padding-bottom:20px;max-height:300px;overflow:auto}:host .tb-kv-map-config .body .row{padding-top:5px;max-height:40px}:host .tb-kv-map-config .body .cell{padding-left:5px;padding-right:5px}:host ::ng-deep .tb-kv-map-config .body mat-form-field.cell{margin:0;max-height:40px}:host ::ng-deep .tb-kv-map-config .body mat-form-field.cell .mat-form-field-infix{border-top:0}:host ::ng-deep .tb-kv-map-config .body button.mat-button{margin:0}"]}),h("design:paramtypes",[o.Store,n.TranslateService,t.Injector,i.FormBuilder])],r)}(a.PageComponent),ee=function(e){function r(t,r){var n=e.call(this,t)||this;return n.store=t,n.fb=r,n.directionTypes=Object.keys(a.EntitySearchDirection),n.directionTypeTranslations=a.entitySearchDirectionTranslations,n.entityType=a.EntityType,n.propagateChange=null,n}var n;return y(r,e),n=r,Object.defineProperty(r.prototype,"required",{get:function(){return this.requiredValue},set:function(e){this.requiredValue=u.coerceBooleanProperty(e)},enumerable:!0,configurable:!0}),r.prototype.ngOnInit=function(){var e=this;this.deviceRelationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[i.Validators.required]],maxLevel:[null,[]],relationType:[null],deviceTypes:[null,[i.Validators.required]]}),this.deviceRelationsQueryFormGroup.valueChanges.subscribe((function(t){e.deviceRelationsQueryFormGroup.valid?e.propagateChange(t):e.propagateChange(null)}))},r.prototype.registerOnChange=function(e){this.propagateChange=e},r.prototype.registerOnTouched=function(e){},r.prototype.setDisabledState=function(e){this.disabled=e,this.disabled?this.deviceRelationsQueryFormGroup.disable({emitEvent:!1}):this.deviceRelationsQueryFormGroup.enable({emitEvent:!1})},r.prototype.writeValue=function(e){this.deviceRelationsQueryFormGroup.reset(e,{emitEvent:!1})},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder}]},b([t.Input(),h("design:type",Boolean)],r.prototype,"disabled",void 0),b([t.Input(),h("design:type",Boolean),h("design:paramtypes",[Boolean])],r.prototype,"required",null),r=n=b([t.Component({selector:"tb-device-relations-query-config",template:'
\n \n {{ \'relation.last-level-relation\' | translate }}\n \n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n
\n
relation.relation-type
\n \n \n
device.device-types
\n \n \n
\n',providers:[{provide:i.NG_VALUE_ACCESSOR,useExisting:t.forwardRef((function(){return n})),multi:!0}]}),h("design:paramtypes",[o.Store,i.FormBuilder])],r)}(a.PageComponent),te=function(e){function r(t,r){var n=e.call(this,t)||this;return n.store=t,n.fb=r,n.directionTypes=Object.keys(a.EntitySearchDirection),n.directionTypeTranslations=a.entitySearchDirectionTranslations,n.propagateChange=null,n}var n;return y(r,e),n=r,Object.defineProperty(r.prototype,"required",{get:function(){return this.requiredValue},set:function(e){this.requiredValue=u.coerceBooleanProperty(e)},enumerable:!0,configurable:!0}),r.prototype.ngOnInit=function(){var e=this;this.relationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[i.Validators.required]],maxLevel:[null,[]],filters:[null]}),this.relationsQueryFormGroup.valueChanges.subscribe((function(t){e.relationsQueryFormGroup.valid?e.propagateChange(t):e.propagateChange(null)}))},r.prototype.registerOnChange=function(e){this.propagateChange=e},r.prototype.registerOnTouched=function(e){},r.prototype.setDisabledState=function(e){this.disabled=e,this.disabled?this.relationsQueryFormGroup.disable({emitEvent:!1}):this.relationsQueryFormGroup.enable({emitEvent:!1})},r.prototype.writeValue=function(e){this.relationsQueryFormGroup.reset(e,{emitEvent:!1})},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder}]},b([t.Input(),h("design:type",Boolean)],r.prototype,"disabled",void 0),b([t.Input(),h("design:type",Boolean),h("design:paramtypes",[Boolean])],r.prototype,"required",null),r=n=b([t.Component({selector:"tb-relations-query-config",template:'
\n \n {{ \'relation.last-level-relation\' | translate }}\n \n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n
\n
relation.relation-filters
\n \n
\n',providers:[{provide:i.NG_VALUE_ACCESSOR,useExisting:t.forwardRef((function(){return n})),multi:!0}]}),h("design:paramtypes",[o.Store,i.FormBuilder])],r)}(a.PageComponent),re=function(e){function r(t,r,n,o){var i,l,m=e.call(this,t)||this;m.store=t,m.translate=r,m.truncate=n,m.fb=o,m.placeholder="tb.rulenode.message-type",m.separatorKeysCodes=[s.ENTER,s.COMMA,s.SEMICOLON],m.messageTypes=[],m.messageTypesList=[],m.searchText="",m.propagateChange=function(e){},m.messageTypeConfigForm=m.fb.group({messageType:[null]});try{for(var u=C(Object.keys(a.MessageType)),d=u.next();!d.done;d=u.next()){var p=d.value;m.messageTypesList.push({name:a.messageTypeNames.get(a.MessageType[p]),value:p})}}catch(e){i={error:e}}finally{try{d&&!d.done&&(l=u.return)&&l.call(u)}finally{if(i)throw i.error}}return m}var l;return y(r,e),l=r,Object.defineProperty(r.prototype,"required",{get:function(){return this.requiredValue},set:function(e){this.requiredValue=u.coerceBooleanProperty(e)},enumerable:!0,configurable:!0}),r.prototype.registerOnChange=function(e){this.propagateChange=e},r.prototype.registerOnTouched=function(e){},r.prototype.ngOnInit=function(){var e=this;this.filteredMessageTypes=this.messageTypeConfigForm.get("messageType").valueChanges.pipe(f.startWith(""),f.map((function(e){return e||""})),f.mergeMap((function(t){return e.fetchMessageTypes(t)})),f.share())},r.prototype.ngAfterViewInit=function(){},r.prototype.setDisabledState=function(e){this.disabled=e,this.disabled?this.messageTypeConfigForm.disable({emitEvent:!1}):this.messageTypeConfigForm.enable({emitEvent:!1})},r.prototype.writeValue=function(e){var t=this;this.searchText="",this.messageTypes.length=0,e&&e.forEach((function(e){var r=t.messageTypesList.find((function(t){return t.value===e}));r?t.messageTypes.push({name:r.name,value:r.value}):t.messageTypes.push({name:e,value:e})}))},r.prototype.displayMessageTypeFn=function(e){return e?e.name:void 0},r.prototype.textIsNotEmpty=function(e){return!!(e&&null!=e&&e.length>0)},r.prototype.createMessageType=function(e,t){e.preventDefault(),this.transformMessageType(t)},r.prototype.add=function(e){this.transformMessageType(e.value)},r.prototype.fetchMessageTypes=function(e){if(this.searchText=e,this.searchText&&this.searchText.length){var t=this.searchText.toUpperCase();return c.of(this.messageTypesList.filter((function(e){return e.name.toUpperCase().includes(t)})))}return c.of(this.messageTypesList)},r.prototype.transformMessageType=function(e){if((e||"").trim()){var t=null,r=e.trim(),n=this.messageTypesList.find((function(e){return e.name===r}));(t=n?{name:n.name,value:n.value}:{name:r,value:r})&&this.addMessageType(t)}this.clear("")},r.prototype.remove=function(e){var t=this.messageTypes.indexOf(e);t>=0&&(this.messageTypes.splice(t,1),this.updateModel())},r.prototype.selected=function(e){this.addMessageType(e.option.value),this.clear("")},r.prototype.addMessageType=function(e){-1===this.messageTypes.findIndex((function(t){return t.value===e.value}))&&(this.messageTypes.push(e),this.updateModel())},r.prototype.onFocus=function(){this.messageTypeConfigForm.get("messageType").updateValueAndValidity({onlySelf:!0,emitEvent:!0})},r.prototype.clear=function(e){var t=this;void 0===e&&(e=""),this.messageTypeInput.nativeElement.value=e,this.messageTypeConfigForm.get("messageType").patchValue(null,{emitEvent:!0}),setTimeout((function(){t.messageTypeInput.nativeElement.blur(),t.messageTypeInput.nativeElement.focus()}),0)},r.prototype.updateModel=function(){var e=this.messageTypes.map((function(e){return e.value}));this.required?(this.chipList.errorState=!e.length,this.propagateChange(e.length>0?e:null)):(this.chipList.errorState=!1,this.propagateChange(e))},r.ctorParameters=function(){return[{type:o.Store},{type:n.TranslateService},{type:a.TruncatePipe},{type:i.FormBuilder}]},b([t.Input(),h("design:type",Boolean),h("design:paramtypes",[Boolean])],r.prototype,"required",null),b([t.Input(),h("design:type",String)],r.prototype,"label",void 0),b([t.Input(),h("design:type",Object)],r.prototype,"placeholder",void 0),b([t.Input(),h("design:type",Boolean)],r.prototype,"disabled",void 0),b([t.ViewChild("chipList",{static:!1}),h("design:type",d.MatChipList)],r.prototype,"chipList",void 0),b([t.ViewChild("messageTypeAutocomplete",{static:!1}),h("design:type",p.MatAutocomplete)],r.prototype,"matAutocomplete",void 0),b([t.ViewChild("messageTypeInput",{static:!1}),h("design:type",t.ElementRef)],r.prototype,"messageTypeInput",void 0),r=l=b([t.Component({selector:"tb-message-types-config",template:'\n {{ label }}\n \n \n {{messageType.name}}\n close\n \n \n \n \n \n \n \n \n
\n
\n tb.rulenode.no-message-types-found\n
\n \n \n {{ translate.get(\'tb.rulenode.no-message-type-matching\',\n {messageType: truncate.transform(searchText, true, 6, '...')}) | async }}\n \n \n \n tb.rulenode.create-new-message-type\n \n
\n
\n
\n \n {{ \'tb.rulenode.message-types-required\' | translate }}\n \n
\n',providers:[{provide:i.NG_VALUE_ACCESSOR,useExisting:t.forwardRef((function(){return l})),multi:!0}]}),h("design:paramtypes",[o.Store,n.TranslateService,a.TruncatePipe,i.FormBuilder])],r)}(a.PageComponent),ne=function(){function e(){}return e=b([t.NgModule({declarations:[X,ee,te,re],imports:[r.CommonModule,a.SharedModule,m.HomeComponentsModule],exports:[X,ee,te,re]})],e)}(),ae=function(e){function r(t,r){var n=e.call(this,t)||this;return n.store=t,n.fb=r,n}return y(r,e),r.prototype.configForm=function(){return this.unassignCustomerConfigForm},r.prototype.onConfigurationSet=function(e){this.unassignCustomerConfigForm=this.fb.group({customerNamePattern:[e?e.customerNamePattern:null,[i.Validators.required]],customerCacheExpiration:[e?e.customerCacheExpiration:null,[i.Validators.required,i.Validators.min(0)]]})},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder}]},r=b([t.Component({selector:"tb-action-node-un-assign-to-customer-config",template:'
\n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n \n \n \n tb.rulenode.customer-cache-expiration\n \n \n {{ \'tb.rulenode.customer-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.customer-cache-expiration-range\' | translate }}\n \n \n \n
\n'}),h("design:paramtypes",[o.Store,i.FormBuilder])],r)}(a.RuleNodeConfigurationComponent),oe=function(e){function r(t,r){var n=e.call(this,t)||this;return n.store=t,n.fb=r,n}return y(r,e),r.prototype.configForm=function(){return this.snsConfigForm},r.prototype.onConfigurationSet=function(e){this.snsConfigForm=this.fb.group({topicArnPattern:[e?e.topicArnPattern:null,[i.Validators.required]],accessKeyId:[e?e.accessKeyId:null,[i.Validators.required]],secretAccessKey:[e?e.secretAccessKey:null,[i.Validators.required]],region:[e?e.region:null,[i.Validators.required]]})},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder}]},r=b([t.Component({selector:"tb-action-node-sns-config",template:'
\n \n tb.rulenode.topic-arn-pattern\n \n \n {{ \'tb.rulenode.topic-arn-pattern-required\' | translate }}\n \n \n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
\n'}),h("design:paramtypes",[o.Store,i.FormBuilder])],r)}(a.RuleNodeConfigurationComponent),ie=function(e){function r(t,r){var n=e.call(this,t)||this;return n.store=t,n.fb=r,n.sqsQueueType=G,n.sqsQueueTypes=Object.keys(G),n.sqsQueueTypeTranslationsMap=z,n}return y(r,e),r.prototype.configForm=function(){return this.sqsConfigForm},r.prototype.onConfigurationSet=function(e){this.sqsConfigForm=this.fb.group({queueType:[e?e.queueType:null,[i.Validators.required]],queueUrlPattern:[e?e.queueUrlPattern:null,[i.Validators.required]],delaySeconds:[e?e.delaySeconds:null,[i.Validators.min(0),i.Validators.max(900)]],messageAttributes:[e?e.messageAttributes:null,[]],accessKeyId:[e?e.accessKeyId:null,[i.Validators.required]],secretAccessKey:[e?e.secretAccessKey:null,[i.Validators.required]],region:[e?e.region:null,[i.Validators.required]]})},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder}]},r=b([t.Component({selector:"tb-action-node-sqs-config",template:'
\n \n tb.rulenode.queue-type\n \n \n {{ sqsQueueTypeTranslationsMap.get(type) | translate }}\n \n \n \n \n tb.rulenode.queue-url-pattern\n \n \n {{ \'tb.rulenode.queue-url-pattern-required\' | translate }}\n \n \n \n \n tb.rulenode.delay-seconds\n \n \n {{ \'tb.rulenode.min-delay-seconds-message\' | translate }}\n \n \n {{ \'tb.rulenode.max-delay-seconds-message\' | translate }}\n \n \n \n
tb.rulenode.message-attributes-hint
\n \n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
\n'}),h("design:paramtypes",[o.Store,i.FormBuilder])],r)}(a.RuleNodeConfigurationComponent),le=function(e){function r(t,r){var n=e.call(this,t)||this;return n.store=t,n.fb=r,n}return y(r,e),r.prototype.configForm=function(){return this.pubSubConfigForm},r.prototype.onConfigurationSet=function(e){this.pubSubConfigForm=this.fb.group({projectId:[e?e.projectId:null,[i.Validators.required]],topicName:[e?e.topicName:null,[i.Validators.required]],serviceAccountKey:[e?e.serviceAccountKey:null,[i.Validators.required]],serviceAccountKeyFileName:[e?e.serviceAccountKeyFileName:null,[i.Validators.required]],messageAttributes:[e?e.messageAttributes:null,[]]})},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder}]},r=b([t.Component({selector:"tb-action-node-pub-sub-config",template:'
\n \n tb.rulenode.gcp-project-id\n \n \n {{ \'tb.rulenode.gcp-project-id-required\' | translate }}\n \n \n \n tb.rulenode.pubsub-topic-name\n \n \n {{ \'tb.rulenode.pubsub-topic-name-required\' | translate }}\n \n \n \n \n \n
tb.rulenode.message-attributes-hint
\n \n \n
\n'}),h("design:paramtypes",[o.Store,i.FormBuilder])],r)}(a.RuleNodeConfigurationComponent),se=function(e){function r(t,r){var n=e.call(this,t)||this;return n.store=t,n.fb=r,n.ackValues=["all","-1","0","1"],n}return y(r,e),r.prototype.configForm=function(){return this.kafkaConfigForm},r.prototype.onConfigurationSet=function(e){this.kafkaConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[i.Validators.required]],bootstrapServers:[e?e.bootstrapServers:null,[i.Validators.required]],retries:[e?e.retries:null,[i.Validators.min(0)]],batchSize:[e?e.batchSize:null,[i.Validators.min(0)]],linger:[e?e.linger:null,[i.Validators.min(0)]],bufferMemory:[e?e.bufferMemory:null,[i.Validators.min(0)]],acks:[e?e.acks:null,[i.Validators.required]],keySerializer:[e?e.keySerializer:null,[i.Validators.required]],valueSerializer:[e?e.valueSerializer:null,[i.Validators.required]],otherProperties:[e?e.otherProperties:null,[]]})},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder}]},r=b([t.Component({selector:"tb-action-node-kafka-config",template:'
\n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n \n \n tb.rulenode.bootstrap-servers\n \n \n {{ \'tb.rulenode.bootstrap-servers-required\' | translate }}\n \n \n \n tb.rulenode.retries\n \n \n {{ \'tb.rulenode.min-retries-message\' | translate }}\n \n \n \n tb.rulenode.batch-size-bytes\n \n \n {{ \'tb.rulenode.min-batch-size-bytes-message\' | translate }}\n \n \n \n tb.rulenode.linger-ms\n \n \n {{ \'tb.rulenode.min-linger-ms-message\' | translate }}\n \n \n \n tb.rulenode.buffer-memory-bytes\n \n \n {{ \'tb.rulenode.min-buffer-memory-bytes-message\' | translate }}\n \n \n \n tb.rulenode.acks\n \n \n {{ ackValue }}\n \n \n \n \n tb.rulenode.key-serializer\n \n \n {{ \'tb.rulenode.key-serializer-required\' | translate }}\n \n \n \n tb.rulenode.value-serializer\n \n \n {{ \'tb.rulenode.value-serializer-required\' | translate }}\n \n \n \n \n \n
\n'}),h("design:paramtypes",[o.Store,i.FormBuilder])],r)}(a.RuleNodeConfigurationComponent),me=function(e){function r(t,r){var n=e.call(this,t)||this;return n.store=t,n.fb=r,n.allMqttCredentialsTypes=$,n.mqttCredentialsTypeTranslationsMap=_,n}return y(r,e),r.prototype.configForm=function(){return this.mqttConfigForm},r.prototype.onConfigurationSet=function(e){this.mqttConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[i.Validators.required]],host:[e?e.host:null,[i.Validators.required]],port:[e?e.port:null,[i.Validators.required,i.Validators.min(1),i.Validators.max(65535)]],connectTimeoutSec:[e?e.connectTimeoutSec:null,[i.Validators.required,i.Validators.min(1),i.Validators.max(200)]],clientId:[e?e.clientId:null,[]],cleanSession:[!!e&&e.cleanSession,[]],ssl:[!!e&&e.ssl,[]],credentials:this.fb.group({type:[e&&e.credentials?e.credentials.type:null,[i.Validators.required]],username:[e&&e.credentials?e.credentials.username:null,[]],password:[e&&e.credentials?e.credentials.password:null,[]],caCert:[e&&e.credentials?e.credentials.caCert:null,[]],caCertFileName:[e&&e.credentials?e.credentials.caCertFileName:null,[]],privateKey:[e&&e.credentials?e.credentials.privateKey:null,[]],privateKeyFileName:[e&&e.credentials?e.credentials.privateKeyFileName:null,[]],cert:[e&&e.credentials?e.credentials.cert:null,[]],certFileName:[e&&e.credentials?e.credentials.certFileName:null,[]]})})},r.prototype.prepareOutputConfig=function(e){var t=e.credentials.type;switch(t){case"anonymous":e.credentials={type:t};break;case"basic":e.credentials={type:t,username:e.credentials.username,password:e.credentials.password};break;case"cert.PEM":delete e.credentials.username}return e},r.prototype.validatorTriggers=function(){return["credentials.type"]},r.prototype.updateValidators=function(e){var t=this.mqttConfigForm.get("credentials"),r=t.get("type").value;switch(e&&t.reset({type:r},{emitEvent:!1}),t.get("username").setValidators([]),t.get("password").setValidators([]),t.get("caCert").setValidators([]),t.get("caCertFileName").setValidators([]),t.get("privateKey").setValidators([]),t.get("privateKeyFileName").setValidators([]),t.get("cert").setValidators([]),t.get("certFileName").setValidators([]),r){case"anonymous":break;case"basic":t.get("username").setValidators([i.Validators.required]),t.get("password").setValidators([i.Validators.required]);break;case"cert.PEM":t.get("caCert").setValidators([i.Validators.required]),t.get("caCertFileName").setValidators([i.Validators.required]),t.get("privateKey").setValidators([i.Validators.required]),t.get("privateKeyFileName").setValidators([i.Validators.required]),t.get("cert").setValidators([i.Validators.required]),t.get("certFileName").setValidators([i.Validators.required])}t.get("username").updateValueAndValidity({emitEvent:e}),t.get("password").updateValueAndValidity({emitEvent:e}),t.get("caCert").updateValueAndValidity({emitEvent:e}),t.get("caCertFileName").updateValueAndValidity({emitEvent:e}),t.get("privateKey").updateValueAndValidity({emitEvent:e}),t.get("privateKeyFileName").updateValueAndValidity({emitEvent:e}),t.get("cert").updateValueAndValidity({emitEvent:e}),t.get("certFileName").updateValueAndValidity({emitEvent:e})},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder}]},r=b([t.Component({selector:"tb-action-node-mqtt-config",template:'
\n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n \n \n
\n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n \n tb.rulenode.connect-timeout\n \n \n {{ \'tb.rulenode.connect-timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n
\n \n tb.rulenode.client-id\n \n \n \n {{ \'tb.rulenode.clean-session\' | translate }}\n \n \n {{ \'tb.rulenode.enable-ssl\' | translate }}\n \n \n \n tb.rulenode.credentials\n \n {{ mqttCredentialsTypeTranslationsMap.get(mqttConfigForm.get(\'credentials\').get(\'type\').value) | translate }}\n \n \n
\n \n tb.rulenode.credentials-type\n \n \n {{ mqttCredentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
\n \n \n \n \n tb.rulenode.username\n \n \n {{ \'tb.rulenode.username-required\' | translate }}\n \n \n \n tb.rulenode.password\n \n \n {{ \'tb.rulenode.password-required\' | translate }}\n \n \n \n \n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n
\n
\n
\n
\n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}"]}),h("design:paramtypes",[o.Store,i.FormBuilder])],r)}(a.RuleNodeConfigurationComponent),ue=function(e){function r(t,r){var n=e.call(this,t)||this;return n.store=t,n.fb=r,n.messageProperties=[null,"BASIC","TEXT_PLAIN","MINIMAL_BASIC","MINIMAL_PERSISTENT_BASIC","PERSISTENT_BASIC","PERSISTENT_TEXT_PLAIN"],n}return y(r,e),r.prototype.configForm=function(){return this.rabbitMqConfigForm},r.prototype.onConfigurationSet=function(e){this.rabbitMqConfigForm=this.fb.group({exchangeNamePattern:[e?e.exchangeNamePattern:null,[]],routingKeyPattern:[e?e.routingKeyPattern:null,[]],messageProperties:[e?e.messageProperties:null,[]],host:[e?e.host:null,[i.Validators.required]],port:[e?e.port:null,[i.Validators.required,i.Validators.min(1),i.Validators.max(65535)]],virtualHost:[e?e.virtualHost:null,[]],username:[e?e.username:null,[]],password:[e?e.password:null,[]],automaticRecoveryEnabled:[!!e&&e.automaticRecoveryEnabled,[]],connectionTimeout:[e?e.connectionTimeout:null,[i.Validators.min(0)]],handshakeTimeout:[e?e.handshakeTimeout:null,[i.Validators.min(0)]],clientProperties:[e?e.clientProperties:null,[]]})},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder}]},r=b([t.Component({selector:"tb-action-node-rabbit-mq-config",template:'
\n \n tb.rulenode.exchange-name-pattern\n \n \n \n tb.rulenode.routing-key-pattern\n \n \n \n tb.rulenode.message-properties\n \n \n {{ property }}\n \n \n \n
\n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n
\n \n tb.rulenode.virtual-host\n \n \n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n {{ \'tb.rulenode.automatic-recovery\' | translate }}\n \n \n tb.rulenode.connection-timeout-ms\n \n \n {{ \'tb.rulenode.min-connection-timeout-ms-message\' | translate }}\n \n \n \n tb.rulenode.handshake-timeout-ms\n \n \n {{ \'tb.rulenode.min-handshake-timeout-ms-message\' | translate }}\n \n \n \n \n \n
\n'}),h("design:paramtypes",[o.Store,i.FormBuilder])],r)}(a.RuleNodeConfigurationComponent),de=function(e){function r(t,r){var n=e.call(this,t)||this;return n.store=t,n.fb=r,n.httpRequestTypes=Object.keys(Q),n}return y(r,e),r.prototype.configForm=function(){return this.restApiCallConfigForm},r.prototype.onConfigurationSet=function(e){this.restApiCallConfigForm=this.fb.group({restEndpointUrlPattern:[e?e.restEndpointUrlPattern:null,[i.Validators.required]],requestMethod:[e?e.requestMethod:null,[i.Validators.required]],useSimpleClientHttpFactory:[!!e&&e.useSimpleClientHttpFactory,[]],readTimeoutMs:[e?e.readTimeoutMs:null,[]],maxParallelRequestsCount:[e?e.maxParallelRequestsCount:null,[i.Validators.min(0)]],headers:[e?e.headers:null,[]],useRedisQueueForMsgPersistence:[!!e&&e.useRedisQueueForMsgPersistence,[]],trimQueue:[!!e&&e.trimQueue,[]],maxQueueSize:[e?e.maxQueueSize:null,[]]})},r.prototype.validatorTriggers=function(){return["useSimpleClientHttpFactory","useRedisQueueForMsgPersistence"]},r.prototype.updateValidators=function(e){var t=this.restApiCallConfigForm.get("useSimpleClientHttpFactory").value,r=this.restApiCallConfigForm.get("useRedisQueueForMsgPersistence").value;t?this.restApiCallConfigForm.get("readTimeoutMs").setValidators([]):this.restApiCallConfigForm.get("readTimeoutMs").setValidators([i.Validators.min(0)]),r?this.restApiCallConfigForm.get("maxQueueSize").setValidators([i.Validators.min(0)]):this.restApiCallConfigForm.get("maxQueueSize").setValidators([]),this.restApiCallConfigForm.get("readTimeoutMs").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("maxQueueSize").updateValueAndValidity({emitEvent:e})},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder}]},r=b([t.Component({selector:"tb-action-node-rest-api-call-config",template:'
\n \n tb.rulenode.endpoint-url-pattern\n \n \n {{ \'tb.rulenode.endpoint-url-pattern-required\' | translate }}\n \n \n \n \n tb.rulenode.request-method\n \n \n {{ requestType }}\n \n \n \n \n {{ \'tb.rulenode.use-simple-client-http-factory\' | translate }}\n \n \n tb.rulenode.read-timeout\n \n \n \n \n tb.rulenode.max-parallel-requests-count\n \n \n \n \n
tb.rulenode.headers-hint
\n \n \n \n {{ \'tb.rulenode.use-redis-queue\' | translate }}\n \n
\n \n {{ \'tb.rulenode.trim-redis-queue\' | translate }}\n \n \n tb.rulenode.redis-queue-max-size\n \n \n
\n
\n'}),h("design:paramtypes",[o.Store,i.FormBuilder])],r)}(a.RuleNodeConfigurationComponent),pe=function(e){function r(t,r){var n=e.call(this,t)||this;return n.store=t,n.fb=r,n.smtpProtocols=["smtp","smtps"],n.tlsVersions=["TLSv1","TLSv1.1","TLSv1.2","TLSv1.3"],n}return y(r,e),r.prototype.configForm=function(){return this.sendEmailConfigForm},r.prototype.onConfigurationSet=function(e){this.sendEmailConfigForm=this.fb.group({useSystemSmtpSettings:[!!e&&e.useSystemSmtpSettings,[]],smtpProtocol:[e?e.smtpProtocol:null,[]],smtpHost:[e?e.smtpHost:null,[]],smtpPort:[e?e.smtpPort:null,[]],timeout:[e?e.timeout:null,[]],enableTls:[!!e&&e.enableTls,[]],tlsVersion:[e?e.tlsVersion:null,[]],username:[e?e.username:null,[]],password:[e?e.password:null,[]]})},r.prototype.validatorTriggers=function(){return["useSystemSmtpSettings"]},r.prototype.updateValidators=function(e){this.sendEmailConfigForm.get("useSystemSmtpSettings").value?(this.sendEmailConfigForm.get("smtpProtocol").setValidators([]),this.sendEmailConfigForm.get("smtpHost").setValidators([]),this.sendEmailConfigForm.get("smtpPort").setValidators([]),this.sendEmailConfigForm.get("timeout").setValidators([])):(this.sendEmailConfigForm.get("smtpProtocol").setValidators([i.Validators.required]),this.sendEmailConfigForm.get("smtpHost").setValidators([i.Validators.required]),this.sendEmailConfigForm.get("smtpPort").setValidators([i.Validators.required,i.Validators.min(1),i.Validators.max(65535)]),this.sendEmailConfigForm.get("timeout").setValidators([i.Validators.required,i.Validators.min(0)])),this.sendEmailConfigForm.get("smtpProtocol").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("smtpHost").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("smtpPort").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("timeout").updateValueAndValidity({emitEvent:e})},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder}]},r=b([t.Component({selector:"tb-action-node-send-email-config",template:'
\n \n {{ \'tb.rulenode.use-system-smtp-settings\' | translate }}\n \n
\n \n tb.rulenode.smtp-protocol\n \n \n {{ smtpProtocol.toUpperCase() }}\n \n \n \n
\n \n tb.rulenode.smtp-host\n \n \n {{ \'tb.rulenode.smtp-host-required\' | translate }}\n \n \n \n tb.rulenode.smtp-port\n \n \n {{ \'tb.rulenode.smtp-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n
\n \n tb.rulenode.timeout-msec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-msec-message\' | translate }}\n \n \n \n {{ \'tb.rulenode.enable-tls\' | translate }}\n \n \n tb.rulenode.tls-version\n \n \n {{ tlsVersion }}\n \n \n \n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n
\n
\n'}),h("design:paramtypes",[o.Store,i.FormBuilder])],r)}(a.RuleNodeConfigurationComponent),ce=function(){function e(){}return e=b([t.NgModule({declarations:[T,x,q,S,I,k,N,V,E,A,L,W,J,Y,Z,ae,oe,ie,le,se,me,ue,de,pe],imports:[r.CommonModule,a.SharedModule,ne],exports:[T,x,q,S,I,k,N,V,E,A,L,W,J,Y,Z,ae,oe,ie,le,se,me,ue,de,pe]})],e)}(),fe=function(e){function r(t,r){var n=e.call(this,t)||this;return n.store=t,n.fb=r,n.separatorKeysCodes=[s.ENTER,s.COMMA,s.SEMICOLON],n}return y(r,e),r.prototype.configForm=function(){return this.checkMessageConfigForm},r.prototype.onConfigurationSet=function(e){this.checkMessageConfigForm=this.fb.group({messageNames:[e?e.messageNames:null,[]],metadataNames:[e?e.metadataNames:null,[]],checkAllKeys:[!!e&&e.checkAllKeys,[]]})},r.prototype.validateConfig=function(){var e=this.checkMessageConfigForm.get("messageNames").value,t=this.checkMessageConfigForm.get("metadataNames").value;return e.length>0||t.length>0},r.prototype.removeMessageName=function(e){var t=this.checkMessageConfigForm.get("messageNames").value,r=t.indexOf(e);r>=0&&(t.splice(r,1),this.checkMessageConfigForm.get("messageNames").setValue(t,{emitEvent:!0}))},r.prototype.removeMetadataName=function(e){var t=this.checkMessageConfigForm.get("metadataNames").value,r=t.indexOf(e);r>=0&&(t.splice(r,1),this.checkMessageConfigForm.get("metadataNames").setValue(t,{emitEvent:!0}))},r.prototype.addMessageName=function(e){var t=e.input,r=e.value;if((r||"").trim()){r=r.trim();var n=this.checkMessageConfigForm.get("messageNames").value;n&&-1!==n.indexOf(r)||(n||(n=[]),n.push(r),this.checkMessageConfigForm.get("messageNames").setValue(n,{emitEvent:!0}))}t&&(t.value="")},r.prototype.addMetadataName=function(e){var t=e.input,r=e.value;if((r||"").trim()){r=r.trim();var n=this.checkMessageConfigForm.get("metadataNames").value;n&&-1!==n.indexOf(r)||(n||(n=[]),n.push(r),this.checkMessageConfigForm.get("metadataNames").setValue(n,{emitEvent:!0}))}t&&(t.value="")},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder}]},r=b([t.Component({selector:"tb-filter-node-check-message-config",template:'
\n \n \n \n \n \n {{messageName}}\n close\n \n \n \n \n
tb.rulenode.separator-hint
\n \n \n \n \n \n {{metadataName}}\n close\n \n \n \n \n
tb.rulenode.separator-hint
\n \n {{ \'tb.rulenode.check-all-keys\' | translate }}\n \n
tb.rulenode.check-all-keys-hint
\n
\n',styles:[":host label.tb-title{margin-bottom:-10px}"]}),h("design:paramtypes",[o.Store,i.FormBuilder])],r)}(a.RuleNodeConfigurationComponent),ge=function(e){function r(t,r){var n=e.call(this,t)||this;return n.store=t,n.fb=r,n.entitySearchDirection=Object.keys(a.EntitySearchDirection),n.entitySearchDirectionTranslationsMap=a.entitySearchDirectionTranslations,n}return y(r,e),r.prototype.configForm=function(){return this.checkRelationConfigForm},r.prototype.onConfigurationSet=function(e){this.checkRelationConfigForm=this.fb.group({checkForSingleEntity:[!!e&&e.checkForSingleEntity,[]],direction:[e?e.direction:null,[]],entityType:[e?e.entityType:null,e&&e.checkForSingleEntity?[i.Validators.required]:[]],entityId:[e?e.entityId:null,e&&e.checkForSingleEntity?[i.Validators.required]:[]],relationType:[e?e.relationType:null,[i.Validators.required]]})},r.prototype.validatorTriggers=function(){return["checkForSingleEntity"]},r.prototype.updateValidators=function(e){var t=this.checkRelationConfigForm.get("checkForSingleEntity").value;this.checkRelationConfigForm.get("entityType").setValidators(t?[i.Validators.required]:[]),this.checkRelationConfigForm.get("entityType").updateValueAndValidity({emitEvent:e}),this.checkRelationConfigForm.get("entityId").setValidators(t?[i.Validators.required]:[]),this.checkRelationConfigForm.get("entityId").updateValueAndValidity({emitEvent:e})},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder}]},r=b([t.Component({selector:"tb-filter-node-check-relation-config",template:'
\n \n {{ \'tb.rulenode.check-relation-to-specific-entity\' | translate }}\n \n
tb.rulenode.check-relation-hint
\n \n relation.direction\n \n \n {{ entitySearchDirectionTranslationsMap.get(direction) | translate }}\n \n \n \n
\n \n \n \n \n
\n \n \n
\n'}),h("design:paramtypes",[o.Store,i.FormBuilder])],r)}(a.RuleNodeConfigurationComponent),ye=function(e){function r(t,r){var n=e.call(this,t)||this;return n.store=t,n.fb=r,n.perimeterType=M,n.perimeterTypes=Object.keys(M),n.perimeterTypeTranslationMap=w,n.rangeUnits=Object.keys(D),n.rangeUnitTranslationMap=B,n}return y(r,e),r.prototype.configForm=function(){return this.geoFilterConfigForm},r.prototype.onConfigurationSet=function(e){this.geoFilterConfigForm=this.fb.group({latitudeKeyName:[e?e.latitudeKeyName:null,[i.Validators.required]],longitudeKeyName:[e?e.longitudeKeyName:null,[i.Validators.required]],fetchPerimeterInfoFromMessageMetadata:[!!e&&e.fetchPerimeterInfoFromMessageMetadata,[]],perimeterType:[e?e.perimeterType:null,[]],centerLatitude:[e?e.centerLatitude:null,[]],centerLongitude:[e?e.centerLatitude:null,[]],range:[e?e.range:null,[]],rangeUnit:[e?e.rangeUnit:null,[]],polygonsDefinition:[e?e.polygonsDefinition:null,[]]})},r.prototype.validatorTriggers=function(){return["fetchPerimeterInfoFromMessageMetadata","perimeterType"]},r.prototype.updateValidators=function(e){var t=this.geoFilterConfigForm.get("fetchPerimeterInfoFromMessageMetadata").value,r=this.geoFilterConfigForm.get("perimeterType").value;t?this.geoFilterConfigForm.get("perimeterType").setValidators([]):this.geoFilterConfigForm.get("perimeterType").setValidators([i.Validators.required]),t||r!==M.CIRCLE?(this.geoFilterConfigForm.get("centerLatitude").setValidators([]),this.geoFilterConfigForm.get("centerLongitude").setValidators([]),this.geoFilterConfigForm.get("range").setValidators([]),this.geoFilterConfigForm.get("rangeUnit").setValidators([])):(this.geoFilterConfigForm.get("centerLatitude").setValidators([i.Validators.required,i.Validators.min(-90),i.Validators.max(90)]),this.geoFilterConfigForm.get("centerLongitude").setValidators([i.Validators.required,i.Validators.min(-180),i.Validators.max(180)]),this.geoFilterConfigForm.get("range").setValidators([i.Validators.required,i.Validators.min(0)]),this.geoFilterConfigForm.get("rangeUnit").setValidators([i.Validators.required])),t||r!==M.POLYGON?this.geoFilterConfigForm.get("polygonsDefinition").setValidators([]):this.geoFilterConfigForm.get("polygonsDefinition").setValidators([i.Validators.required]),this.geoFilterConfigForm.get("perimeterType").updateValueAndValidity({emitEvent:!1}),this.geoFilterConfigForm.get("centerLatitude").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("centerLongitude").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("range").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("rangeUnit").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("polygonsDefinition").updateValueAndValidity({emitEvent:e})},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder}]},r=b([t.Component({selector:"tb-filter-node-gps-geofencing-config",template:'
\n \n tb.rulenode.latitude-key-name\n \n \n {{ \'tb.rulenode.latitude-key-name-required\' | translate }}\n \n \n \n tb.rulenode.longitude-key-name\n \n \n {{ \'tb.rulenode.longitude-key-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.fetch-perimeter-info-from-message-metadata\' | translate }}\n \n
\n \n tb.rulenode.perimeter-type\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
\n
\n
\n \n tb.rulenode.circle-center-latitude\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n tb.rulenode.circle-center-longitude\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
\n
\n \n tb.rulenode.range\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n tb.rulenode.range-units\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n
\n
\n
\n
\n \n tb.rulenode.polygon-definition\n \n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
\n
\n
\n'}),h("design:paramtypes",[o.Store,i.FormBuilder])],r)}(a.RuleNodeConfigurationComponent),be=function(e){function r(t,r){var n=e.call(this,t)||this;return n.store=t,n.fb=r,n}return y(r,e),r.prototype.configForm=function(){return this.messageTypeConfigForm},r.prototype.onConfigurationSet=function(e){this.messageTypeConfigForm=this.fb.group({messageTypes:[e?e.messageTypes:null,[i.Validators.required]]})},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder}]},r=b([t.Component({selector:"tb-filter-node-message-type-config",template:'
\n \n
\n'}),h("design:paramtypes",[o.Store,i.FormBuilder])],r)}(a.RuleNodeConfigurationComponent),he=function(e){function r(t,r){var n=e.call(this,t)||this;return n.store=t,n.fb=r,n.allowedEntityTypes=[a.EntityType.DEVICE,a.EntityType.ASSET,a.EntityType.ENTITY_VIEW,a.EntityType.TENANT,a.EntityType.CUSTOMER,a.EntityType.USER,a.EntityType.DASHBOARD,a.EntityType.RULE_CHAIN,a.EntityType.RULE_NODE],n}return y(r,e),r.prototype.configForm=function(){return this.originatorTypeConfigForm},r.prototype.onConfigurationSet=function(e){this.originatorTypeConfigForm=this.fb.group({originatorTypes:[e?e.originatorTypes:null,[i.Validators.required]]})},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder}]},r=b([t.Component({selector:"tb-filter-node-originator-type-config",template:'
\n \n \n \n
\n',styles:[":host ::ng-deep tb-entity-type-list .mat-form-field-flex{padding-top:0}:host ::ng-deep tb-entity-type-list .mat-form-field-infix{border-top:0}"]}),h("design:paramtypes",[o.Store,i.FormBuilder])],r)}(a.RuleNodeConfigurationComponent),Ce=function(e){function r(t,r,n,a){var o=e.call(this,t)||this;return o.store=t,o.fb=r,o.nodeScriptTestService=n,o.translate=a,o}return y(r,e),r.prototype.configForm=function(){return this.scriptConfigForm},r.prototype.onConfigurationSet=function(e){this.scriptConfigForm=this.fb.group({jsScript:[e?e.jsScript:null,[i.Validators.required]]})},r.prototype.testScript=function(){var e=this,t=this.scriptConfigForm.get("jsScript").value;this.nodeScriptTestService.testNodeScript(t,"filter",this.translate.instant("tb.rulenode.filter"),"Filter",["msg","metadata","msgType"],this.ruleNodeId).subscribe((function(t){t&&e.scriptConfigForm.get("jsScript").setValue(t)}))},r.prototype.onValidate=function(){this.jsFuncComponent.validateOnSubmit()},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder},{type:l.NodeScriptTestService},{type:n.TranslateService}]},b([t.ViewChild("jsFuncComponent",{static:!0}),h("design:type",a.JsFuncComponent)],r.prototype,"jsFuncComponent",void 0),r=b([t.Component({selector:"tb-filter-node-script-config",template:'
\n \n \n \n
\n \n
\n
\n'}),h("design:paramtypes",[o.Store,i.FormBuilder,l.NodeScriptTestService,n.TranslateService])],r)}(a.RuleNodeConfigurationComponent),ve=function(e){function r(t,r,n,a){var o=e.call(this,t)||this;return o.store=t,o.fb=r,o.nodeScriptTestService=n,o.translate=a,o}return y(r,e),r.prototype.configForm=function(){return this.switchConfigForm},r.prototype.onConfigurationSet=function(e){this.switchConfigForm=this.fb.group({jsScript:[e?e.jsScript:null,[i.Validators.required]]})},r.prototype.testScript=function(){var e=this,t=this.switchConfigForm.get("jsScript").value;this.nodeScriptTestService.testNodeScript(t,"switch",this.translate.instant("tb.rulenode.switch"),"Switch",["msg","metadata","msgType"],this.ruleNodeId).subscribe((function(t){t&&e.switchConfigForm.get("jsScript").setValue(t)}))},r.prototype.onValidate=function(){this.jsFuncComponent.validateOnSubmit()},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder},{type:l.NodeScriptTestService},{type:n.TranslateService}]},b([t.ViewChild("jsFuncComponent",{static:!0}),h("design:type",a.JsFuncComponent)],r.prototype,"jsFuncComponent",void 0),r=b([t.Component({selector:"tb-filter-node-switch-config",template:'
\n \n \n \n
\n \n
\n
\n'}),h("design:paramtypes",[o.Store,i.FormBuilder,l.NodeScriptTestService,n.TranslateService])],r)}(a.RuleNodeConfigurationComponent),Fe=function(e){function r(t,r,n){var o,l,s=e.call(this,t)||this;s.store=t,s.translate=r,s.fb=n,s.alarmStatusTranslationsMap=a.alarmStatusTranslations,s.alarmStatusList=[],s.searchText="",s.displayStatusFn=s.displayStatus.bind(s);try{for(var m=C(Object.keys(a.AlarmStatus)),u=m.next();!u.done;u=m.next()){var d=u.value;s.alarmStatusList.push(a.AlarmStatus[d])}}catch(e){o={error:e}}finally{try{u&&!u.done&&(l=m.return)&&l.call(m)}finally{if(o)throw o.error}}return s.statusFormControl=new i.FormControl(""),s.filteredAlarmStatus=s.statusFormControl.valueChanges.pipe(f.startWith(""),f.map((function(e){return e||""})),f.mergeMap((function(e){return s.fetchAlarmStatus(e)})),f.share()),s}return y(r,e),r.prototype.ngOnInit=function(){e.prototype.ngOnInit.call(this)},r.prototype.configForm=function(){return this.alarmStatusConfigForm},r.prototype.prepareInputConfig=function(e){return this.searchText="",this.statusFormControl.patchValue("",{emitEvent:!0}),e},r.prototype.onConfigurationSet=function(e){this.alarmStatusConfigForm=this.fb.group({alarmStatusList:[e?e.alarmStatusList:null,[i.Validators.required]]})},r.prototype.displayStatus=function(e){return e?this.translate.instant(a.alarmStatusTranslations.get(e)):void 0},r.prototype.fetchAlarmStatus=function(e){var t=this,r=this.getAlarmStatusList();if(this.searchText=e,this.searchText&&this.searchText.length){var n=this.searchText.toUpperCase();return c.of(r.filter((function(e){return t.translate.instant(a.alarmStatusTranslations.get(a.AlarmStatus[e])).toUpperCase().includes(n)})))}return c.of(r)},r.prototype.alarmStatusSelected=function(e){this.addAlarmStatus(e.option.value),this.clear("")},r.prototype.removeAlarmStatus=function(e){var t=this.alarmStatusConfigForm.get("alarmStatusList").value;if(t){var r=t.indexOf(e);r>=0&&(t.splice(r,1),this.alarmStatusConfigForm.get("alarmStatusList").setValue(t))}},r.prototype.addAlarmStatus=function(e){var t=this.alarmStatusConfigForm.get("alarmStatusList").value;t||(t=[]),-1===t.indexOf(e)&&(t.push(e),this.alarmStatusConfigForm.get("alarmStatusList").setValue(t))},r.prototype.getAlarmStatusList=function(){var e=this;return this.alarmStatusList.filter((function(t){return-1===e.alarmStatusConfigForm.get("alarmStatusList").value.indexOf(t)}))},r.prototype.onAlarmStatusInputFocus=function(){this.statusFormControl.updateValueAndValidity({onlySelf:!0,emitEvent:!0})},r.prototype.clear=function(e){var t=this;void 0===e&&(e=""),this.alarmStatusInput.nativeElement.value=e,this.statusFormControl.patchValue(null,{emitEvent:!0}),setTimeout((function(){t.alarmStatusInput.nativeElement.blur(),t.alarmStatusInput.nativeElement.focus()}),0)},r.ctorParameters=function(){return[{type:o.Store},{type:n.TranslateService},{type:i.FormBuilder}]},b([t.ViewChild("alarmStatusInput",{static:!1}),h("design:type",t.ElementRef)],r.prototype,"alarmStatusInput",void 0),r=b([t.Component({selector:"tb-filter-node-check-alarm-status-config",template:'
\n \n tb.rulenode.alarm-status-filter\n \n \n \n {{alarmStatusTranslationsMap.get(alarmStatus) | translate}}\n \n close\n \n \n \n \n \n \n \n \n
\n
\n tb.rulenode.no-alarm-status-matching\n
\n
\n
\n
\n
\n \n
\n\n\n\n'}),h("design:paramtypes",[o.Store,n.TranslateService,i.FormBuilder])],r)}(a.RuleNodeConfigurationComponent),Te=function(){function e(){}return e=b([t.NgModule({declarations:[fe,ge,ye,be,he,Ce,ve,Fe],imports:[r.CommonModule,a.SharedModule,ne],exports:[fe,ge,ye,be,he,Ce,ve,Fe]})],e)}(),xe=function(e){function r(t,r){var n=e.call(this,t)||this;return n.store=t,n.fb=r,n}return y(r,e),r.prototype.configForm=function(){return this.customerAttributesConfigForm},r.prototype.onConfigurationSet=function(e){this.customerAttributesConfigForm=this.fb.group({telemetry:[!!e&&e.telemetry,[]],attrMapping:[e?e.attrMapping:null,[i.Validators.required]]})},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder}]},r=b([t.Component({selector:"tb-enrichment-node-customer-attributes-config",template:'
\n \n \n {{ \'tb.rulenode.latest-telemetry\' | translate }}\n \n \n \n
\n'}),h("design:paramtypes",[o.Store,i.FormBuilder])],r)}(a.RuleNodeConfigurationComponent),qe=function(e){function r(t,r,n){var a,o,l=e.call(this,t)||this;l.store=t,l.translate=r,l.fb=n,l.entityDetailsTranslationsMap=H,l.entityDetailsList=[],l.searchText="",l.displayDetailsFn=l.displayDetails.bind(l);try{for(var s=C(Object.keys(K)),m=s.next();!m.done;m=s.next()){var u=m.value;l.entityDetailsList.push(K[u])}}catch(e){a={error:e}}finally{try{m&&!m.done&&(o=s.return)&&o.call(s)}finally{if(a)throw a.error}}return l.detailsFormControl=new i.FormControl(""),l.filteredEntityDetails=l.detailsFormControl.valueChanges.pipe(f.startWith(""),f.map((function(e){return e||""})),f.mergeMap((function(e){return l.fetchEntityDetails(e)})),f.share()),l}return y(r,e),r.prototype.ngOnInit=function(){e.prototype.ngOnInit.call(this)},r.prototype.configForm=function(){return this.entityDetailsConfigForm},r.prototype.prepareInputConfig=function(e){return this.searchText="",this.detailsFormControl.patchValue("",{emitEvent:!0}),e},r.prototype.onConfigurationSet=function(e){this.entityDetailsConfigForm=this.fb.group({detailsList:[e?e.detailsList:null,[i.Validators.required]],addToMetadata:[!!e&&e.addToMetadata,[]]})},r.prototype.displayDetails=function(e){return e?this.translate.instant(H.get(e)):void 0},r.prototype.fetchEntityDetails=function(e){var t=this;if(this.searchText=e,this.searchText&&this.searchText.length){var r=this.searchText.toUpperCase();return c.of(this.entityDetailsList.filter((function(e){return t.translate.instant(H.get(K[e])).toUpperCase().includes(r)})))}return c.of(this.entityDetailsList)},r.prototype.detailsFieldSelected=function(e){this.addDetailsField(e.option.value),this.clear("")},r.prototype.removeDetailsField=function(e){var t=this.entityDetailsConfigForm.get("detailsList").value;if(t){var r=t.indexOf(e);r>=0&&(t.splice(r,1),this.entityDetailsConfigForm.get("detailsList").setValue(t))}},r.prototype.addDetailsField=function(e){var t=this.entityDetailsConfigForm.get("detailsList").value;t||(t=[]),-1===t.indexOf(e)&&(t.push(e),this.entityDetailsConfigForm.get("detailsList").setValue(t))},r.prototype.onEntityDetailsInputFocus=function(){this.detailsFormControl.updateValueAndValidity({onlySelf:!0,emitEvent:!0})},r.prototype.clear=function(e){var t=this;void 0===e&&(e=""),this.detailsInput.nativeElement.value=e,this.detailsFormControl.patchValue(null,{emitEvent:!0}),setTimeout((function(){t.detailsInput.nativeElement.blur(),t.detailsInput.nativeElement.focus()}),0)},r.ctorParameters=function(){return[{type:o.Store},{type:n.TranslateService},{type:i.FormBuilder}]},b([t.ViewChild("detailsInput",{static:!1}),h("design:type",t.ElementRef)],r.prototype,"detailsInput",void 0),r=b([t.Component({selector:"tb-enrichment-node-entity-details-config",template:'
\n \n tb.rulenode.entity-details\n \n \n \n {{entityDetailsTranslationsMap.get(details) | translate}}\n \n close\n \n \n \n \n \n \n \n \n
\n
\n tb.rulenode.no-entity-details-matching\n
\n
\n
\n
\n
\n \n \n {{ \'tb.rulenode.add-to-metadata\' | translate }}\n \n
tb.rulenode.add-to-metadata-hint
\n
\n',styles:[":host ::ng-deep mat-form-field.entity-fields-list .mat-form-field-wrapper{margin-bottom:-1.25em}"]}),h("design:paramtypes",[o.Store,n.TranslateService,i.FormBuilder])],r)}(a.RuleNodeConfigurationComponent),Se=function(e){function r(t,r){var n=e.call(this,t)||this;return n.store=t,n.fb=r,n.separatorKeysCodes=[s.ENTER,s.COMMA,s.SEMICOLON],n}return y(r,e),r.prototype.configForm=function(){return this.deviceAttributesConfigForm},r.prototype.onConfigurationSet=function(e){this.deviceAttributesConfigForm=this.fb.group({deviceRelationsQuery:[e?e.deviceRelationsQuery:null,[i.Validators.required]],tellFailureIfAbsent:[!!e&&e.tellFailureIfAbsent,[]],clientAttributeNames:[e?e.clientAttributeNames:null,[]],sharedAttributeNames:[e?e.sharedAttributeNames:null,[]],serverAttributeNames:[e?e.serverAttributeNames:null,[]],latestTsKeyNames:[e?e.latestTsKeyNames:null,[]],getLatestValueWithTs:[!!e&&e.getLatestValueWithTs,[]]})},r.prototype.removeKey=function(e,t){var r=this.deviceAttributesConfigForm.get(t).value,n=r.indexOf(e);n>=0&&(r.splice(n,1),this.deviceAttributesConfigForm.get(t).setValue(r,{emitEvent:!0}))},r.prototype.addKey=function(e,t){var r=e.input,n=e.value;if((n||"").trim()){n=n.trim();var a=this.deviceAttributesConfigForm.get(t).value;a&&-1!==a.indexOf(n)||(a||(a=[]),a.push(n),this.deviceAttributesConfigForm.get(t).setValue(a,{emitEvent:!0}))}r&&(r.value="")},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder}]},r=b([t.Component({selector:"tb-enrichment-node-device-attributes-config",template:'
\n \n \n \n \n {{ \'tb.rulenode.tell-failure-if-absent\' | translate }}\n \n
tb.rulenode.tell-failure-if-absent-hint
\n \n \n \n \n \n {{key}}\n close\n \n \n \n \n \n \n \n \n \n {{key}}\n close\n \n \n \n \n \n \n \n \n \n {{key}}\n close\n \n \n \n \n \n \n \n \n \n {{key}}\n close\n \n \n \n \n \n {{ \'tb.rulenode.get-latest-value-with-ts\' | translate }}\n \n
\n
\n',styles:[":host label.tb-title{margin-bottom:-10px}"]}),h("design:paramtypes",[o.Store,i.FormBuilder])],r)}(a.RuleNodeConfigurationComponent),Ie=function(e){function r(t,r){var n=e.call(this,t)||this;return n.store=t,n.fb=r,n.separatorKeysCodes=[s.ENTER,s.COMMA,s.SEMICOLON],n}return y(r,e),r.prototype.configForm=function(){return this.originatorAttributesConfigForm},r.prototype.onConfigurationSet=function(e){this.originatorAttributesConfigForm=this.fb.group({tellFailureIfAbsent:[!!e&&e.tellFailureIfAbsent,[]],clientAttributeNames:[e?e.clientAttributeNames:null,[]],sharedAttributeNames:[e?e.sharedAttributeNames:null,[]],serverAttributeNames:[e?e.serverAttributeNames:null,[]],latestTsKeyNames:[e?e.latestTsKeyNames:null,[]],getLatestValueWithTs:[!!e&&e.getLatestValueWithTs,[]]})},r.prototype.removeKey=function(e,t){var r=this.originatorAttributesConfigForm.get(t).value,n=r.indexOf(e);n>=0&&(r.splice(n,1),this.originatorAttributesConfigForm.get(t).setValue(r,{emitEvent:!0}))},r.prototype.addKey=function(e,t){var r=e.input,n=e.value;if((n||"").trim()){n=n.trim();var a=this.originatorAttributesConfigForm.get(t).value;a&&-1!==a.indexOf(n)||(a||(a=[]),a.push(n),this.originatorAttributesConfigForm.get(t).setValue(a,{emitEvent:!0}))}r&&(r.value="")},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder}]},r=b([t.Component({selector:"tb-enrichment-node-originator-attributes-config",template:'
\n \n {{ \'tb.rulenode.tell-failure-if-absent\' | translate }}\n \n
tb.rulenode.tell-failure-if-absent-hint
\n \n \n \n \n \n {{key}}\n close\n \n \n \n \n \n \n \n \n \n {{key}}\n close\n \n \n \n \n \n \n \n \n \n {{key}}\n close\n \n \n \n \n \n \n \n \n \n {{key}}\n close\n \n \n \n \n \n {{ \'tb.rulenode.get-latest-value-with-ts\' | translate }}\n \n
\n
\n',styles:[":host label.tb-title{margin-bottom:-10px}"]}),h("design:paramtypes",[o.Store,i.FormBuilder])],r)}(a.RuleNodeConfigurationComponent),ke=function(e){function r(t,r){var n=e.call(this,t)||this;return n.store=t,n.fb=r,n}return y(r,e),r.prototype.configForm=function(){return this.originatorFieldsConfigForm},r.prototype.onConfigurationSet=function(e){this.originatorFieldsConfigForm=this.fb.group({fieldsMapping:[e?e.fieldsMapping:null,[i.Validators.required]]})},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder}]},r=b([t.Component({selector:"tb-enrichment-node-originator-fields-config",template:'
\n \n \n \n
\n'}),h("design:paramtypes",[o.Store,i.FormBuilder])],r)}(a.RuleNodeConfigurationComponent),Ne=function(e){function r(t,r){var n=e.call(this,t)||this;return n.store=t,n.fb=r,n.separatorKeysCodes=[s.ENTER,s.COMMA,s.SEMICOLON],n.fetchMode=j,n.fetchModes=Object.keys(j),n.samplingOrders=Object.keys(U),n.timeUnits=Object.keys(R),n.timeUnitsTranslationMap=O,n}return y(r,e),r.prototype.configForm=function(){return this.getTelemetryFromDatabaseConfigForm},r.prototype.onConfigurationSet=function(e){this.getTelemetryFromDatabaseConfigForm=this.fb.group({latestTsKeyNames:[e?e.latestTsKeyNames:null,[]],fetchMode:[e?e.fetchMode:null,[i.Validators.required]],orderBy:[e?e.orderBy:null,[]],limit:[e?e.limit:null,[]],useMetadataIntervalPatterns:[!!e&&e.useMetadataIntervalPatterns,[]],startInterval:[e?e.startInterval:null,[]],startIntervalTimeUnit:[e?e.startIntervalTimeUnit:null,[]],endInterval:[e?e.endInterval:null,[]],endIntervalTimeUnit:[e?e.endIntervalTimeUnit:null,[]],startIntervalPattern:[e?e.startIntervalPattern:null,[]],endIntervalPattern:[e?e.endIntervalPattern:null,[]]})},r.prototype.validatorTriggers=function(){return["fetchMode","useMetadataIntervalPatterns"]},r.prototype.updateValidators=function(e){var t=this.getTelemetryFromDatabaseConfigForm.get("fetchMode").value,r=this.getTelemetryFromDatabaseConfigForm.get("useMetadataIntervalPatterns").value;t&&t===j.ALL?(this.getTelemetryFromDatabaseConfigForm.get("orderBy").setValidators([i.Validators.required]),this.getTelemetryFromDatabaseConfigForm.get("limit").setValidators([i.Validators.required,i.Validators.min(2),i.Validators.max(1e3)])):(this.getTelemetryFromDatabaseConfigForm.get("orderBy").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("limit").setValidators([])),r?(this.getTelemetryFromDatabaseConfigForm.get("startInterval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("startIntervalTimeUnit").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("endInterval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("endIntervalTimeUnit").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").setValidators([i.Validators.required]),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").setValidators([i.Validators.required])):(this.getTelemetryFromDatabaseConfigForm.get("startInterval").setValidators([i.Validators.required,i.Validators.min(1),i.Validators.max(2147483647)]),this.getTelemetryFromDatabaseConfigForm.get("startIntervalTimeUnit").setValidators([i.Validators.required]),this.getTelemetryFromDatabaseConfigForm.get("endInterval").setValidators([i.Validators.required,i.Validators.min(1),i.Validators.max(2147483647)]),this.getTelemetryFromDatabaseConfigForm.get("endIntervalTimeUnit").setValidators([i.Validators.required]),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").setValidators([])),this.getTelemetryFromDatabaseConfigForm.get("orderBy").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("limit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("startInterval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("startIntervalTimeUnit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("endInterval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("endIntervalTimeUnit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").updateValueAndValidity({emitEvent:e})},r.prototype.removeKey=function(e,t){var r=this.getTelemetryFromDatabaseConfigForm.get(t).value,n=r.indexOf(e);n>=0&&(r.splice(n,1),this.getTelemetryFromDatabaseConfigForm.get(t).setValue(r,{emitEvent:!0}))},r.prototype.addKey=function(e,t){var r=e.input,n=e.value;if((n||"").trim()){n=n.trim();var a=this.getTelemetryFromDatabaseConfigForm.get(t).value;a&&-1!==a.indexOf(n)||(a||(a=[]),a.push(n),this.getTelemetryFromDatabaseConfigForm.get(t).setValue(a,{emitEvent:!0}))}r&&(r.value="")},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder}]},r=b([t.Component({selector:"tb-enrichment-node-get-telemetry-from-database",template:'
\n \n \n \n \n \n {{key}}\n close\n \n \n \n \n \n tb.rulenode.fetch-mode\n \n \n {{ mode }}\n \n \n tb.rulenode.fetch-mode-hint\n \n
\n \n tb.rulenode.order-by\n \n \n {{ order }}\n \n \n tb.rulenode.order-by-hint\n \n \n tb.rulenode.limit\n \n tb.rulenode.limit-hint\n \n
\n \n {{ \'tb.rulenode.use-metadata-interval-patterns\' | translate }}\n \n
tb.rulenode.use-metadata-interval-patterns-hint
\n
\n
\n \n tb.rulenode.start-interval\n \n \n {{ \'tb.rulenode.start-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.start-interval-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n \n tb.rulenode.end-interval\n \n \n {{ \'tb.rulenode.end-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.end-interval-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n \n \n tb.rulenode.start-interval-pattern\n \n \n {{ \'tb.rulenode.start-interval-pattern-required\' | translate }}\n \n \n \n \n tb.rulenode.end-interval-pattern\n \n \n {{ \'tb.rulenode.end-interval-pattern-required\' | translate }}\n \n \n \n \n
\n',styles:[":host label.tb-title{margin-bottom:-10px}"]}),h("design:paramtypes",[o.Store,i.FormBuilder])],r)}(a.RuleNodeConfigurationComponent),Ve=function(e){function r(t,r){var n=e.call(this,t)||this;return n.store=t,n.fb=r,n}return y(r,e),r.prototype.configForm=function(){return this.relatedAttributesConfigForm},r.prototype.onConfigurationSet=function(e){this.relatedAttributesConfigForm=this.fb.group({relationsQuery:[e?e.relationsQuery:null,[i.Validators.required]],telemetry:[!!e&&e.telemetry,[]],attrMapping:[e?e.attrMapping:null,[i.Validators.required]]})},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder}]},r=b([t.Component({selector:"tb-enrichment-node-related-attributes-config",template:'
\n \n \n \n \n \n {{ \'tb.rulenode.latest-telemetry\' | translate }}\n \n \n \n
\n'}),h("design:paramtypes",[o.Store,i.FormBuilder])],r)}(a.RuleNodeConfigurationComponent),Ee=function(e){function r(t,r){var n=e.call(this,t)||this;return n.store=t,n.fb=r,n}return y(r,e),r.prototype.configForm=function(){return this.tenantAttributesConfigForm},r.prototype.onConfigurationSet=function(e){this.tenantAttributesConfigForm=this.fb.group({telemetry:[!!e&&e.telemetry,[]],attrMapping:[e?e.attrMapping:null,[i.Validators.required]]})},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder}]},r=b([t.Component({selector:"tb-enrichment-node-tenant-attributes-config",template:'
\n \n \n {{ \'tb.rulenode.latest-telemetry\' | translate }}\n \n \n \n
\n'}),h("design:paramtypes",[o.Store,i.FormBuilder])],r)}(a.RuleNodeConfigurationComponent),Ae=function(){function e(){}return e=b([t.NgModule({declarations:[xe,qe,Se,Ie,ke,Ne,Ve,Ee],imports:[r.CommonModule,a.SharedModule,ne],exports:[xe,qe,Se,Ie,ke,Ne,Ve,Ee]})],e)}(),Le=function(e){function r(t,r){var n=e.call(this,t)||this;return n.store=t,n.fb=r,n.originatorSource=v,n.originatorSources=Object.keys(v),n.originatorSourceTranslationMap=P,n}return y(r,e),r.prototype.configForm=function(){return this.changeOriginatorConfigForm},r.prototype.onConfigurationSet=function(e){this.changeOriginatorConfigForm=this.fb.group({originatorSource:[e?e.originatorSource:null,[i.Validators.required]],relationsQuery:[e?e.relationsQuery:null,[]]})},r.prototype.validatorTriggers=function(){return["originatorSource"]},r.prototype.updateValidators=function(e){var t=this.changeOriginatorConfigForm.get("originatorSource").value;t&&t===v.RELATED?this.changeOriginatorConfigForm.get("relationsQuery").setValidators([i.Validators.required]):this.changeOriginatorConfigForm.get("relationsQuery").setValidators([]),this.changeOriginatorConfigForm.get("relationsQuery").updateValueAndValidity({emitEvent:e})},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder}]},r=b([t.Component({selector:"tb-transformation-node-change-originator-config",template:'
\n \n tb.rulenode.originator-source\n \n \n {{ originatorSourceTranslationMap.get(source) | translate }}\n \n \n \n
\n \n \n \n
\n
\n'}),h("design:paramtypes",[o.Store,i.FormBuilder])],r)}(a.RuleNodeConfigurationComponent),Me=function(e){function r(t,r,n,a){var o=e.call(this,t)||this;return o.store=t,o.fb=r,o.nodeScriptTestService=n,o.translate=a,o}return y(r,e),r.prototype.configForm=function(){return this.scriptConfigForm},r.prototype.onConfigurationSet=function(e){this.scriptConfigForm=this.fb.group({jsScript:[e?e.jsScript:null,[i.Validators.required]]})},r.prototype.testScript=function(){var e=this,t=this.scriptConfigForm.get("jsScript").value;this.nodeScriptTestService.testNodeScript(t,"update",this.translate.instant("tb.rulenode.transformer"),"Transform",["msg","metadata","msgType"],this.ruleNodeId).subscribe((function(t){t&&e.scriptConfigForm.get("jsScript").setValue(t)}))},r.prototype.onValidate=function(){this.jsFuncComponent.validateOnSubmit()},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder},{type:l.NodeScriptTestService},{type:n.TranslateService}]},b([t.ViewChild("jsFuncComponent",{static:!0}),h("design:type",a.JsFuncComponent)],r.prototype,"jsFuncComponent",void 0),r=b([t.Component({selector:"tb-transformation-node-script-config",template:'
\n \n \n \n
\n \n
\n
\n'}),h("design:paramtypes",[o.Store,i.FormBuilder,l.NodeScriptTestService,n.TranslateService])],r)}(a.RuleNodeConfigurationComponent),Pe=function(e){function r(t,r){var n=e.call(this,t)||this;return n.store=t,n.fb=r,n}return y(r,e),r.prototype.configForm=function(){return this.toEmailConfigForm},r.prototype.onConfigurationSet=function(e){this.toEmailConfigForm=this.fb.group({fromTemplate:[e?e.fromTemplate:null,[i.Validators.required]],toTemplate:[e?e.toTemplate:null,[i.Validators.required]],ccTemplate:[e?e.ccTemplate:null,[]],bccTemplate:[e?e.bccTemplate:null,[]],subjectTemplate:[e?e.subjectTemplate:null,[i.Validators.required]],bodyTemplate:[e?e.bodyTemplate:null,[i.Validators.required]]})},r.ctorParameters=function(){return[{type:o.Store},{type:i.FormBuilder}]},r=b([t.Component({selector:"tb-transformation-node-to-email-config",template:'
\n \n tb.rulenode.from-template\n \n \n {{ \'tb.rulenode.from-template-required\' | translate }}\n \n \n \n \n tb.rulenode.to-template\n \n \n {{ \'tb.rulenode.to-template-required\' | translate }}\n \n \n \n \n tb.rulenode.cc-template\n \n \n \n \n tb.rulenode.bcc-template\n \n \n \n \n tb.rulenode.subject-template\n \n \n {{ \'tb.rulenode.subject-template-required\' | translate }}\n \n \n \n \n tb.rulenode.body-template\n \n \n {{ \'tb.rulenode.body-template-required\' | translate }}\n \n \n \n
\n'}),h("design:paramtypes",[o.Store,i.FormBuilder])],r)}(a.RuleNodeConfigurationComponent),Re=function(){function e(){}return e=b([t.NgModule({declarations:[Le,Me,Pe],imports:[r.CommonModule,a.SharedModule,ne],exports:[Le,Me,Pe]})],e)}(),we=function(){function e(e){!function(e){e.setTranslation("en_US",{tb:{rulenode:{"create-entity-if-not-exists":"Create new entity if not exists","create-entity-if-not-exists-hint":"Create a new entity set above if it does not exist.","entity-name-pattern":"Name pattern","entity-name-pattern-required":"Name pattern is required","entity-name-pattern-hint":"Name pattern, use ${metaKeyName} to substitute variables from metadata","entity-type-pattern":"Type pattern","entity-type-pattern-required":"Type pattern is required","entity-type-pattern-hint":"Type pattern, use ${metaKeyName} to substitute variables from metadata","entity-cache-expiration":"Entities cache expiration time (sec)","entity-cache-expiration-hint":"Specifies maximum time interval allowed to store found entity records. 0 value means that records will never expire.","entity-cache-expiration-required":"Entities cache expiration time is required.","entity-cache-expiration-range":"Entities cache expiration time should be greater than or equal to 0.","customer-name-pattern":"Customer name pattern","customer-name-pattern-required":"Customer name pattern is required","create-customer-if-not-exists":"Create new customer if not exists","customer-cache-expiration":"Customers cache expiration time (sec)","customer-name-pattern-hint":"Customer name pattern, use ${metaKeyName} to substitute variables from metadata","customer-cache-expiration-hint":"Specifies maximum time interval allowed to store found customer records. 0 value means that records will never expire.","customer-cache-expiration-required":"Customers cache expiration time is required.","customer-cache-expiration-range":"Customers cache expiration time should be greater than or equal to 0.","start-interval":"Start Interval","end-interval":"End Interval","start-interval-time-unit":"Start Interval Time Unit","end-interval-time-unit":"End Interval Time Unit","fetch-mode":"Fetch mode","fetch-mode-hint":"If selected fetch mode 'ALL' you able to choose telemetry sampling order.","order-by":"Order by","order-by-hint":"Select to choose telemetry sampling order.",limit:"Limit","limit-hint":"Min limit value is 2, max - 1000. In case you want to fetch a single entry, select fetch mode 'FIRST' or 'LAST'.","time-unit-milliseconds":"Milliseconds","time-unit-seconds":"Seconds","time-unit-minutes":"Minutes","time-unit-hours":"Hours","time-unit-days":"Days","time-value-range":"Time value should be in a range from 1 to 2147483647.","start-interval-value-required":"Start interval value is required.","end-interval-value-required":"End interval value is required.",filter:"Filter",switch:"Switch","message-type":"Message type","message-type-required":"Message type is required.","message-types-filter":"Message types filter","no-message-types-found":"No message types found","no-message-type-matching":"'{{messageType}}' not found.","create-new-message-type":"Create a new one!","message-types-required":"Message types are required.","client-attributes":"Client attributes","shared-attributes":"Shared attributes","server-attributes":"Server attributes","latest-timeseries":"Latest timeseries","data-keys":"Message data","metadata-keys":"Message metadata","relations-query":"Relations query","device-relations-query":"Device relations query","max-relation-level":"Max relation level","relation-type-pattern":"Relation type pattern","relation-type-pattern-hint":"Relation type pattern, use ${metaKeyName} to substitute variables from metadata","relation-type-pattern-required":"Relation type pattern is required","relation-types-list":"Relation types to propagate","relation-types-list-hint":"If Propagate relation types are not selected, alarms will be propagated without filtering by relation type.","unlimited-level":"Unlimited level","latest-telemetry":"Latest telemetry","attr-mapping":"Attributes mapping","source-attribute":"Source attribute","source-attribute-required":"Source attribute is required.","source-telemetry":"Source telemetry","source-telemetry-required":"Source telemetry is required.","target-attribute":"Target attribute","target-attribute-required":"Target attribute is required.","attr-mapping-required":"At least one attribute mapping should be specified.","fields-mapping":"Fields mapping","fields-mapping-required":"At least one field mapping should be specified.","source-field":"Source field","source-field-required":"Source field is required.","originator-source":"Originator source","originator-customer":"Customer","originator-tenant":"Tenant","originator-related":"Related","originator-alarm-originator":"Alarm Originator","clone-message":"Clone message",transform:"Transform","default-ttl":"Default TTL in seconds","default-ttl-required":"Default TTL is required.","min-default-ttl-message":"Only 0 minimum TTL is allowed.","message-count":"Message count (0 - unlimited)","message-count-required":"Message count is required.","min-message-count-message":"Only 0 minimum message count is allowed.","period-seconds":"Period in seconds","period-seconds-required":"Period is required.","use-metadata-period-in-seconds-patterns":"Use metadata period in seconds pattern","use-metadata-period-in-seconds-patterns-hint":"If selected, rule node use period in seconds interval pattern from message metadata assuming that intervals are in the seconds.","period-in-seconds-pattern":"Period in seconds metadata pattern","period-in-seconds-pattern-required":"Period in seconds pattern is required","period-in-seconds-pattern-hint":"Period in seconds pattern, use ${metaKeyName} to substitute variables from metadata","min-period-seconds-message":"Only 1 second minimum period is allowed.",originator:"Originator","message-body":"Message body","message-metadata":"Message metadata",generate:"Generate","test-generator-function":"Test generator function",generator:"Generator","test-filter-function":"Test filter function","test-switch-function":"Test switch function","test-transformer-function":"Test transformer function",transformer:"Transformer","alarm-create-condition":"Alarm create condition","test-condition-function":"Test condition function","alarm-clear-condition":"Alarm clear condition","alarm-details-builder":"Alarm details builder","test-details-function":"Test details function","alarm-type":"Alarm type","alarm-type-required":"Alarm type is required.","alarm-severity":"Alarm severity","alarm-severity-required":"Alarm severity is required","alarm-status-filter":"Alarm status filter","alarm-status-list-empty":"Alarm status list is empty","no-alarm-status-matching":"No alarm status matching were found.",propagate:"Propagate",condition:"Condition",details:"Details","to-string":"To string","test-to-string-function":"Test to string function","from-template":"From Template","from-template-required":"From Template is required","from-template-hint":"From address template, use ${metaKeyName} to substitute variables from metadata","to-template":"To Template","to-template-required":"To Template is required","mail-address-list-template-hint":"Comma separated address list, use ${metaKeyName} to substitute variables from metadata","cc-template":"Cc Template","bcc-template":"Bcc Template","subject-template":"Subject Template","subject-template-required":"Subject Template is required","subject-template-hint":"Mail subject template, use ${metaKeyName} to substitute variables from metadata","body-template":"Body Template","body-template-required":"Body Template is required","body-template-hint":"Mail body template, use ${metaKeyName} to substitute variables from metadata","request-id-metadata-attribute":"Request Id Metadata attribute name","timeout-sec":"Timeout in seconds","timeout-required":"Timeout is required","min-timeout-message":"Only 0 minimum timeout value is allowed.","endpoint-url-pattern":"Endpoint URL pattern","endpoint-url-pattern-required":"Endpoint URL pattern is required","endpoint-url-pattern-hint":"HTTP URL address pattern, use ${metaKeyName} to substitute variables from metadata","request-method":"Request method","use-simple-client-http-factory":"Use simple client HTTP factory","read-timeout":"Read timeout in millis","read-timeout-hint":"The value of 0 means an infinite timeout","max-parallel-requests-count":"Max number of parallel requests","max-parallel-requests-count-hint":"The value of 0 specifies no limit in parallel processing",headers:"Headers","headers-hint":"Use ${metaKeyName} in header/value fields to substitute variables from metadata",header:"Header","header-required":"Header is required",value:"Value","value-required":"Value is required","topic-pattern":"Topic pattern","topic-pattern-required":"Topic pattern is required","mqtt-topic-pattern-hint":"MQTT topic pattern, use ${metaKeyName} to substitute variables from metadata","bootstrap-servers":"Bootstrap servers","bootstrap-servers-required":"Bootstrap servers value is required","other-properties":"Other properties",key:"Key","key-required":"Key is required",retries:"Automatically retry times if fails","min-retries-message":"Only 0 minimum retries is allowed.","batch-size-bytes":"Produces batch size in bytes","min-batch-size-bytes-message":"Only 0 minimum batch size is allowed.","linger-ms":"Time to buffer locally (ms)","min-linger-ms-message":"Only 0 ms minimum value is allowed.","buffer-memory-bytes":"Client buffer max size in bytes","min-buffer-memory-message":"Only 0 minimum buffer size is allowed.",acks:"Number of acknowledgments","key-serializer":"Key serializer","key-serializer-required":"Key serializer is required","value-serializer":"Value serializer","value-serializer-required":"Value serializer is required","topic-arn-pattern":"Topic ARN pattern","topic-arn-pattern-required":"Topic ARN pattern is required","topic-arn-pattern-hint":"Topic ARN pattern, use ${metaKeyName} to substitute variables from metadata","aws-access-key-id":"AWS Access Key ID","aws-access-key-id-required":"AWS Access Key ID is required","aws-secret-access-key":"AWS Secret Access Key","aws-secret-access-key-required":"AWS Secret Access Key is required","aws-region":"AWS Region","aws-region-required":"AWS Region is required","exchange-name-pattern":"Exchange name pattern","routing-key-pattern":"Routing key pattern","message-properties":"Message properties",host:"Host","host-required":"Host is required",port:"Port","port-required":"Port is required","port-range":"Port should be in a range from 1 to 65535.","virtual-host":"Virtual host",username:"Username",password:"Password","automatic-recovery":"Automatic recovery","connection-timeout-ms":"Connection timeout (ms)","min-connection-timeout-ms-message":"Only 0 ms minimum value is allowed.","handshake-timeout-ms":"Handshake timeout (ms)","min-handshake-timeout-ms-message":"Only 0 ms minimum value is allowed.","client-properties":"Client properties","queue-url-pattern":"Queue URL pattern","queue-url-pattern-required":"Queue URL pattern is required","queue-url-pattern-hint":"Queue URL pattern, use ${metaKeyName} to substitute variables from metadata","delay-seconds":"Delay (seconds)","min-delay-seconds-message":"Only 0 seconds minimum value is allowed.","max-delay-seconds-message":"Only 900 seconds maximum value is allowed.",name:"Name","name-required":"Name is required","queue-type":"Queue type","sqs-queue-standard":"Standard","sqs-queue-fifo":"FIFO","gcp-project-id":"GCP project ID","gcp-project-id-required":"GCP project ID is required","gcp-service-account-key":"GCP service account key file","gcp-service-account-key-required":"GCP service account key file is required","pubsub-topic-name":"Topic name","pubsub-topic-name-required":"Topic name is required","message-attributes":"Message attributes","message-attributes-hint":"Use ${metaKeyName} in name/value fields to substitute variables from metadata","connect-timeout":"Connection timeout (sec)","connect-timeout-required":"Connection timeout is required.","connect-timeout-range":"Connection timeout should be in a range from 1 to 200.","client-id":"Client ID","clean-session":"Clean session","enable-ssl":"Enable SSL",credentials:"Credentials","credentials-type":"Credentials type","credentials-type-required":"Credentials type is required.","credentials-anonymous":"Anonymous","credentials-basic":"Basic","credentials-pem":"PEM","username-required":"Username is required.","password-required":"Password is required.","ca-cert":"CA certificate file *","private-key":"Private key file *",cert:"Certificate file *","no-file":"No file selected.","drop-file":"Drop a file or click to select a file to upload.","private-key-password":"Private key password","use-system-smtp-settings":"Use system SMTP settings","use-metadata-interval-patterns":"Use metadata interval patterns","use-metadata-interval-patterns-hint":"If selected, rule node use start and end interval patterns from message metadata assuming that intervals are in the milliseconds.","use-message-alarm-data":"Use message alarm data","check-all-keys":"Check that all selected keys are present","check-all-keys-hint":"If selected, checks that all specified keys are present in the message data and metadata.","check-relation-to-specific-entity":"Check relation to specific entity","check-relation-hint":"Checks existence of relation to specific entity or to any entity based on direction and relation type.","delete-relation-to-specific-entity":"Delete relation to specific entity","delete-relation-hint":"Deletes relation from the originator of the incoming message to the specified entity or list of entities based on direction and type.","remove-current-relations":"Remove current relations","remove-current-relations-hint":"Removes current relations from the originator of the incoming message based on direction and type.","change-originator-to-related-entity":"Change originator to related entity","change-originator-to-related-entity-hint":"Used to process submitted message as a message from another entity.","start-interval-pattern":"Start interval pattern","end-interval-pattern":"End interval pattern","start-interval-pattern-required":"Start interval pattern is required","end-interval-pattern-required":"End interval pattern is required","start-interval-pattern-hint":"Start interval pattern, use ${metaKeyName} to substitute variables from metadata","end-interval-pattern-hint":"End interval pattern, use ${metaKeyName} to substitute variables from metadata","smtp-protocol":"Protocol","smtp-host":"SMTP host","smtp-host-required":"SMTP host is required.","smtp-port":"SMTP port","smtp-port-required":"You must supply a smtp port.","smtp-port-range":"SMTP port should be in a range from 1 to 65535.","timeout-msec":"Timeout ms","min-timeout-msec-message":"Only 0 ms minimum value is allowed.","enter-username":"Enter username","enter-password":"Enter password","enable-tls":"Enable TLS","tls-version":"TLS version","min-period-0-seconds-message":"Only 0 second minimum period is allowed.","max-pending-messages":"Maximum pending messages","max-pending-messages-required":"Maximum pending messages is required.","max-pending-messages-range":"Maximum pending messages should be in a range from 1 to 100000.","originator-types-filter":"Originator types filter","interval-seconds":"Interval in seconds","interval-seconds-required":"Interval is required.","min-interval-seconds-message":"Only 1 second minimum interval is allowed.","output-timeseries-key-prefix":"Output timeseries key prefix","output-timeseries-key-prefix-required":"Output timeseries key prefix required.","separator-hint":'You should press "enter" to complete field input.',"entity-details":"Select entity details:","entity-details-title":"Title","entity-details-country":"Country","entity-details-state":"State","entity-details-zip":"Zip","entity-details-address":"Address","entity-details-address2":"Address2","entity-details-additional_info":"Additional Info","entity-details-phone":"Phone","entity-details-email":"Email","add-to-metadata":"Add selected details to message metadata","add-to-metadata-hint":"If selected, adds the selected details keys to the message metadata instead of message data.","entity-details-list-empty":"No entity details selected.","no-entity-details-matching":"No entity details matching were found.","custom-table-name":"Custom table name","custom-table-name-required":"Table Name is required","custom-table-hint":"You should enter the table name without prefix 'cs_tb_'.","message-field":"Message field","message-field-required":"Message field is required.","table-col":"Table column","table-col-required":"Table column is required.","latitude-key-name":"Latitude key name","longitude-key-name":"Longitude key name","latitude-key-name-required":"Latitude key name is required.","longitude-key-name-required":"Longitude key name is required.","fetch-perimeter-info-from-message-metadata":"Fetch perimeter information from message metadata","perimeter-circle":"Circle","perimeter-polygon":"Polygon","perimeter-type":"Perimeter type","circle-center-latitude":"Center latitude","circle-center-latitude-required":"Center latitude is required.","circle-center-longitude":"Center longitude","circle-center-longitude-required":"Center longitude is required.","range-unit-meter":"Meter","range-unit-kilometer":"Kilometer","range-unit-foot":"Foot","range-unit-mile":"Mile","range-unit-nautical-mile":"Nautical mile","range-units":"Range units",range:"Range","range-required":"Range is required.","polygon-definition":"Polygon definition","polygon-definition-required":"Polygon definition is required.","polygon-definition-hint":"Please, use the following format for manual definition of polygon: [[lat1,lon1],[lat2,lon2], ... ,[latN,lonN]].","min-inside-duration":"Minimal inside duration","min-inside-duration-value-required":"Minimal inside duration is required","min-inside-duration-time-unit":"Minimal inside duration time unit","min-outside-duration":"Minimal outside duration","min-outside-duration-value-required":"Minimal outside duration is required","min-outside-duration-time-unit":"Minimal outside duration time unit","tell-failure-if-absent":"Tell Failure","tell-failure-if-absent-hint":'If at least one selected key doesn\'t exist the outbound message will report "Failure".',"get-latest-value-with-ts":"Fetch Latest telemetry with Timestamp","get-latest-value-with-ts-hint":'If selected, latest telemetry values will be added to the outbound message metadata with timestamp, e.g: "temp": "{\\"ts\\":1574329385897,\\"value\\":42}"',"use-redis-queue":"Use redis queue for message persistence","trim-redis-queue":"Trim redis queue","redis-queue-max-size":"Redis queue max size"},"key-val":{key:"Key",value:"Value","remove-entry":"Remove entry","add-entry":"Add entry"}}},!0)}(e)}return e.ctorParameters=function(){return[{type:n.TranslateService}]},e=b([t.NgModule({declarations:[F],imports:[r.CommonModule,a.SharedModule],exports:[ce,Te,Ae,Re,F]}),h("design:paramtypes",[n.TranslateService])],e)}();e.RuleNodeCoreConfigModule=we,e.ɵa=F,e.ɵb=ce,e.ɵba=ne,e.ɵbb=X,e.ɵbc=ee,e.ɵbd=te,e.ɵbe=re,e.ɵbf=Te,e.ɵbg=fe,e.ɵbh=ge,e.ɵbi=ye,e.ɵbj=be,e.ɵbk=he,e.ɵbl=Ce,e.ɵbm=ve,e.ɵbn=Fe,e.ɵbo=Ae,e.ɵbp=xe,e.ɵbq=qe,e.ɵbr=Se,e.ɵbs=Ie,e.ɵbt=ke,e.ɵbu=Ne,e.ɵbv=Ve,e.ɵbw=Ee,e.ɵbx=Re,e.ɵby=Le,e.ɵbz=Me,e.ɵc=T,e.ɵca=Pe,e.ɵd=x,e.ɵe=q,e.ɵf=S,e.ɵg=I,e.ɵh=k,e.ɵi=N,e.ɵj=V,e.ɵk=E,e.ɵl=A,e.ɵm=L,e.ɵn=W,e.ɵo=J,e.ɵp=Y,e.ɵq=Z,e.ɵr=ae,e.ɵs=oe,e.ɵt=ie,e.ɵu=le,e.ɵv=se,e.ɵw=me,e.ɵx=ue,e.ɵy=de,e.ɵz=pe,Object.defineProperty(e,"__esModule",{value:!0})})); -//# sourceMappingURL=rulenode-core-config.umd.min.js.map \ No newline at end of file +//# sourceMappingURL=rulenode-core-config.umd.min.js.map diff --git a/ui-ngx/LICENSE b/ui-ngx/LICENSE new file mode 100644 index 0000000000..f49a4e16e6 --- /dev/null +++ b/ui-ngx/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. \ No newline at end of file diff --git a/ui-ngx/angular.json b/ui-ngx/angular.json index f88469f4f1..2ca77a91ec 100644 --- a/ui-ngx/angular.json +++ b/ui-ngx/angular.json @@ -37,7 +37,9 @@ "node_modules/tooltipster/dist/css/plugins/tooltipster/sideTip/themes/tooltipster-sideTip-shadow.min.css", "src/app/shared/components/json-form/react/json-form.scss", "node_modules/rc-select/assets/index.less", - "node_modules/jstree-bootstrap-theme/dist/themes/proton/style.min.css" + "node_modules/jstree-bootstrap-theme/dist/themes/proton/style.min.css", + "node_modules/leaflet/dist/leaflet.css", + "src/app/modules/home/components/widget/lib/maps/markers.scss" ], "stylePreprocessorOptions": { "includePaths": [ diff --git a/ui-ngx/package-lock.json b/ui-ngx/package-lock.json index 57f1a26264..1df4bab465 100644 --- a/ui-ngx/package-lock.json +++ b/ui-ngx/package-lock.json @@ -1833,6 +1833,12 @@ "resolved": "https://registry.npmjs.org/@types/flowjs/-/flowjs-2.13.1.tgz", "integrity": "sha512-cPuORQrWmJV7pmiSt1ApDOsQSooVka53Ugr3LB0MW/bsG/fDtOXSxsT5Aiej98VD3eCIZNyABfk3NBWU7CorsQ==" }, + "@types/geojson": { + "version": "7946.0.7", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.7.tgz", + "integrity": "sha512-wE2v81i4C4Ol09RtsWFAqg3BUitWbHSpSlIo+bNdsCJijO9sjme+zm+73ZMCa/qMC8UEERxzGbvmr1cffo2SiQ==", + "dev": true + }, "@types/glob": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", @@ -1882,6 +1888,30 @@ "@types/jquery": "*" } }, + "@types/leaflet": { + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.5.9.tgz", + "integrity": "sha512-vFj2Y764lC6PpmmoFTui3yEMAKf+Dy08eGIaFgM+efJoKNxDP/bsEr2UHloP6kkJqc+4VO9+KYea2ZhiZCnNrQ==", + "dev": true, + "requires": { + "@types/geojson": "*" + } + }, + "@types/leaflet-polylinedecorator": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@types/leaflet-polylinedecorator/-/leaflet-polylinedecorator-1.6.0.tgz", + "integrity": "sha512-Z2BXZDjKEqHclwrAmhYdF1RwyFfa/NFxsoF79sitzaj5D/4YWHp/zDRcUZar5cQFKRgK66AYEIF7nKVuMzUGdw==", + "dev": true, + "requires": { + "@types/leaflet": "*" + } + }, + "@types/lodash": { + "version": "4.14.149", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.149.tgz", + "integrity": "sha512-ijGqzZt/b7BfzcK9vTrS6MFljQRPn5BFWOx8oE0GYxribu6uV+aA9zZuXI1zc/etK9E8nrgdoF2+LgUw7+9tJQ==", + "dev": true + }, "@types/minimatch": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", @@ -1894,9 +1924,9 @@ "integrity": "sha512-13gmo3M2qVvjQrWNseqM3+cR6S2Ss3grbR2NZltgMq94wOwqJYQdgn8qzwDshzgXqMlSUtyPZjysImmktu22ew==" }, "@types/node": { - "version": "13.7.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-13.7.2.tgz", - "integrity": "sha512-uvilvAQbdJvnSBFcKJ2td4016urcGvsiR+N4dHGU87ml8O2Vl6l+ErOi9w0kXSPiwJ1AYlIW+0pDXDWWMOiWbw==", + "version": "13.7.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-13.7.6.tgz", + "integrity": "sha512-eyK7MWD0R1HqVTp+PtwRgFeIsemzuj4gBFSQxfPHY5iMjS7474e5wq+VFgTcdpyHeNxyKSaetYAjdMLJlKoWqA==", "dev": true }, "@types/prop-types": { @@ -8240,6 +8270,47 @@ "invert-kv": "^2.0.0" } }, + "leaflet": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.6.0.tgz", + "integrity": "sha512-CPkhyqWUKZKFJ6K8umN5/D2wrJ2+/8UIpXppY7QDnUZW5bZL5+SEI2J7GBpwh4LIupOKqbNSQXgqmrEJopHVNQ==" + }, + "leaflet-geometryutil": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/leaflet-geometryutil/-/leaflet-geometryutil-0.9.3.tgz", + "integrity": "sha512-Wi6YvfNx/Xu9q35AEfXpsUXmIFLen/MO+C2qimxHRnjyeyOxBhdcZa6kSiReaOX0cGK7yQInqrzz0dkIqZ8Dpg==", + "requires": { + "leaflet": ">=0.7.0" + } + }, + "leaflet-polylinedecorator": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/leaflet-polylinedecorator/-/leaflet-polylinedecorator-1.6.0.tgz", + "integrity": "sha1-nvef0bUwLWe3Lv6Vmo7NJVPycmY=", + "requires": { + "leaflet-rotatedmarker": "^0.2.0" + } + }, + "leaflet-providers": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/leaflet-providers/-/leaflet-providers-1.9.1.tgz", + "integrity": "sha512-YpJB9y4/nT5NGicU9vuqlttJaCer6paD3J3b8Wrw+IIQvK9dtcdzE9CsTkDg7Dg9FeGp5NEr3hu17xcHbYI/2w==" + }, + "leaflet-rotatedmarker": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/leaflet-rotatedmarker/-/leaflet-rotatedmarker-0.2.0.tgz", + "integrity": "sha1-RGf0n5jRv9VpWb2cZwUgPdJgEnc=" + }, + "leaflet.gridlayer.googlemutant": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/leaflet.gridlayer.googlemutant/-/leaflet.gridlayer.googlemutant-0.8.0.tgz", + "integrity": "sha512-Ain+jgDKRhlM6qNDDj2QFJa9vXUqV096N0PmpHO3DoNLS4I7EynTQCJXN+9qY4C51ZpV4Q4CI+apNv5XiP5aUA==" + }, + "leaflet.markercluster": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/leaflet.markercluster/-/leaflet.markercluster-1.4.1.tgz", + "integrity": "sha512-ZSEpE/EFApR0bJ1w/dUGwTSUvWlpalKqIzkaYdYB7jaftQA/Y2Jav+eT4CMtEYFj+ZK4mswP13Q2acnPBnhGOw==" + }, "less": { "version": "3.10.3", "resolved": "https://registry.npmjs.org/less/-/less-3.10.3.tgz", diff --git a/ui-ngx/package.json b/ui-ngx/package.json index d11f30e086..beeaed5dad 100644 --- a/ui-ngx/package.json +++ b/ui-ngx/package.json @@ -56,6 +56,12 @@ "json-schema-defaults": "^0.4.0", "jstree": "^3.3.9", "jstree-bootstrap-theme": "^1.0.1", + "leaflet": "^1.6.0", + "leaflet-geometryutil": "^0.9.3", + "leaflet-polylinedecorator": "^1.6.0", + "leaflet-providers": "^1.9.1", + "leaflet.gridlayer.googlemutant": "^0.8.0", + "leaflet.markercluster": "^1.4.1", "material-design-icons": "^3.0.1", "messageformat": "^2.3.0", "moment": "^2.24.0", @@ -99,7 +105,9 @@ "@types/jquery": "^3.3.32", "@types/js-beautify": "^1.8.1", "@types/jstree": "^3.3.39", - "@types/node": "^13.7.2", + "@types/leaflet": "^1.5.9", + "@types/leaflet-polylinedecorator": "^1.6.0", + "@types/lodash": "^4.14.149", "@types/raphael": "^2.1.30", "@types/react": "^16.9.20", "@types/react-dom": "^16.9.5", diff --git a/ui-ngx/src/app/core/schema-utils.ts b/ui-ngx/src/app/core/schema-utils.ts new file mode 100644 index 0000000000..eb84fba92f --- /dev/null +++ b/ui-ngx/src/app/core/schema-utils.ts @@ -0,0 +1,83 @@ +/// +/// Copyright © 2016-2020 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 { JsonSchema, JsonSettingsSchema } from '@app/shared/public-api'; + + +export function initSchema(): JsonSettingsSchema { + return { + schema: { + type: 'object', + properties: {}, + required: [] + }, + form: [], + groupInfoes: [] + }; +} + +export function addGroupInfo(schema: JsonSettingsSchema, title: string) { + schema.groupInfoes.push({ + formIndex: schema.groupInfoes?.length || 0, + GroupTitle: title + }); +} + +export function addToSchema(schema: JsonSettingsSchema, newSchema: JsonSettingsSchema) { + Object.assign(schema.schema.properties, newSchema.schema.properties); + schema.schema.required = schema.schema.required.concat(newSchema.schema.required); + schema.form.push(newSchema.form); +} + +export function mergeSchemes(schemes: JsonSettingsSchema[]): JsonSettingsSchema { + return schemes.reduce((finalSchema: JsonSettingsSchema, schema: JsonSettingsSchema) => { + return { + schema: { + properties: { + ...finalSchema.schema.properties, + ...schema.schema.properties + }, + required: [ + ...finalSchema.schema.required, + ...schema.schema.required + ] + }, + form: [ + ...finalSchema.form, + ...schema.form + ] + } as JsonSettingsSchema; + }, initSchema()); +} + +export function addCondition(schema: JsonSettingsSchema, condition: String): JsonSettingsSchema { + schema.form = schema.form.map(element => { + if (typeof element === 'string') { + return { + key: element, + condition + } + } + if (typeof element == 'object') { + if (element.condition) { + element.condition += ' && ' + condition + } + else element.condition = condition; + } + return element; + }); + return schema; +} \ No newline at end of file diff --git a/ui-ngx/src/app/core/utils.ts b/ui-ngx/src/app/core/utils.ts index 381aadfdb7..cddbed643b 100644 --- a/ui-ngx/src/app/core/utils.ts +++ b/ui-ngx/src/app/core/utils.ts @@ -15,8 +15,8 @@ /// import _ from 'lodash'; -import { Observable, Subject } from 'rxjs'; -import { finalize, share } from 'rxjs/operators'; +import { Observable, Subject, from, fromEvent, of } from 'rxjs'; +import { finalize, share, map } from 'rxjs/operators'; import base64js from 'base64-js'; export function onParentScrollOrWindowResize(el: Node): Observable { @@ -101,7 +101,7 @@ export function isNumber(value: any): boolean { } export function isNumeric(value: any): boolean { - return (value - parseFloat( value ) + 1) >= 0; + return (value - parseFloat(value) + 1) >= 0; } export function isString(value: any): boolean { @@ -221,6 +221,18 @@ function scrollParents(node: Node): Node[] { return scrollParentNodes; } +function hashCode(str) { + let hash = 0; + let i, char; + if (str.length == 0) return hash; + for (i = 0; i < str.length; i++) { + char = str.charCodeAt(i); + hash = ((hash << 5) - hash) + char; + hash = hash & hash; // Convert to 32bit integer + } + return hash; +} + function easeInOut( currentTime: number, startTime: number, @@ -411,3 +423,147 @@ export function snakeCase(name: string, separator: string): string { export function getDescendantProp(obj: any, path: string): any { return path.split('.').reduce((acc, part) => acc && acc[part], obj); } + +export function imageLoader(imageUrl: string): Observable { + const image = new Image(); + const imageLoad$ = fromEvent(image, 'load').pipe(map(event => image)); + image.src = imageUrl; + return imageLoad$; +} + +const imageAspectMap = {}; + +export function aspectCache(imageUrl: string): Observable { + if (imageUrl?.length) { + const hash = hashCode(imageUrl); + let aspect = imageAspectMap[hash]; + if (aspect) { + return of(aspect); + } + else return imageLoader(imageUrl).pipe(map(image => { + aspect = image.width / image.height; + imageAspectMap[hash] = aspect; + return aspect; + })) + } +} + + +export function parseArray(input: any[]): any[] { + const alliases: any = _(input).groupBy(el => el?.datasource?.aliasName).values().value(); + return alliases.map((alliasArray, dsIndex) => + alliasArray[0].data.map((el, i) => { + const obj = { + aliasName: alliasArray[0]?.datasource?.aliasName, + entityName: alliasArray[0]?.datasource?.entityName, + $datasource: alliasArray[0]?.datasource, + dsIndex, + time: el[0], + deviceType: null + }; + alliasArray.forEach(el => { + obj[el?.dataKey?.label] = el?.data[i][1]; + obj[el?.dataKey?.label + '|ts'] = el?.data[0][0]; + if (el?.dataKey?.label === 'type') { + obj.deviceType = el?.data[0][1]; + } + }); + return obj; + }) + ); +} + +export function parseData(input: any[]): any[] { + return _(input).groupBy(el => el?.datasource?.aliasName).values().value().map((alliasArray, i) => { + const obj = { + aliasName: alliasArray[0]?.datasource?.aliasName, + entityName: alliasArray[0]?.datasource?.entityName, + $datasource: alliasArray[0]?.datasource, + dsIndex: i, + deviceType: null + }; + alliasArray.forEach(el => { + obj[el?.dataKey?.label] = el?.data[0][1]; + obj[el?.dataKey?.label + '|ts'] = el?.data[0][0]; + if (el?.dataKey?.label === 'type') { + obj.deviceType = el?.data[0][1]; + } + }); + return obj; + }); +} + +export function safeExecute(func: Function, params = []) { + let res = null; + if (func && typeof (func) === 'function') { + try { + res = func(...params); + } + catch (err) { + console.log('error in external function:', err); + res = null; + } + } + return res; +} + +export function parseFunction(source: any, params: string[] = []): Function { + let res = null; + if (source?.length) { + try { + res = new Function(...params, source); + } + catch (err) { + console.error(err); + res = null; + } + } + return res; +} + +export function parseTemplate(template: string, data: object) { + let res = ''; + try { + let variables = ''; + const expressions = template + .match(/\{(.*?)\}/g) // find expressions + .map(exp => exp.replace(/{|}/g, '')) // remove brackets + .map(exp => exp.split(':')) + .map(arr => { + variables += `let ${arr[0]} = ''; `; + return arr; + }) + .filter(arr => !!arr[1]) // filter expressions without format + .reduce((res, current) => { + res[current[0]] = current[1]; + return res; + }, {}); + + for (const key in data) { + if (!key.includes('|')) + variables += `${key} = '${expressions[key] ? padValue(data[key], +expressions[key]) : data[key]}';`; + } + template = template.replace(/:\d+}/g, '}'); + res = safeExecute(parseFunction(variables + 'return' + '`' + template + '`')); + } + catch (ex) { + } + return res; +} + +export function padValue(val: any, dec: number): string { + let strVal; + let n; + + val = parseFloat(val); + n = (val < 0); + val = Math.abs(val); + + if (dec > 0) { + strVal = val.toFixed(dec).toString() + } else { + strVal = Math.round(val).toString(); + } + strVal = (n ? '-' : '') + strVal; + return strVal; +} \ No newline at end of file diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/canvas-digital-gauge.ts b/ui-ngx/src/app/modules/home/components/widget/lib/canvas-digital-gauge.ts index 5712f31e52..507d84fcc4 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/canvas-digital-gauge.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/canvas-digital-gauge.ts @@ -18,7 +18,7 @@ import * as CanvasGauges from 'canvas-gauges'; import { FontStyle, FontWeight } from '@home/components/widget/lib/settings.models'; import * as tinycolor_ from 'tinycolor2'; import { ColorFormats } from 'tinycolor2'; -import { isDefined, isString, isUndefined } from '@core/utils'; +import { isDefined, isString, isUndefined, padValue } from '@core/utils'; import GenericOptions = CanvasGauges.GenericOptions; import BaseGauge = CanvasGauges.BaseGauge; @@ -786,24 +786,6 @@ function drawDigitalMinMax(context: DigitalGaugeCanvasRenderingContext2D, option drawText(context, options, 'MinMax', options.maxValue+'', maxX, maxY); } -function padValue(val: any, options: CanvasDigitalGaugeOptions): string { - const dec = options.valueDec; - let strVal; - let n; - - val = parseFloat(val); - n = (val < 0); - val = Math.abs(val); - - if (dec > 0) { - strVal = val.toFixed(dec).toString() - } else { - strVal = Math.round(val).toString(); - } - strVal = (n ? '-' : '') + strVal; - return strVal; -} - function drawDigitalValue(context: DigitalGaugeCanvasRenderingContext2D, options: CanvasDigitalGaugeOptions, value: any) { if (options.hideValue) return; @@ -813,7 +795,7 @@ function drawDigitalValue(context: DigitalGaugeCanvasRenderingContext2D, options const textX = Math.round(baseX + width / 2); const textY = valueY; - let text = options.valueText || padValue(value, options); + let text = options.valueText || padValue(value, options.valueDec); text += options.symbol; context.save(); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts new file mode 100644 index 0000000000..9c15a378fd --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts @@ -0,0 +1,310 @@ +/// +/// Copyright © 2016-2020 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 L from 'leaflet'; + +import 'leaflet-providers'; +import 'leaflet.markercluster/dist/MarkerCluster.css' +import 'leaflet.markercluster/dist/MarkerCluster.Default.css' +import 'leaflet.markercluster/dist/leaflet.markercluster' + +import { MapSettings, MarkerSettings, FormattedData, UnitedMapSettings, PolygonSettings } from './map-models'; +import { Marker } from './markers'; +import { Observable, of, BehaviorSubject, Subject } from 'rxjs'; +import { filter } from 'rxjs/operators'; +import { Polyline } from './polyline'; +import { Polygon } from './polygon'; + +export default abstract class LeafletMap { + + markers: Map = new Map(); + dragMode = true; + poly: Polyline; + polygon: Polygon; + map: L.Map; + map$: BehaviorSubject = new BehaviorSubject(null); + ready$: Observable = this.map$.pipe(filter(map => !!map)); + options: UnitedMapSettings; + isMarketCluster: boolean; + bounds: L.LatLngBounds; + newMarker: L.Marker; + datasources: FormattedData[]; + + constructor(public $container: HTMLElement, options: UnitedMapSettings) { + this.options = options; + } + + public initSettings(options: MapSettings) { + const { initCallback, + disableScrollZooming, }: MapSettings = options; + if (disableScrollZooming) { + this.map.scrollWheelZoom.disable(); + } + if (initCallback) { + setTimeout(options.initCallback, 0); + } + } + + addMarkerControl() { + if (this.options.draggableMarker) { + let mousePositionOnMap: L.LatLng; + let addMarker: L.Control; + this.map.on('mouseup', (e: L.LeafletMouseEvent) => { + mousePositionOnMap = e.latlng + }) + const dragListener = (e: L.DragEndEvent) => { + if (e.type === 'dragend' && mousePositionOnMap) { + const newMarker = L.marker(mousePositionOnMap).addTo(this.map); + const datasourcesList = document.createElement('div'); + const customLatLng = this.convertToCustomFormat(mousePositionOnMap); + this.datasources.forEach(ds => { + const dsItem = document.createElement('p'); + dsItem.appendChild(document.createTextNode(ds.entityName)); + dsItem.setAttribute('style', 'font-size: 14px'); + dsItem.onclick = () => { + const updatedEnttity = { ...ds, ...customLatLng }; + this.saveMarkerLocation(updatedEnttity); + this.map.removeLayer(newMarker); + this.deleteMarker(ds.aliasName); + this.createMarker(ds.aliasName, updatedEnttity, this.datasources, this.options, false); + } + datasourcesList.append(dsItem); + }) + const popup = L.popup(); + popup.setContent(datasourcesList); + newMarker.bindPopup(popup).openPopup(); + + } + addMarker.setPosition('topright') + } + L.Control.AddMarker = L.Control.extend({ + onAdd(map) { + const img = L.DomUtil.create('img') as any; + img.src = `assets/add_location.svg`; + img.style.width = '32px'; + img.style.height = '32px'; + img.onclick = this.dragMarker; + img.draggable = true; + const draggableImg = new L.Draggable(img); + draggableImg.enable(); + draggableImg.on('dragend', dragListener) + return img; + }, + onRemove(map) { + }, + dragMarker: this.dragMarker + + } as any); + + L.control.addMarker = (opts) => { + return new L.Control.AddMarker(opts); + } + + addMarker = L.control.addMarker({ position: 'topright' }).addTo(this.map); + } + } + + public setMap(map: L.Map) { + this.map = map; + if (this.options.useDefaultCenterPosition) { + this.map.panTo(this.options.defaultCenterPosition); + this.bounds = map.getBounds(); + } + else this.bounds = new L.LatLngBounds(null, null); + if (this.options.draggableMarker) { + this.addMarkerControl(); + } + this.map$.next(this.map); + } + + public setDataSources(dataSources) { + this.datasources = dataSources; + } + + public saveMarkerLocation(e) { + + } + + createLatLng(lat: number, lng: number): L.LatLng { + return L.latLng(lat, lng); + } + + createBounds(): L.LatLngBounds { + return this.map.getBounds(); + } + + extendBounds(bounds: L.LatLngBounds, polyline: L.Polyline) { + if (polyline && polyline.getLatLngs() && polyline.getBounds()) { + bounds.extend(polyline.getBounds()); + } + } + + invalidateSize() { + this.map?.invalidateSize(true); + } + + onResize() { + + } + + getCenter() { + return this.map.getCenter(); + } + + convertPosition(expression: object): L.LatLng { + const lat = expression[this.options.latKeyName]; + const lng = expression[this.options.lngKeyName]; + if (isNaN(lat) || isNaN(lng)) + return null; + else + return L.latLng(lat, lng) as L.LatLng; + } + + convertToCustomFormat(position: L.LatLng): object { + return { + [this.options.latKeyName]: position.lat, + [this.options.lngKeyName]: position.lng + } + } + + // Markers + updateMarkers(markersData) { + markersData.forEach(data => { + if (this.convertPosition(data)) { + if (data.rotationAngle) { + this.options.icon = L.divIcon({ + html: `
` + }) + } + else { + this.options.icon = null; + } + if (this.markers.get(data.aliasName)) { + this.updateMarker(data.aliasName, data, markersData, this.options) + } + else { + this.createMarker(data.aliasName, data, markersData, this.options as MarkerSettings); + } + } + }); + } + + dragMarker = (e, data?) => { + if (e.type !== 'dragend') return; + this.saveMarkerLocation({ ...data, ...this.convertToCustomFormat(e.target._latlng) }); + } + + private createMarker(key, data: FormattedData, dataSources: FormattedData[], settings: MarkerSettings, setFocus = true) { + this.ready$.subscribe(() => { + const newMarker = new Marker(this.map, this.convertPosition(data), settings, data, dataSources, () => { }, this.dragMarker); + if (setFocus) + this.map.fitBounds(this.bounds.extend(newMarker.leafletMarker.getLatLng())); + this.markers.set(key, newMarker); + }); + } + + private updateMarker(key, data, dataSources, settings: MarkerSettings) { + const marker: Marker = this.markers.get(key); + const location = this.convertPosition(data) + if (!location.equals(marker.location)) { + marker.updateMarkerPosition(location); + } + if (settings.showTooltip) { + marker.updateMarkerTooltip(data); + } + marker.setDataSources(data, dataSources); + marker.updateMarkerIcon(settings); + } + + deleteMarker(key) { + let marker = this.markers.get(key)?.leafletMarker; + if (marker) { + this.map.removeLayer(marker); + this.markers.delete(key); + marker = null; + } + } + + // Polyline + + updatePolylines(polyData: Array>) { + polyData.forEach(data => { + if (data.length) { + const dataSource = polyData.map(arr => arr[0]); + if (this.poly) { + this.updatePolyline(data, dataSource, this.options); + } + else { + this.createPolyline(data, dataSource, this.options); + } + } + }) + } + + createPolyline(data: any[], dataSources, settings) { + if (data.length) + this.ready$.subscribe(() => { + this.poly = new Polyline(this.map, + data.map(el => this.convertPosition(el)).filter(el => !!el), data, dataSources, settings); + const bounds = this.bounds.extend(this.poly.leafletPoly.getBounds()); + if (bounds.isValid()) { + this.map.fitBounds(bounds); + this.bounds = bounds; + } + }); + } + + updatePolyline(data, dataSources, settings) { + this.ready$.subscribe(() => { + this.poly.updatePolyline(settings, data, dataSources); + }); + } + + // Polygon + + updatePolygons(polyData: any[]) { + polyData.forEach((data: any) => { + if (data.data.length && data.dataKey.name === this.options.polygonKeyName) { + if (typeof (data?.data[0][1]) === 'string') { + data.data = JSON.parse(data.data[0][1]); + } + if (this.polygon) { + this.updatePolygon(data.data, polyData, this.options); + } + else { + this.createPolygon(data.data, polyData, this.options); + } + } + }); + } + + createPolygon(data: FormattedData, dataSources: FormattedData[], settings: PolygonSettings) { + this.ready$.subscribe(() => { + this.polygon = new Polygon(this.map, data, dataSources, settings); + const bounds = this.bounds.extend(this.polygon.leafletPoly.getBounds()); + if (bounds.isValid()) { + this.map.fitBounds(bounds); + this.bounds = bounds; + } + }); + } + + updatePolygon(data, dataSources, settings) { + this.ready$.subscribe(() => { + // this.polygon.updatePolygon(settings, data, dataSources); + }); + } +} \ No newline at end of file diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts new file mode 100644 index 0000000000..92b6c094d9 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts @@ -0,0 +1,133 @@ +/// +/// Copyright © 2016-2020 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 { LatLngTuple } from 'leaflet'; + +export type GenericFunction = (data: FormattedData, dsData: FormattedData[], dsIndex: number) => string; +export type MarkerImageFunction = (data: FormattedData, dsData: FormattedData[], dsIndex: number) => string; + +export type MapSettings = { + polygonKeyName: any; + draggableMarker: boolean; + initCallback?: () => any; + defaultZoomLevel?: number; + dontFitMapBounds?: boolean; + disableScrollZooming?: boolean; + minZoomLevel?: number; + latKeyName?: string; + lngKeyName?: string; + xPosKeyName?: string; + yPosKeyName?: string; + mapProvider: MapProviders; + mapUrl?: string; + mapImageUrl?: string; + provider?: MapProviders; + credentials?: any; // declare credentials format + defaultCenterPosition?: LatLngTuple; + markerClusteringSetting?; + useDefaultCenterPosition?: boolean; + gmDefaultMapType?: string; + useLabelFunction: string; + icon?: any; +} + +export enum MapProviders { + google = 'google-map', + openstreet = 'openstreet-map', + here = 'here', + image = 'image-map', + tencent = 'tencent-map' +} + +export type MarkerSettings = { + tooltipPattern?: any; + icon?: any; + showLabel?: boolean; + label: string; + labelColor: string; + labelText: string; + useLabelFunction: boolean; + draggableMarker: boolean; + showTooltip?: boolean; + color?: string; + autocloseTooltip: boolean; + displayTooltipAction: string; + currentImage?: string; + useMarkerImageFunction?: boolean; + markerImages?: string[]; + useMarkerImage: boolean; + markerImageSize: number; + markerImage: { + length: number + } + + colorFunction: GenericFunction; + tooltipFunction: GenericFunction; + labelFunction: GenericFunction; + markerImageFunction?: MarkerImageFunction; +} + +export interface FormattedData { + aliasName: string; + entityName: string; + $datasource: string; + dsIndex: number; + deviceType: string +} + +export type PolygonSettings = { + showPolygon: boolean; + showTooltip: any; + polygonStrokeOpacity: number; + polygonOpacity: number; + polygonStrokeWeight: number; + polygonStrokeColor: string; + polygonColor: string; + autocloseTooltip: boolean; + displayTooltipAction: string; + + polygonColorFunction?: GenericFunction; +} + +export type PolylineSettings = { + usePolylineDecorator: any; + autocloseTooltip: boolean; + displayTooltipAction: string; + useColorFunction: any; + color: string; + useStrokeOpacityFunction: any; + strokeOpacity: number; + useStrokeWeightFunction: any; + strokeWeight: number; + decoratorOffset: string | number; + endDecoratorOffset: string | number; + decoratorRepeat: string | number; + decoratorSymbol: any; + decoratorSymbolSize: any; + useDecoratorCustomColor: any; + decoratorCustomColor: any; + + + colorFunction: GenericFunction; + strokeOpacityFunction: GenericFunction; + strokeWeightFunction: GenericFunction; +} + +export interface HistorySelectSettings { + buttonColor: string; +} + +export type UnitedMapSettings = MapSettings & PolygonSettings & MarkerSettings & PolygonSettings; \ No newline at end of file diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget.interface.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget.interface.ts new file mode 100644 index 0000000000..1547ea16c9 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget.interface.ts @@ -0,0 +1,31 @@ +/// +/// Copyright © 2016-2020 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 { JsonSettingsSchema } from '@app/shared/public-api'; + +export interface MapWidgetInterface { + resize(), + update(), + onInit(), + onDestroy(); +} + +export interface MapWidgetStaticInterface { + settingsSchema(mapProvider?, drawRoutes?): JsonSettingsSchema; + getProvidersSchema():JsonSettingsSchema + dataKeySettingsSchema(): object; + actionSources(): object; +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget2.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget2.ts new file mode 100644 index 0000000000..049a985353 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget2.ts @@ -0,0 +1,258 @@ +/// +/// Copyright © 2016-2020 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 { MapProviders, UnitedMapSettings } from './map-models'; +import LeafletMap from './leaflet-map'; +import { + openstreetMapSettingsSchema, + googleMapSettingsSchema, + imageMapSettingsSchema, + tencentMapSettingsSchema, + commonMapSettingsSchema, + routeMapSettingsSchema, + markerClusteringSettingsSchema, + markerClusteringSettingsSchemaLeaflet, + hereMapSettingsSchema, + mapProviderSchema +} from './schemes'; +import { MapWidgetStaticInterface, MapWidgetInterface } from './map-widget.interface'; +import { OpenStreetMap, TencentMap, GoogleMap, HEREMap, ImageMap } from './providers'; +import { parseFunction, parseArray, parseData } from '@app/core/utils'; +import { initSchema, addToSchema, mergeSchemes, addCondition, addGroupInfo } from '@app/core/schema-utils'; +import { AttributeScope, EntityId, JsonSettingsSchema } from '@app/shared/public-api'; +import { forkJoin } from 'rxjs'; +import { WidgetContext } from '@app/modules/home/models/widget-component.models'; +import { AttributeService } from '@app/core/public-api'; +import { getDefCenterPosition } from './maps-utils'; + +let providerSets; +let defaultSettings; + +export class MapWidgetController implements MapWidgetInterface { + + constructor(public mapProvider: MapProviders, private drawRoutes: boolean, public ctx: WidgetContext, $element: HTMLElement) { + if (this.map) { + this.map.map.remove(); + delete this.map; + } + + this.data = ctx.data; + if (!$element) { + $element = ctx.$container[0]; + } + this.settings = this.initSettings(ctx.settings); + + const MapClass = providerSets[this.provider]?.MapClass; + if (!MapClass) { + return; + } + this.map = new MapClass($element, this.settings); + this.map.saveMarkerLocation = this.setMarkerLocation; + } + + map: LeafletMap; + provider: MapProviders; + schema: JsonSettingsSchema; + data; + settings: UnitedMapSettings; + + public static dataKeySettingsSchema(): object { + return {}; + } + + public static getProvidersSchema() { + return mergeSchemes([mapProviderSchema, + ...Object.values(providerSets)?.map( + (setting: IProvider) => addCondition(setting?.schema, `model.provider === '${setting.name}'`))]); + } + + public static settingsSchema(mapProvider: MapProviders, drawRoutes: boolean): JsonSettingsSchema { + const schema = initSchema(); + addToSchema(schema, this.getProvidersSchema()); + addGroupInfo(schema, 'Map Provider Settings'); + addToSchema(schema, commonMapSettingsSchema); + addGroupInfo(schema, 'Common Map Settings'); + + if (drawRoutes) { + addToSchema(schema, routeMapSettingsSchema); + addGroupInfo(schema, 'Route Map Settings'); + } else if (mapProvider !== 'image-map') { + const clusteringSchema = mergeSchemes([markerClusteringSettingsSchemaLeaflet, markerClusteringSettingsSchema]) + addToSchema(schema, clusteringSchema); + addGroupInfo(schema, 'Markers Clustering Settings'); + } + return schema; + } + + public static actionSources(): object { + return { + markerClick: { + name: 'widget-action.marker-click', + multiple: false + }, + polygonClick: { + name: 'widget-action.polygon-click', + multiple: false + }, + tooltipAction: { + name: 'widget-action.tooltip-tag-action', + multiple: true + } + }; + } + + onInit() { + } + + setMarkerLocation = (e) => { + const attributeService = this.ctx.$injector.get(AttributeService); + forkJoin( + this.data.filter(data => !!e[data.dataKey.name]) + .map(data => { + const entityId: EntityId = { + entityType: data.datasource.entityType, + id: data.datasource.entityId + }; + return attributeService.saveEntityAttributes( + entityId, + AttributeScope.SHARED_SCOPE, + [{ + key: data.dataKey.name, + value: e[data.dataKey.name] + }] + ); + })).subscribe(res => { + console.log('MapWidgetController -> setMarkerLocation -> res', res) + }); + } + + initSettings(settings: UnitedMapSettings) { + const functionParams = ['data', 'dsData', 'dsIndex']; + this.provider = settings.provider || this.mapProvider; + const customOptions = { + provider: this.provider, + mapUrl: settings?.mapImageUrl, + labelFunction: parseFunction(settings.labelFunction, functionParams), + tooltipFunction: parseFunction(settings.tooltipFunction, functionParams), + colorFunction: parseFunction(settings.colorFunction, functionParams), + polygonColorFunction: parseFunction(settings.polygonColorFunction, functionParams), + markerImageFunction: parseFunction(settings.markerImageFunction, ['data', 'images', 'dsData', 'dsIndex']), + labelColor: this.ctx.widgetConfig.color, + tooltipPattern: settings.tooltipPattern || + '${entityName}

Latitude: ${' + + settings.latKeyName + ':7}
Longitude: ${' + settings.lngKeyName + ':7}', + defaultCenterPosition: getDefCenterPosition(settings?.defaultCenterPosition), + currentImage: (settings.useMarkerImage && settings.markerImage?.length) ? { + url: settings.markerImage, + size: settings.markerImageSize || 34 + } : null + } + return { ...defaultSettings, ...settings, ...customOptions, } + } + + update() { + if (this.drawRoutes) + this.map.updatePolylines(parseArray(this.data)); + if (this.settings.showPolygon) { + this.map.updatePolygons(this.data); + } + if (this.settings.draggableMarker) { + this.map.setDataSources(parseData(this.data)); + } + else + this.map.updateMarkers(parseData(this.data)); + } + + resize() { + this.map?.invalidateSize(); + this.map.onResize(); + } + + onDestroy() { + } +} + +export let TbMapWidgetV2: MapWidgetStaticInterface = MapWidgetController; + +interface IProvider { + MapClass: LeafletMap, + schema: JsonSettingsSchema, + name: string +} + +providerSets = { + 'openstreet-map': { + MapClass: OpenStreetMap, + schema: openstreetMapSettingsSchema, + name: 'openstreet-map', + }, + 'tencent-map': { + MapClass: TencentMap, + schema: tencentMapSettingsSchema, + name: 'tencent-map' + }, + 'google-map': { + MapClass: GoogleMap, + schema: googleMapSettingsSchema, + name: 'google-map' + }, + here: { + MapClass: HEREMap, + schema: hereMapSettingsSchema, + name: 'here' + }, + 'image-map': { + MapClass: ImageMap, + schema: imageMapSettingsSchema, + name: 'image-map' + } +} + +defaultSettings = { + xPosKeyName: 'xPos', + yPosKeyName: 'yPos', + markerOffsetX: 0.5, + markerOffsetY: 1, + latKeyName: 'latitude', + lngKeyName: 'longitude', + polygonKeyName: 'coordinates', + showLabel: false, + label: '${entityName}', + showTooltip: false, + useDefaultCenterPosition: false, + showTooltipAction: 'click', + autocloseTooltip: false, + showPolygon: true, + labelColor: '#000000', + color: '#FE7569', + polygonColor: '#0000ff', + polygonStrokeColor: '#fe0001', + polygonOpacity: 0.5, + polygonStrokeOpacity: 1, + polygonStrokeWeight: 1, + useLabelFunction: false, + markerImages: [], + strokeWeight: 2, + strokeOpacity: 1.0, + initCallback: () => { }, + defaultZoomLevel: 8, + dontFitMapBounds: false, + disableScrollZooming: false, + minZoomLevel: 16, + credentials: '', + markerClusteringSetting: null, + draggableMarker: false +} \ No newline at end of file diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/maps-utils.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/maps-utils.ts new file mode 100644 index 0000000000..7af0828891 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/maps-utils.ts @@ -0,0 +1,55 @@ +/// +/// Copyright © 2016-2020 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 L from 'leaflet'; +import _ from 'lodash'; +import { MarkerSettings, PolylineSettings, PolygonSettings } from './map-models'; + +export function createTooltip(target: L.Layer, settings: MarkerSettings | PolylineSettings | PolygonSettings): L.Popup { + const popup = L.popup(); + popup.setContent(''); + target.bindPopup(popup, { autoClose: settings.autocloseTooltip, closeOnClick: false }); + if (settings.displayTooltipAction === 'hover') { + target.off('click'); + target.on('mouseover', function () { + this.openPopup(); + }); + target.on('mouseout', function () { + this.closePopup(); + }); + } + return popup; +} + +export function getRatio(firsMoment: number, secondMoment: number, intermediateMoment: number): number { + return (intermediateMoment - firsMoment) / (secondMoment - firsMoment); +}; + +export function findAngle(startPoint, endPoint) { + let angle = -Math.atan2(endPoint.latitude - startPoint.latitude, endPoint.longitude - startPoint.longitude); + angle = angle * 180 / Math.PI; + return parseInt(angle.toFixed(2), 10); +} + + +export function getDefCenterPosition(position) { + if (typeof (position) === 'string') + return position.split(','); + if (typeof (position) === 'object') + return position; + return [0, 0]; +} + diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/markers.scss b/ui-ngx/src/app/modules/home/components/widget/lib/maps/markers.scss new file mode 100644 index 0000000000..a017edeb9f --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/markers.scss @@ -0,0 +1,31 @@ +/** + * Copyright © 2016-2020 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. + */ +.arrow { + height: 30px; + width: 30px; + background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC0AAAAtCAMAAAANxBKoAAACAVBMVEUAAAAAqv9AgP8ggP8udP8qgP8ndv8kbf8kgP8eeP8rcf8mc/8jdP8hev8me/8kdv8jcv8pcP8ic/8neP8leP8ofP8mef8pev8nef8oe/8nef8pef8qfv8qgf8qe/8mev8off8oev8oef8oe/8pev8qe/8oe/8off8pfP8oev8pev8qe/8qfP8pev8pe/8qfP8pe/8oev8pe/8qe/8qfP8qfP8qff8qff8qfP8qff8pe/8qff8qfP8qfP8pev8pev8JYf8KYP8UY/8UZf8WY/8WZv8YZP8bZP8fZv8fZ/8gZv8gZ/8hZP8iZ/8jaf8jav8kaP8kav8ka/8kbP8kbf8kb/8lbP8lbf8lbv8lb/8lcP8mb/8mcP8mcf8ncf8ncv8nc/8ndP8ndf8ocv4odP8odf8odv8od/8oeP8peP8pef8pev8qev8qe/8qfP8rbP8rfP8rff8tc/4vcP4xbv4zcf42dP49df4+gP4/fv5Rif5biP1ul/14mvx4nvyMrfuMrvuWsfuctvuguPuww/vD0fnH1vrI1frK2PrL2fnV3vnb4vnc5fnd5fnd5vne5fnj6vnl6/jm7Pno7fXo7fbo7ffo7fjp7fnp7vjq7vjs8fnt8Pjt8fjw8fXw8fbw8fjy8/jz9fn5+fj7+/f++/j/+/X/+/b/+/f/+/j//Pj//vhoUaHMAAAAQHRSTlMAAwQICwwNDg4REhQWFxscHTI1QkRGSktOU1RdYWFscXJzhYWKqre6wMHDw8PHx8rN09TW1uLi7e/x8vLz9fj5hfwW0QAAAnVJREFUSMeV1fdb00AYB/BzoQjurSjuvQcuFLcgWqTVtLVpL0GS2GuDuLeouPeAiLOuwOFf6WU0ucvq4/d52v6Qz/M+18u97wHgyfh5m5vUYlHt2rV8BojOqGUqonNhVgTegfxZE2JXoMAUFgXYsSoKy3YfnoIiUqxm8UwUnSoaT0WVUuPi6lCUz+ft/+pqNYwqsiwrlm8s45XBVpE7BQgFyeZLbB1ihVwmefjpDSjbi7HwziArCdlU/MArjDHfaestBh4dZs9/JBb/4kVbo5FEr/JaWRL4VPvZ39jMVV4q63qiCx7bIfDJtst/LYt/JnLldaNuACbS9JwiQj4Zu/3HlDr5nEyJivMcgPn0Nogwfaq1Z9igQ7pO9AuqNEJzQINTV5ZghjvywLFG6dYMVRptAF3uPvBc8xPsWH0Q44ccpEqjvaBoa0lI7/ts2kHdCsbDJ5jSSC2/SEU8856x+hDGd+JZujQquvp6ieT7Nyel0o/jCSgzTefq0y81I30f7PRr2i1fbWrd+98yXtMGfOt29wTyiebHpu83dZ+m3U969qSBeje5DHeod8Dx5PeYZ7/rPO8y0XLvk+1J8UcJyLzLScw5kTsgz8Xu2vXJV0uaOSfsGcznZZGcwdi1L5qV13HmDILV3tY1z3fbxa8Wv+Se74VEj/H3jmz0TvuVN4Z+x/ZORF8efU64s/CtUT0vCbk0d/DZTSgxPQ/WhswTSYTZrDNPllaaVQo1q/Y4k63mv+YgmFZxxk6gR/LsCngcO+6nR9lCrfcqqQ2/dxqD7rT1IXhxyB24O8BuCr9eq9axU7F7wYjoy3ty3TZVLaCC2rRxru/hPwVgtEdFK5vOAAAAAElFTkSuQmCC"); + background-size: cover; + background-repeat: no-repeat; + background-position: center center; +} + +.leaflet-div-icon, +.tb-marker-label, +.tb-marker-label:before { + border: none; + background: none; + box-shadow: none; +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/markers.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/markers.ts new file mode 100644 index 0000000000..ca5400d4f6 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/markers.ts @@ -0,0 +1,184 @@ +/// +/// Copyright © 2016-2020 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 L from 'leaflet'; +import { MarkerSettings, FormattedData } from './map-models'; +import { aspectCache, safeExecute, parseTemplate } from '@app/core/utils'; +import { createTooltip } from './maps-utils'; + +export class Marker { + + leafletMarker: L.Marker; + tooltipOffset: [number, number]; + tooltip: L.Popup; + location: L.LatLngExpression; + data: FormattedData; + dataSources: FormattedData[]; + + constructor(private map: L.Map, location: L.LatLngExpression, public settings: MarkerSettings, + data?, dataSources?, onClickListener?, onDragendListener?) { + this.setDataSources(data, dataSources); + this.leafletMarker = L.marker(location, { + draggable: settings.draggableMarker + }); + + this.createMarkerIcon((iconInfo) => { + this.leafletMarker.setIcon(iconInfo.icon); + this.tooltipOffset = [0, -iconInfo.size[1] + 10]; + this.updateMarkerLabel(settings); + this.leafletMarker.addTo(map); + }); + + if (settings.showTooltip) { + this.tooltip = createTooltip(this.leafletMarker, settings); + this.tooltip.setContent(parseTemplate(this.settings.tooltipPattern, data)); + } + + if (onClickListener) { + this.leafletMarker.on('click', onClickListener); + } + + if (onDragendListener) { + this.leafletMarker.on('dragend', (e) => onDragendListener(e, this.data)); + } + } + + setDataSources(data: FormattedData, dataSources: FormattedData[]) { + this.data = data; + this.dataSources = dataSources; + } + + updateMarkerTooltip(data: FormattedData) { + this.tooltip.setContent(parseTemplate(this.settings.tooltipPattern, data)); + } + + updateMarkerPosition(position: L.LatLngExpression) { + this.leafletMarker.setLatLng(position); + } + + updateMarkerLabel(settings: MarkerSettings) { + this.leafletMarker.unbindTooltip(); + + if (settings.showLabel) { + if (settings.useLabelFunction) { + settings.labelText = safeExecute(settings.labelFunction, [this.data, this.dataSources, this.data.dsIndex]) + } + else settings.labelText = parseTemplate(settings.label, this.data); + this.leafletMarker.bindTooltip(`
${settings.labelText}
`, + { className: 'tb-marker-label', permanent: true, direction: 'top', offset: this.tooltipOffset }); + } + } + + updateMarkerColor(color) { + this.createDefaultMarkerIcon(color, (iconInfo) => { + this.leafletMarker.setIcon(iconInfo.icon); + }); + } + + updateMarkerIcon(settings: MarkerSettings) { + this.createMarkerIcon((iconInfo) => { + this.leafletMarker.setIcon(iconInfo.icon); + this.tooltipOffset = [0, -iconInfo.size[1] + 10]; + this.updateMarkerLabel(settings); + }); + } + + createMarkerIcon(onMarkerIconReady) { + + if (this.settings.icon) { + onMarkerIconReady({ + size: [30, 30], + icon: this.settings.icon, + }); + return; + } + + const currentImage = this.settings.useMarkerImageFunction ? + safeExecute(this.settings.markerImageFunction, + [this.data, this.settings.markerImages, this.dataSources, this.data.dsIndex]) : this.settings.currentImage; + + + if (currentImage && currentImage.url) { + aspectCache(currentImage.url).subscribe( + (aspect) => { + if (aspect) { + let width; + let height; + if (aspect > 1) { + width = currentImage.size; + height = currentImage.size / aspect; + } else { + width = currentImage.size * aspect; + height = currentImage.size; + } + const icon = L.icon({ + iconUrl: currentImage.url, + iconSize: [width, height], + iconAnchor: [width / 2, height], + popupAnchor: [0, -height] + }); + const iconInfo = { + size: [width, height], + icon + }; + onMarkerIconReady(iconInfo); + } else { + this.createDefaultMarkerIcon(this.settings.color, onMarkerIconReady); + } + } + ); + } else { + this.createDefaultMarkerIcon(this.settings.color, onMarkerIconReady); + } + } + + createDefaultMarkerIcon(color, onMarkerIconReady) { + const pinColor = color.substr(1); + const icon = L.icon({ + iconUrl: 'https://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|' + pinColor, + iconSize: [21, 34], + iconAnchor: [10, 34], + popupAnchor: [0, -34], + shadowUrl: 'https://chart.apis.google.com/chart?chst=d_map_pin_shadow', + shadowSize: [40, 37], + shadowAnchor: [12, 35] + }); + const iconInfo = { + size: [21, 34], + icon + }; + onMarkerIconReady(iconInfo); + } + + + + removeMarker() { + /* this.map$.subscribe(map => + this.leafletMarker.addTo(map))*/ + } + + extendBoundsWithMarker(bounds) { + bounds.extend(this.leafletMarker.getLatLng()); + } + + getMarkerPosition() { + return this.leafletMarker.getLatLng(); + } + + setMarkerPosition(latLng) { + this.leafletMarker.setLatLng(latLng); + } +} \ No newline at end of file diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/polygon.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/polygon.ts new file mode 100644 index 0000000000..e38eaae1c6 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/polygon.ts @@ -0,0 +1,70 @@ +/// +/// Copyright © 2016-2020 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 L, { LatLngExpression } from 'leaflet'; +import { createTooltip } from './maps-utils'; +import { PolygonSettings } from './map-models'; + +export class Polygon { + + leafletPoly: L.Polygon; + tooltip; + + constructor(public map, coordinates, dataSources, settings: PolygonSettings, onClickListener?) { + this.leafletPoly = L.polygon(coordinates, { + fill: true, + fillColor: settings.polygonColor, + color: settings.polygonStrokeColor, + weight: settings.polygonStrokeWeight, + fillOpacity: settings.polygonOpacity, + opacity: settings.polygonStrokeOpacity + }).addTo(this.map); + + if (settings.showTooltip) { + this.tooltip = createTooltip(this.leafletPoly, settings); + } + if (onClickListener) { + this.leafletPoly.on('click', onClickListener); + } + } + + removePolygon() { + this.map.removeLayer(this.leafletPoly); + } + + updatePolygonColor(settings) { + console.log('Polygon -> updatePolygonColor -> settings', settings) + const style: L.PathOptions = { + + fill: true, + fillColor: settings.color, + color: settings.color, + weight: settings.polygonStrokeWeight, + fillOpacity: settings.polygonOpacity, + opacity: settings.polygonStrokeOpacity + }; + this.leafletPoly.setStyle(style); + } + + getPolygonLatLngs() { + return this.leafletPoly.getLatLngs(); + } + + setPolygonLatLngs(latLngs: LatLngExpression[]) { + this.leafletPoly.setLatLngs(latLngs); + this.leafletPoly.redraw(); + } +} \ No newline at end of file diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/polyline.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/polyline.ts new file mode 100644 index 0000000000..9feb0ff08e --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/polyline.ts @@ -0,0 +1,92 @@ +/// +/// Copyright © 2016-2020 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 L, { PolylineDecoratorOptions } from 'leaflet'; +import 'leaflet-polylinedecorator'; + +import { safeExecute } from '@app/core/utils'; +import { PolylineSettings } from './map-models'; + +export class Polyline { + + leafletPoly: L.Polyline; + polylineDecorator: L.PolylineDecorator; + dataSources; + data; + + constructor(private map: L.Map, locations, data, dataSources, settings: PolylineSettings) { + this.dataSources = dataSources; + this.data = data; + + this.leafletPoly = L.polyline(locations, + this.getPolyStyle(settings) + ).addTo(this.map); + if (settings.usePolylineDecorator) { + this.polylineDecorator = L.polylineDecorator(this.leafletPoly, this.getDecoratorSettings(settings)).addTo(this.map); + } + } + + getDecoratorSettings(settings: PolylineSettings): PolylineDecoratorOptions { + return { + patterns: [ + { + offset: settings.decoratorOffset, + endOffset: settings.endDecoratorOffset, + repeat: settings.decoratorRepeat, + symbol: L.Symbol[settings.decoratorSymbol]({ + pixelSize: settings.decoratorSymbolSize, + polygon: false, + pathOptions: { + color: settings.useDecoratorCustomColor ? settings.decoratorCustomColor : this.getPolyStyle(settings).color, + stroke: true + } + }) + } + ], + interactive: false, + } as PolylineDecoratorOptions + } + + updatePolyline(settings, data, dataSources) { + this.leafletPoly.setStyle(this.getPolyStyle(settings)); + // this.setPolylineLatLngs(data); + if(this.polylineDecorator) + this.polylineDecorator.setPaths(this.leafletPoly); + } + + getPolyStyle(settings: PolylineSettings): L.PolylineOptions { + return { + color: settings.useColorFunction ? + safeExecute(settings.colorFunction, [this.data, this.dataSources, this.data[0]?.dsIndex]) : settings.color, + opacity: settings.useStrokeOpacityFunction ? + safeExecute(settings.strokeOpacityFunction, [this.data, this.dataSources, this.data[0]?.dsIndex]) : settings.strokeOpacity, + weight: settings.useStrokeWeightFunction ? + safeExecute(settings.strokeWeightFunction, [this.data, this.dataSources, this.data[0]?.dsIndex]) : settings.strokeWeight, + } + } + + removePolyline() { + this.map.removeLayer(this.leafletPoly); + } + + getPolylineLatLngs() { + return this.leafletPoly.getLatLngs(); + } + + setPolylineLatLngs(latLngs) { + this.leafletPoly.setLatLngs(latLngs); + } +} \ No newline at end of file diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/google-map.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/google-map.ts new file mode 100644 index 0000000000..0b0d269ce1 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/google-map.ts @@ -0,0 +1,57 @@ +/// +/// Copyright © 2016-2020 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 L from 'leaflet'; +import LeafletMap from '../leaflet-map'; +import { MapSettings, UnitedMapSettings } from '../map-models'; +import 'leaflet.gridlayer.googlemutant'; + +let googleLoaded = false; + + +export class GoogleMap extends LeafletMap { + constructor($container, options: UnitedMapSettings) { + + super($container, options); + this.loadGoogle(() => { + const map = L.map($container).setView(options?.defaultCenterPosition, options?.defaultZoomLevel); + const roads = (L.gridLayer as any).googleMutant({ + type: options?.gmDefaultMapType || 'roadmap' + }).addTo(map); + super.setMap(map); + }, options.credentials.apiKey); + super.initSettings(options); + } + + private loadGoogle(callback, apiKey = 'AIzaSyDoEx2kaGz3PxwbI9T7ccTSg5xjdw8Nw8Q') { + if (googleLoaded) { + callback() + } + else { + googleLoaded = true; + const script = document.createElement('script'); + script.onload = () => { + callback(); + } + script.onerror = () => { + googleLoaded = false; + } + script.src = `https://maps.googleapis.com/maps/api/js?key=${apiKey}`; + document.getElementsByTagName('head')[0].appendChild(script); + } + } +} \ No newline at end of file diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/here-map.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/here-map.ts new file mode 100644 index 0000000000..60221b62a3 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/here-map.ts @@ -0,0 +1,35 @@ +/// +/// Copyright © 2016-2020 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 L from 'leaflet'; +import LeafletMap from '../leaflet-map'; +import { MapSettings, UnitedMapSettings } from '../map-models'; + +export class HEREMap extends LeafletMap { + constructor($container, options: UnitedMapSettings) { + const defaultCredentials = + { + app_id: 'AhM6TzD9ThyK78CT3ptx', + app_code: 'p6NPiITB3Vv0GMUFnkLOOg' + } + super($container, options); + const map = L.map($container).setView(options?.defaultCenterPosition, options?.defaultZoomLevel); + const tileLayer = (L.tileLayer as any).provider(options.mapProvider || 'HERE.normalDay', options.credentials || defaultCredentials); + tileLayer.addTo(map); + super.setMap(map); + super.initSettings(options); + } +} \ No newline at end of file diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/image-map.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/image-map.ts new file mode 100644 index 0000000000..d90bb42db3 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/image-map.ts @@ -0,0 +1,133 @@ +/// +/// Copyright © 2016-2020 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 L from 'leaflet'; +import LeafletMap from '../leaflet-map'; +import { MapSettings, UnitedMapSettings } from '../map-models'; +import { aspectCache } from '@app/core/utils'; + +const maxZoom = 4;// ? + +export class ImageMap extends LeafletMap { + + imageOverlay; + aspect = 0; + width = 0; + height = 0; + + constructor($container: HTMLElement, options: UnitedMapSettings) { + super($container, options); + aspectCache(options.mapUrl).subscribe(aspect => { + this.aspect = aspect; + this.onResize(); + super.setMap(this.map); + super.initSettings(options); + }); + } + + updateBounds(updateImage?, lastCenterPos?) { + const w = this.width; + const h = this.height; + let southWest = this.pointToLatLng(0, h); + let northEast = this.pointToLatLng(w, 0); + const bounds = new L.LatLngBounds(southWest, northEast); + + if (updateImage && this.imageOverlay) { + this.imageOverlay.remove(); + this.imageOverlay = null; + } + + if (this.imageOverlay) { + this.imageOverlay.setBounds(bounds); + } else { + this.imageOverlay = L.imageOverlay(this.options.mapUrl, bounds).addTo(this.map); + + } + const padding = 200 * maxZoom; + southWest = this.pointToLatLng(-padding, h + padding); + northEast = this.pointToLatLng(w + padding, -padding); + const maxBounds = new L.LatLngBounds(southWest, northEast); + this.map.setMaxBounds(maxBounds); + if (lastCenterPos) { + lastCenterPos.x *= w; + lastCenterPos.y *= h; + /* this.ctx.$scope.$injector.get('$mdUtil').nextTick(() => { + this.map.panTo(center, { animate: false }); + });*/ + } + } + + onResize(updateImage?) { + let width = this.$container.clientWidth; + if (width > 0 && this.aspect) { + let height = width / this.aspect; + const imageMapHeight = this.$container.clientHeight; + if (imageMapHeight > 0 && height > imageMapHeight) { + height = imageMapHeight; + width = height * this.aspect; + } + width *= maxZoom; + const prevWidth = this.width; + const prevHeight = this.height; + if (this.width !== width) { + this.width = width; + this.height = width / this.aspect; + if (!this.map) { + this.initMap(updateImage); + } else { + const lastCenterPos = this.latLngToPoint(this.map.getCenter()); + lastCenterPos.x /= prevWidth; + lastCenterPos.y /= prevHeight; + this.updateBounds(updateImage, lastCenterPos); + this.map.invalidateSize(true); + // this.updateMarkers(); + } + + } + } + } + + initMap(updateImage?) { + if (!this.map && this.aspect > 0) { + const center = this.pointToLatLng(this.width / 2, this.height / 2); + this.map = L.map(this.$container, { + minZoom: 1, + maxZoom, + scrollWheelZoom: !this.options.disableScrollZooming, + center, + zoom: 1, + crs: L.CRS.Simple, + attributionControl: false + }); + this.updateBounds(updateImage); + // this.updateMarkers(); + } + } + + convertPosition(expression): L.LatLng { + return this.pointToLatLng( + expression[this.options.xPosKeyName] * this.width, + expression[this.options.yPosKeyName] * this.height); + } + + pointToLatLng(x, y): L.LatLng { + return L.CRS.Simple.pointToLatLng({ x, y } as L.PointExpression, maxZoom - 1); + } + + latLngToPoint(latLng) { + return L.CRS.Simple.latLngToPoint(latLng, maxZoom - 1); + } +} \ No newline at end of file diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/index.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/index.ts new file mode 100644 index 0000000000..16d411c167 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/index.ts @@ -0,0 +1,21 @@ +/// +/// Copyright © 2016-2020 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. +/// + +export * from './tencent-map'; +export * from './google-map'; +export * from './here-map'; +export * from './image-map'; +export * from './openstreet-map'; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/openstreet-map.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/openstreet-map.ts new file mode 100644 index 0000000000..0412b0450d --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/openstreet-map.ts @@ -0,0 +1,30 @@ +/// +/// Copyright © 2016-2020 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 L from 'leaflet'; +import LeafletMap from '../leaflet-map'; +import { MapSettings, UnitedMapSettings } from '../map-models'; + +export class OpenStreetMap extends LeafletMap { + constructor($container, options: UnitedMapSettings) { + super($container, options); + const map = L.map($container).setView(options?.defaultCenterPosition, options?.defaultZoomLevel); + const tileLayer = (L.tileLayer as any).provider('OpenStreetMap.Mapnik'); + tileLayer.addTo(map); + super.setMap(map); + super.initSettings(options); + } +} \ No newline at end of file diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/tencent-map.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/tencent-map.ts new file mode 100644 index 0000000000..980846796c --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/tencent-map.ts @@ -0,0 +1,32 @@ +/// +/// Copyright © 2016-2020 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 L from 'leaflet'; +import LeafletMap from '../leaflet-map'; +import { MapSettings, UnitedMapSettings } from '../map-models'; + +export class TencentMap extends LeafletMap { + constructor($container, options: UnitedMapSettings) { + super($container, options); + const txUrl = 'http://rt{s}.map.gtimg.com/realtimerender?z={z}&x={x}&y={y}&type=vector&style=0'; + const map = L.map($container).setView(options?.defaultCenterPosition, options?.defaultZoomLevel); + const txLayer = L.tileLayer(txUrl, { subdomains: '0123', tms: true }).addTo(map); + txLayer.addTo(map); + super.setMap(map); + super.initSettings(options); + } +} \ No newline at end of file diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/schemes.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/schemes.ts new file mode 100644 index 0000000000..f2bcf35f15 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/schemes.ts @@ -0,0 +1,1250 @@ +/// +/// Copyright © 2016-2020 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. +/// + +export const googleMapSettingsSchema = +{ + schema: { + title: 'Google Map Configuration', + type: 'object', + properties: { + gmApiKey: { + title: 'Google Maps API Key', + type: 'string' + }, + gmDefaultMapType: { + title: 'Default map type', + type: 'string', + default: 'roadmap' + } + }, + required: [ + ] + }, + form: [ + 'gmApiKey', + { + key: 'gmDefaultMapType', + type: 'rc-select', + multiple: false, + items: [ + { + value: 'roadmap', + label: 'Roadmap' + }, + { + value: 'satellite', + label: 'Satellite' + }, + { + value: 'hybrid', + label: 'Hybrid' + }, + { + value: 'terrain', + label: 'Terrain' + } + ] + } + ] +}; + +export const tencentMapSettingsSchema = +{ + schema: { + title: 'Tencent Map Configuration', + type: 'object', + properties: { + tmApiKey: { + title: 'Tencent Maps API Key', + type: 'string' + }, + tmDefaultMapType: { + title: 'Default map type', + type: 'string', + default: 'roadmap' + } + }, + required: [ + ] + }, + form: [ + 'tmApiKey', + { + key: 'tmDefaultMapType', + type: 'rc-select', + multiple: false, + items: [ + { + value: 'roadmap', + label: 'Roadmap' + }, + { + value: 'satellite', + label: 'Satellite' + }, + { + value: 'hybrid', + label: 'Hybrid' + }, + ] + } + ] +}; + +export const hereMapSettingsSchema = +{ + schema: { + title: 'HERE Map Configuration', + type: 'object', + properties: { + mapProvider: { + title: 'Map layer', + type: 'string', + default: 'HERE.normalDay' + }, + credentials: { + type: 'object', + properties: { + app_id: { + title: 'HERE app id', + type: 'string' + }, + app_code: { + title: 'HERE app code', + type: 'string' + } + }, + required: ['app_id', 'app_code'] + } + }, + required: [] + }, + form: [ + { + key: 'mapProvider', + type: 'rc-select', + multiple: false, + items: [ + { + value: 'HERE.normalDay', + label: 'HERE.normalDay (Default)' + }, + { + value: 'HERE.normalNight', + label: 'HERE.normalNight' + }, + { + value: 'HERE.hybridDay', + label: 'HERE.hybridDay' + }, + { + value: 'HERE.terrainDay', + label: 'HERE.terrainDay' + } + ] + }, + 'credentials' + ] +}; + +export const openstreetMapSettingsSchema = +{ + schema: { + title: 'Openstreet Map Configuration', + type: 'object', + properties: { + mapProvider: { + title: 'Map provider', + type: 'string', + default: 'OpenStreetMap.Mapnik' + }, + useCustomProvider: { + title: 'Use custom provider', + type: 'boolean', + default: false + }, + customProviderTileUrl: { + title: 'Custom provider tile URL', + type: 'string', + default: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png' + } + }, + required: [] + }, + form: [ + { + key: 'mapProvider', + type: 'rc-select', + multiple: false, + items: [ + { + value: 'OpenStreetMap.Mapnik', + label: 'OpenStreetMap.Mapnik (Default)' + }, + { + value: 'OpenStreetMap.BlackAndWhite', + label: 'OpenStreetMap.BlackAndWhite' + }, + { + value: 'OpenStreetMap.HOT', + label: 'OpenStreetMap.HOT' + }, + { + value: 'Esri.WorldStreetMap', + label: 'Esri.WorldStreetMap' + }, + { + value: 'Esri.WorldTopoMap', + label: 'Esri.WorldTopoMap' + }, + { + value: 'CartoDB.Positron', + label: 'CartoDB.Positron' + }, + { + value: 'CartoDB.DarkMatter', + label: 'CartoDB.DarkMatter' + } + ] + }, + 'useCustomProvider', + { + key: 'customProviderTileUrl', + condition: 'model.useCustomProvider === true', + } + ] +}; + +export const commonMapSettingsSchema = +{ + schema: { + title: 'Map Configuration', + type: 'object', + properties: { + defaultZoomLevel: { + title: 'Default map zoom level (0 - 20)', + type: 'number' + }, + useDefaultCenterPosition: { + title: 'Use default map center position', + type: 'boolean', + default: false + }, + defaultCenterPosition: { + title: 'Default map center position (0,0)', + type: 'string', + default: '0,0' + }, + fitMapBounds: { + title: 'Fit map bounds to cover all markers', + type: 'boolean', + default: true + }, + disableScrollZooming: { + title: 'Disable scroll zooming', + type: 'boolean', + default: false + }, + latKeyName: { + title: 'Latitude key name', + type: 'string', + default: 'latitude' + }, + lngKeyName: { + title: 'Longitude key name', + type: 'string', + default: 'longitude' + }, + showLabel: { + title: 'Show label', + type: 'boolean', + default: true + }, + label: { + title: 'Label (pattern examples: \'${entityName}\', \'${entityName}: (Text ${keyName} units.)\' )', + type: 'string', + default: '${entityName}' + }, + useLabelFunction: { + title: 'Use label function', + type: 'boolean', + default: false + }, + labelFunction: { + title: 'Label function: f(data, dsData, dsIndex)', + type: 'string' + }, + showTooltip: { + title: 'Show tooltip', + type: 'boolean', + default: true + }, + showTooltipAction: { + title: 'Action for displaying the tooltip', + type: 'string', + default: 'click' + }, + autocloseTooltip: { + title: 'Auto-close tooltips', + type: 'boolean', + default: true + }, + tooltipPattern: { + title: 'Tooltip (for ex. \'Text ${keyName} units.\' or Link text\')', + type: 'string', + default: '${entityName}

Latitude: ${latitude:7}
Longitude: ${longitude:7}' + }, + useTooltipFunction: { + title: 'Use tooltip function', + type: 'boolean', + default: false + }, + tooltipFunction: { + title: 'Tooltip function: f(data, dsData, dsIndex)', + type: 'string' + }, + color: { + title: 'Color', + type: 'string' + }, + useColorFunction: { + title: 'Use color function', + type: 'boolean', + default: false + }, + colorFunction: { + title: 'Color function: f(data, dsData, dsIndex)', + type: 'string' + }, + showPolygon: { + title: 'Show polygon', + type: 'boolean', + default: false + }, + polygonKeyName: { + title: 'Polygon key name', + type: 'string', + default: 'coordinates' + }, + polygonColor: { + title: 'Polygon color', + type: 'string' + }, + polygonOpacity: { + title: 'Polygon opacity', + type: 'number', + default: 0.5 + }, + polygonStrokeColor: { + title: 'Stroke color', + type: 'string' + }, + polygonStrokeOpacity: { + title: 'Stroke opacity', + type: 'number', + default: 1 + }, + polygonStrokeWeight: { + title: 'Stroke weight', + type: 'number', + default: 1 + }, + usePolygonColorFunction: { + title: 'Use polygon color function', + type: 'boolean', + default: false + }, + polygonColorFunction: { + title: 'Polygon Color function: f(data, dsData, dsIndex)', + type: 'string' + }, + draggableMarker: { + title: 'Draggable Marker', + type: 'boolean', + default: false + }, + markerImage: { + title: 'Custom marker image', + type: 'string' + }, + markerImageSize: { + title: 'Custom marker image size (px)', + type: 'number', + default: 34 + }, + useMarkerImageFunction: { + title: 'Use marker image function', + type: 'boolean', + default: false + }, + markerImageFunction: { + title: 'Marker image function: f(data, images, dsData, dsIndex)', + type: 'string' + }, + markerImages: { + title: 'Marker images', + type: 'array', + items: { + title: 'Marker image', + type: 'string' + } + } + }, + required: [] + }, + form: [ + 'defaultZoomLevel', + 'useDefaultCenterPosition', + 'defaultCenterPosition', + 'fitMapBounds', + 'disableScrollZooming', + 'latKeyName', + 'lngKeyName', + 'showLabel', + 'label', + 'useLabelFunction', + 'draggableMarker', + { + key: 'labelFunction', + type: 'javascript' + }, + 'showTooltip', + { + key: 'showTooltipAction', + type: 'rc-select', + multiple: false, + items: [ + { + value: 'click', + label: 'Show tooltip on click (Default)' + }, + { + value: 'hover', + label: 'Show tooltip on hover' + } + ] + }, + 'autocloseTooltip', + { + key: 'tooltipPattern', + type: 'textarea' + }, + 'useTooltipFunction', + { + key: 'tooltipFunction', + type: 'javascript' + }, + { + key: 'color', + type: 'color' + }, + 'useColorFunction', + { + key: 'colorFunction', + type: 'javascript' + }, 'showPolygon', 'polygonKeyName', + { + key: 'polygonColor', + type: 'color' + }, + 'polygonOpacity', + { + key: 'polygonStrokeColor', + type: 'color' + }, + 'polygonStrokeOpacity', 'polygonStrokeWeight', 'usePolygonColorFunction', + { + key: 'polygonColorFunction', + type: 'javascript' + }, + { + key: 'markerImage', + type: 'image' + }, + 'markerImageSize', + 'useMarkerImageFunction', + { + key: 'markerImageFunction', + type: 'javascript' + }, + { + key: 'markerImages', + items: [ + { + key: 'markerImages[]', + type: 'image' + } + ] + } + ] +}; + +export const routeMapSettingsSchema = +{ + schema: { + title: 'Route Map Configuration', + type: 'object', + properties: { + strokeWeight: { + title: 'Stroke weight', + type: 'number', + default: 2 + }, + strokeOpacity: { + title: 'Stroke opacity', + type: 'number', + default: 1.0 + } + }, + required: [] + }, + form: [ + 'strokeWeight', + 'strokeOpacity' + ] +}; + +export const markerClusteringSettingsSchema = +{ + schema: { + title: 'Markers Clustering Configuration', + type: 'object', + properties: { + useClusterMarkers: { + title: 'Use map markers clustering', + type: 'boolean', + default: false + }, + zoomOnClick: { + title: 'Zoom when clicking on a cluster', + type: 'boolean', + default: true + }, + maxZoom: { + title: 'The maximum zoom level when a marker can be part of a cluster (0 - 18)', + type: 'number' + } + }, + required: [] + }, + form: [ + 'useClusterMarkers', + 'zoomOnClick', + 'maxZoom' + ] +}; + +export const markerClusteringSettingsSchemaGoogle = +{ + schema: { + title: 'Marker Clustering Configuration Google', + type: 'object', + properties: { + gridSize: { + title: 'Maximum radius that a cluster will cover in pixels', + type: 'number', + default: 60 + }, + minimumClusterSize: { + title: 'The minimum number of markers in a cluster', + type: 'number' + } + }, + required: [] + }, + form: [ + 'gridSize', + 'minimumClusterSize' + ] +}; + +export const markerClusteringSettingsSchemaLeaflet = +{ + schema: { + title: 'Markers Clustering Configuration Leaflet', + type: 'object', + properties: { + showCoverageOnHover: { + title: 'Show the bounds of markers when mouse over a cluster', + type: 'boolean', + default: true + }, + animate: { + title: 'Show animation on markers when zooming', + type: 'boolean', + default: true + }, + maxClusterRadius: { + title: 'Maximum radius that a cluster will cover in pixels', + type: 'number', + default: 80 + }, + chunkedLoading: { + title: 'Use chunks for adding markers so that the page does not freeze', + type: 'boolean', + default: false + }, + removeOutsideVisibleBounds: { + title: 'Use lazy load for adding markers', + type: 'boolean', + default: true + } + }, + required: [] + }, + form: [ + 'showCoverageOnHover', + 'animate', + 'maxClusterRadius', + 'chunkedLoading', + 'removeOutsideVisibleBounds' + ] +}; + +export const imageMapSettingsSchema = +{ + schema: { + title: 'Image Map Configuration', + type: 'object', + properties: { + mapImageUrl: { + title: 'Image map background', + type: 'string', + default: 'data:image/svg+xml;base64,PHN2ZyBpZD0ic3ZnMiIgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTAwIiB3aWR0aD0iMTAwIiB2ZXJzaW9uPSIxLjEiIHhtbG5zOmNjPSJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9ucyMiIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgdmlld0JveD0iMCAwIDEwMCAxMDAiPgogPGcgaWQ9ImxheWVyMSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCAtOTUyLjM2KSI+CiAgPHJlY3QgaWQ9InJlY3Q0Njg0IiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBoZWlnaHQ9Ijk5LjAxIiB3aWR0aD0iOTkuMDEiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiB5PSI5NTIuODYiIHg9Ii40OTUwNSIgc3Ryb2tlLXdpZHRoPSIuOTkwMTAiIGZpbGw9IiNlZWUiLz4KICA8dGV4dCBpZD0idGV4dDQ2ODYiIHN0eWxlPSJ3b3JkLXNwYWNpbmc6MHB4O2xldHRlci1zcGFjaW5nOjBweDt0ZXh0LWFuY2hvcjptaWRkbGU7dGV4dC1hbGlnbjpjZW50ZXIiIGZvbnQtd2VpZ2h0PSJib2xkIiB4bWw6c3BhY2U9InByZXNlcnZlIiBmb250LXNpemU9IjEwcHgiIGxpbmUtaGVpZ2h0PSIxMjUlIiB5PSI5NzAuNzI4MDkiIHg9IjQ5LjM5NjQ3NyIgZm9udC1mYW1pbHk9IlJvYm90byIgZmlsbD0iIzY2NjY2NiI+PHRzcGFuIGlkPSJ0c3BhbjQ2OTAiIHg9IjUwLjY0NjQ3NyIgeT0iOTcwLjcyODA5Ij5JbWFnZSBiYWNrZ3JvdW5kIDwvdHNwYW4+PHRzcGFuIGlkPSJ0c3BhbjQ2OTIiIHg9IjQ5LjM5NjQ3NyIgeT0iOTgzLjIyODA5Ij5pcyBub3QgY29uZmlndXJlZDwvdHNwYW4+PC90ZXh0PgogIDxyZWN0IGlkPSJyZWN0NDY5NCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgaGVpZ2h0PSIxOS4zNiIgd2lkdGg9IjY5LjM2IiBzdHJva2U9IiMwMDAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgeT0iOTkyLjY4IiB4PSIxNS4zMiIgc3Ryb2tlLXdpZHRoPSIuNjM5ODYiIGZpbGw9Im5vbmUiLz4KIDwvZz4KPC9zdmc+Cg==' + }, + imageEntityAlias: { + title: 'Image URL source entity alias', + type: 'string', + default: '' + }, + imageUrlAttribute: { + title: 'Image URL source entity attribute', + type: 'string', + default: '' + }, + disableScrollZooming: { + title: 'Disable scroll zooming', + type: 'boolean', + default: false + }, + xPosKeyName: { + title: 'X position key name', + type: 'string', + default: 'xPos' + }, + yPosKeyName: { + title: 'Y position key name', + type: 'string', + default: 'yPos' + }, + showLabel: { + title: 'Show label', + type: 'boolean', + default: true + }, + label: { + title: 'Label (pattern examples: \'${entityName}\', \'${entityName}: (Text ${keyName} units.)\' )', + type: 'string', + default: '${entityName}' + }, + useLabelFunction: { + title: 'Use label function', + type: 'boolean', + default: false + }, + labelFunction: { + title: 'Label function: f(data, dsData, dsIndex)', + type: 'string' + }, + showTooltip: { + title: 'Show tooltip', + type: 'boolean', + default: true + }, + showTooltipAction: { + title: 'Action for displaying the tooltip', + type: 'string', + default: 'click' + }, + autocloseTooltip: { + title: 'Auto-close tooltips', + type: 'boolean', + default: true + }, + tooltipPattern: { + title: 'Tooltip (for ex. \'Text ${keyName} units.\' or Link text\')', + type: 'string', + default: '${entityName}

X Pos: ${xPos:2}
Y Pos: ${yPos:2}' + }, + useTooltipFunction: { + title: 'Use tooltip function', + type: 'boolean', + default: false + }, + tooltipFunction: { + title: 'Tooltip function: f(data, dsData, dsIndex)', + type: 'string' + }, + color: { + title: 'Color', + type: 'string' + }, + posFunction: { + title: 'Position conversion function: f(origXPos, origYPos), should return x,y coordinates as double from 0 to 1 each', + type: 'string', + default: 'return {x: origXPos, y: origYPos};' + }, + markerOffsetX: { + title: 'Marker X offset relative to position', + type: 'number', + default: 0.5 + }, + markerOffsetY: { + title: 'Marker Y offset relative to position', + type: 'number', + default: 1 + }, + useColorFunction: { + title: 'Use color function', + type: 'boolean', + default: false + }, + colorFunction: { + title: 'Color function: f(data, dsData, dsIndex)', + type: 'string' + }, + markerImage: { + title: 'Custom marker image', + type: 'string' + }, + markerImageSize: { + title: 'Custom marker image size (px)', + type: 'number', + default: 34 + }, + useMarkerImageFunction: { + title: 'Use marker image function', + type: 'boolean', + default: false + }, + markerImageFunction: { + title: 'Marker image function: f(data, images, dsData, dsIndex)', + type: 'string' + }, + markerImages: { + title: 'Marker images', + type: 'array', + items: { + title: 'Marker image', + type: 'string' + } + } + }, + required: [] + }, + form: [ + { + key: 'mapImageUrl', + type: 'image' + }, + 'imageEntityAlias', + 'imageUrlAttribute', + 'disableScrollZooming', + 'xPosKeyName', + 'yPosKeyName', + 'showLabel', + 'label', + 'useLabelFunction', + { + key: 'labelFunction', + type: 'javascript' + }, + 'showTooltip', + { + key: 'showTooltipAction', + type: 'rc-select', + multiple: false, + items: [ + { + value: 'click', + label: 'Show tooltip on click (Default)' + }, + { + value: 'hover', + label: 'Show tooltip on hover' + } + ] + }, + 'autocloseTooltip', + { + key: 'tooltipPattern', + type: 'textarea' + }, + 'useTooltipFunction', + { + key: 'tooltipFunction', + type: 'javascript' + }, + { + key: 'color', + type: 'color' + }, + { + key: 'posFunction', + type: 'javascript' + }, + 'markerOffsetX', + 'markerOffsetY', + 'useColorFunction', + { + key: 'colorFunction', + type: 'javascript' + }, + { + key: 'markerImage', + type: 'image' + }, + 'markerImageSize', + 'useMarkerImageFunction', + { + key: 'markerImageFunction', + type: 'javascript' + }, + { + key: 'markerImages', + items: [ + { + key: 'markerImages[]', + type: 'image' + } + ] + } + ] +}; + +export const mapProviderSchema = +{ + schema: { + title: 'Map Provider Configuration', + type: 'object', + properties: { + provider: { + title: 'Map Provider', + type: 'string', + default: 'openstreet-map' + } + }, + required: [] + }, + form: [ + { + key: 'provider', + type: 'rc-select', + multiple: false, + items: [ + { + value: 'google-map', + label: 'Google maps' + }, + { + value: 'openstreet-map', + label: 'Openstreet maps' + }, + { + value: 'here', + label: 'HERE maps' + }, + { + value: 'image-map', + label: 'Image map' + }, + { + value: 'tencent-map', + label: 'Tencent maps' + } + ] + } + ] +}; + + +export const tripAnimationSchema = { + schema: { + title: 'Openstreet Map Configuration', + type: 'object', + properties: { + normalizationStep: { + title: 'Normalization data step (ms)', + type: 'number', + default: 1000 + }, + latKeyName: { + title: 'Latitude key name', + type: 'string', + default: 'latitude' + }, + lngKeyName: { + title: 'Longitude key name', + type: 'string', + default: 'longitude' + }, + polKeyName: { + title: 'Polygon key name', + type: 'string', + default: 'coordinates' + }, + showLabel: { + title: 'Show label', + type: 'boolean', + default: true + }, + label: { + title: 'Label (pattern examples: \'${entityName}\', \'${entityName}: (Text ${keyName} units.)\' )', + type: 'string', + default: '${entityName}' + }, + useLabelFunction: { + title: 'Use label function', + type: 'boolean', + default: false + }, + labelFunction: { + title: 'Label function: f(data, dsData, dsIndex)', + type: 'string' + }, + showTooltip: { + title: 'Show tooltip', + type: 'boolean', + default: true + }, + tooltipColor: { + title: 'Tooltip background color', + type: 'string', + default: '#fff' + }, + tooltipFontColor: { + title: 'Tooltip font color', + type: 'string', + default: '#000' + }, + tooltipOpacity: { + title: 'Tooltip opacity (0-1)', + type: 'number', + default: 1 + }, + tooltipPattern: { + title: 'Tooltip (for ex. \'Text ${keyName} units.\' or Link text\')', + type: 'string', + default: '${entityName}

Latitude: ${latitude:7}
Longitude: ${longitude:7}' + }, + useTooltipFunction: { + title: 'Use tooltip function', + type: 'boolean', + default: false + }, + tooltipFunction: { + title: 'Tooltip function: f(data, dsData, dsIndex)', + type: 'string' + }, + color: { + title: 'Path color', + type: 'string' + }, + strokeWeight: { + title: 'Stroke weight', + type: 'number', + default: 2 + }, + strokeOpacity: { + title: 'Stroke opacity', + type: 'number', + default: 1 + }, + useColorFunction: { + title: 'Use path color function', + type: 'boolean', + default: false + }, + colorFunction: { + title: 'Path color function: f(data, dsData, dsIndex)', + type: 'string' + }, + usePolylineDecorator: { + title: 'Use path decorator', + type: 'boolean', + default: false + }, + decoratorSymbol: { + title: 'Decorator symbol', + type: 'string', + default: 'arrowHead' + }, + decoratorSymbolSize: { + title: 'Decorator symbol size (px)', + type: 'number', + default: 10 + }, + useDecoratorCustomColor: { + title: 'Use path decorator custom color', + type: 'boolean', + default: false + }, + decoratorCustomColor: { + title: 'Decorator custom color', + type: 'string', + default: '#000' + }, + decoratorOffset: { + title: 'Decorator offset', + type: 'string', + default: '20px' + }, + endDecoratorOffset: { + title: 'End decorator offset', + type: 'string', + default: '20px' + }, + decoratorRepeat: { + title: 'Decorator repeat', + type: 'string', + default: '20px' + }, + showPolygon: { + title: 'Show polygon', + type: 'boolean', + default: false + }, + polygonTooltipPattern: { + title: 'Tooltip (for ex. \'Text ${keyName} units.\' or Link text\')', + type: 'string', + default: '${entityName}

TimeStamp: ${ts:7}' + }, + usePolygonTooltipFunction: { + title: 'Use polygon tooltip function', + type: 'boolean', + default: false + }, + polygonTooltipFunction: { + title: 'Polygon tooltip function: f(data, dsData, dsIndex)', + type: 'string' + }, + polygonColor: { + title: 'Polygon color', + type: 'string' + }, + polygonOpacity: { + title: 'Polygon opacity', + type: 'number', + default: 0.5 + }, + polygonStrokeColor: { + title: 'Polygon border color', + type: 'string' + }, + polygonStrokeOpacity: { + title: 'Polygon border opacity', + type: 'number', + default: 1 + }, + polygonStrokeWeight: { + title: 'Polygon border weight', + type: 'number', + default: 1 + }, + usePolygonColorFunction: { + title: 'Use polygon color function', + type: 'boolean', + default: false + }, + polygonColorFunction: { + title: 'Polygon Color function: f(data, dsData, dsIndex)', + type: 'string' + }, + showPoints: { + title: 'Show points', + type: 'boolean', + default: false + }, + pointColor: { + title: 'Point color', + type: 'string' + }, + pointSize: { + title: 'Point size (px)', + type: 'number', + default: 10 + }, + usePointAsAnchor: { + title: 'Use point as anchor', + type: 'boolean', + default: false + }, + pointAsAnchorFunction: { + title: 'Point as anchor function: f(data, dsData, dsIndex)', + type: 'string' + }, + pointTooltipOnRightPanel: { + title: 'Independant point tooltip', + type: 'boolean', + default: true + }, + autocloseTooltip: { + title: 'Auto-close point popup', + type: 'boolean', + default: true + }, + markerImage: { + title: 'Custom marker image', + type: 'string' + }, + markerImageSize: { + title: 'Custom marker image size (px)', + type: 'number', + default: 34 + }, + rotationAngle: { + title: 'Set additional rotation angle for marker (deg)', + type: 'number', + default: 180 + }, + useMarkerImageFunction: { + title: 'Use marker image function', + type: 'boolean', + default: false + }, + markerImageFunction: { + title: 'Marker image function: f(data, images, dsData, dsIndex)', + type: 'string' + }, + markerImages: { + title: 'Marker images', + type: 'array', + items: { + title: 'Marker image', + type: 'string' + } + } + }, + required: [] + }, + form: [{ + key: 'mapProvider', + type: 'rc-select', + multiple: false, + items: [{ + value: 'OpenStreetMap.Mapnik', + label: 'OpenStreetMap.Mapnik (Default)' + }, { + value: 'OpenStreetMap.BlackAndWhite', + label: 'OpenStreetMap.BlackAndWhite' + }, { + value: 'OpenStreetMap.HOT', + label: 'OpenStreetMap.HOT' + }, { + value: 'Esri.WorldStreetMap', + label: 'Esri.WorldStreetMap' + }, { + value: 'Esri.WorldTopoMap', + label: 'Esri.WorldTopoMap' + }, { + value: 'CartoDB.Positron', + label: 'CartoDB.Positron' + }, { + value: 'CartoDB.DarkMatter', + label: 'CartoDB.DarkMatter' + }] + }, 'normalizationStep', 'latKeyName', 'lngKeyName', 'polKeyName', 'showLabel', 'label', 'useLabelFunction', { + key: 'labelFunction', + type: 'javascript' + }, 'showTooltip', { + key: 'tooltipColor', + type: 'color' + }, { + key: 'tooltipFontColor', + type: 'color' + }, 'tooltipOpacity', { + key: 'tooltipPattern', + type: 'textarea' + }, 'useTooltipFunction', { + key: 'tooltipFunction', + type: 'javascript' + }, { + key: 'color', + type: 'color' + }, 'useColorFunction', { + key: 'colorFunction', + type: 'javascript' + }, 'usePolylineDecorator', { + key: 'decoratorSymbol', + type: 'rc-select', + multiple: false, + items: [{ + value: 'arrowHead', + label: 'Arrow' + }, { + value: 'dash', + label: 'Dash' + }] + }, 'decoratorSymbolSize', 'useDecoratorCustomColor', { + key: 'decoratorCustomColor', + type: 'color' + }, { + key: 'decoratorOffset', + type: 'textarea' + }, { + key: 'endDecoratorOffset', + type: 'textarea' + }, { + key: 'decoratorRepeat', + type: 'textarea' + }, 'strokeWeight', 'strokeOpacity', 'showPolygon', { + key: 'polygonTooltipPattern', + type: 'textarea' + }, 'usePolygonTooltipFunction', { + key: 'polygonTooltipFunction', + type: 'javascript' + }, { + key: 'polygonColor', + type: 'color' + }, 'polygonOpacity', { + key: 'polygonStrokeColor', + type: 'color' + }, 'polygonStrokeOpacity', 'polygonStrokeWeight', 'usePolygonColorFunction', { + key: 'polygonColorFunction', + type: 'javascript' + }, 'showPoints', { + key: 'pointColor', + type: 'color' + }, 'pointSize', 'usePointAsAnchor', { + key: 'pointAsAnchorFunction', + type: 'javascript' + }, 'pointTooltipOnRightPanel', 'autocloseTooltip', { + key: 'markerImage', + type: 'image' + }, 'markerImageSize', 'rotationAngle', 'useMarkerImageFunction', + { + key: 'markerImageFunction', + type: 'javascript' + }, { + key: 'markerImages', + items: [ + { + key: 'markerImages[]', + type: 'image' + } + ] + }] +} \ No newline at end of file diff --git a/ui-ngx/src/app/modules/home/components/widget/trip-animation/trip-animation.component.html b/ui-ngx/src/app/modules/home/components/widget/trip-animation/trip-animation.component.html new file mode 100644 index 0000000000..e6f6a1c741 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/trip-animation/trip-animation.component.html @@ -0,0 +1,37 @@ + +
+
+ {{settings.label | tbParseTemplate: activeTrip}} +
+
+
+
+ +
+
+
+
+ +
\ No newline at end of file diff --git a/ui-ngx/src/app/modules/home/components/widget/trip-animation/trip-animation.component.scss b/ui-ngx/src/app/modules/home/components/widget/trip-animation/trip-animation.component.scss new file mode 100644 index 0000000000..d7be4629c3 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/trip-animation/trip-animation.component.scss @@ -0,0 +1,89 @@ +/** + * Copyright © 2016-2020 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. + */ + +.trip-animation-widget { + position: relative; + width: 100%; + height: 100%; + font-size: 16px; + line-height: 24px; + display: flex; + flex-direction: column; + + .trip-animation-label-container { + height: 24px; + } + + .trip-animation-container { + position: relative; + z-index: 1; + flex: 1; + width: 100%; + + .map { + width: 100%; + height: 100%; + } + + .trip-animation-info-panel { + position: absolute; + top: 0; + right: 0; + pointer-events: none; + + .tooltip-button { + top: 0; + left: 0; + width: 32px; + min-width: 32px; + height: 32px; + min-height: 32px; + padding: 0 0 2px; + margin: 2px; + line-height: 24px; + z-index: 999; + + &::ng-deep .mat-button-wrapper { + padding: 0; + } + + mat-icon { + width: 24px; + height: 24px; + + svg { + width: inherit; + height: inherit; + } + } + } + } + + .trip-animation-tooltip { + position: absolute; + top: 38px; + right: 0; + z-index: 400; + padding: 10px; + background-color: #fff; + transition: 0.3s ease-in-out; + + &-hidden { + transform: translateX(110%); + } + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/widget/trip-animation/trip-animation.component.ts b/ui-ngx/src/app/modules/home/components/widget/trip-animation/trip-animation.component.ts new file mode 100644 index 0000000000..07e2c2d697 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/trip-animation/trip-animation.component.ts @@ -0,0 +1,156 @@ +/// +/// Copyright © 2016-2020 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 L from 'leaflet'; +import _ from 'lodash'; +import tinycolor from 'tinycolor2'; +import { interpolateOnPointSegment } from 'leaflet-geometryutil'; + +import { Component, OnInit, Input, ViewChild, AfterViewInit, ChangeDetectorRef, SecurityContext } from '@angular/core'; +import { MapWidgetController, TbMapWidgetV2 } from '../lib/maps/map-widget2'; +import { MapProviders } from '../lib/maps/map-models'; +import { parseArray, parseTemplate, safeExecute } from '@app/core/utils'; +import { initSchema, addToSchema, addGroupInfo } from '@app/core/schema-utils'; +import { tripAnimationSchema } from '../lib/maps/schemes'; +import { DomSanitizer } from '@angular/platform-browser'; +import { WidgetConfig, JsonSchema, JsonSettingsSchema } from '@app/shared/public-api'; +import { WidgetContext } from '@app/modules/home/models/widget-component.models'; +import { getRatio, findAngle } from '../lib/maps/maps-utils'; + + +@Component({ + selector: 'trip-animation', + templateUrl: './trip-animation.component.html', + styleUrls: ['./trip-animation.component.scss'] +}) +export class TripAnimationComponent implements OnInit, AfterViewInit { + + constructor(private cd: ChangeDetectorRef, private sanitizer: DomSanitizer) { } + + @Input() ctx: WidgetContext; + + @ViewChild('map') mapContainer; + + mapWidget: MapWidgetController; + historicalData; + intervals; + normalizationStep = 1000; + interpolatedData = []; + widgetConfig: WidgetConfig; + settings; + mainTooltip = ''; + visibleTooltip = false; + activeTrip; + + static getSettingsSchema(): JsonSettingsSchema { + const schema = initSchema(); + addToSchema(schema, TbMapWidgetV2.getProvidersSchema()); + addGroupInfo(schema, 'Map Provider Settings'); + addToSchema(schema, tripAnimationSchema); + addGroupInfo(schema, 'Trip Animation Settings'); + return schema; + } + + ngOnInit(): void { + this.widgetConfig = this.ctx.widgetConfig; + const settings = { + normalizationStep: 1000, + showLabel: false, + buttonColor: tinycolor(this.widgetConfig.color).setAlpha(0.54).toRgbString(), + disabledButtonColor: tinycolor(this.widgetConfig.color).setAlpha(0.3).toRgbString(), + rotationAngle: 0 + } + this.settings = { ...settings, ...this.ctx.settings }; + const subscription = this.ctx.subscriptions[Object.keys(this.ctx.subscriptions)[0]]; + if (subscription) subscription.callbacks.onDataUpdated = (updated) => { + this.historicalData = parseArray(this.ctx.data); + this.activeTrip = this.historicalData[0][0]; + this.calculateIntervals(); + this.timeUpdated(this.intervals[0]); + this.mapWidget.map.updatePolylines(this.interpolatedData.map(ds => _.values(ds))); + + this.mapWidget.map.map?.invalidateSize(); + this.cd.detectChanges(); + } + } + + ngAfterViewInit() { + const ctxCopy: WidgetContext = _.cloneDeep(this.ctx); + ctxCopy.settings.showLabel = false; + ctxCopy.settings.showTooltip = false; + this.mapWidget = new MapWidgetController(MapProviders.openstreet, false, ctxCopy, this.mapContainer.nativeElement); + } + + timeUpdated(time: number) { + const currentPosition = this.interpolatedData.map(dataSource => dataSource[time]); + this.activeTrip = currentPosition[0]; + if (this.settings.showPolygon) { + this.mapWidget.map.updatePolygons(this.interpolatedData); + } + this.mapWidget.map.updateMarkers(currentPosition); + } + + setActiveTrip() { + + } + + calculateIntervals() { + this.historicalData.forEach((dataSource, index) => { + this.intervals = []; + for (let time = dataSource[0]?.time; time < dataSource[dataSource.length - 1]?.time; time += this.normalizationStep) { + this.intervals.push(time); + } + this.intervals.push(dataSource[dataSource.length - 1]?.time); + this.interpolatedData[index] = this.interpolateArray(dataSource, this.intervals); + }); + } + + showHideTooltip() { + const tooltipText: string = this.settings.useTooltipFunction ? + safeExecute(this.settings.tooolTipFunction, [this.activeTrip, this.historicalData, 0]) + : this.settings.tooltipPattern; + + this.mainTooltip = this.sanitizer.sanitize(SecurityContext.HTML, parseTemplate(tooltipText, this.activeTrip)) + this.visibleTooltip = !this.visibleTooltip; + } + + interpolateArray(originData, interpolatedIntervals) { + + const result = {}; + + for (let i = 1, j = 0; i < originData.length && j < interpolatedIntervals.length;) { + const currentTime = interpolatedIntervals[j]; + while (originData[i].time < currentTime) i++; + const before = originData[i - 1]; + const after = originData[i]; + const interpolation = interpolateOnPointSegment( + new L.Point(before.latitude, before.longitude), + new L.Point(after.latitude, after.longitude), + getRatio(before.time, after.time, currentTime)); + result[currentTime] = ({ + ...originData[i], + rotationAngle: findAngle(before, after) + this.settings.rotationAngle, + latitude: interpolation.x, + longitude: interpolation.y + }); + j++; + } + return result; + } +} + +export let TbTripAnimationWidget = TripAnimationComponent; + diff --git a/ui-ngx/src/app/modules/home/components/widget/widget-components.module.ts b/ui-ngx/src/app/modules/home/components/widget/widget-components.module.ts index 6598db5436..c849c09193 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget-components.module.ts +++ b/ui-ngx/src/app/modules/home/components/widget/widget-components.module.ts @@ -31,6 +31,7 @@ import { DateRangeNavigatorWidgetComponent } 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'; @NgModule({ @@ -45,6 +46,7 @@ import { WebCameraInputWidgetComponent } from './lib/web-camera-input.component' DateRangeNavigatorWidgetComponent, DateRangeNavigatorPanelComponent, MultipleInputWidgetComponent, + TripAnimationComponent, WebCameraInputWidgetComponent ], imports: [ @@ -61,6 +63,7 @@ import { WebCameraInputWidgetComponent } from './lib/web-camera-input.component' RpcWidgetsModule, DateRangeNavigatorWidgetComponent, MultipleInputWidgetComponent, + TripAnimationComponent, WebCameraInputWidgetComponent ], providers: [ diff --git a/ui-ngx/src/app/shared/components/dialog/json-object-edit-dialog.component.ts b/ui-ngx/src/app/shared/components/dialog/json-object-edit-dialog.component.ts index 5fc3882a35..aacedd7f3a 100644 --- a/ui-ngx/src/app/shared/components/dialog/json-object-edit-dialog.component.ts +++ b/ui-ngx/src/app/shared/components/dialog/json-object-edit-dialog.component.ts @@ -14,13 +14,13 @@ /// limitations under the License. /// -import {Component, Inject, OnInit} from "@angular/core"; -import {DialogComponent} from "@shared/components/dialog.component"; -import {Store} from "@ngrx/store"; -import {AppState} from "@core/core.state"; -import {Router} from "@angular/router"; -import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog"; -import {FormBuilder, FormGroup} from "@angular/forms"; +import {Component, Inject, OnInit} from '@angular/core'; +import {DialogComponent} from '@shared/components/dialog.component'; +import {Store} from '@ngrx/store'; +import {AppState} from '@core/core.state'; +import {Router} from '@angular/router'; +import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; +import {FormBuilder, FormGroup} from '@angular/forms'; export interface JsonObjectEdittDialogData { jsonValue: Object; diff --git a/ui-ngx/src/app/shared/components/directives/tb-json-to-string.directive.ts b/ui-ngx/src/app/shared/components/directives/tb-json-to-string.directive.ts index cf7cd0a0bd..f19022e590 100644 --- a/ui-ngx/src/app/shared/components/directives/tb-json-to-string.directive.ts +++ b/ui-ngx/src/app/shared/components/directives/tb-json-to-string.directive.ts @@ -14,7 +14,7 @@ /// limitations under the License. /// -import {Directive, ElementRef, forwardRef, HostListener, Renderer2, SkipSelf} from "@angular/core"; +import {Directive, ElementRef, forwardRef, HostListener, Renderer2, SkipSelf} from '@angular/core'; import { ControlValueAccessor, FormControl, FormGroupDirective, @@ -22,8 +22,8 @@ import { NG_VALUE_ACCESSOR, NgForm, ValidationErrors, Validator -} from "@angular/forms"; -import {ErrorStateMatcher} from "@angular/material/core"; +} from '@angular/forms'; +import {ErrorStateMatcher} from '@angular/material/core'; @Directive({ selector: '[tb-json-to-string]', diff --git a/ui-ngx/src/app/shared/components/json-form/react/json-form-utils.ts b/ui-ngx/src/app/shared/components/json-form/react/json-form-utils.ts index 18e985ed45..b83b11d7d5 100644 --- a/ui-ngx/src/app/shared/components/json-form/react/json-form-utils.ts +++ b/ui-ngx/src/app/shared/components/json-form/react/json-form-utils.ts @@ -113,7 +113,7 @@ const canonicalTitleMap = (titleMap: any, originalEnum?: string[]): { name: stri const stdFormObj = (name: string, schema: any, options: DefaultsFormOptions): any => { options = options || {}; - const f = options.global && options.global.formDefaults ? _.cloneDeep(options.global.formDefaults) : {}; + const f: any = options.global && options.global.formDefaults ? _.cloneDeep(options.global.formDefaults) : {}; if (options.global && options.global.supressPropertyTitles === true) { f.title = schema.title; } else { diff --git a/ui-ngx/src/app/shared/components/time/history-selector/history-selector.component.html b/ui-ngx/src/app/shared/components/time/history-selector/history-selector.component.html new file mode 100644 index 0000000000..05d6b20c89 --- /dev/null +++ b/ui-ngx/src/app/shared/components/time/history-selector/history-selector.component.html @@ -0,0 +1,51 @@ + +
+
+ + + + + + + + + {{speedValue}} + +
+
+ {{ this.intervals[this.index] | date:'medium'}} + {{ "widget.no-data-found" | translate}} +
\ No newline at end of file diff --git a/ui-ngx/src/app/shared/components/time/history-selector/history-selector.component.scss b/ui-ngx/src/app/shared/components/time/history-selector/history-selector.component.scss new file mode 100644 index 0000000000..d4e4ae17ed --- /dev/null +++ b/ui-ngx/src/app/shared/components/time/history-selector/history-selector.component.scss @@ -0,0 +1,140 @@ +/** + * Copyright © 2016-2020 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. + */ +.trip-animation-widget { + position: relative; + width: 100%; + height: 100%; + font-size: 16px; + line-height: 24px; + + .trip-animation-label-container { + height: 24px; + } + + .trip-animation-container { + position: relative; + z-index: 1; + flex: 1; + width: 100%; + + #trip-animation-map { + z-index: 1; + width: 100%; + height: 100%; + + .pointsLayerMarkerIcon { + border-radius: 50%; + } + } + + .trip-animation-info-panel { + position: absolute; + top: 0; + right: 0; + z-index: 2; + pointer-events: none; + + .md-button { + top: 0; + left: 0; + width: 32px; + min-width: 32px; + height: 32px; + min-height: 32px; + padding: 0 0 2px; + margin: 2px; + line-height: 24px; + + ng-md-icon { + width: 24px; + height: 24px; + + svg { + width: inherit; + height: inherit; + } + } + } + } + + .trip-animation-tooltip { + position: absolute; + top: 38px; + right: 0; + z-index: 2; + padding: 10px; + background-color: #fff; + transition: 0.3s ease-in-out; + + &-hidden { + transform: translateX(110%); + } + } + } + + .trip-animation-control-panel { + position: relative; + box-sizing: border-box; + width: 100%; + padding-bottom: 16px; + padding-left: 10px; + + md-slider-container { + md-slider { + min-width: 80px; + } + + button.md-button.md-icon-button { + width: 44px; + min-width: 44px; + height: 44px; + min-height: 44px; + margin: 0; + line-height: 28px; + + md-icon { + width: 28px; + height: 28px; + font-size: 28px; + + svg { + width: inherit; + height: inherit; + } + } + } + + md-select { + margin: 0; + } + } + + .panel-timer { + max-width: none; + padding-right: 250px; + padding-left: 90px; + margin-top: -20px; + font-size: 12px; + font-weight: 500; + text-align: center; + } + } +} + +.speed-select{ + width: 50px; + margin-left: 20px; +} diff --git a/ui-ngx/src/app/shared/components/time/history-selector/history-selector.component.ts b/ui-ngx/src/app/shared/components/time/history-selector/history-selector.component.ts new file mode 100644 index 0000000000..2ab3acc283 --- /dev/null +++ b/ui-ngx/src/app/shared/components/time/history-selector/history-selector.component.ts @@ -0,0 +1,119 @@ +/// +/// Copyright © 2016-2020 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 { Component, OnInit, OnChanges, Input, Output, EventEmitter, ChangeDetectorRef } from '@angular/core'; +import { interval, Subscription, Subscriber, SubscriptionLike, Observer } from 'rxjs'; +import { filter, tap } from 'rxjs/operators'; +import { HistorySelectSettings } from '@app/modules/home/components/widget/lib/maps/map-models'; + +@Component({ + selector: 'tb-history-selector', + templateUrl: './history-selector.component.html', + styleUrls: ['./history-selector.component.scss'] +}) +export class HistorySelectorComponent implements OnInit, OnChanges { + + @Input() settings: HistorySelectSettings + @Input() intervals = []; + + @Output() timeUpdated: EventEmitter = new EventEmitter(); + + animationTime; + minTimeIndex = 0; + maxTimeIndex = 0; + speed = 1; + index = 0; + playing = false; + interval; + speeds = [1, 5, 10, 25]; + + + constructor(private cd: ChangeDetectorRef) { } + + ngOnInit(): void { + } + + ngOnChanges() { + this.maxTimeIndex = this.intervals?.length - 1; + } + + play() { + this.playing = true; + if (!this.interval) + this.interval = interval(1000 / this.speed) + .pipe( + filter(() => this.playing), + tap(() => this.index++)).subscribe(() => { + if (this.index < this.maxTimeIndex) { + this.cd.detectChanges(); + this.timeUpdated.emit(this.intervals[this.index]); + } + else { + this.interval.complete(); + } + }, err => { + console.log(err); + }, () => { + this.index = this.minTimeIndex; + this.playing = false; + this.interval = null; + this.cd.detectChanges(); + }); + } + + reeneble() { + if (this.playing) { + const position = this.index; + this.interval.complete(); + this.index = position; + this.play(); + } + } + + pause() { + this.playing = false; + this.cd.detectChanges(); + this.timeUpdated.emit(this.intervals[this.index]); + } + + moveNext() { + if (this.index < this.maxTimeIndex) { + this.index++; + } + this.pause(); + } + + movePrev() { + if (this.index > this.minTimeIndex) { + this.index++; + } + this.pause(); + } + + moveStart() { + this.index = this.minTimeIndex; + this.pause(); + } + + moveEnd() { + this.index = this.maxTimeIndex; + this.pause(); + } + + changeIndex() { + this.timeUpdated.emit(this.intervals[this.index]); + } +} diff --git a/ui-ngx/src/app/shared/components/value-input.component.ts b/ui-ngx/src/app/shared/components/value-input.component.ts index 0913aefe12..f067e6e1b7 100644 --- a/ui-ngx/src/app/shared/components/value-input.component.ts +++ b/ui-ngx/src/app/shared/components/value-input.component.ts @@ -17,12 +17,12 @@ import { Component, forwardRef, Input, OnInit, ViewChild } from '@angular/core'; import { ControlValueAccessor, NG_VALUE_ACCESSOR, NgForm } from '@angular/forms'; import { ValueType, valueTypesMap } from '@shared/models/constants'; -import { isObject } from "@core/utils"; -import { MatDialog } from "@angular/material/dialog"; +import { isObject } from '@core/utils'; +import { MatDialog } from '@angular/material/dialog'; import { JsonObjectEditDialogComponent, JsonObjectEdittDialogData -} from "@shared/components/dialog/json-object-edit-dialog.component"; +} from '@shared/components/dialog/json-object-edit-dialog.component'; @Component({ selector: 'tb-value-input', @@ -79,7 +79,7 @@ export class ValueInputComponent implements OnInit, ControlValueAccessor { (res) => { if (res) { this.modelValue = res; - this.inputForm.control.patchValue({'value': this.modelValue}); + this.inputForm.control.patchValue({value: this.modelValue}); } } ); diff --git a/ui-ngx/src/app/shared/pipe/public-api.ts b/ui-ngx/src/app/shared/pipe/public-api.ts index 4f801b7d51..72edfae70d 100644 --- a/ui-ngx/src/app/shared/pipe/public-api.ts +++ b/ui-ngx/src/app/shared/pipe/public-api.ts @@ -20,3 +20,4 @@ export * from './keyboard-shortcut.pipe'; export * from './milliseconds-to-time-string.pipe'; export * from './nospace.pipe'; export * from './truncate.pipe'; +export * from './template.pipe'; diff --git a/ui-ngx/src/app/shared/pipe/tbJson.pipe.ts b/ui-ngx/src/app/shared/pipe/tbJson.pipe.ts index c31cf161ab..5a5fa684fc 100644 --- a/ui-ngx/src/app/shared/pipe/tbJson.pipe.ts +++ b/ui-ngx/src/app/shared/pipe/tbJson.pipe.ts @@ -15,7 +15,7 @@ /// import {Pipe, PipeTransform} from '@angular/core'; -import {isObject, isNumber} from "@core/utils"; +import {isObject, isNumber} from '@core/utils'; @Pipe({name: 'tbJson'}) export class TbJsonPipe implements PipeTransform { diff --git a/ui-ngx/src/app/shared/pipe/template.pipe.ts b/ui-ngx/src/app/shared/pipe/template.pipe.ts new file mode 100644 index 0000000000..e57863e07c --- /dev/null +++ b/ui-ngx/src/app/shared/pipe/template.pipe.ts @@ -0,0 +1,26 @@ +/// +/// Copyright © 2016-2020 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 { Pipe, PipeTransform } from '@angular/core'; +import { parseTemplate } from '@app/core/utils'; + +@Pipe({ name: 'tbParseTemplate' }) +export class TbTemplatePipe implements PipeTransform { + transform(template, data): string { + console.log('TbTemplatePipe -> transform -> template, data', template, data) + return parseTemplate(template, data); + } +} diff --git a/ui-ngx/src/app/shared/shared.module.ts b/ui-ngx/src/app/shared/shared.module.ts index 1df4469fb2..2b714c61f7 100644 --- a/ui-ngx/src/app/shared/shared.module.ts +++ b/ui-ngx/src/app/shared/shared.module.ts @@ -104,7 +104,7 @@ import { TbErrorComponent } from '@shared/components/tb-error.component'; import { EntityTypeListComponent } from '@shared/components/entity/entity-type-list.component'; import { EntitySubTypeListComponent } from '@shared/components/entity/entity-subtype-list.component'; import { TruncatePipe } from '@shared/pipe/truncate.pipe'; -import { TbJsonPipe } from "@shared/pipe/tbJson.pipe"; +import { TbJsonPipe } from '@shared/pipe/tbJson.pipe'; import { ColorPickerDialogComponent } from '@shared/components/dialog/color-picker-dialog.component'; import { MatChipDraggableDirective } from '@shared/components/mat-chip-draggable.directive'; import { ColorInputComponent } from '@shared/components/color-input.component'; @@ -125,8 +125,10 @@ import { TbCheatSheetComponent } from '@shared/components/cheatsheet.component'; import { TbHotkeysDirective } from '@shared/components/hotkeys.directive'; import { NavTreeComponent } from '@shared/components/nav-tree.component'; import { LedLightComponent } from '@shared/components/led-light.component'; -import { TbJsonToStringDirective } from "@shared/components/directives/tb-json-to-string.directive"; -import { JsonObjectEditDialogComponent } from "@shared/components/dialog/json-object-edit-dialog.component"; +import { TbJsonToStringDirective } from '@shared/components/directives/tb-json-to-string.directive'; +import { JsonObjectEditDialogComponent } from '@shared/components/dialog/json-object-edit-dialog.component'; +import { HistorySelectorComponent } from './components/time/history-selector/history-selector.component'; +import { TbTemplatePipe } from './pipe/public-api'; @NgModule({ providers: [ @@ -207,9 +209,11 @@ import { JsonObjectEditDialogComponent } from "@shared/components/dialog/json-ob HighlightPipe, TruncatePipe, TbJsonPipe, + TbTemplatePipe, KeyboardShortcutPipe, TbJsonToStringDirective, - JsonObjectEditDialogComponent + JsonObjectEditDialogComponent, + HistorySelectorComponent ], imports: [ CommonModule, @@ -365,9 +369,11 @@ import { JsonObjectEditDialogComponent } from "@shared/components/dialog/json-ob HighlightPipe, TruncatePipe, TbJsonPipe, + TbTemplatePipe, KeyboardShortcutPipe, TranslateModule, - JsonObjectEditDialogComponent + JsonObjectEditDialogComponent, + HistorySelectorComponent ] }) export class SharedModule { } diff --git a/ui-ngx/src/assets/add_location.svg b/ui-ngx/src/assets/add_location.svg new file mode 100644 index 0000000000..e3150115b7 --- /dev/null +++ b/ui-ngx/src/assets/add_location.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ui-ngx/src/polyfills.ts b/ui-ngx/src/polyfills.ts index 88f93cac56..68a59ba5c3 100644 --- a/ui-ngx/src/polyfills.ts +++ b/ui-ngx/src/polyfills.ts @@ -93,6 +93,8 @@ import { TbAnalogueCompass } from '@home/components/widget/lib/analogue-compass' import { TbAnalogueRadialGauge } from '@home/components/widget/lib/analogue-radial-gauge'; import { TbAnalogueLinearGauge } from '@home/components/widget/lib/analogue-linear-gauge'; import { TbCanvasDigitalGauge } from '@home/components/widget/lib/digital-gauge'; +import { TbMapWidgetV2 } from '@home/components/widget/lib/maps/map-widget2'; +import { TbTripAnimationWidget } from '@app/modules/home/components/widget/trip-animation/trip-animation.component'; import * as tinycolor_ from 'tinycolor2'; @@ -106,3 +108,5 @@ const tinycolor = tinycolor_; (window as any).TbAnalogueRadialGauge = TbAnalogueRadialGauge; (window as any).TbAnalogueLinearGauge = TbAnalogueLinearGauge; (window as any).TbCanvasDigitalGauge = TbCanvasDigitalGauge; +(window as any).TbMapWidgetV2 = TbMapWidgetV2; +(window as any).TbTripAnimationWidget = TbTripAnimationWidget; diff --git a/ui-ngx/src/typings/add-marker.d.ts b/ui-ngx/src/typings/add-marker.d.ts new file mode 100644 index 0000000000..9762de3c96 --- /dev/null +++ b/ui-ngx/src/typings/add-marker.d.ts @@ -0,0 +1,12 @@ +import * as L from 'leaflet' + +declare module 'leaflet' { + + namespace Control { + class AddMarker extends L.Control { } + } + + namespace control { + function addMarker(options): Control.AddMarker; + } +} \ No newline at end of file diff --git a/ui-ngx/tsconfig.json b/ui-ngx/tsconfig.json index a35b8a413f..8e1880e048 100644 --- a/ui-ngx/tsconfig.json +++ b/ui-ngx/tsconfig.json @@ -19,7 +19,8 @@ "src/typings/jquery.typings.d.ts", "src/typings/jquery.flot.typings.d.ts", "src/typings/jquery.jstree.typings.d.ts", - "src/typings/split.js.typings.d.ts" + "src/typings/split.js.typings.d.ts", + "src/typings/add-marker.d.ts" ], "paths": { "@app/*": ["src/app/*"], @@ -33,6 +34,7 @@ }, "lib": [ "es2018", + "es2019", "dom" ] } diff --git a/ui/src/app/widget/lib/map-widget2.js b/ui/src/app/widget/lib/map-widget2.js index bf300630cc..3fc4084835 100644 --- a/ui/src/app/widget/lib/map-widget2.js +++ b/ui/src/app/widget/lib/map-widget2.js @@ -433,7 +433,7 @@ export default class TbMapWidgetV2 { function calculateLocationColor(location, dataMap) { if (location.settings.useColorFunction && location.settings.colorFunction) { var color; - try { + try { color = location.settings.colorFunction(dataMap.dataMap, dataMap.dsDataMap, location.dsIndex); } catch (e) {/**/ } @@ -450,7 +450,7 @@ export default class TbMapWidgetV2 { if (location.settings.usePolygonColorFunction && location.settings.polygonColorFunction) { var color; try { - color = location.settings.polygonColorFunction(dataMap.dataMap, dataMap.dsDataMap, location.dsIndex); + color = location.settings.polygonColorFunction(dataMap.dataMap, dataMap.dsDataMap, location.dsIndex); } catch (e) {/**/ } if (!color) { @@ -484,7 +484,7 @@ export default class TbMapWidgetV2 { function calculateLocationMarkerImage(location, dataMap) { if (location.settings.useMarkerImageFunction && location.settings.markerImageFunction) { var image = null; - try { + try { image = location.settings.markerImageFunction(dataMap.dataMap, location.settings.markerImages, dataMap.dsDataMap, location.dsIndex); } catch (e) { image = null;