feat: Add dynamic translations. Change how sharing unavailable is handled (no-changelog) (#4758)

* feat: Add dynamic translations. Change how sharing unavailable is handled (no-changelog)

* fix: Add not-allowed cursor for disabled share button

* fix: Remove fakedoor features from workflow details

* fix: Remove fakedoor code from workflow share modal

* fix: change dynamic translation to match shareModal title

* chore: Removed unused import
This commit is contained in:
Alex Grozav 2022-11-29 15:13:10 +02:00 committed by GitHub
parent 86a4965e9a
commit b1287ba8cb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 73 additions and 16 deletions

View file

@ -1022,6 +1022,10 @@ export interface IModalState {
httpNodeParameters?: string;
}
export interface NestedRecord<T> {
[key: string]: T | NestedRecord<T>;
}
export type IRunDataDisplayMode = 'table' | 'json' | 'binary';
export type nodePanelType = 'input' | 'output';
@ -1095,6 +1099,7 @@ export interface UIState {
currentView: string;
mainPanelPosition: number;
fakeDoorFeatures: IFakeDoor[];
dynamicTranslations: NestedRecord<string>;
draggable: {
isDragging: boolean;
type: string;

View file

@ -75,6 +75,25 @@
>
{{ $locale.baseText('workflowDetails.share') }}
</n8n-button>
<template #fallback>
<n8n-tooltip>
<n8n-button
type="secondary"
:class="['mr-2xs', $style.disabledShareButton]"
>
{{ $locale.baseText('workflowDetails.share') }}
</n8n-button>
<template #content>
<i18n :path="dynamicTranslations.workflows.sharing.unavailable.description" tag="span">
<template #action>
<a :href="dynamicTranslations.workflows.sharing.unavailable.linkURL" target="_blank">
{{ $locale.baseText(dynamicTranslations.workflows.sharing.unavailable.action) }}
</a>
</template>
</i18n>
</template>
</n8n-tooltip>
</template>
</enterprise-edition>
<SaveButton
type="primary"
@ -114,7 +133,7 @@ import SaveButton from "@/components/SaveButton.vue";
import TagsDropdown from "@/components/TagsDropdown.vue";
import InlineTextEdit from "@/components/InlineTextEdit.vue";
import BreakpointsObserver from "@/components/BreakpointsObserver.vue";
import {IWorkflowDataUpdate, IWorkflowDb, IWorkflowToShare} from "@/Interface";
import {IWorkflowDataUpdate, IWorkflowDb, IWorkflowToShare, NestedRecord} from "@/Interface";
import { saveAs } from 'file-saver';
import { titleChange } from "@/mixins/titleChange";
@ -169,6 +188,9 @@ export default mixins(workflowHelpers, titleChange).extend({
useWorkflowsStore,
useUsersStore,
),
dynamicTranslations(): NestedRecord<string> {
return this.uiStore.dynamicTranslations;
},
isWorkflowActive(): boolean {
return this.workflowsStore.isWorkflowActive;
},
@ -548,4 +570,8 @@ $--header-spacing: 20px;
.deleteItem {
color: var(--color-danger);
}
.disabledShareButton {
cursor: not-allowed;
}
</style>

View file

@ -1,7 +1,7 @@
<template>
<Modal
width="460px"
:title="$locale.baseText(fakeDoor.actionBoxTitle, { interpolate: { name: workflow.name } })"
:title="$locale.baseText(dynamicTranslations.workflows.shareModal.title, { interpolate: { name: workflow.name } })"
:eventBus="modalBus"
:name="WORKFLOW_SHARE_MODAL_KEY"
:center="true"
@ -52,7 +52,9 @@
</n8n-users-list>
<template #fallback>
<n8n-text>
{{ $locale.baseText(fakeDoor.actionBoxDescription) }}
<i18n :path="dynamicTranslations.workflows.sharing.unavailable.description" tag="span">
<template #action />
</i18n>
</n8n-text>
</template>
</enterprise-edition>
@ -80,12 +82,12 @@
</n8n-button>
<template #fallback>
<n8n-link :to="fakeDoor.linkURL">
<n8n-link :to="dynamicTranslations.workflows.sharing.unavailable.linkURL">
<n8n-button
:loading="loading"
size="medium"
>
{{ $locale.baseText(fakeDoor.actionBoxButtonLabel) }}
{{ $locale.baseText(dynamicTranslations.workflows.sharing.unavailable.button) }}
</n8n-button>
</n8n-link>
</template>
@ -99,11 +101,10 @@ import Vue from 'vue';
import Modal from './Modal.vue';
import {
EnterpriseEditionFeature,
FAKE_DOOR_FEATURES,
PLACEHOLDER_EMPTY_WORKFLOW_ID,
WORKFLOW_SHARE_MODAL_KEY,
} from '../constants';
import {IFakeDoor, IUser, IWorkflowDb} from "@/Interface";
import {IUser, IWorkflowDb, NestedRecord} from "@/Interface";
import { getWorkflowPermissions, IPermissions } from "@/permissions";
import mixins from "vue-typed-mixins";
import {showMessage} from "@/mixins/showMessage";
@ -174,8 +175,8 @@ export default mixins(
isSharingAvailable(): boolean {
return this.settingsStore.isEnterpriseFeatureEnabled(EnterpriseEditionFeature.WorkflowSharing) === true;
},
fakeDoor(): IFakeDoor | undefined {
return this.uiStore.getFakeDoorById(FAKE_DOOR_FEATURES.WORKFLOWS_SHARING);
dynamicTranslations(): NestedRecord<string> {
return this.uiStore.dynamicTranslations;
},
isDirty(): boolean {
const previousSharedWith = this.workflow.sharedWith || [];

View file

@ -489,11 +489,6 @@
"fakeDoor.credentialEdit.sharing.actionBox.title.cloud.upgrade": "Upgrade to add users",
"fakeDoor.credentialEdit.sharing.actionBox.description.cloud.upgrade": "Power and Pro plan users can create multiple user accounts and share credentials. (Sharing workflows is coming soon)",
"fakeDoor.credentialEdit.sharing.actionBox.button.cloud.upgrade": "Upgrade",
"fakeDoor.workflowsSharing.title.cloud.upgrade": "Upgrade to add users",
"fakeDoor.workflowsSharing.description": "Sharing workflows with others is currently available only on n8n cloud, our hosted offering.",
"fakeDoor.workflowsSharing.description.cloud.upgrade": "Power and Pro plan users can create multiple user accounts and share workflows.",
"fakeDoor.workflowsSharing.button": "Explore n8n cloud",
"fakeDoor.workflowsSharing.button.cloud.upgrade": "Upgrade",
"fakeDoor.settings.environments.name": "Environments",
"fakeDoor.settings.environments.infoText": "Environments allow you to use different settings and credentials in a workflow when you're building it vs when it's running in production",
"fakeDoor.settings.environments.actionBox.title": "Were working on environments (as a paid feature)",
@ -1404,5 +1399,14 @@
"importParameter.showError.invalidCurlCommand.message": "This command is in an unsupported format",
"importParameter.showError.invalidProtocol1.title": "Use the {node} node",
"importParameter.showError.invalidProtocol2.title": "Invalid Protocol",
"importParameter.showError.invalidProtocol.message": "The HTTP node doesnt support {protocol} requests"
"importParameter.showError.invalidProtocol.message": "The HTTP node doesnt support {protocol} requests",
"dynamic.workflows.shareModal.title": "Share '{name}'",
"dynamic.workflows.shareModal.title.cloud.upgrade": "Upgrade to add users",
"dynamic.workflows.sharing.unavailable.description": "Sharing workflows with others is currently available only on n8n cloud, our hosted offering. {action}",
"dynamic.workflows.sharing.unavailable.description.cloud.upgrade": "Sharing is available for Team and Enterprise plans. {action} to unlock more features.",
"dynamic.workflows.sharing.unavailable.action": "Explore n8n cloud",
"dynamic.workflows.sharing.unavailable.action.cloud.upgrade": "Upgrade now",
"dynamic.workflows.sharing.unavailable.button": "Explore n8n cloud",
"dynamic.workflows.sharing.unavailable.button.cloud.upgrade": "Upgrade now",
"dynamic.workflows.sharing.unavailable.linkUrl": "https://n8n.cloud"
}

View file

@ -161,6 +161,21 @@ export const useUIStore = defineStore(STORES.UI, {
uiLocations: ['workflowShareModal'],
},
],
dynamicTranslations: {
workflows: {
shareModal: {
title: 'dynamic.workflows.shareModal.title',
},
sharing: {
unavailable: {
description: 'dynamic.workflows.sharing.unavailable.description',
action: 'dynamic.workflows.sharing.unavailable.action',
button: 'dynamic.workflows.sharing.unavailable.button',
linkURL: 'https://n8n.cloud',
},
},
},
},
draggable: {
isDragging: false,
type: '',

View file

@ -1,5 +1,5 @@
import { STORES } from "@/constants";
import { IFakeDoor, INodeUi, IRootState } from "@/Interface";
import {IFakeDoor, INodeUi, IRootState, NestedRecord} from "@/Interface";
import { IMenuItem } from "n8n-design-system";
import { IWorkflowSettings } from "n8n-workflow";
import { defineStore } from "pinia";
@ -15,6 +15,9 @@ export const useWebhooksStore = defineStore(STORES.WEBHOOKS, {
globalRoleName(): string {
return useUsersStore().globalRoleName;
},
getDynamicTranslations () {
return useUIStore().dynamicTranslations;
},
getFakeDoorFeatures () {
return useUIStore().fakeDoorFeatures;
},
@ -61,5 +64,8 @@ export const useWebhooksStore = defineStore(STORES.WEBHOOKS, {
setFakeDoorFeatures(fakeDoors: IFakeDoor[]): void {
useUIStore().fakeDoorFeatures = fakeDoors;
},
setDynamicTranslations(translations: NestedRecord<string>): void {
useUIStore().dynamicTranslations = translations;
},
},
});