Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 4 commits into from
May 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/editor-ui/src/Interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1438,7 +1438,8 @@ export type VersionControlPreferences = {
repositoryUrl: string;
authorName: string;
authorEmail: string;
branchName: string;
currentBranch: string;
branches: string[];
branchReadOnly: boolean;
branchColor: string;
publicKey?: string;
Expand Down
18 changes: 13 additions & 5 deletions packages/editor-ui/src/plugins/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1290,18 +1290,26 @@
"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.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.repoUrl": "Git repository URL",
"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.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. [email protected]:my-team/my-repository",
"settings.versionControl.repoUrlDescription": "The SSH url of your Git repository",
"settings.versionControl.authorName": "Author name",
"settings.versionControl.authorEmail": "Author email",
"settings.versionControl.authorName": "Commit author name",
"settings.versionControl.authorEmail": "Commit author email",
"settings.versionControl.sshKey": "SSH Key",
"settings.versionControl.sshKeyDescription": "Paste the SSH key in yout git repository settings. {link}.",
"settings.versionControl.sshKeyDescriptionLink": "More info.",
"settings.versionControl.button.continue": "Continue",
"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.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",
Expand Down
6 changes: 4 additions & 2 deletions packages/editor-ui/src/stores/versionControl.store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@ export const useVersionControlStore = defineStore('versionControl', () => {
);

const preferences = reactive<VersionControlPreferences>({
branchName: '',
currentBranch: '',
branches: [],
authorName: '',
authorEmail: '',
repositoryUrl: '',
branchReadOnly: false,
branchColor: '#000000',
branchColor: '#F4A6DC',
connected: false,
publicKey: '',
});
Expand Down Expand Up @@ -77,6 +78,7 @@ export const useVersionControlStore = defineStore('versionControl', () => {
return {
isEnterpriseVersionControlEnabled,
state,
preferences,
initSsh,
initRepository,
sync,
Expand Down
195 changes: 137 additions & 58 deletions packages/editor-ui/src/views/SettingsVersionControl.vue
Original file line number Diff line number Diff line change
@@ -1,19 +1,14 @@
<script lang="ts" setup>
import { computed, ref } from 'vue';
import { i18n as locale } from '@/plugins/i18n';
import { useVersionControlStore } from '@/stores/versionControl.store';
import { useUIStore } from '@/stores/ui.store';
import { useMessage } from '@/composables';
import CopyInput from '@/components/CopyInput.vue';

const versionControlStore = useVersionControlStore();
const uiStore = useUIStore();
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 = () => {
void versionControlStore.initSsh({
name: versionControlStore.state.authorName,
Expand All @@ -26,22 +21,15 @@ const onConnect = () => {
void versionControlStore.initRepository();
};

const onSave = () => {
void versionControlStore.savePreferences(versionControlStore.preferences);
};

const onSelect = async (b: string) => {
if (b === branch.value) {
if (b === versionControlStore.preferences.currentBranch) {
return;
}
const switchBranch = await message
.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();
}
versionControlStore.preferences.currentBranch = b;
};

const goToUpgrade = () => {
Expand All @@ -51,40 +39,59 @@ const goToUpgrade = () => {

<template>
<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
v-if="versionControlStore.isEnterpriseVersionControlEnabled"
data-test-id="version-control-content-licensed"
>
<n8n-callout theme="secondary" icon="info-circle" class="mt-2xl mb-l">{{
locale.baseText('settings.versionControl.description')
}}</n8n-callout>
<n8n-callout theme="secondary" icon="info-circle" class="mt-2xl mb-l">
<i18n path="settings.versionControl.description">
<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">
<label for="repoUrl">{{ locale.baseText('settings.versionControl.repoUrl') }}</label>
<n8n-input
id="repoUrl"
:placeholder="locale.baseText('settings.versionControl.repoUrlPlaceholder')"
v-model="versionControlStore.state.repositoryUrl"
v-model="versionControlStore.preferences.repositoryUrl"
/>
<small>{{ locale.baseText('settings.versionControl.repoUrlDescription') }}</small>
</div>
<div :class="$style.group">
<label for="authorName">{{ locale.baseText('settings.versionControl.authorName') }}</label>
<n8n-input id="authorName" v-model="versionControlStore.state.authorName" />
</div>
<div :class="$style.group">
<label for="authorEmail">{{
locale.baseText('settings.versionControl.authorEmail')
}}</label>
<n8n-input id="authorEmail" v-model="versionControlStore.state.authorEmail" />
<div :class="[$style.group, $style.groupFlex]">
<div>
<label for="authorName">{{
locale.baseText('settings.versionControl.authorName')
}}</label>
<n8n-input id="authorName" v-model="versionControlStore.preferences.authorName" />
</div>
<div>
<label for="authorEmail">{{
locale.baseText('settings.versionControl.authorEmail')
}}</label>
<n8n-input id="authorEmail" v-model="versionControlStore.preferences.authorEmail" />
</div>
</div>
<n8n-button v-if="!sshKey" @click="onContinue" size="large" class="mt-2xs">{{
locale.baseText('settings.versionControl.button.continue')
}}</n8n-button>
<div v-if="sshKey" :class="$style.group">
<n8n-button
v-if="!versionControlStore.preferences.publicKey"
@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>
<CopyInput
:value="versionControlStore.state.sshKey"
:value="versionControlStore.preferences.publicKey"
:copy-button-text="locale.baseText('generic.clickToCopy')"
/>
<n8n-notice type="info" class="mt-s">
Expand All @@ -97,25 +104,70 @@ const goToUpgrade = () => {
</i18n>
</n8n-notice>
</div>
<n8n-button v-if="sshKey" @click="onConnect" size="large" :class="$style.connect">{{
locale.baseText('settings.versionControl.button.connect')
}}</n8n-button>
<div v-if="versionControlStore.state.branches.length" :class="$style.group">
<label>{{ locale.baseText('settings.versionControl.branches') }}</label>
<n8n-select
ref="selectElement"
:value="versionControlStore.state.currentBranch"
size="medium"
filterable
@input="onSelect"
>
<n8n-option
v-for="b in versionControlStore.state.branches"
:key="b"
:value="b"
:label="b"
/>
</n8n-select>
<n8n-button
v-if="
versionControlStore.preferences.publicKey &&
!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>
<n8n-select
:value="versionControlStore.preferences.currentBranch"
class="mb-s"
size="medium"
filterable
@input="onSelect"
>
<n8n-option
v-for="b in versionControlStore.preferences.branches"
:key="b"
:value="b"
:label="b"
/>
</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>
<n8n-action-box
Expand All @@ -135,7 +187,7 @@ const goToUpgrade = () => {

<style lang="scss" module>
.group {
padding: 0 0 var(--spacing-2xs);
padding: 0 0 var(--spacing-s);

label {
display: inline-block;
Expand All @@ -151,11 +203,38 @@ 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 {
margin: calc(var(--spacing-2xs) * -1) 0 var(--spacing-2xs);
}

.actionBox {
margin: var(--spacing-2xl) 0 0;
}

hr {
margin: 0 0 var(--spacing-xl);
border: 1px solid var(--color-foreground-light);
}
</style>