From e7840bb89b49565f36d562aed0dfbffe32b3bac1 Mon Sep 17 00:00:00 2001 From: Pascal Jufer Date: Tue, 5 Mar 2024 22:31:31 +0100 Subject: [PATCH] Display missing extensions (#21704) --- app/src/constants/extension-type-icon-map.ts | 3 +- app/src/lang/translations/en-US.yaml | 1 + .../components/extension-group-divider.vue | 4 +- .../extensions/components/extension-item.vue | 54 +++++++++++-------- .../settings/routes/extensions/extensions.vue | 13 ++++- 5 files changed, 50 insertions(+), 25 deletions(-) diff --git a/app/src/constants/extension-type-icon-map.ts b/app/src/constants/extension-type-icon-map.ts index 4591789cbb..1cbaa1a989 100644 --- a/app/src/constants/extension-type-icon-map.ts +++ b/app/src/constants/extension-type-icon-map.ts @@ -1,6 +1,6 @@ import type { ExtensionType } from '@directus/extensions'; -export const extensionTypeIconMap: Record = { +export const extensionTypeIconMap: Record = { interface: 'design_services', display: 'label', layout: 'dataset', @@ -11,4 +11,5 @@ export const extensionTypeIconMap: Record = { endpoint: 'api', operation: 'flowsheet', bundle: 'hub', + missing: 'warning', }; diff --git a/app/src/lang/translations/en-US.yaml b/app/src/lang/translations/en-US.yaml index b15cc108f3..2ce1f8dbba 100644 --- a/app/src/lang/translations/en-US.yaml +++ b/app/src/lang/translations/en-US.yaml @@ -80,6 +80,7 @@ extension_hooks: Hooks extension_endpoints: Endpoints extension_operations: Operations extension_bundles: Bundles +extension_missing: Missing extension_reload_required: Page Reload Required extension_reload_required_copy: A page reload is required to see the changes after enabling or disabling app extensions. extension_reload_now: Reload now diff --git a/app/src/modules/settings/routes/extensions/components/extension-group-divider.vue b/app/src/modules/settings/routes/extensions/components/extension-group-divider.vue index 2f89d59a4d..3047310e72 100644 --- a/app/src/modules/settings/routes/extensions/components/extension-group-divider.vue +++ b/app/src/modules/settings/routes/extensions/components/extension-group-divider.vue @@ -6,12 +6,12 @@ import { computed } from 'vue'; import { useI18n } from 'vue-i18n'; const props = defineProps<{ - type: ExtensionType; + type: ExtensionType | 'missing'; }>(); const { t } = useI18n(); -const label = computed(() => t(`extension_${pluralize(props.type)}`)); +const label = computed(() => t(`extension_${props.type !== 'missing' ? pluralize(props.type) : props.type}`)); const icon = computed(() => extensionTypeIconMap[props.type]); diff --git a/app/src/modules/settings/routes/extensions/components/extension-item.vue b/app/src/modules/settings/routes/extensions/components/extension-item.vue index 7742c993d5..5d9b8a6b90 100644 --- a/app/src/modules/settings/routes/extensions/components/extension-item.vue +++ b/app/src/modules/settings/routes/extensions/components/extension-item.vue @@ -29,8 +29,16 @@ const devMode = import.meta.env.DEV; const saving = ref(false); -const type = computed(() => props.extension.schema?.type); -const icon = computed(() => (type.value ? extensionTypeIconMap[type.value] : 'warning')); +const type = computed(() => props.extension.schema?.type ?? 'missing'); +const icon = computed(() => extensionTypeIconMap[type.value]); + +const disabled = computed(() => { + if (type.value === 'missing') return true; + if (devMode) return false; + + return !props.extension.meta.enabled; +}); + const disableLocked = computed(() => devMode && isOrHasAppExtension.value); const uninstallLocked = computed(() => props.extension.meta.source !== 'registry'); @@ -52,11 +60,13 @@ const isPartiallyEnabled = computed(() => { }); const isOrHasAppExtension = computed(() => { - if (type.value === 'bundle') { + const type = props.extension.schema?.type; + + if (type === 'bundle') { return props.children.some((e) => isAppExtension(e.schema?.type)); } - return isAppExtension(type.value); + return isAppExtension(type); }); const state = computed<{ text: string; status: ExtensionStatus }>(() => { @@ -102,7 +112,7 @@ const uninstall = async () => {