Skip to content

Commit

Permalink
fix(editor): Add Set up version control CTA (#6356)
Browse files Browse the repository at this point in the history
* fix(editor): Add Set up version control CTA

* fix(editor): add unit test

* fix(editor): extend unit test

* fix(editor): update menu sidebar styles

* fix(editor): update menu sidebar styles

* fix(editor): fixes after conflict

* fix(editor): hide branch color when not connected

* fix(editor): fix connected collapsed paddings
  • Loading branch information
cstuncsik committed Jun 6, 2023
1 parent 97295f6 commit e72521d
Show file tree
Hide file tree
Showing 6 changed files with 215 additions and 81 deletions.
5 changes: 0 additions & 5 deletions packages/design-system/src/components/N8nMenu/Menu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -193,9 +193,4 @@ export default defineComponent({
display: none !important;
}
}
.menuPrefix,
.menuSuffix {
padding: var(--spacing-xs) var(--spacing-l);
}
</style>
30 changes: 15 additions & 15 deletions packages/editor-ui/src/components/MainSidebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
v-if="!isCollapsed && userIsTrialing"
/></template>
<template #menuSuffix>
<div v-if="hasVersionUpdates || versionControlStore.preferences.connected">
<div>
<div v-if="hasVersionUpdates" :class="$style.updates" @click="openUpdatesPanel">
<div :class="$style.giftContainer">
<GiftNotificationIcon />
Expand All @@ -46,10 +46,7 @@
}}
</n8n-text>
</div>
<MainSidebarVersionControl
v-if="versionControlStore.preferences.connected"
:is-collapsed="isCollapsed"
/>
<MainSidebarVersionControl :is-collapsed="isCollapsed" />
</div>
</template>
<template #footer v-if="showUserArea">
Expand Down Expand Up @@ -115,15 +112,17 @@ import { userHelpers } from '@/mixins/userHelpers';
import { debounceHelper } from '@/mixins/debounce';
import Vue, { defineComponent } from 'vue';
import { mapStores } from 'pinia';
import { useUIStore } from '@/stores/ui.store';
import { useSettingsStore } from '@/stores/settings.store';
import { useUsersStore } from '@/stores/users.store';
import { useWorkflowsStore } from '@/stores/workflows.store';
import { useRootStore } from '@/stores/n8nRoot.store';
import { useVersionsStore } from '@/stores/versions.store';
import {
useUIStore,
useSettingsStore,
useUsersStore,
useWorkflowsStore,
useRootStore,
useVersionsStore,
useCloudPlanStore,
useVersionControlStore,
} from '@/stores/';
import { isNavigationFailure } from 'vue-router';
import { useVersionControlStore } from '@/stores/versionControl.store';
import { useCloudPlanStore } from '@/stores/cloudPlan.store';
import ExecutionsUsage from '@/components/ExecutionsUsage.vue';
import MainSidebarVersionControl from '@/components/MainSidebarVersionControl.vue';
Expand Down Expand Up @@ -155,8 +154,8 @@ export default defineComponent({
useUsersStore,
useVersionsStore,
useWorkflowsStore,
useVersionControlStore,
useCloudPlanStore,
useVersionControlStore,
),
hasVersionUpdates(): boolean {
return this.versionsStore.hasVersionUpdates;
Expand Down Expand Up @@ -543,8 +542,9 @@ export default defineComponent({
.updates {
display: flex;
align-items: center;
height: 26px;
cursor: pointer;
padding: var(--spacing-2xs) var(--spacing-l);
margin: var(--spacing-2xs) 0 0;
svg {
color: var(--color-text-base) !important;
Expand Down
178 changes: 118 additions & 60 deletions packages/editor-ui/src/components/MainSidebarVersionControl.vue
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
<script lang="ts" setup>
import { useVersionControlStore } from '@/stores/versionControl.store';
import { computed, ref } from 'vue';
import { useI18n, useLoadingService, useMessage, useToast } from '@/composables';
import { useUIStore } from '@/stores';
import { VERSION_CONTROL_PUSH_MODAL_KEY } from '@/constants';
import { useRouter } from 'vue-router/composables';
import { createEventBus } from 'n8n-design-system/utils';
import { useI18n, useLoadingService, useMessage, useToast } from '@/composables';
import { useUIStore, useUsersStore, useVersionControlStore } from '@/stores';
import { VERSION_CONTROL_PUSH_MODAL_KEY, VIEWS } from '@/constants';
const props = defineProps<{
isCollapsed: boolean;
}>();
const router = useRouter();
const loadingService = useLoadingService();
const uiStore = useUIStore();
const versionControlStore = useVersionControlStore();
const usersStore = useUsersStore();
const message = useMessage();
const toast = useToast();
const { i18n } = useI18n();
Expand All @@ -24,6 +26,8 @@ const currentBranch = computed(() => {
return versionControlStore.preferences.branchName;
});
const setupButtonTooltipPlacement = computed(() => (props.isCollapsed ? 'right' : 'top'));
async function pushWorkfolder() {
loadingService.startLoading();
try {
Expand Down Expand Up @@ -68,76 +72,127 @@ async function pullWorkfolder() {
loadingService.setLoadingText(i18n.baseText('genericHelpers.loading'));
}
}
const goToVersionControlSetup = async () => {
await router.push({ name: VIEWS.VERSION_CONTROL });
};
</script>

<template>
<div
:class="{ [$style.sync]: true, [$style.collapsed]: isCollapsed }"
:class="{
[$style.sync]: true,
[$style.collapsed]: isCollapsed,
[$style.isConnected]:
versionControlStore.preferences.connected && versionControlStore.preferences.branchName,
}"
:style="{ borderLeftColor: versionControlStore.preferences.branchColor }"
data-test-id="main-sidebar-version-control"
>
<span>
<n8n-icon icon="code-branch" />
{{ currentBranch }}
</span>
<div :class="{ 'pt-xs': !isCollapsed }">
<n8n-tooltip :disabled="!isCollapsed" :open-delay="tooltipOpenDelay" placement="right">
<template #content>
<div>
{{ i18n.baseText('settings.versionControl.button.pull') }}
</div>
</template>
<n8n-button
:class="{
'mr-2xs': !isCollapsed,
'mb-2xs': isCollapsed && !versionControlStore.preferences.branchReadOnly,
}"
icon="arrow-down"
type="tertiary"
size="mini"
:square="isCollapsed"
@click="pullWorkfolder"
<div
v-if="versionControlStore.preferences.connected && versionControlStore.preferences.branchName"
:class="$style.connected"
data-test-id="main-sidebar-version-control-connected"
>
<span>
<n8n-icon icon="code-branch" />
{{ currentBranch }}
</span>
<div :class="{ 'pt-xs': !isCollapsed }">
<n8n-tooltip :disabled="!isCollapsed" :open-delay="tooltipOpenDelay" placement="right">
<template #content>
<div>
{{ i18n.baseText('settings.versionControl.button.pull') }}
</div>
</template>
<n8n-button
:class="{
'mr-2xs': !isCollapsed,
'mb-2xs': isCollapsed && !versionControlStore.preferences.branchReadOnly,
}"
icon="arrow-down"
type="tertiary"
size="mini"
:square="isCollapsed"
@click="pullWorkfolder"
>
<span v-if="!isCollapsed">{{
i18n.baseText('settings.versionControl.button.pull')
}}</span>
</n8n-button>
</n8n-tooltip>
<n8n-tooltip
v-if="!versionControlStore.preferences.branchReadOnly"
:disabled="!isCollapsed"
:open-delay="tooltipOpenDelay"
placement="right"
>
<span v-if="!isCollapsed">{{
i18n.baseText('settings.versionControl.button.pull')
}}</span>
</n8n-button>
</n8n-tooltip>
<n8n-tooltip
v-if="!versionControlStore.preferences.branchReadOnly"
:disabled="!isCollapsed"
:open-delay="tooltipOpenDelay"
placement="right"
>
<template #content>
<div>
{{ i18n.baseText('settings.versionControl.button.push') }}
</div>
</template>
<n8n-button
:square="isCollapsed"
icon="arrow-up"
type="tertiary"
size="mini"
@click="pushWorkfolder"
>
<span v-if="!isCollapsed">{{
i18n.baseText('settings.versionControl.button.push')
}}</span>
</n8n-button>
</n8n-tooltip>
<template #content>
<div>
{{ i18n.baseText('settings.versionControl.button.push') }}
</div>
</template>
<n8n-button
:square="isCollapsed"
icon="arrow-up"
type="tertiary"
size="mini"
@click="pushWorkfolder"
>
<span v-if="!isCollapsed">{{
i18n.baseText('settings.versionControl.button.push')
}}</span>
</n8n-button>
</n8n-tooltip>
</div>
</div>
<n8n-tooltip
v-else-if="
versionControlStore.isEnterpriseVersionControlEnabled && usersStore.isInstanceOwner
"
:open-delay="tooltipOpenDelay"
:placement="setupButtonTooltipPlacement"
data-test-id="main-sidebar-version-control-setup"
>
<template #content>
<div>
{{ i18n.baseText('settings.versionControl.button.setup.tooltip') }}
</div>
</template>
<n8n-button
icon="code-branch"
type="tertiary"
size="mini"
:square="isCollapsed"
@click="goToVersionControlSetup"
>
<span v-if="!isCollapsed">{{ i18n.baseText('settings.versionControl.button.setup') }}</span>
</n8n-button>
</n8n-tooltip>
</div>
</template>

<style lang="scss" module>
.sync {
padding: var(--spacing-s) var(--spacing-s) var(--spacing-s) var(--spacing-m);
margin: 0 calc(var(--spacing-l) * -1) calc(var(--spacing-m) * -1);
padding: var(--spacing-s) var(--spacing-s) var(--spacing-s) var(--spacing-l);
margin: var(--spacing-2xs) 0 calc(var(--spacing-2xs) * -1);
background: var(--color-background-light);
border-top: var(--border-width-base) var(--border-style-base) var(--color-foreground-base);
border-left: var(--spacing-3xs) var(--border-style-base) var(--color-foreground-base);
font-size: var(--font-size-2xs);
&.isConnected {
padding-left: var(--spacing-m);
border-left: var(--spacing-3xs) var(--border-style-base) var(--color-foreground-base);
&.collapsed {
padding-left: var(--spacing-xs);
}
}
&:empty {
display: none;
}
span {
color: var(--color-text-base);
}
Expand All @@ -149,10 +204,13 @@ async function pullWorkfolder() {
.collapsed {
text-align: center;
padding-left: var(--spacing-xs);
padding-left: var(--spacing-s);
padding-right: var(--spacing-s);
> span {
display: none;
.connected {
> span {
display: none;
}
}
}
</style>
5 changes: 4 additions & 1 deletion packages/editor-ui/src/components/SettingsSidebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -246,8 +246,11 @@ export default defineComponent({
}
}
.versionContainer {
padding: var(--spacing-xs) var(--spacing-l);
}
@media screen and (max-height: 420px) {
.updatesSubmenu,
.versionContainer {
display: none;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { describe, it, expect, vi } from 'vitest';
import { render } from '@testing-library/vue';
import { PiniaVuePlugin } from 'pinia';
import { createTestingPinia } from '@pinia/testing';
import { STORES } from '@/constants';
import { i18nInstance } from '@/plugins/i18n';
import { SETTINGS_STORE_DEFAULT_STATE } from '@/__tests__/utils';
import MainSidebarVersionControl from '@/components/MainSidebarVersionControl.vue';
import { useUsersStore, useVersionControlStore } from '@/stores';
import { merge } from 'lodash-es';

let pinia: ReturnType<typeof createTestingPinia>;
let versionControlStore: ReturnType<typeof useVersionControlStore>;
let usersStore: ReturnType<typeof useUsersStore>;

const renderComponent = (renderOptions: Parameters<typeof render>[1] = {}) => {
return render(
MainSidebarVersionControl,
{
pinia,
i18n: i18nInstance,
...renderOptions,
},
(vue) => {
vue.use(PiniaVuePlugin);
},
);
};

describe('MainSidebarVersionControl', () => {
beforeEach(() => {
pinia = createTestingPinia({
initialState: {
[STORES.SETTINGS]: {
settings: merge({}, SETTINGS_STORE_DEFAULT_STATE.settings),
},
},
});

versionControlStore = useVersionControlStore();
usersStore = useUsersStore();
});

it('should render empty content', async () => {
const { getByTestId } = renderComponent({ props: { isCollapsed: false } });
expect(getByTestId('main-sidebar-version-control')).toBeInTheDocument();
expect(getByTestId('main-sidebar-version-control')).toBeEmptyDOMElement();
});

it('should render setup content', async () => {
vi.spyOn(versionControlStore, 'isEnterpriseVersionControlEnabled', 'get').mockReturnValue(true);
vi.spyOn(usersStore, 'isInstanceOwner', 'get').mockReturnValue(true);

const { getByTestId, queryByTestId } = renderComponent({ props: { isCollapsed: false } });
expect(getByTestId('main-sidebar-version-control-setup')).toBeInTheDocument();
expect(queryByTestId('main-sidebar-version-control-connected')).not.toBeInTheDocument();
});

it('should render connected content', async () => {
vi.spyOn(versionControlStore, 'preferences', 'get').mockReturnValue({
branchName: 'main',
branches: [],
authorName: '',
authorEmail: '',
repositoryUrl: '',
branchReadOnly: false,
branchColor: '#F4A6DC',
connected: true,
publicKey: '',
});

const { getByTestId, queryByTestId } = renderComponent({ props: { isCollapsed: false } });
expect(getByTestId('main-sidebar-version-control-connected')).toBeInTheDocument();
expect(queryByTestId('main-sidebar-version-control-setup')).not.toBeInTheDocument();
});
});
Loading

0 comments on commit e72521d

Please sign in to comment.