mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 18:12:04 +00:00
feat(core): Add folder synchronization to environments feature (#14005)
This commit is contained in:
@@ -55,6 +55,7 @@ const ITEM_TITLES: Record<Exclude<SourceControlledFileType, 'file'>, string> = {
|
||||
[SOURCE_CONTROL_FILE_TYPE.credential]: 'Credentials',
|
||||
[SOURCE_CONTROL_FILE_TYPE.variables]: 'Variables',
|
||||
[SOURCE_CONTROL_FILE_TYPE.tags]: 'Tags',
|
||||
[SOURCE_CONTROL_FILE_TYPE.folders]: 'Folders',
|
||||
} as const;
|
||||
|
||||
const files = computed<ItemsList>(() =>
|
||||
@@ -63,6 +64,7 @@ const files = computed<ItemsList>(() =>
|
||||
SOURCE_CONTROL_FILE_TYPE.credential,
|
||||
SOURCE_CONTROL_FILE_TYPE.variables,
|
||||
SOURCE_CONTROL_FILE_TYPE.tags,
|
||||
SOURCE_CONTROL_FILE_TYPE.folders,
|
||||
].reduce<ItemsList>((acc, fileType) => {
|
||||
if (!groupedFilesByType.value[fileType]) {
|
||||
return acc;
|
||||
|
||||
@@ -214,6 +214,16 @@ describe('SourceControlPushModal', () => {
|
||||
file: '/Users/raul/.n8n/git/tags.json',
|
||||
updatedAt: '2024-12-04T11:29:22.095Z',
|
||||
},
|
||||
{
|
||||
id: 'mappings',
|
||||
name: 'folders',
|
||||
type: 'folders',
|
||||
status: 'modified',
|
||||
location: 'local',
|
||||
conflict: false,
|
||||
file: '/Users/raul/.n8n/git/folders.json',
|
||||
updatedAt: '2024-12-04T11:29:22.095Z',
|
||||
},
|
||||
];
|
||||
|
||||
const sourceControlStore = mockedStore(useSourceControlStore);
|
||||
@@ -233,6 +243,7 @@ describe('SourceControlPushModal', () => {
|
||||
expect(getByRole('alert').textContent).toContain('Credentials: 1 added.');
|
||||
expect(getByRole('alert').textContent).toContain('Variables: at least one new or modified.');
|
||||
expect(getByRole('alert').textContent).toContain('Tags: at least one new or modified.');
|
||||
expect(getByRole('alert').textContent).toContain('Folders: at least one new or modified.');
|
||||
|
||||
await userEvent.type(getByTestId('source-control-push-modal-commit'), commitMessage);
|
||||
|
||||
|
||||
@@ -62,6 +62,7 @@ type Changes = {
|
||||
credentials: SourceControlledFile[];
|
||||
workflows: SourceControlledFile[];
|
||||
currentWorkflow?: SourceControlledFile;
|
||||
folders: SourceControlledFile[];
|
||||
};
|
||||
|
||||
const classifyFilesByType = (files: SourceControlledFile[], currentWorkflowId?: string): Changes =>
|
||||
@@ -86,6 +87,11 @@ const classifyFilesByType = (files: SourceControlledFile[], currentWorkflowId?:
|
||||
return acc;
|
||||
}
|
||||
|
||||
if (file.type === SOURCE_CONTROL_FILE_TYPE.folders) {
|
||||
acc.folders.push(file);
|
||||
return acc;
|
||||
}
|
||||
|
||||
if (file.type === SOURCE_CONTROL_FILE_TYPE.workflow && currentWorkflowId === file.id) {
|
||||
acc.currentWorkflow = file;
|
||||
}
|
||||
@@ -102,7 +108,14 @@ const classifyFilesByType = (files: SourceControlledFile[], currentWorkflowId?:
|
||||
|
||||
return acc;
|
||||
},
|
||||
{ tags: [], variables: [], credentials: [], workflows: [], currentWorkflow: undefined },
|
||||
{
|
||||
tags: [],
|
||||
variables: [],
|
||||
credentials: [],
|
||||
workflows: [],
|
||||
folders: [],
|
||||
currentWorkflow: undefined,
|
||||
},
|
||||
);
|
||||
|
||||
const userNotices = computed(() => {
|
||||
@@ -135,6 +148,13 @@ const userNotices = computed(() => {
|
||||
});
|
||||
}
|
||||
|
||||
if (changes.value.folders.length) {
|
||||
messages.push({
|
||||
title: 'Folders',
|
||||
content: 'at least one new or modified',
|
||||
});
|
||||
}
|
||||
|
||||
return messages;
|
||||
});
|
||||
const workflowId = computed(
|
||||
@@ -220,6 +240,7 @@ const isSubmitDisabled = computed(() => {
|
||||
changes.value.credentials.length +
|
||||
changes.value.tags.length +
|
||||
changes.value.variables.length +
|
||||
changes.value.folders.length +
|
||||
selectedChanges.value.size;
|
||||
|
||||
return toBePushed <= 0;
|
||||
@@ -309,6 +330,10 @@ const successNotificationMessage = () => {
|
||||
messages.push(i18n.baseText('generic.variable_plural'));
|
||||
}
|
||||
|
||||
if (changes.value.folders.length) {
|
||||
messages.push(i18n.baseText('generic.folders_plural'));
|
||||
}
|
||||
|
||||
if (changes.value.tags.length) {
|
||||
messages.push(i18n.baseText('generic.tag_plural'));
|
||||
}
|
||||
@@ -323,6 +348,7 @@ async function commitAndPush() {
|
||||
const files = changes.value.tags
|
||||
.concat(changes.value.variables)
|
||||
.concat(changes.value.credentials)
|
||||
.concat(changes.value.folders)
|
||||
.concat(changes.value.workflows.filter((file) => selectedChanges.value.has(file.id)));
|
||||
loadingService.startLoading(i18n.baseText('settings.sourceControl.loading.push'));
|
||||
close();
|
||||
@@ -481,6 +507,9 @@ watch(refDebounced(search, 500), (term) => {
|
||||
<span v-if="file.type === SOURCE_CONTROL_FILE_TYPE.credential">
|
||||
Deleted Credential:
|
||||
</span>
|
||||
<span v-if="file.type === SOURCE_CONTROL_FILE_TYPE.folders">
|
||||
Deleted Folders:
|
||||
</span>
|
||||
<strong>{{ file.name || file.id }}</strong>
|
||||
</N8nText>
|
||||
<N8nText v-else tag="div" bold color="text-dark" :class="[$style.listItemName]">
|
||||
@@ -517,7 +546,7 @@ watch(refDebounced(search, 500), (term) => {
|
||||
|
||||
<template #footer>
|
||||
<N8nNotice v-if="userNotices.length" :compact="false" class="mt-0">
|
||||
<N8nText bold size="medium">Changes to credentials, variables and tags </N8nText>
|
||||
<N8nText bold size="medium">Changes to credentials, variables, tags and folders </N8nText>
|
||||
<br />
|
||||
<template v-for="{ title, content } in userNotices" :key="title">
|
||||
<N8nText bold size="small">{{ title }}</N8nText>
|
||||
|
||||
Reference in New Issue
Block a user