feat(editor): Version Control settings update (WIP) (#6233)

This commit is contained in:
Csaba Tuncsik 2023-05-12 09:26:41 +02:00 committed by GitHub
parent 51c89db6dc
commit 0666377ef8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 156 additions and 66 deletions

View file

@ -1438,7 +1438,8 @@ export type VersionControlPreferences = {
repositoryUrl: string; repositoryUrl: string;
authorName: string; authorName: string;
authorEmail: string; authorEmail: string;
branchName: string; currentBranch: string;
branches: string[];
branchReadOnly: boolean; branchReadOnly: boolean;
branchColor: string; branchColor: string;
publicKey?: string; publicKey?: string;

View file

@ -1290,18 +1290,26 @@
"settings.versionControl.actionBox.title": "Available on Enterprise plan", "settings.versionControl.actionBox.title": "Available on Enterprise plan",
"settings.versionControl.actionBox.description": "Use Version Control to connect your instance to an external Git repository to backup and track changes made to your workflows, variables, and credentials. With Version Control you can also sync instances across multiple environments (development, production...).", "settings.versionControl.actionBox.description": "Use Version Control to connect your instance to an external Git repository to backup and track changes made to your workflows, variables, and credentials. With Version Control you can also sync instances across multiple environments (development, production...).",
"settings.versionControl.actionBox.buttonText": "See plans", "settings.versionControl.actionBox.buttonText": "See plans",
"settings.versionControl.description": "Versioning allows you to connect your n8n instance to a Git branch of a repository. You can connect your branches to multiples n8n instances to create a multi environments setup. Learn how to set up versioning and environments in n8n.", "settings.versionControl.description": "Versioning allows you to connect your n8n instance to a Git branch of a repository. You can connect your branches to multiples n8n instances to create a multi environments setup. {link}",
"settings.versionControl.repoUrl": "Git repository URL", "settings.versionControl.description.link": "Learn how to set up versioning and environments in n8n.",
"settings.versionControl.gitConfig": "Git configuration",
"settings.versionControl.repoUrl": "Git repository URL (SSH)",
"settings.versionControl.repoUrlPlaceholder": "e.g. git@github.com:my-team/my-repository", "settings.versionControl.repoUrlPlaceholder": "e.g. git@github.com:my-team/my-repository",
"settings.versionControl.repoUrlDescription": "The SSH url of your Git repository", "settings.versionControl.repoUrlDescription": "The SSH url of your Git repository",
"settings.versionControl.authorName": "Author name", "settings.versionControl.authorName": "Commit author name",
"settings.versionControl.authorEmail": "Author email", "settings.versionControl.authorEmail": "Commit author email",
"settings.versionControl.sshKey": "SSH Key", "settings.versionControl.sshKey": "SSH Key",
"settings.versionControl.sshKeyDescription": "Paste the SSH key in yout git repository settings. {link}.", "settings.versionControl.sshKeyDescription": "Paste the SSH key in yout git repository settings. {link}.",
"settings.versionControl.sshKeyDescriptionLink": "More info.", "settings.versionControl.sshKeyDescriptionLink": "More info.",
"settings.versionControl.button.continue": "Continue", "settings.versionControl.button.continue": "Continue",
"settings.versionControl.button.connect": "Connect", "settings.versionControl.button.connect": "Connect",
"settings.versionControl.branches": "Select branch", "settings.versionControl.button.save": "Save settings",
"settings.versionControl.instanceSettings": "Instance settings",
"settings.versionControl.branches": "Branch connected to this n8n instance",
"settings.versionControl.readonly": "{bold}: prevent editing workflows (recommended for production environments). {link}",
"settings.versionControl.readonly.bold": "Read-only instance",
"settings.versionControl.readonly.link": "Learn more.",
"settings.versionControl.color": "Color",
"settings.versionControl.switchBranch.title": "Switch to {branch} branch", "settings.versionControl.switchBranch.title": "Switch to {branch} branch",
"settings.versionControl.switchBranch.description": "Please confirm you want to switch the current n8n instance to the branch: {branch}", "settings.versionControl.switchBranch.description": "Please confirm you want to switch the current n8n instance to the branch: {branch}",
"settings.versionControl.sync.prompt.title": "Sync changes in {branch} branch", "settings.versionControl.sync.prompt.title": "Sync changes in {branch} branch",

View file

@ -16,12 +16,13 @@ export const useVersionControlStore = defineStore('versionControl', () => {
); );
const preferences = reactive<VersionControlPreferences>({ const preferences = reactive<VersionControlPreferences>({
branchName: '', currentBranch: '',
branches: [],
authorName: '', authorName: '',
authorEmail: '', authorEmail: '',
repositoryUrl: '', repositoryUrl: '',
branchReadOnly: false, branchReadOnly: false,
branchColor: '#000000', branchColor: '#F4A6DC',
connected: false, connected: false,
publicKey: '', publicKey: '',
}); });
@ -77,6 +78,7 @@ export const useVersionControlStore = defineStore('versionControl', () => {
return { return {
isEnterpriseVersionControlEnabled, isEnterpriseVersionControlEnabled,
state, state,
preferences,
initSsh, initSsh,
initRepository, initRepository,
sync, sync,

View file

@ -1,19 +1,14 @@
<script lang="ts" setup> <script lang="ts" setup>
import { computed, ref } from 'vue';
import { i18n as locale } from '@/plugins/i18n'; import { i18n as locale } from '@/plugins/i18n';
import { useVersionControlStore } from '@/stores/versionControl.store'; import { useVersionControlStore } from '@/stores/versionControl.store';
import { useUIStore } from '@/stores/ui.store'; import { useUIStore } from '@/stores/ui.store';
import { useMessage } from '@/composables'; import { useMessage } from '@/composables';
import CopyInput from '@/components/CopyInput.vue';
const versionControlStore = useVersionControlStore(); const versionControlStore = useVersionControlStore();
const uiStore = useUIStore(); const uiStore = useUIStore();
const message = useMessage(); const message = useMessage();
const sshKey = computed(() => versionControlStore.state.sshKey);
const branch = computed(() => versionControlStore.state.currentBranch);
const branches = ref<string[]>([]);
const selectElement = ref<HTMLSelectElement | null>(null);
const onContinue = () => { const onContinue = () => {
void versionControlStore.initSsh({ void versionControlStore.initSsh({
name: versionControlStore.state.authorName, name: versionControlStore.state.authorName,
@ -26,22 +21,15 @@ const onConnect = () => {
void versionControlStore.initRepository(); void versionControlStore.initRepository();
}; };
const onSave = () => {
void versionControlStore.savePreferences(versionControlStore.preferences);
};
const onSelect = async (b: string) => { const onSelect = async (b: string) => {
if (b === branch.value) { if (b === versionControlStore.preferences.currentBranch) {
return; return;
} }
const switchBranch = await message versionControlStore.preferences.currentBranch = b;
.confirm(
locale.baseText('settings.versionControl.switchBranch.description', {
interpolate: { branch: b },
}),
locale.baseText('settings.versionControl.switchBranch.title', { interpolate: { branch: b } }),
)
.catch(() => {});
if (switchBranch === 'confirm') {
versionControlStore.state.currentBranch = b;
selectElement.value?.blur();
}
}; };
const goToUpgrade = () => { const goToUpgrade = () => {
@ -51,40 +39,59 @@ const goToUpgrade = () => {
<template> <template>
<div> <div>
<n8n-heading size="2xlarge">{{ locale.baseText('settings.versionControl.title') }}</n8n-heading> <n8n-heading size="2xlarge" tag="h1">{{
locale.baseText('settings.versionControl.title')
}}</n8n-heading>
<div <div
v-if="versionControlStore.isEnterpriseVersionControlEnabled" v-if="versionControlStore.isEnterpriseVersionControlEnabled"
data-test-id="version-control-content-licensed" data-test-id="version-control-content-licensed"
> >
<n8n-callout theme="secondary" icon="info-circle" class="mt-2xl mb-l">{{ <n8n-callout theme="secondary" icon="info-circle" class="mt-2xl mb-l">
locale.baseText('settings.versionControl.description') <i18n path="settings.versionControl.description">
}}</n8n-callout> <template #link>
<a href="#" target="_blank">
{{ locale.baseText('settings.versionControl.description.link') }}
</a>
</template>
</i18n>
</n8n-callout>
<n8n-heading size="xlarge" tag="h2" class="mb-s">{{
locale.baseText('settings.versionControl.gitConfig')
}}</n8n-heading>
<div :class="$style.group"> <div :class="$style.group">
<label for="repoUrl">{{ locale.baseText('settings.versionControl.repoUrl') }}</label> <label for="repoUrl">{{ locale.baseText('settings.versionControl.repoUrl') }}</label>
<n8n-input <n8n-input
id="repoUrl" id="repoUrl"
:placeholder="locale.baseText('settings.versionControl.repoUrlPlaceholder')" :placeholder="locale.baseText('settings.versionControl.repoUrlPlaceholder')"
v-model="versionControlStore.state.repositoryUrl" v-model="versionControlStore.preferences.repositoryUrl"
/> />
<small>{{ locale.baseText('settings.versionControl.repoUrlDescription') }}</small> <small>{{ locale.baseText('settings.versionControl.repoUrlDescription') }}</small>
</div> </div>
<div :class="$style.group"> <div :class="[$style.group, $style.groupFlex]">
<label for="authorName">{{ locale.baseText('settings.versionControl.authorName') }}</label> <div>
<n8n-input id="authorName" v-model="versionControlStore.state.authorName" /> <label for="authorName">{{
locale.baseText('settings.versionControl.authorName')
}}</label>
<n8n-input id="authorName" v-model="versionControlStore.preferences.authorName" />
</div> </div>
<div :class="$style.group"> <div>
<label for="authorEmail">{{ <label for="authorEmail">{{
locale.baseText('settings.versionControl.authorEmail') locale.baseText('settings.versionControl.authorEmail')
}}</label> }}</label>
<n8n-input id="authorEmail" v-model="versionControlStore.state.authorEmail" /> <n8n-input id="authorEmail" v-model="versionControlStore.preferences.authorEmail" />
</div> </div>
<n8n-button v-if="!sshKey" @click="onContinue" size="large" class="mt-2xs">{{ </div>
locale.baseText('settings.versionControl.button.continue') <n8n-button
}}</n8n-button> v-if="!versionControlStore.preferences.publicKey"
<div v-if="sshKey" :class="$style.group"> @click="onContinue"
size="large"
class="mt-2xs"
>{{ locale.baseText('settings.versionControl.button.continue') }}</n8n-button
>
<div v-if="versionControlStore.preferences.publicKey" :class="$style.group">
<label>{{ locale.baseText('settings.versionControl.sshKey') }}</label> <label>{{ locale.baseText('settings.versionControl.sshKey') }}</label>
<CopyInput <CopyInput
:value="versionControlStore.state.sshKey" :value="versionControlStore.preferences.publicKey"
:copy-button-text="locale.baseText('generic.clickToCopy')" :copy-button-text="locale.baseText('generic.clickToCopy')"
/> />
<n8n-notice type="info" class="mt-s"> <n8n-notice type="info" class="mt-s">
@ -97,25 +104,70 @@ const goToUpgrade = () => {
</i18n> </i18n>
</n8n-notice> </n8n-notice>
</div> </div>
<n8n-button v-if="sshKey" @click="onConnect" size="large" :class="$style.connect">{{ <n8n-button
locale.baseText('settings.versionControl.button.connect') v-if="
}}</n8n-button> versionControlStore.preferences.publicKey &&
<div v-if="versionControlStore.state.branches.length" :class="$style.group"> !versionControlStore.preferences.branches.length
"
@click="onConnect"
size="large"
:class="$style.connect"
>{{ locale.baseText('settings.versionControl.button.connect') }}</n8n-button
>
<div v-if="versionControlStore.preferences.branches.length">
<div :class="$style.group">
<hr />
<n8n-heading size="xlarge" tag="h2" class="mb-s">{{
locale.baseText('settings.versionControl.instanceSettings')
}}</n8n-heading>
<label>{{ locale.baseText('settings.versionControl.branches') }}</label> <label>{{ locale.baseText('settings.versionControl.branches') }}</label>
<n8n-select <n8n-select
ref="selectElement" :value="versionControlStore.preferences.currentBranch"
:value="versionControlStore.state.currentBranch" class="mb-s"
size="medium" size="medium"
filterable filterable
@input="onSelect" @input="onSelect"
> >
<n8n-option <n8n-option
v-for="b in versionControlStore.state.branches" v-for="b in versionControlStore.preferences.branches"
:key="b" :key="b"
:value="b" :value="b"
:label="b" :label="b"
/> />
</n8n-select> </n8n-select>
<n8n-checkbox
v-model="versionControlStore.preferences.branchReadOnly"
:class="$style.readOnly"
>
<i18n path="settings.versionControl.readonly">
<template #bold>
<strong>{{ locale.baseText('settings.versionControl.readonly.bold') }}</strong>
</template>
<template #link>
<a href="#" target="_blank">
{{ locale.baseText('settings.versionControl.readonly.link') }}
</a>
</template>
</i18n>
</n8n-checkbox>
</div>
<div :class="$style.group">
<label>{{ locale.baseText('settings.versionControl.color') }}</label>
<div>
<n8n-color-picker size="small" v-model="versionControlStore.preferences.branchColor" />
</div>
</div>
<div :class="[$style.group, 'pt-s']">
<n8n-button
v-if="
versionControlStore.preferences.publicKey &&
versionControlStore.preferences.currentBranch
"
@click="onSave"
size="large"
>{{ locale.baseText('settings.versionControl.button.save') }}</n8n-button
>
</div>
</div> </div>
</div> </div>
<n8n-action-box <n8n-action-box
@ -135,7 +187,7 @@ const goToUpgrade = () => {
<style lang="scss" module> <style lang="scss" module>
.group { .group {
padding: 0 0 var(--spacing-2xs); padding: 0 0 var(--spacing-s);
label { label {
display: inline-block; display: inline-block;
@ -151,6 +203,28 @@ const goToUpgrade = () => {
} }
} }
.readOnly {
span {
font-size: var(--font-size-s) !important;
}
}
.groupFlex {
display: flex;
> div {
flex: 1;
&:last-child {
margin-left: var(--spacing-2xs);
}
}
input {
width: 100%;
}
}
.connect { .connect {
margin: calc(var(--spacing-2xs) * -1) 0 var(--spacing-2xs); margin: calc(var(--spacing-2xs) * -1) 0 var(--spacing-2xs);
} }
@ -158,4 +232,9 @@ const goToUpgrade = () => {
.actionBox { .actionBox {
margin: var(--spacing-2xl) 0 0; margin: var(--spacing-2xl) 0 0;
} }
hr {
margin: 0 0 var(--spacing-xl);
border: 1px solid var(--color-foreground-light);
}
</style> </style>