Skip to content

Commit

Permalink
Display missing extensions (#21704)
Browse files Browse the repository at this point in the history
  • Loading branch information
paescuj committed Mar 5, 2024
1 parent 829810d commit e7840bb
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 27 deletions.
3 changes: 2 additions & 1 deletion app/src/constants/extension-type-icon-map.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { ExtensionType } from '@directus/extensions';

export const extensionTypeIconMap: Record<ExtensionType, string> = {
export const extensionTypeIconMap: Record<ExtensionType | 'missing', string> = {
interface: 'design_services',
display: 'label',
layout: 'dataset',
Expand All @@ -11,4 +11,5 @@ export const extensionTypeIconMap: Record<ExtensionType, string> = {
endpoint: 'api',
operation: 'flowsheet',
bundle: 'hub',
missing: 'warning',
};
1 change: 1 addition & 0 deletions app/src/lang/translations/en-US.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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]);
</script>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand All @@ -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 }>(() => {
Expand Down Expand Up @@ -102,7 +112,7 @@ const uninstall = async () => {
</script>

<template>
<v-list-item block :class="{ disabled: devMode ? false : !extension.meta.enabled }">
<v-list-item block :class="{ disabled }">
<v-list-item-icon v-tooltip="t(`extension_${type}`)"><v-icon :name="icon" small /></v-list-item-icon>
<v-list-item-content>
<span class="monospace">
Expand All @@ -120,24 +130,26 @@ const uninstall = async () => {
</span>
</v-list-item-content>
<span v-if="saving" class="spinner">
<v-progress-circular indeterminate small />
</span>
<v-chip class="state" :class="state.status" small>
{{ state.text }}
</v-chip>
<extension-item-options
class="options"
:type="type"
:status="state.status"
:disable-locked="disableLocked"
:uninstall-locked="uninstallLocked"
:bundle-entry="bundleEntry"
@toggle-status="toggleState"
@uninstall="uninstall"
/>
<template v-if="type !== 'missing'">
<span v-if="saving" class="spinner">
<v-progress-circular indeterminate small />
</span>
<v-chip class="state" :class="state.status" small>
{{ state.text }}
</v-chip>
<extension-item-options
class="options"
:type="type"
:status="state.status"
:disable-locked="disableLocked"
:uninstall-locked="uninstallLocked"
:bundle-entry="bundleEntry"
@toggle-status="toggleState"
@uninstall="uninstall"
/>
</template>
</v-list-item>
<v-list v-if="children.length > 0" class="nested" :class="{ partial: isPartialEnabled }">
Expand Down
13 changes: 12 additions & 1 deletion app/src/modules/settings/routes/extensions/extensions.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,19 @@ const extensionsStore = useExtensionsStore();
const { extensions, loading } = storeToRefs(extensionsStore);
const bundled = computed(() => extensionsStore.extensions.filter(({ bundle }) => bundle !== null));
const regular = computed(() => extensionsStore.extensions.filter(({ bundle }) => bundle === null));
const extensionsByType = computed(() => groupBy(regular.value, 'schema.type'));
const extensionsByType = computed(() => {
const groups = groupBy(regular.value, 'schema.type');
if ('undefined' in groups) {
groups['missing'] = groups['undefined'];
delete groups['undefined'];
}
return groups;
});
</script>

<template>
Expand Down

0 comments on commit e7840bb

Please sign in to comment.