mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-24 20:24:05 -08:00
refactor(editor): Migrate SettingsCommunityNodesView.vue
to composition API (#10724)
This commit is contained in:
parent
8d4afddcf4
commit
482b5d8bec
|
@ -1,4 +1,4 @@
|
||||||
<script lang="ts">
|
<script setup lang="ts">
|
||||||
import {
|
import {
|
||||||
COMMUNITY_PACKAGE_INSTALL_MODAL_KEY,
|
COMMUNITY_PACKAGE_INSTALL_MODAL_KEY,
|
||||||
COMMUNITY_NODES_INSTALLATION_DOCS_URL,
|
COMMUNITY_NODES_INSTALLATION_DOCS_URL,
|
||||||
|
@ -10,177 +10,172 @@ import type { PublicInstalledPackage } from 'n8n-workflow';
|
||||||
|
|
||||||
import { useCommunityNodesStore } from '@/stores/communityNodes.store';
|
import { useCommunityNodesStore } from '@/stores/communityNodes.store';
|
||||||
import { useUIStore } from '@/stores/ui.store';
|
import { useUIStore } from '@/stores/ui.store';
|
||||||
import { mapStores } from 'pinia';
|
|
||||||
import { useSettingsStore } from '@/stores/settings.store';
|
import { useSettingsStore } from '@/stores/settings.store';
|
||||||
import { defineComponent } from 'vue';
|
import { onBeforeUnmount, ref } from 'vue';
|
||||||
import { useExternalHooks } from '@/composables/useExternalHooks';
|
import { useExternalHooks } from '@/composables/useExternalHooks';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import { usePushConnection } from '@/composables/usePushConnection';
|
import { usePushConnection } from '@/composables/usePushConnection';
|
||||||
import { usePushConnectionStore } from '@/stores/pushConnection.store';
|
import { usePushConnectionStore } from '@/stores/pushConnection.store';
|
||||||
|
import { computed } from 'vue';
|
||||||
|
import { useI18n } from '@/composables/useI18n';
|
||||||
|
import { onBeforeMount } from 'vue';
|
||||||
|
import { onMounted } from 'vue';
|
||||||
|
import { useTelemetry } from '@/composables/useTelemetry';
|
||||||
|
|
||||||
const PACKAGE_COUNT_THRESHOLD = 31;
|
const PACKAGE_COUNT_THRESHOLD = 31;
|
||||||
|
|
||||||
export default defineComponent({
|
const loading = ref(false);
|
||||||
name: 'SettingsCommunityNodesView',
|
|
||||||
components: {
|
|
||||||
CommunityPackageCard,
|
|
||||||
},
|
|
||||||
setup() {
|
|
||||||
const router = useRouter();
|
|
||||||
const pushConnection = usePushConnection({ router });
|
|
||||||
const externalHooks = useExternalHooks();
|
|
||||||
|
|
||||||
return {
|
const router = useRouter();
|
||||||
externalHooks,
|
const pushConnection = usePushConnection({ router });
|
||||||
...useToast(),
|
const pushStore = usePushConnectionStore();
|
||||||
pushConnection,
|
const externalHooks = useExternalHooks();
|
||||||
};
|
const i18n = useI18n();
|
||||||
},
|
const telemetry = useTelemetry();
|
||||||
data() {
|
const toast = useToast();
|
||||||
return {
|
|
||||||
loading: false,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapStores(useCommunityNodesStore, useSettingsStore, useUIStore, usePushConnectionStore),
|
|
||||||
getEmptyStateDescription(): string {
|
|
||||||
const packageCount = this.communityNodesStore.availablePackageCount;
|
|
||||||
|
|
||||||
if (this.settingsStore.isDesktopDeployment) {
|
const communityNodesStore = useCommunityNodesStore();
|
||||||
return this.$locale.baseText('contextual.communityNodes.unavailable.description.desktop');
|
const settingsStore = useSettingsStore();
|
||||||
}
|
const uiStore = useUIStore();
|
||||||
|
|
||||||
return packageCount < PACKAGE_COUNT_THRESHOLD
|
const getEmptyStateDescription = computed(() => {
|
||||||
? this.$locale.baseText('settings.communityNodes.empty.description.no-packages', {
|
const packageCount = communityNodesStore.availablePackageCount;
|
||||||
interpolate: {
|
|
||||||
docURL: COMMUNITY_NODES_INSTALLATION_DOCS_URL,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
: this.$locale.baseText('settings.communityNodes.empty.description', {
|
|
||||||
interpolate: {
|
|
||||||
docURL: COMMUNITY_NODES_INSTALLATION_DOCS_URL,
|
|
||||||
count: (Math.floor(packageCount / 10) * 10).toString(),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
},
|
|
||||||
getEmptyStateButtonText(): string {
|
|
||||||
if (this.settingsStore.isDesktopDeployment) {
|
|
||||||
return this.$locale.baseText('contextual.communityNodes.unavailable.button.desktop');
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.shouldShowInstallButton
|
if (settingsStore.isDesktopDeployment) {
|
||||||
? this.$locale.baseText('settings.communityNodes.empty.installPackageLabel')
|
return i18n.baseText('contextual.communityNodes.unavailable.description.desktop');
|
||||||
: '';
|
}
|
||||||
},
|
|
||||||
shouldShowInstallButton(): boolean {
|
|
||||||
return this.settingsStore.isDesktopDeployment || this.settingsStore.isNpmAvailable;
|
|
||||||
},
|
|
||||||
actionBoxConfig(): {
|
|
||||||
calloutText: string;
|
|
||||||
calloutTheme: 'warning' | string;
|
|
||||||
hideButton: boolean;
|
|
||||||
} {
|
|
||||||
if (!this.settingsStore.isNpmAvailable) {
|
|
||||||
return {
|
|
||||||
calloutText: this.$locale.baseText('settings.communityNodes.npmUnavailable.warning', {
|
|
||||||
interpolate: { npmUrl: COMMUNITY_NODES_NPM_INSTALLATION_URL },
|
|
||||||
}),
|
|
||||||
calloutTheme: 'warning',
|
|
||||||
hideButton: true,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return packageCount < PACKAGE_COUNT_THRESHOLD
|
||||||
calloutText: '',
|
? i18n.baseText('settings.communityNodes.empty.description.no-packages', {
|
||||||
calloutTheme: '',
|
interpolate: {
|
||||||
hideButton: false,
|
docURL: COMMUNITY_NODES_INSTALLATION_DOCS_URL,
|
||||||
};
|
},
|
||||||
},
|
})
|
||||||
},
|
: i18n.baseText('settings.communityNodes.empty.description', {
|
||||||
beforeMount() {
|
interpolate: {
|
||||||
this.pushConnection.initialize();
|
docURL: COMMUNITY_NODES_INSTALLATION_DOCS_URL,
|
||||||
// The push connection is needed here to receive `reloadNodeType` and `removeNodeType` events when community nodes are installed, updated, or removed.
|
count: (Math.floor(packageCount / 10) * 10).toString(),
|
||||||
this.pushStore.pushConnect();
|
},
|
||||||
},
|
|
||||||
async mounted() {
|
|
||||||
try {
|
|
||||||
this.loading = true;
|
|
||||||
await this.communityNodesStore.fetchInstalledPackages();
|
|
||||||
|
|
||||||
const installedPackages: PublicInstalledPackage[] =
|
|
||||||
this.communityNodesStore.getInstalledPackages;
|
|
||||||
const packagesToUpdate: PublicInstalledPackage[] = installedPackages.filter(
|
|
||||||
(p) => p.updateAvailable,
|
|
||||||
);
|
|
||||||
this.$telemetry.track('user viewed cnr settings page', {
|
|
||||||
num_of_packages_installed: installedPackages.length,
|
|
||||||
installed_packages: installedPackages.map((p) => {
|
|
||||||
return {
|
|
||||||
package_name: p.packageName,
|
|
||||||
package_version: p.installedVersion,
|
|
||||||
package_nodes: p.installedNodes.map((node) => `${node.name}-v${node.latestVersion}`),
|
|
||||||
is_update_available: p.updateAvailable !== undefined,
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
packages_to_update: packagesToUpdate.map((p) => {
|
|
||||||
return {
|
|
||||||
package_name: p.packageName,
|
|
||||||
package_version_current: p.installedVersion,
|
|
||||||
package_version_available: p.updateAvailable,
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
number_of_updates_available: packagesToUpdate.length,
|
|
||||||
});
|
});
|
||||||
} catch (error) {
|
});
|
||||||
this.showError(
|
|
||||||
error,
|
|
||||||
this.$locale.baseText('settings.communityNodes.fetchError.title'),
|
|
||||||
this.$locale.baseText('settings.communityNodes.fetchError.message'),
|
|
||||||
);
|
|
||||||
} finally {
|
|
||||||
this.loading = false;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
await this.communityNodesStore.fetchAvailableCommunityPackageCount();
|
|
||||||
} finally {
|
|
||||||
this.loading = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
beforeUnmount() {
|
|
||||||
this.pushStore.pushDisconnect();
|
|
||||||
this.pushConnection.terminate();
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
onClickEmptyStateButton(): void {
|
|
||||||
if (this.settingsStore.isDesktopDeployment) {
|
|
||||||
return this.goToUpgrade();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.openInstallModal();
|
const shouldShowInstallButton = computed(() => {
|
||||||
},
|
return settingsStore.isDesktopDeployment || settingsStore.isNpmAvailable;
|
||||||
goToUpgrade(): void {
|
});
|
||||||
void this.uiStore.goToUpgrade('community-nodes', 'upgrade-community-nodes');
|
|
||||||
},
|
|
||||||
openInstallModal(): void {
|
|
||||||
const telemetryPayload = {
|
|
||||||
is_empty_state: this.communityNodesStore.getInstalledPackages.length === 0,
|
|
||||||
};
|
|
||||||
this.$telemetry.track('user clicked cnr install button', telemetryPayload);
|
|
||||||
|
|
||||||
void this.externalHooks.run('settingsCommunityNodesView.openInstallModal', telemetryPayload);
|
const getEmptyStateButtonText = computed(() => {
|
||||||
this.uiStore.openModal(COMMUNITY_PACKAGE_INSTALL_MODAL_KEY);
|
if (settingsStore.isDesktopDeployment) {
|
||||||
},
|
return i18n.baseText('contextual.communityNodes.unavailable.button.desktop');
|
||||||
},
|
}
|
||||||
|
|
||||||
|
return shouldShowInstallButton.value
|
||||||
|
? i18n.baseText('settings.communityNodes.empty.installPackageLabel')
|
||||||
|
: '';
|
||||||
|
});
|
||||||
|
|
||||||
|
const actionBoxConfig = computed(() => {
|
||||||
|
if (!settingsStore.isNpmAvailable) {
|
||||||
|
return {
|
||||||
|
calloutText: i18n.baseText('settings.communityNodes.npmUnavailable.warning', {
|
||||||
|
interpolate: { npmUrl: COMMUNITY_NODES_NPM_INSTALLATION_URL },
|
||||||
|
}),
|
||||||
|
calloutTheme: 'warning',
|
||||||
|
hideButton: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
calloutText: '',
|
||||||
|
calloutTheme: '',
|
||||||
|
hideButton: false,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const goToUpgrade = () => {
|
||||||
|
void uiStore.goToUpgrade('community-nodes', 'upgrade-community-nodes');
|
||||||
|
};
|
||||||
|
|
||||||
|
const onClickEmptyStateButton = () => {
|
||||||
|
if (settingsStore.isDesktopDeployment) {
|
||||||
|
return goToUpgrade();
|
||||||
|
}
|
||||||
|
|
||||||
|
openInstallModal();
|
||||||
|
};
|
||||||
|
|
||||||
|
const openInstallModal = () => {
|
||||||
|
const telemetryPayload = {
|
||||||
|
is_empty_state: communityNodesStore.getInstalledPackages.length === 0,
|
||||||
|
};
|
||||||
|
telemetry.track('user clicked cnr install button', telemetryPayload);
|
||||||
|
|
||||||
|
void externalHooks.run('settingsCommunityNodesView.openInstallModal', telemetryPayload);
|
||||||
|
uiStore.openModal(COMMUNITY_PACKAGE_INSTALL_MODAL_KEY);
|
||||||
|
};
|
||||||
|
|
||||||
|
onBeforeMount(() => {
|
||||||
|
pushConnection.initialize();
|
||||||
|
// The push connection is needed here to receive `reloadNodeType` and `removeNodeType` events when community nodes are installed, updated, or removed.
|
||||||
|
pushStore.pushConnect();
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
try {
|
||||||
|
loading.value = true;
|
||||||
|
await communityNodesStore.fetchInstalledPackages();
|
||||||
|
|
||||||
|
const installedPackages: PublicInstalledPackage[] = communityNodesStore.getInstalledPackages;
|
||||||
|
const packagesToUpdate: PublicInstalledPackage[] = installedPackages.filter(
|
||||||
|
(p) => p.updateAvailable,
|
||||||
|
);
|
||||||
|
telemetry.track('user viewed cnr settings page', {
|
||||||
|
num_of_packages_installed: installedPackages.length,
|
||||||
|
installed_packages: installedPackages.map((p) => {
|
||||||
|
return {
|
||||||
|
package_name: p.packageName,
|
||||||
|
package_version: p.installedVersion,
|
||||||
|
package_nodes: p.installedNodes.map((node) => `${node.name}-v${node.latestVersion}`),
|
||||||
|
is_update_available: p.updateAvailable !== undefined,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
packages_to_update: packagesToUpdate.map((p) => {
|
||||||
|
return {
|
||||||
|
package_name: p.packageName,
|
||||||
|
package_version_current: p.installedVersion,
|
||||||
|
package_version_available: p.updateAvailable,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
number_of_updates_available: packagesToUpdate.length,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
toast.showError(
|
||||||
|
error,
|
||||||
|
i18n.baseText('settings.communityNodes.fetchError.title'),
|
||||||
|
i18n.baseText('settings.communityNodes.fetchError.message'),
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await communityNodesStore.fetchAvailableCommunityPackageCount();
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
pushStore.pushDisconnect();
|
||||||
|
pushConnection.terminate();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div :class="$style.container">
|
<div :class="$style.container">
|
||||||
<div :class="$style.headingContainer">
|
<div :class="$style.headingContainer">
|
||||||
<n8n-heading size="2xlarge">{{ $locale.baseText('settings.communityNodes') }}</n8n-heading>
|
<n8n-heading size="2xlarge">{{ i18n.baseText('settings.communityNodes') }}</n8n-heading>
|
||||||
<n8n-button
|
<n8n-button
|
||||||
v-if="communityNodesStore.getInstalledPackages.length > 0 && !loading"
|
v-if="communityNodesStore.getInstalledPackages.length > 0 && !loading"
|
||||||
:label="$locale.baseText('settings.communityNodes.installModal.installButton.label')"
|
:label="i18n.baseText('settings.communityNodes.installModal.installButton.label')"
|
||||||
size="large"
|
size="large"
|
||||||
@click="openInstallModal"
|
@click="openInstallModal"
|
||||||
/>
|
/>
|
||||||
|
@ -197,7 +192,7 @@ export default defineComponent({
|
||||||
:class="$style.actionBoxContainer"
|
:class="$style.actionBoxContainer"
|
||||||
>
|
>
|
||||||
<n8n-action-box
|
<n8n-action-box
|
||||||
:heading="$locale.baseText('settings.communityNodes.empty.title')"
|
:heading="i18n.baseText('settings.communityNodes.empty.title')"
|
||||||
:description="getEmptyStateDescription"
|
:description="getEmptyStateDescription"
|
||||||
:button-text="getEmptyStateButtonText"
|
:button-text="getEmptyStateButtonText"
|
||||||
:callout-text="actionBoxConfig.calloutText"
|
:callout-text="actionBoxConfig.calloutText"
|
||||||
|
|
Loading…
Reference in a new issue