From a5add7f52a66797d1e1335b02ca74a69f6018c4e Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Thu, 15 Jul 2021 12:40:36 +0200 Subject: [PATCH] Groundwork for internationalization of designer components --- .../elsa-workflows-studio/package-lock.json | 28 +++++++- .../elsa-workflows-studio/package.json | 2 + .../elsa-workflows-studio/src/components.d.ts | 20 ++++++ .../elsa-studio-home/elsa-studio-home.tsx | 55 +++++++++------ .../pages/elsa-studio-home/localizations.ts | 14 ++++ .../elsa-studio-root/elsa-studio-root.tsx | 46 +++++++++---- .../pages/elsa-studio-root/localizations.ts | 18 +++++ .../elsa-studio-webhook-definitions-list.tsx | 13 +++- .../localizations.ts | 14 ++++ .../elsa-studio-workflow-definitions-edit.tsx | 3 +- .../elsa-studio-workflow-definitions-list.tsx | 19 +++++- .../localizations.ts | 14 ++++ .../src/components/i18n/i18n-loader.ts | 14 ++++ .../src/components/i18n/intl-message.tsx | 9 +++ .../elsa-activity-editor-modal.tsx | 45 ++++++++---- .../localizations.ts | 68 +++++++++++++++++++ ...elsa-workflow-definition-editor-screen.tsx | 35 +++++++--- .../localizations.ts | 22 ++++++ .../elsa-workflow-publish-button.tsx | 34 +++++++--- .../localizations.ts | 20 ++++++ .../elsa-workflow-definitions-list-screen.tsx | 30 +++++--- .../localizations.ts | 30 ++++++++ .../elsa-confirm-dialog.tsx | 17 ++++- .../elsa-confirm-dialog/localizations.ts | 14 ++++ .../elsa-workflows-studio/src/index.html | 2 +- 25 files changed, 496 insertions(+), 90 deletions(-) create mode 100644 src/designer/elsa-workflows-studio/src/components/dashboard/pages/elsa-studio-home/localizations.ts create mode 100644 src/designer/elsa-workflows-studio/src/components/dashboard/pages/elsa-studio-root/localizations.ts create mode 100644 src/designer/elsa-workflows-studio/src/components/dashboard/pages/elsa-studio-webhook-definitions-list/localizations.ts create mode 100644 src/designer/elsa-workflows-studio/src/components/dashboard/pages/elsa-studio-workflow-definitions-list/localizations.ts create mode 100644 src/designer/elsa-workflows-studio/src/components/i18n/i18n-loader.ts create mode 100644 src/designer/elsa-workflows-studio/src/components/i18n/intl-message.tsx create mode 100644 src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-activity-editor-modal/localizations.ts create mode 100644 src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-workflow-definition-editor-screen/localizations.ts create mode 100644 src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-workflow-publish-button/localizations.ts create mode 100644 src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-list/elsa-workflow-definitions-screen/localizations.ts create mode 100644 src/designer/elsa-workflows-studio/src/components/shared/elsa-confirm-dialog/localizations.ts diff --git a/src/designer/elsa-workflows-studio/package-lock.json b/src/designer/elsa-workflows-studio/package-lock.json index 494d3eaf1..a7fab4b95 100644 --- a/src/designer/elsa-workflows-studio/package-lock.json +++ b/src/designer/elsa-workflows-studio/package-lock.json @@ -1,6 +1,6 @@ { "name": "@elsa-workflows/elsa-workflows-studio", - "version": "2.1.3", + "version": "2.1.4", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -27,6 +27,14 @@ "js-tokens": "^4.0.0" } }, + "@babel/runtime": { + "version": "7.14.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.6.tgz", + "integrity": "sha512-/PCB2uJ7oM44tz8YhC4Z/6PeOKXp4K588f+5M3clr1M4zbqztlo0XEfJ2LEzj/FgwfgGcIdl8n7YYjTCI0BYwg==", + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, "@csstools/convert-colors": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/@csstools/convert-colors/-/convert-colors-1.4.0.tgz", @@ -2391,6 +2399,19 @@ "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.1.0.tgz", "integrity": "sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg==" }, + "i18next": { + "version": "20.3.3", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-20.3.3.tgz", + "integrity": "sha512-tx9EUhHeaipvZ5pFLTaN9Xdm5Ssal774MpujaTA1Wv/ST/1My5SnoBmliY1lOpyEP5Z51Dq1gXifk/y4Yt3agQ==", + "requires": { + "@babel/runtime": "^7.12.0" + } + }, + "i18next-wc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/i18next-wc/-/i18next-wc-1.1.0.tgz", + "integrity": "sha512-CL1KYATH6MViR4wXRxXx3rRvlHh5hHD0GTzy5DpxrDlmDmzJMjHoCqd5HCWKmdLrUkFtdTkfNT0hARpsyJ8OKA==" + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -4083,6 +4104,11 @@ } } }, + "regenerator-runtime": { + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" + }, "regexpp": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", diff --git a/src/designer/elsa-workflows-studio/package.json b/src/designer/elsa-workflows-studio/package.json index 2349bddb3..7eb02ad98 100644 --- a/src/designer/elsa-workflows-studio/package.json +++ b/src/designer/elsa-workflows-studio/package.json @@ -51,6 +51,8 @@ "dagre-d3": "^0.6.4", "el-transition": "^0.0.7", "eslint": "7.29.0", + "i18next": "^20.3.3", + "i18next-wc": "^1.1.0", "js-event-bus": "^1.1.0", "lodash": "^4.17.21", "moment": "^2.29.1", diff --git a/src/designer/elsa-workflows-studio/src/components.d.ts b/src/designer/elsa-workflows-studio/src/components.d.ts index 1c72f27d4..4f75557cd 100644 --- a/src/designer/elsa-workflows-studio/src/components.d.ts +++ b/src/designer/elsa-workflows-studio/src/components.d.ts @@ -19,6 +19,7 @@ import { ToastNotificationOptions } from "./components/shared/elsa-toast-notific import { WebhookDefinition } from "./models/webhook"; export namespace Components { interface ElsaActivityEditorModal { + "culture": string; } interface ElsaActivityPickerModal { } @@ -32,6 +33,7 @@ export namespace Components { "propertyModel": ActivityDefinitionProperty; } interface ElsaConfirmDialog { + "culture": string; "hide": () => Promise; "show": (caption: string, message: string) => Promise; } @@ -160,8 +162,10 @@ export namespace Components { "propertyModel": ActivityDefinitionProperty; } interface ElsaStudioHome { + "culture": string; } interface ElsaStudioRoot { + "culture": string; "monacoLibPath": string; "serverUrl": string; } @@ -171,6 +175,7 @@ export namespace Components { "serverUrl": string; } interface ElsaStudioWebhookDefinitionsList { + "culture": string; "history": RouterHistory; "serverUrl": string; } @@ -179,11 +184,13 @@ export namespace Components { "serverUrl": string; } interface ElsaStudioWorkflowDefinitionsEdit { + "culture": string; "match": MatchResults; "monacoLibPath": string; "serverUrl": string; } interface ElsaStudioWorkflowDefinitionsList { + "culture": string; "history": RouterHistory; "serverUrl": string; } @@ -229,6 +236,7 @@ export namespace Components { interface ElsaWorkflowDefinitionEditorNotifications { } interface ElsaWorkflowDefinitionEditorScreen { + "culture": string; "exportWorkflow": () => Promise; "getServerUrl": () => Promise; "getWorkflowDefinitionId": () => Promise; @@ -238,6 +246,7 @@ export namespace Components { "workflowDefinitionId": string; } interface ElsaWorkflowDefinitionsListScreen { + "culture": string; "history"?: RouterHistory; "serverUrl": string; } @@ -264,6 +273,7 @@ export namespace Components { "workflowInstanceId": string; } interface ElsaWorkflowPublishButton { + "culture": string; "publishing": boolean; "workflowDefinition": WorkflowDefinition; } @@ -625,6 +635,7 @@ declare global { } declare namespace LocalJSX { interface ElsaActivityEditorModal { + "culture"?: string; } interface ElsaActivityPickerModal { } @@ -638,6 +649,7 @@ declare namespace LocalJSX { "propertyModel"?: ActivityDefinitionProperty; } interface ElsaConfirmDialog { + "culture"?: string; } interface ElsaContextMenu { "history"?: RouterHistory; @@ -772,8 +784,10 @@ declare namespace LocalJSX { "propertyModel"?: ActivityDefinitionProperty; } interface ElsaStudioHome { + "culture"?: string; } interface ElsaStudioRoot { + "culture"?: string; "monacoLibPath"?: string; "serverUrl"?: string; } @@ -783,6 +797,7 @@ declare namespace LocalJSX { "serverUrl"?: string; } interface ElsaStudioWebhookDefinitionsList { + "culture"?: string; "history"?: RouterHistory; "serverUrl"?: string; } @@ -791,11 +806,13 @@ declare namespace LocalJSX { "serverUrl"?: string; } interface ElsaStudioWorkflowDefinitionsEdit { + "culture"?: string; "match"?: MatchResults; "monacoLibPath"?: string; "serverUrl"?: string; } interface ElsaStudioWorkflowDefinitionsList { + "culture"?: string; "history"?: RouterHistory; "serverUrl"?: string; } @@ -836,12 +853,14 @@ declare namespace LocalJSX { interface ElsaWorkflowDefinitionEditorNotifications { } interface ElsaWorkflowDefinitionEditorScreen { + "culture"?: string; "monacoLibPath"?: string; "onWorkflowSaved"?: (event: CustomEvent) => void; "serverUrl"?: string; "workflowDefinitionId"?: string; } interface ElsaWorkflowDefinitionsListScreen { + "culture"?: string; "history"?: RouterHistory; "serverUrl"?: string; } @@ -865,6 +884,7 @@ declare namespace LocalJSX { "workflowInstanceId"?: string; } interface ElsaWorkflowPublishButton { + "culture"?: string; "onExportClicked"?: (event: CustomEvent) => void; "onImportClicked"?: (event: CustomEvent) => void; "onPublishClicked"?: (event: CustomEvent) => void; diff --git a/src/designer/elsa-workflows-studio/src/components/dashboard/pages/elsa-studio-home/elsa-studio-home.tsx b/src/designer/elsa-workflows-studio/src/components/dashboard/pages/elsa-studio-home/elsa-studio-home.tsx index de0f5c332..d3619b373 100644 --- a/src/designer/elsa-workflows-studio/src/components/dashboard/pages/elsa-studio-home/elsa-studio-home.tsx +++ b/src/designer/elsa-workflows-studio/src/components/dashboard/pages/elsa-studio-home/elsa-studio-home.tsx @@ -1,4 +1,9 @@ -import {Component, h, Prop, getAssetPath} from '@stencil/core'; +import {Component, getAssetPath, h, Prop} from '@stencil/core'; +import 'i18next-wc'; +import {GetIntlMessage, IntlMessage} from "../../../i18n/intl-message"; +import {loadTranslations} from "../../../i18n/i18n-loader"; +import {resources} from "./localizations"; +import {i18n} from "i18next"; @Component({ tag: 'elsa-studio-home', @@ -7,36 +12,42 @@ import {Component, h, Prop, getAssetPath} from '@stencil/core'; }) export class ElsaStudioHome { + @Prop() culture: string; + private i18next: i18n; + + async componentWillLoad() { + this.i18next = await loadTranslations(this.culture, resources); + } + render() { const visualPath = getAssetPath('./assets/undraw_breaking_barriers_vnf3.svg'); - + const IntlMessage = GetIntlMessage(this.i18next); + return (
-
-
-
-
-
-

- Welcome to - - Elsa Workflows 2.0 -

-

- Use the dashboard app to manage all the things. -

+
+
+
+
+
+

+ +

+

+ +

+
-
-
-
-
- +
+
+
+ +
-
-
+
); } diff --git a/src/designer/elsa-workflows-studio/src/components/dashboard/pages/elsa-studio-home/localizations.ts b/src/designer/elsa-workflows-studio/src/components/dashboard/pages/elsa-studio-home/localizations.ts new file mode 100644 index 000000000..e0056da9f --- /dev/null +++ b/src/designer/elsa-workflows-studio/src/components/dashboard/pages/elsa-studio-home/localizations.ts @@ -0,0 +1,14 @@ +export const resources = { + 'en': { + 'default': { + 'Welcome': 'Welcome to {{title}}', + 'Tagline': 'Use the dashboard app to manage all the things.' + } + }, + 'nl-NL': { + 'default': { + 'Welcome': 'Welkom bij {{title}}', + 'Tagline': 'Gebruik het dashboard om alles te regelen.' + } + } +}; \ No newline at end of file diff --git a/src/designer/elsa-workflows-studio/src/components/dashboard/pages/elsa-studio-root/elsa-studio-root.tsx b/src/designer/elsa-workflows-studio/src/components/dashboard/pages/elsa-studio-root/elsa-studio-root.tsx index 7d1761b62..96a4377c5 100644 --- a/src/designer/elsa-workflows-studio/src/components/dashboard/pages/elsa-studio-root/elsa-studio-root.tsx +++ b/src/designer/elsa-workflows-studio/src/components/dashboard/pages/elsa-studio-root/elsa-studio-root.tsx @@ -1,4 +1,8 @@ import {Component, h, Prop, getAssetPath} from '@stencil/core'; +import {loadTranslations} from "../../../i18n/i18n-loader"; +import {resources} from "./localizations"; +import {i18n} from "i18next"; +import {GetIntlMessage} from "../../../i18n/intl-message"; @Component({ tag: 'elsa-studio-root', @@ -9,10 +13,17 @@ export class ElsaStudioRoot { @Prop({attribute: 'server-url', reflect: true}) serverUrl: string; @Prop({attribute: 'monaco-lib-path', reflect: true}) monacoLibPath: string; + @Prop({attribute: 'culture', reflect: true}) culture: string; + private i18next: i18n; + + async componentWillLoad() { + this.i18next = await loadTranslations(this.culture, resources); + } render() { const serverUrl = this.serverUrl; + const culture = this.culture; const monacoLibPath = this.monacoLibPath; const logoPath = getAssetPath('./assets/logo.png'); @@ -20,6 +31,8 @@ export class ElsaStudioRoot { // const tunnelState: DashboardState = { // serverUrl: serverUrl, // }; + + const IntlMessage = GetIntlMessage(this.i18next); return (
@@ -28,25 +41,28 @@ export class ElsaStudioRoot {
- Workflow + Workflow
@@ -58,15 +74,15 @@ export class ElsaStudioRoot { {/**/} - - - - - - - - - + + + + + + + + + {/**/} diff --git a/src/designer/elsa-workflows-studio/src/components/dashboard/pages/elsa-studio-root/localizations.ts b/src/designer/elsa-workflows-studio/src/components/dashboard/pages/elsa-studio-root/localizations.ts new file mode 100644 index 000000000..bc45afdf5 --- /dev/null +++ b/src/designer/elsa-workflows-studio/src/components/dashboard/pages/elsa-studio-root/localizations.ts @@ -0,0 +1,18 @@ +export const resources = { + 'en': { + default: { + 'WorkflowDefinitions': 'Workflow Definitions', + 'WorkflowInstances': 'Workflow Instances', + 'WorkflowRegistry': 'Workflow Registry', + 'WebhookDefinitions': 'Webhook Definitions', + } + }, + 'nl-NL': { + default: { + 'WorkflowDefinitions': 'Workflow Definities', + 'WorkflowInstances': 'Workflows', + 'WorkflowRegistry': 'Workflow Register', + 'WebhookDefinitions': 'Webhook Definities', + } + } +}; \ No newline at end of file diff --git a/src/designer/elsa-workflows-studio/src/components/dashboard/pages/elsa-studio-webhook-definitions-list/elsa-studio-webhook-definitions-list.tsx b/src/designer/elsa-workflows-studio/src/components/dashboard/pages/elsa-studio-webhook-definitions-list/elsa-studio-webhook-definitions-list.tsx index e8eb5c6ce..33d86c016 100644 --- a/src/designer/elsa-workflows-studio/src/components/dashboard/pages/elsa-studio-webhook-definitions-list/elsa-studio-webhook-definitions-list.tsx +++ b/src/designer/elsa-workflows-studio/src/components/dashboard/pages/elsa-studio-webhook-definitions-list/elsa-studio-webhook-definitions-list.tsx @@ -1,5 +1,9 @@ import {Component, h, Prop, State} from '@stencil/core'; import {RouterHistory} from "@stencil/router"; +import 'i18next-wc'; +import {IntlMessage} from "../../../i18n/intl-message"; +import {loadTranslations} from "../../../i18n/i18n-loader"; +import {resources} from "./localizations"; @Component({ tag: 'elsa-studio-webhook-definitions-list', @@ -8,6 +12,11 @@ import {RouterHistory} from "@stencil/router"; export class ElsaStudioWebhookDefinitionsList { @Prop() history: RouterHistory; @Prop() serverUrl: string; + @Prop() culture: string; + + async componentWillLoad() { + await loadTranslations(this.culture, resources); + } render() { return ( @@ -15,13 +24,13 @@ export class ElsaStudioWebhookDefinitionsList {

- Webhook Definitions +

- Create Webhook +
diff --git a/src/designer/elsa-workflows-studio/src/components/dashboard/pages/elsa-studio-webhook-definitions-list/localizations.ts b/src/designer/elsa-workflows-studio/src/components/dashboard/pages/elsa-studio-webhook-definitions-list/localizations.ts new file mode 100644 index 000000000..1eb734c00 --- /dev/null +++ b/src/designer/elsa-workflows-studio/src/components/dashboard/pages/elsa-studio-webhook-definitions-list/localizations.ts @@ -0,0 +1,14 @@ +export const resources = { + 'en': { + default: { + 'Title': 'Webhook Definitions', + 'CreateButton': 'Create Webhook' + } + }, + 'nl-NL': { + default: { + 'Title': 'Webhook Definitie', + 'CreateButton': 'Maak Webhook' + } + } +}; \ No newline at end of file diff --git a/src/designer/elsa-workflows-studio/src/components/dashboard/pages/elsa-studio-workflow-definitions-edit/elsa-studio-workflow-definitions-edit.tsx b/src/designer/elsa-workflows-studio/src/components/dashboard/pages/elsa-studio-workflow-definitions-edit/elsa-studio-workflow-definitions-edit.tsx index 71f12b016..349faef9d 100644 --- a/src/designer/elsa-workflows-studio/src/components/dashboard/pages/elsa-studio-workflow-definitions-edit/elsa-studio-workflow-definitions-edit.tsx +++ b/src/designer/elsa-workflows-studio/src/components/dashboard/pages/elsa-studio-workflow-definitions-edit/elsa-studio-workflow-definitions-edit.tsx @@ -9,6 +9,7 @@ export class ElsaStudioWorkflowDefinitionsEdit { @Prop() match: MatchResults; @Prop() serverUrl: string; @Prop() monacoLibPath: string; + @Prop() culture: string; id?: string; @@ -25,7 +26,7 @@ export class ElsaStudioWorkflowDefinitionsEdit { const id = this.id; return
- +
; } } diff --git a/src/designer/elsa-workflows-studio/src/components/dashboard/pages/elsa-studio-workflow-definitions-list/elsa-studio-workflow-definitions-list.tsx b/src/designer/elsa-workflows-studio/src/components/dashboard/pages/elsa-studio-workflow-definitions-list/elsa-studio-workflow-definitions-list.tsx index ca4e43437..622f94ab7 100644 --- a/src/designer/elsa-workflows-studio/src/components/dashboard/pages/elsa-studio-workflow-definitions-list/elsa-studio-workflow-definitions-list.tsx +++ b/src/designer/elsa-workflows-studio/src/components/dashboard/pages/elsa-studio-workflow-definitions-list/elsa-studio-workflow-definitions-list.tsx @@ -1,5 +1,10 @@ import {Component, h, Prop, State} from '@stencil/core'; import {RouterHistory} from "@stencil/router"; +import 'i18next-wc'; +import {GetIntlMessage, IntlMessage} from "../../../i18n/intl-message"; +import {loadTranslations} from "../../../i18n/i18n-loader"; +import {resources} from "./localizations"; +import {i18n} from "i18next"; @Component({ tag: 'elsa-studio-workflow-definitions-list', @@ -8,25 +13,33 @@ import {RouterHistory} from "@stencil/router"; export class ElsaStudioWorkflowDefinitionsList { @Prop() history: RouterHistory; @Prop() serverUrl: string; + @Prop() culture: string; + private i18next: i18n; + + async componentWillLoad() { + this.i18next = await loadTranslations(this.culture, resources); + } render() { + const IntlMessage = GetIntlMessage(this.i18next); + return (

- Workflow Definitions +

- Create Workflow +
- +
); } diff --git a/src/designer/elsa-workflows-studio/src/components/dashboard/pages/elsa-studio-workflow-definitions-list/localizations.ts b/src/designer/elsa-workflows-studio/src/components/dashboard/pages/elsa-studio-workflow-definitions-list/localizations.ts new file mode 100644 index 000000000..b7cd56087 --- /dev/null +++ b/src/designer/elsa-workflows-studio/src/components/dashboard/pages/elsa-studio-workflow-definitions-list/localizations.ts @@ -0,0 +1,14 @@ +export const resources = { + 'en': { + default: { + 'Title': 'Workflow Definitions', + 'CreateButton': 'Create Workflow' + } + }, + 'nl-NL': { + default: { + 'Title': 'Workflow Definities', + 'CreateButton': 'Nieuwe Workflow' + } + } +}; \ No newline at end of file diff --git a/src/designer/elsa-workflows-studio/src/components/i18n/i18n-loader.ts b/src/designer/elsa-workflows-studio/src/components/i18n/i18n-loader.ts new file mode 100644 index 000000000..8d6aab3e6 --- /dev/null +++ b/src/designer/elsa-workflows-studio/src/components/i18n/i18n-loader.ts @@ -0,0 +1,14 @@ +import i18next from 'i18next'; + +export async function loadTranslations(language: string, resources: any, defaultNamespace?: string): Promise { + const instance = i18next.createInstance(); + await instance.init({ + lng: language, + fallbackLng: "en", + resources: resources, + defaultNS: defaultNamespace || 'default', + debug: true + }); + + return instance; +} \ No newline at end of file diff --git a/src/designer/elsa-workflows-studio/src/components/i18n/intl-message.tsx b/src/designer/elsa-workflows-studio/src/components/i18n/intl-message.tsx new file mode 100644 index 000000000..f6eb09ef2 --- /dev/null +++ b/src/designer/elsa-workflows-studio/src/components/i18n/intl-message.tsx @@ -0,0 +1,9 @@ +import i18next, {i18n} from 'i18next'; +import 'i18next-wc'; +import {h} from "@stencil/core"; + +export const IntlMessage = (props) => (); + +export function GetIntlMessage(i18next: i18n){ + return (props) => (); +} \ No newline at end of file diff --git a/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-activity-editor-modal/elsa-activity-editor-modal.tsx b/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-activity-editor-modal/elsa-activity-editor-modal.tsx index e5c613c53..57f37ccac 100644 --- a/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-activity-editor-modal/elsa-activity-editor-modal.tsx +++ b/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-activity-editor-modal/elsa-activity-editor-modal.tsx @@ -1,20 +1,24 @@ -import {Component, Event, h, Host, State} from '@stencil/core'; +import {Component, Event, h, Host, Prop, State} from '@stencil/core'; import {eventBus} from '../../../../services/event-bus'; import state from '../../../../utils/store'; import {ActivityDescriptor, ActivityModel, ActivityPropertyDescriptor, EventTypes, WorkflowStorageDescriptor} from "../../../../models"; import {propertyDisplayManager} from '../../../../services/property-display-manager'; import {checkBox, FormContext, section, selectField, SelectOption, textArea, textInput} from "../../../../utils/forms"; +import {i18n} from "i18next"; +import {loadTranslations} from "../../../i18n/i18n-loader"; +import {resources} from "./localizations"; @Component({ tag: 'elsa-activity-editor-modal', shadow: false, }) export class ElsaActivityEditorModal { - + @Prop() culture: string; @State() workflowStorageDescriptors: Array = []; @State() activityModel: ActivityModel; @State() activityDescriptor: ActivityDescriptor; @State() selectedTab: string = 'Properties'; + i18next: i18n; dialog: HTMLElsaModalDialogElement; form: HTMLFormElement; formContext: FormContext; @@ -24,18 +28,26 @@ export class ElsaActivityEditorModal { // This prevents the issue where the designer has e.g. one activity where the user edits the properties, cancels out, then opens the editor again, seeing the entered value still there. timestamp: Date = new Date(); + async componentWillLoad() { + this.i18next = await loadTranslations(this.culture, resources); + } + componentDidLoad() { + const t = this.t; + eventBus.on(EventTypes.ShowActivityEditor, async (activity: ActivityModel, animate: boolean) => { this.activityModel = JSON.parse(JSON.stringify(activity)); this.activityDescriptor = state.activityDescriptors.find(x => x.type == activity.type); this.workflowStorageDescriptors = state.workflowStorageDescriptors; this.formContext = new FormContext(this.activityModel, newValue => this.activityModel = newValue); - this.selectedTab = 'Properties'; + this.selectedTab = t('Properties'); this.timestamp = new Date(); await this.dialog.show(animate); }); } + t = (key: string) => this.i18next.t(key); + updateActivity(formData: FormData) { const activity = this.activityModel; const activityDescriptor = this.activityDescriptor; @@ -67,15 +79,16 @@ export class ElsaActivityEditorModal { const activityDescriptor: ActivityDescriptor = this.activityDescriptor || {displayName: '', type: '', outcomes: [], category: '', traits: 0, browsable: false, inputProperties: [], outputProperties: [], description: ''}; const propertyCategories = activityDescriptor.inputProperties.filter(x => x.category).map(x => x.category).distinct(); const defaultProperties = activityDescriptor.inputProperties.filter(x => !x.category || x.category.length == 0); + const t = this.t; let tabs: Array = []; if (defaultProperties.length > 0) { - tabs.push('Properties'); + tabs.push(t('Tabs.Properties.Name')); } tabs = [...tabs, ...propertyCategories]; - tabs.push('Common'); - tabs.push('Storage'); + tabs.push(t('Tabs.Common.Name')); + tabs.push(t('Tabs.Storage.Name')); let selectedTab = this.selectedTab; @@ -103,6 +116,7 @@ export class ElsaActivityEditorModal { const activityModel: ActivityModel = renderProps.activityModel; const inactiveClass = 'elsa-border-transparent elsa-text-gray-500 hover:elsa-text-gray-700 hover:elsa-border-gray-300'; const selectedClass = 'elsa-border-blue-500 elsa-text-blue-600'; + const t = this.t; return ( @@ -143,12 +157,12 @@ export class ElsaActivityEditorModal {
@@ -172,6 +186,7 @@ export class ElsaActivityEditorModal { renderStorageTab(activityModel: ActivityModel, activityDescriptor: ActivityDescriptor) { const formContext = this.formContext; + const t = this.t; let storageDescriptorOptions: Array = this.workflowStorageDescriptors.map(x => ({value: x.name, text: x.displayName})); let outputProperties = activityDescriptor.outputProperties; let inputProperties = activityDescriptor.inputProperties; @@ -185,7 +200,7 @@ export class ElsaActivityEditorModal { } return ( -
+
{section('Workflow Context')} @@ -209,13 +224,14 @@ export class ElsaActivityEditorModal { renderCommonTab(activityModel: ActivityModel) { const formContext = this.formContext; + const t = this.t; return ( -
+
- {textInput(formContext, 'name', 'Name', activityModel.name, 'The technical name of the activity.', 'activityName')} - {textInput(formContext, 'displayName', 'Display Name', activityModel.displayName, 'A friendly name of the activity.', 'activityDisplayName')} - {textArea(formContext, 'description', 'Description', activityModel.description, 'A custom description for this activity', 'activityDescription')} + {textInput(formContext, 'name', t('Tabs.Common.Fields.Name.Label'), activityModel.name, t('Tabs.Common.Fields.Name.Hint'), 'activityName')} + {textInput(formContext, 'displayName', t('Tabs.Common.Fields.DisplayName.Label'), activityModel.displayName, t('Tabs.Common.Fields.DisplayName.Hint'), 'activityDisplayName')} + {textArea(formContext, 'description', t('Tabs.Common.Fields.Description.Label'), activityModel.description, t('Tabs.Common.Fields.Description.Hint'), 'activityDescription')}
); @@ -228,9 +244,10 @@ export class ElsaActivityEditorModal { return undefined; const key = `activity-settings:${activityModel.activityId}`; + const t = this.t; return ( -
+
{propertyDescriptors.map(property => this.renderPropertyEditor(activityModel, property))}
); diff --git a/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-activity-editor-modal/localizations.ts b/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-activity-editor-modal/localizations.ts new file mode 100644 index 000000000..4e5f488e6 --- /dev/null +++ b/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-activity-editor-modal/localizations.ts @@ -0,0 +1,68 @@ +export const resources = { + 'en': { + 'default': { + "Buttons": { + 'Save': 'Save', + 'Cancel': 'Cancel' + }, + 'Tabs': { + 'Properties': { + 'Name': 'Properties' + }, + 'Common': { + 'Name': 'Common', + 'Fields': { + 'Name': { + 'Label': 'Name', + 'Hint': 'The technical name of the activity.' + }, + 'DisplayName': { + 'Label': 'Display Name', + 'Hint': 'The friendly name of the activity.' + }, + 'Description': { + 'Label': 'Description', + 'Hint': 'A custom description for this activity.' + } + } + }, + 'Storage': { + 'Name': 'Storage' + } + } + } + }, + 'nl-NL': { + 'default': { + 'Buttons': { + 'Save': 'Opslaan', + 'Cancel': 'Annuleren' + }, + 'Tabs': { + 'Properties': { + 'Name': 'Eigenschappen' + }, + 'Common': { + 'Name': 'Algemeen', + 'Fields': { + 'Name': { + 'Label': 'Naam', + 'Hint': 'De technische naam van de activity.' + }, + 'DisplayName': { + 'Label': 'Weergave Naam', + 'Hint': 'De gebruikersvriendelijke naam van de activity.' + }, + 'Description': { + 'Label': 'Omschrijving', + 'Hint': 'Een aangepaste omschrijving van de activity.' + } + } + }, + 'Storage': { + 'Name': 'Opslag' + } + } + } + } +}; \ No newline at end of file diff --git a/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-workflow-definition-editor-screen/elsa-workflow-definition-editor-screen.tsx b/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-workflow-definition-editor-screen/elsa-workflow-definition-editor-screen.tsx index 41ae543f1..f1025381b 100644 --- a/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-workflow-definition-editor-screen/elsa-workflow-definition-editor-screen.tsx +++ b/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-workflow-definition-editor-screen/elsa-workflow-definition-editor-screen.tsx @@ -8,6 +8,9 @@ import Tunnel, {WorkflowEditorState} from '../../../../data/workflow-editor'; import {downloadFromBlob} from "../../../../utils/download"; import {ActivityContextMenuState, WorkflowDesignerMode} from "../../../designers/tree/elsa-designer-tree/models"; import {registerClickOutside} from "stencil-click-outside"; +import {i18n} from "i18next"; +import {loadTranslations} from "../../../i18n/i18n-loader"; +import {resources} from "./localizations"; @Component({ tag: 'elsa-workflow-definition-editor-screen', @@ -23,6 +26,7 @@ export class ElsaWorkflowDefinitionEditorScreen { @Prop({attribute: 'workflow-definition-id', reflect: true}) workflowDefinitionId: string; @Prop({attribute: 'server-url', reflect: true}) serverUrl: string; @Prop({attribute: 'monaco-lib-path', reflect: true}) monacoLibPath: string; + @Prop() culture: string; @State() workflowDefinition: WorkflowDefinition; @State() workflowModel: WorkflowModel; @State() publishing: boolean; @@ -41,6 +45,7 @@ export class ElsaWorkflowDefinitionEditorScreen { activity: null, }; + i18next: i18n; el: HTMLElement; designer: HTMLElsaDesignerTreeElement; @@ -127,11 +132,20 @@ export class ElsaWorkflowDefinitionEditorScreen { } async componentWillLoad() { + this.i18next = await loadTranslations(this.culture, resources); await this.serverUrlChangedHandler(this.serverUrl); await this.workflowDefinitionIdChangedHandler(this.workflowDefinitionId); await this.monacoLibPathChangedHandler(this.monacoLibPath); } + async componentDidLoad() { + + if (!this.designer) { + this.designer = this.el.querySelector("elsa-designer-tree") as HTMLElsaDesignerTreeElement; + this.designer.model = this.workflowModel; + } + } + connectedCallback() { eventBus.on(EventTypes.UpdateWorkflowSettings, this.onUpdateWorkflowSettings); } @@ -139,13 +153,8 @@ export class ElsaWorkflowDefinitionEditorScreen { disconnectedCallback() { eventBus.detach(EventTypes.UpdateWorkflowSettings, this.onUpdateWorkflowSettings); } - - componentDidLoad() { - if (!this.designer) { - this.designer = this.el.querySelector("elsa-designer-tree") as HTMLElsaDesignerTreeElement; - this.designer.model = this.workflowModel; - } - } + + t = (key: string) => this.i18next.t(key); async loadActivityDescriptors() { const client = createElsaClient(this.serverUrl); @@ -402,6 +411,8 @@ export class ElsaWorkflowDefinitionEditorScreen { } renderActivityContextMenu() { + const t = this.t; + return
- Edit + {t('ActivityContextMenu.Edit')}
@@ -434,7 +445,7 @@ export class ElsaWorkflowDefinitionEditorScreen { href="#" class="elsa-block elsa-px-4 elsa-py-2 elsa-text-sm elsa-leading-5 elsa-text-gray-700 hover:elsa-bg-gray-100 hover:elsa-text-gray-900 focus:elsa-outline-none focus:elsa-bg-gray-100 focus:elsa-text-gray-900" role="menuitem"> - Delete + {t('ActivityContextMenu.Delete')}
@@ -446,7 +457,7 @@ export class ElsaWorkflowDefinitionEditorScreen { } renderActivityEditor() { - return ; + return ; } renderWorkflowSettingsButton() { @@ -471,8 +482,9 @@ export class ElsaWorkflowDefinitionEditorScreen { if (this.publishing) return undefined; + const t = this.t; const message = - this.unPublishing ? 'Unpublishing...' : this.unPublished ? 'Unpublished' + this.unPublishing ? t('Unpublishing...') : this.unPublished ? t('Unpublished') : this.saving ? 'Saving...' : this.saved ? 'Saved' : this.importing ? 'Importing...' : this.imported ? 'Imported' : null; @@ -505,6 +517,7 @@ export class ElsaWorkflowDefinitionEditorScreen { onUnPublishClicked={() => this.onUnPublishClicked()} onExportClicked={() => this.onExportClicked()} onImportClicked={e => this.onImportClicked(e.detail)} + culture={this.culture} />; } diff --git a/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-workflow-definition-editor-screen/localizations.ts b/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-workflow-definition-editor-screen/localizations.ts new file mode 100644 index 000000000..da730fe72 --- /dev/null +++ b/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-workflow-definition-editor-screen/localizations.ts @@ -0,0 +1,22 @@ +export const resources = { + 'en': { + 'default': { + 'Publishing': 'Publishing...', + 'Published': 'Published', + "ActivityContextMenu":{ + "Edit": "Edit", + "Delete": "Delete" + } + } + }, + 'nl-NL': { + 'default': { + 'Publishing': 'Publiceren...', + 'Published': 'Gepubliceerd', + "ActivityContextMenu":{ + "Edit": "Bewerken", + "Delete": "Verwijderen" + } + } + } +}; \ No newline at end of file diff --git a/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-workflow-publish-button/elsa-workflow-publish-button.tsx b/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-workflow-publish-button/elsa-workflow-publish-button.tsx index df774e961..113e4c256 100644 --- a/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-workflow-publish-button/elsa-workflow-publish-button.tsx +++ b/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-workflow-publish-button/elsa-workflow-publish-button.tsx @@ -1,9 +1,11 @@ import {Component, Host, h, Prop, State, Event, EventEmitter, Watch} from '@stencil/core'; -import {enter, leave, toggle} from 'el-transition' +import {leave, toggle} from 'el-transition' import {registerClickOutside} from "stencil-click-outside"; -import {VersionOptions, WorkflowDefinition} from "../../../../models"; -import {createElsaClient} from "../../../../services/elsa-client"; +import {WorkflowDefinition} from "../../../../models"; import Tunnel from '../../../../data/workflow-editor'; +import {i18n} from "i18next"; +import {loadTranslations} from "../../../i18n/i18n-loader"; +import {resources} from "./localizations"; @Component({ tag: 'elsa-workflow-publish-button', @@ -13,13 +15,21 @@ export class ElsaWorkflowPublishButton { @Prop() workflowDefinition: WorkflowDefinition; @Prop() publishing: boolean; + @Prop() culture: string; @Event({bubbles: true}) publishClicked: EventEmitter; @Event({bubbles: true}) unPublishClicked: EventEmitter; @Event({bubbles: true}) exportClicked: EventEmitter; @Event({bubbles: true}) importClicked: EventEmitter; + i18next: i18n; menu: HTMLElement; fileInput: HTMLInputElement; + + async componentWillLoad(){ + this.i18next = await loadTranslations(this.culture, resources); + } + + t = (key: string) => this.i18next.t(key); closeMenu() { leave(this.menu); @@ -66,6 +76,8 @@ export class ElsaWorkflowPublishButton { } render() { + const t = this.t; + return ( registerClickOutside(this, el, this.closeMenu)}> @@ -90,11 +102,11 @@ export class ElsaWorkflowPublishButton { @@ -110,16 +122,20 @@ export class ElsaWorkflowPublishButton { } renderPublishButton() { + const t = this.t; + return ( ); } renderPublishingButton() { + const t = this.t; + return ( ); } @@ -137,10 +153,12 @@ export class ElsaWorkflowPublishButton { if (!this.workflowDefinition.isPublished) return undefined; + const t = this.t; + return ( ); diff --git a/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-workflow-publish-button/localizations.ts b/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-workflow-publish-button/localizations.ts new file mode 100644 index 000000000..ed547fd61 --- /dev/null +++ b/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-workflow-publish-button/localizations.ts @@ -0,0 +1,20 @@ +export const resources = { + 'en': { + 'default': { + 'Publish': 'Publish', + 'Publishing': 'Publishing', + 'Unpublish': 'Unpublish', + 'Import': 'Import', + 'Export': 'Export', + } + }, + 'nl-NL': { + 'default': { + 'Publish': 'Publiceren', + 'Publishing': 'Bezig met publiceren', + 'Unpublish': 'Niet-publiceren', + 'Import': 'Importeren', + 'Export': 'Exporteren', + } + } +}; \ No newline at end of file diff --git a/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-list/elsa-workflow-definitions-screen/elsa-workflow-definitions-list-screen.tsx b/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-list/elsa-workflow-definitions-screen/elsa-workflow-definitions-list-screen.tsx index 78edfaf35..37d57f3c0 100644 --- a/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-list/elsa-workflow-definitions-screen/elsa-workflow-definitions-list-screen.tsx +++ b/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-list/elsa-workflow-definitions-screen/elsa-workflow-definitions-list-screen.tsx @@ -2,6 +2,10 @@ import {Component, h, Prop, State} from '@stencil/core'; import {createElsaClient} from "../../../../services/elsa-client"; import {PagedList, VersionOptions, WorkflowDefinitionSummary} from "../../../../models"; import {RouterHistory} from "@stencil/router"; +import {i18n} from "i18next"; +import {loadTranslations} from "../../../i18n/i18n-loader"; +import {resources} from "./localizations"; +import {GetIntlMessage} from "../../../i18n/intl-message"; @Component({ tag: 'elsa-workflow-definitions-list-screen', @@ -10,17 +14,21 @@ import {RouterHistory} from "@stencil/router"; export class ElsaWorkflowDefinitionsListScreen { @Prop() history?: RouterHistory; @Prop() serverUrl: string; + @Prop() culture: string; @State() workflowDefinitions: PagedList = {items: [], page: 1, pageSize: 50, totalCount: 0}; @State() publishedWorkflowDefinitions: WorkflowDefinitionSummary[] = []; + private i18next: i18n; confirmDialog: HTMLElsaConfirmDialogElement; async componentWillLoad() { + this.i18next = await loadTranslations(this.culture, resources); await this.loadWorkflowDefinitions(); } async onDeleteClick(e: Event, workflowDefinition: WorkflowDefinitionSummary) { - const result = await this.confirmDialog.show('Delete Workflow Definition', 'Are you sure you wish to permanently delete this workflow, including all of its workflow instances?'); + const t = x => this.i18next.t(x); + const result = await this.confirmDialog.show(t('DeleteConfirmationModel.Title'), t('DeleteConfirmationModel.Message')); if (!result) return; @@ -48,6 +56,8 @@ export class ElsaWorkflowDefinitionsListScreen { render() { const workflowDefinitions = this.workflowDefinitions.items; + const i18next = this.i18next; + const IntlMessage = GetIntlMessage(i18next); return (
@@ -55,15 +65,17 @@ export class ElsaWorkflowDefinitionsListScreen { - + @@ -112,7 +124,7 @@ export class ElsaWorkflowDefinitionsListScreen { @@ -120,8 +132,8 @@ export class ElsaWorkflowDefinitionsListScreen { @@ -131,7 +143,7 @@ export class ElsaWorkflowDefinitionsListScreen {
Name - Instances + + +
- Instances +
this.onDeleteClick(e, workflowDefinition), icon: deleteIcon} + {text: i18next.t('Edit'), anchorUrl: editUrl, icon: editIcon}, + {text: i18next.t('Delete'), clickHandler: e => this.onDeleteClick(e, workflowDefinition), icon: deleteIcon} ]}/>
- this.confirmDialog = el}/> + this.confirmDialog = el} culture={this.culture}/>
); } diff --git a/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-list/elsa-workflow-definitions-screen/localizations.ts b/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-list/elsa-workflow-definitions-screen/localizations.ts new file mode 100644 index 000000000..d38b71d20 --- /dev/null +++ b/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-list/elsa-workflow-definitions-screen/localizations.ts @@ -0,0 +1,30 @@ +export const resources = { + 'en': { + 'default': { + 'Name': 'Name', + 'Instances': 'Instances', + 'LatestVersion': 'Latest Version', + 'PublishedVersion': 'Published Version', + 'Edit': 'Edit', + 'Delete': 'Delete', + 'DeleteConfirmationModel': { + 'Title': 'Delete Workflow Definition', + 'Message': 'Are you sure you wish to permanently delete this workflow, including all of its workflow instances?' + } + } + }, + 'nl-NL': { + 'default': { + 'Name': 'Naam', + 'Instances': 'Instanties', + 'LatestVersion': 'Laatste Versie', + 'PublishedVersion': 'Gepubliceerde Versie', + 'Edit': 'Bewerken', + 'Delete': 'Verwijderen', + 'DeleteConfirmationModel': { + 'Title': 'Verwijder Workflow Definitie', + 'Message': 'Weet je zeker dat je deze workflow permanent wilt verwijderen, inclusief alle bijbehorende workflow instanties?' + } + } + } +}; \ No newline at end of file diff --git a/src/designer/elsa-workflows-studio/src/components/shared/elsa-confirm-dialog/elsa-confirm-dialog.tsx b/src/designer/elsa-workflows-studio/src/components/shared/elsa-confirm-dialog/elsa-confirm-dialog.tsx index fb0fefdcb..574d455ed 100644 --- a/src/designer/elsa-workflows-studio/src/components/shared/elsa-confirm-dialog/elsa-confirm-dialog.tsx +++ b/src/designer/elsa-workflows-studio/src/components/shared/elsa-confirm-dialog/elsa-confirm-dialog.tsx @@ -1,4 +1,7 @@ -import {Component, h, Host, Method, State} from '@stencil/core'; +import {Component, h, Host, Method, Prop, State} from '@stencil/core'; +import {i18n} from "i18next"; +import {loadTranslations} from "../../i18n/i18n-loader"; +import {resources} from "./localizations"; @Component({ tag: 'elsa-confirm-dialog', @@ -8,6 +11,8 @@ export class ElsaConfirmDialog { @State() caption: string; @State() message: string; + @Prop() culture: string; + private i18next: i18n; dialog: HTMLElsaModalDialogElement; fulFill: (value: (PromiseLike | boolean)) => void; @@ -31,6 +36,10 @@ export class ElsaConfirmDialog { await this.dialog.hide(true); } + async componentWillLoad() { + this.i18next = await loadTranslations(this.culture, resources); + } + async onDismissClick() { this.fulFill(false); await this.hide(); @@ -44,6 +53,8 @@ export class ElsaConfirmDialog { } render() { + const t = x => this.i18next.t(x); + return ( this.dialog = el}> @@ -81,12 +92,12 @@ export class ElsaConfirmDialog {
diff --git a/src/designer/elsa-workflows-studio/src/components/shared/elsa-confirm-dialog/localizations.ts b/src/designer/elsa-workflows-studio/src/components/shared/elsa-confirm-dialog/localizations.ts new file mode 100644 index 000000000..072df82f4 --- /dev/null +++ b/src/designer/elsa-workflows-studio/src/components/shared/elsa-confirm-dialog/localizations.ts @@ -0,0 +1,14 @@ +export const resources = { + 'en': { + 'default': { + 'Yes': 'Yes', + 'No': 'No' + } + }, + 'nl-NL': { + 'default': { + 'Yes': 'Ja', + 'No': 'Nee', + } + } +}; \ No newline at end of file diff --git a/src/designer/elsa-workflows-studio/src/index.html b/src/designer/elsa-workflows-studio/src/index.html index a56b287ed..14fb1245b 100644 --- a/src/designer/elsa-workflows-studio/src/index.html +++ b/src/designer/elsa-workflows-studio/src/index.html @@ -14,7 +14,7 @@ - +