From 00e9fb2c7b3c164fbf5fb382ef04dfc913d342c1 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Wed, 19 Oct 2022 16:49:22 +0300 Subject: [PATCH 1/2] UI: Add MVEL script lang support --- ui-ngx/src/app/core/auth/auth.models.ts | 1 + ui-ngx/src/app/core/auth/auth.reducer.ts | 3 ++- ui-ngx/src/app/core/auth/auth.selectors.ts | 5 +++++ ui-ngx/src/app/core/auth/auth.service.ts | 12 +++++++++++- ui-ngx/src/app/core/http/rule-chain.service.ts | 10 +++++++--- .../core/services/script/node-script-test.service.ts | 12 ++++++++---- .../dialog/node-script-test-dialog.component.ts | 6 ++++-- ui-ngx/src/app/shared/models/rule-node.models.ts | 5 +++++ 8 files changed, 43 insertions(+), 11 deletions(-) diff --git a/ui-ngx/src/app/core/auth/auth.models.ts b/ui-ngx/src/app/core/auth/auth.models.ts index 33b84945aa..7e97cb7a13 100644 --- a/ui-ngx/src/app/core/auth/auth.models.ts +++ b/ui-ngx/src/app/core/auth/auth.models.ts @@ -21,6 +21,7 @@ export interface SysParamsState { allowedDashboardIds: string[]; edgesSupportEnabled: boolean; hasRepository: boolean; + mvelEnabled: boolean; } export interface AuthPayload extends SysParamsState { diff --git a/ui-ngx/src/app/core/auth/auth.reducer.ts b/ui-ngx/src/app/core/auth/auth.reducer.ts index cace62660e..7408f29145 100644 --- a/ui-ngx/src/app/core/auth/auth.reducer.ts +++ b/ui-ngx/src/app/core/auth/auth.reducer.ts @@ -24,7 +24,8 @@ const emptyUserAuthState: AuthPayload = { forceFullscreen: false, allowedDashboardIds: [], edgesSupportEnabled: false, - hasRepository: false + hasRepository: false, + mvelEnabled: false }; export const initialState: AuthState = { diff --git a/ui-ngx/src/app/core/auth/auth.selectors.ts b/ui-ngx/src/app/core/auth/auth.selectors.ts index 4a63dbcbed..f703d72f57 100644 --- a/ui-ngx/src/app/core/auth/auth.selectors.ts +++ b/ui-ngx/src/app/core/auth/auth.selectors.ts @@ -60,6 +60,11 @@ export const selectHasRepository = createSelector( (state: AuthState) => state.hasRepository ); +export const selectMvelEnabled = createSelector( + selectAuthState, + (state: AuthState) => state.mvelEnabled +); + export function getCurrentAuthState(store: Store): AuthState { let state: AuthState; store.pipe(select(selectAuth), take(1)).subscribe( diff --git a/ui-ngx/src/app/core/auth/auth.service.ts b/ui-ngx/src/app/core/auth/auth.service.ts index 172e4d5ac9..2b54306e2c 100644 --- a/ui-ngx/src/app/core/auth/auth.service.ts +++ b/ui-ngx/src/app/core/auth/auth.service.ts @@ -478,11 +478,20 @@ export class AuthService { } } + private loadMvelEnabled(authUser: AuthUser): Observable { + if (authUser.authority === Authority.TENANT_ADMIN) { + return this.http.get('/api/ruleChain/mvelEnabled', defaultHttpOptions()); + } else { + return of(false); + } + } + private loadSystemParams(authPayload: AuthPayload): Observable { const sources = [this.loadIsUserTokenAccessEnabled(authPayload.authUser), this.fetchAllowedDashboardIds(authPayload), this.loadIsEdgesSupportEnabled(), this.loadHasRepository(authPayload.authUser), + this.loadMvelEnabled(authPayload.authUser), this.timeService.loadMaxDatapointsLimit()]; return forkJoin(sources) .pipe(map((data) => { @@ -490,7 +499,8 @@ export class AuthService { const allowedDashboardIds: string[] = data[1] as string[]; const edgesSupportEnabled: boolean = data[2] as boolean; const hasRepository: boolean = data[3] as boolean; - return {userTokenAccessEnabled, allowedDashboardIds, edgesSupportEnabled, hasRepository}; + const mvelEnabled: boolean = data[4] as boolean; + return {userTokenAccessEnabled, allowedDashboardIds, edgesSupportEnabled, hasRepository, mvelEnabled}; }, catchError((err) => { return of({}); }))); diff --git a/ui-ngx/src/app/core/http/rule-chain.service.ts b/ui-ngx/src/app/core/http/rule-chain.service.ts index 6b0f3c3f22..8fcb5ecc5c 100644 --- a/ui-ngx/src/app/core/http/rule-chain.service.ts +++ b/ui-ngx/src/app/core/http/rule-chain.service.ts @@ -31,7 +31,7 @@ import { ComponentDescriptorService } from './component-descriptor.service'; import { IRuleNodeConfigurationComponent, LinkLabel, - RuleNodeComponentDescriptor, RuleNodeConfiguration, + RuleNodeComponentDescriptor, RuleNodeConfiguration, ScriptLanguage, TestScriptInputParams, TestScriptResult } from '@app/shared/models/rule-node.models'; @@ -170,8 +170,12 @@ export class RuleChainService { return this.http.get(`/api/ruleNode/${ruleNodeId}/debugIn`, defaultHttpOptionsFromConfig(config)); } - public testScript(inputParams: TestScriptInputParams, config?: RequestConfig): Observable { - return this.http.post('/api/ruleChain/testScript', inputParams, defaultHttpOptionsFromConfig(config)); + public testScript(inputParams: TestScriptInputParams, scriptLang?: ScriptLanguage, config?: RequestConfig): Observable { + let url = '/api/ruleChain/testScript'; + if (scriptLang) { + url += `?scriptLang=${scriptLang}`; + } + return this.http.post(url, inputParams, defaultHttpOptionsFromConfig(config)); } private loadRuleNodeComponents(ruleChainType: RuleChainType, config?: RequestConfig): Observable> { diff --git a/ui-ngx/src/app/core/services/script/node-script-test.service.ts b/ui-ngx/src/app/core/services/script/node-script-test.service.ts index 5dcdb192af..2aca503daa 100644 --- a/ui-ngx/src/app/core/services/script/node-script-test.service.ts +++ b/ui-ngx/src/app/core/services/script/node-script-test.service.ts @@ -24,6 +24,7 @@ import { NodeScriptTestDialogData } from '@shared/components/dialog/node-script-test-dialog.component'; import { sortObjectKeys } from '@core/utils'; +import { ScriptLanguage } from '@shared/models/rule-node.models'; @Injectable({ providedIn: 'root' @@ -35,7 +36,8 @@ export class NodeScriptTestService { } testNodeScript(script: string, scriptType: string, functionTitle: string, - functionName: string, argNames: string[], ruleNodeId: string, helpId?: string): Observable { + functionName: string, argNames: string[], ruleNodeId: string, helpId?: string, + scriptLang?: ScriptLanguage): Observable { if (ruleNodeId) { return this.ruleChainService.getLatestRuleNodeDebugInput(ruleNodeId).pipe( switchMap((debugIn) => { @@ -57,13 +59,14 @@ export class NodeScriptTestService { ); } else { return this.openTestScriptDialog(script, scriptType, functionTitle, - functionName, argNames, null, null, null, helpId); + functionName, argNames, null, null, null, helpId, scriptLang); } } private openTestScriptDialog(script: string, scriptType: string, functionTitle: string, functionName: string, argNames: string[], - msg?: any, metadata?: {[key: string]: string}, msgType?: string, helpId?: string): Observable { + msg?: any, metadata?: {[key: string]: string}, msgType?: string, helpId?: string, + scriptLang?: ScriptLanguage): Observable { if (!msg) { msg = { temperature: 22.4, @@ -95,7 +98,8 @@ export class NodeScriptTestService { script, scriptType, argNames, - helpId + helpId, + scriptLang } }).afterClosed(); } diff --git a/ui-ngx/src/app/shared/components/dialog/node-script-test-dialog.component.ts b/ui-ngx/src/app/shared/components/dialog/node-script-test-dialog.component.ts index fd2f7cd976..542e108aaa 100644 --- a/ui-ngx/src/app/shared/components/dialog/node-script-test-dialog.component.ts +++ b/ui-ngx/src/app/shared/components/dialog/node-script-test-dialog.component.ts @@ -37,7 +37,7 @@ import { Router } from '@angular/router'; import { DialogComponent } from '@shared/components/dialog.component'; import { ContentType } from '@shared/models/constants'; import { JsonContentComponent } from '@shared/components/json-content.component'; -import { TestScriptInputParams } from '@shared/models/rule-node.models'; +import { ScriptLanguage, TestScriptInputParams } from '@shared/models/rule-node.models'; import { RuleChainService } from '@core/http/rule-chain.service'; import { mergeMap } from 'rxjs/operators'; import { ActionNotificationShow } from '@core/notification/notification.actions'; @@ -49,6 +49,7 @@ export interface NodeScriptTestDialogData { functionTitle: string; functionName: string; argNames: string[]; + scriptLang?: ScriptLanguage; msg?: any; metadata?: {[key: string]: string}; msgType?: string; @@ -191,7 +192,8 @@ export class NodeScriptTestDialogComponent extends DialogComponent { if (result.error) { this.store.dispatch(new ActionNotificationShow( diff --git a/ui-ngx/src/app/shared/models/rule-node.models.ts b/ui-ngx/src/app/shared/models/rule-node.models.ts index df8ea3ed87..2c5ccd3015 100644 --- a/ui-ngx/src/app/shared/models/rule-node.models.ts +++ b/ui-ngx/src/app/shared/models/rule-node.models.ts @@ -328,6 +328,11 @@ export interface FcRuleEdge extends FcEdge { labels?: string[]; } +export enum ScriptLanguage { + JS = 'JS', + MVEL = 'MVEL' +} + export interface TestScriptInputParams { script: string; scriptType: string; From 05f47f37963a2e9fe48c222c4a1bab99142706b6 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Wed, 19 Oct 2022 17:21:53 +0300 Subject: [PATCH 2/2] UI: Update public API --- ui-ngx/src/app/core/auth/public-api.ts | 21 +++++++++++++++++++++ ui-ngx/src/app/core/public-api.ts | 1 + 2 files changed, 22 insertions(+) create mode 100644 ui-ngx/src/app/core/auth/public-api.ts diff --git a/ui-ngx/src/app/core/auth/public-api.ts b/ui-ngx/src/app/core/auth/public-api.ts new file mode 100644 index 0000000000..07dc03ea83 --- /dev/null +++ b/ui-ngx/src/app/core/auth/public-api.ts @@ -0,0 +1,21 @@ +/// +/// Copyright © 2016-2022 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 './auth.actions'; +export * from './auth.models'; +export * from './auth.reducer'; +export * from './auth.selectors'; +export * from './auth.service'; diff --git a/ui-ngx/src/app/core/public-api.ts b/ui-ngx/src/app/core/public-api.ts index e2c9352229..6232736584 100644 --- a/ui-ngx/src/app/core/public-api.ts +++ b/ui-ngx/src/app/core/public-api.ts @@ -22,3 +22,4 @@ export * from './ws/telemetry-websocket.service'; export * from './core.state'; export * from './core.module'; export * from './utils'; +export * from './auth/public-api';