mirror of
https://github.com/directus/directus.git
synced 2026-01-24 07:27:59 -05:00
Remove use-m2m (#15955)
* remove old composable * Fix linter warnings Co-authored-by: rijkvanzanten <rijkvanzanten@me.com>
This commit is contained in:
@@ -1,87 +0,0 @@
|
||||
import { useCollection } from '@directus/shared/composables';
|
||||
import { useCollectionsStore } from '@/stores/collections';
|
||||
import { useRelationsStore } from '@/stores/relations';
|
||||
import { Field, Relation } from '@directus/shared/types';
|
||||
import { Collection } from '@/types/collections';
|
||||
import { computed, ComputedRef, Ref } from 'vue';
|
||||
|
||||
export type RelationInfo = {
|
||||
junctionPkField: string;
|
||||
relationPkField: string;
|
||||
junctionField: string;
|
||||
sortField: string;
|
||||
junctionCollection: string;
|
||||
relationCollection: string;
|
||||
};
|
||||
|
||||
type UsableRelation = {
|
||||
junction: ComputedRef<Relation>;
|
||||
junctionCollection: ComputedRef<Collection>;
|
||||
relation: ComputedRef<Relation>;
|
||||
relationCollection: ComputedRef<Collection>;
|
||||
relationInfo: ComputedRef<RelationInfo>;
|
||||
junctionPrimaryKeyField: ComputedRef<Field | null>;
|
||||
relationPrimaryKeyField: ComputedRef<Field | null>;
|
||||
junctionFields: ComputedRef<Field[]>;
|
||||
relationFields: ComputedRef<Field[]>;
|
||||
};
|
||||
|
||||
export function useRelation(collection: Ref<string>, field: Ref<string>): UsableRelation {
|
||||
const relationsStore = useRelationsStore();
|
||||
const collectionsStore = useCollectionsStore();
|
||||
|
||||
const relations = computed(() => {
|
||||
return relationsStore.getRelationsForField(collection.value, field.value) as Relation[];
|
||||
});
|
||||
|
||||
const junction = computed(() => {
|
||||
return relations.value.find(
|
||||
(relation) => relation.related_collection === collection.value && relation.meta?.one_field === field.value
|
||||
) as Relation;
|
||||
});
|
||||
|
||||
const relation = computed(() => {
|
||||
return relations.value.find(
|
||||
(relation) =>
|
||||
relation.collection === junction.value.collection && relation.field === junction.value.meta?.junction_field
|
||||
) as Relation;
|
||||
});
|
||||
|
||||
const junctionCollection = computed(() => {
|
||||
return collectionsStore.getCollection(junction.value.collection)!;
|
||||
});
|
||||
|
||||
const relationCollection = computed(() => {
|
||||
return collectionsStore.getCollection(relation.value.related_collection!)!;
|
||||
});
|
||||
|
||||
const { primaryKeyField: junctionPrimaryKeyField, fields: junctionFields } = useCollection(
|
||||
junctionCollection.value.collection
|
||||
);
|
||||
const { primaryKeyField: relationPrimaryKeyField, fields: relationFields } = useCollection(
|
||||
relationCollection.value.collection
|
||||
);
|
||||
|
||||
const relationInfo = computed(() => {
|
||||
return {
|
||||
junctionPkField: junctionPrimaryKeyField.value?.field,
|
||||
relationPkField: relationPrimaryKeyField.value?.field,
|
||||
junctionField: junction.value.meta?.junction_field as string,
|
||||
sortField: junction.value.meta?.sort_field as string,
|
||||
junctionCollection: junctionCollection.value.collection,
|
||||
relationCollection: relationCollection.value.collection,
|
||||
} as RelationInfo;
|
||||
});
|
||||
|
||||
return {
|
||||
junction,
|
||||
junctionCollection,
|
||||
relation,
|
||||
relationCollection,
|
||||
relationInfo,
|
||||
junctionPrimaryKeyField,
|
||||
relationPrimaryKeyField,
|
||||
junctionFields,
|
||||
relationFields,
|
||||
};
|
||||
}
|
||||
@@ -1,7 +1,11 @@
|
||||
<template>
|
||||
<value-null v-if="!junctionCollection.collection" />
|
||||
<value-null v-if="!relationInfo?.junctionCollection?.collection" />
|
||||
<div v-else class="display-translations">
|
||||
<render-template :template="internalTemplate" :item="displayItem" :collection="junctionCollection.collection" />
|
||||
<render-template
|
||||
:template="internalTemplate"
|
||||
:item="displayItem"
|
||||
:collection="relationInfo.junctionCollection.collection"
|
||||
/>
|
||||
<v-menu class="menu" show-arrow :disabled="value.length === 0">
|
||||
<template #activator="{ toggle, deactivate, active }">
|
||||
<v-icon small class="icon" :class="{ active }" name="info" @click.stop="toggle" @focusout="deactivate"></v-icon>
|
||||
@@ -20,7 +24,7 @@
|
||||
<render-template
|
||||
:template="internalTemplate"
|
||||
:item="item.item"
|
||||
:collection="junctionCollection.collection"
|
||||
:collection="relationInfo.junctionCollection.collection"
|
||||
/>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
@@ -29,103 +33,90 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, computed, PropType, toRefs } from 'vue';
|
||||
import { useRelation } from '@/composables/use-m2m';
|
||||
<script setup lang="ts">
|
||||
import { computed, toRefs } from 'vue';
|
||||
import { useUserStore } from '@/stores/user';
|
||||
import { isNil } from 'lodash';
|
||||
import { useRelationM2M } from '@/composables/use-relation-m2m';
|
||||
import { useFieldsStore } from '@/stores/fields';
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
collection: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
field: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
value: {
|
||||
type: [Array] as PropType<Record<string, any>[]>,
|
||||
default: null,
|
||||
},
|
||||
template: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
userLanguage: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
defaultLanguage: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
languageField: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const { collection, field } = toRefs(props);
|
||||
interface Props {
|
||||
collection: string;
|
||||
field: string;
|
||||
type: string;
|
||||
value?: Record<string, any>[];
|
||||
template?: string;
|
||||
userLanguage?: boolean;
|
||||
defaultLanguage?: string;
|
||||
languageField?: string;
|
||||
}
|
||||
|
||||
const {
|
||||
junctionPrimaryKeyField: primaryKeyField,
|
||||
junctionCollection,
|
||||
relation,
|
||||
junctionFields,
|
||||
relationPrimaryKeyField,
|
||||
} = useRelation(collection, field);
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
value: () => [],
|
||||
template: undefined,
|
||||
userLanguage: false,
|
||||
defaultLanguage: undefined,
|
||||
languageField: undefined,
|
||||
});
|
||||
|
||||
const internalTemplate = computed(() => {
|
||||
return (
|
||||
props.template || junctionCollection.value?.meta?.display_template || `{{ ${primaryKeyField.value!.field} }}`
|
||||
);
|
||||
});
|
||||
const { collection, field } = toRefs(props);
|
||||
const fieldsStore = useFieldsStore();
|
||||
|
||||
const displayItem = computed(() => {
|
||||
const langPkField = relationPrimaryKeyField.value?.field;
|
||||
if (!langPkField) return {};
|
||||
const { relationInfo } = useRelationM2M(collection, field);
|
||||
|
||||
let item =
|
||||
props.value.find((val) => val?.[relation.value.field]?.[langPkField] === props.defaultLanguage) ??
|
||||
props.value[0];
|
||||
const internalTemplate = computed(() => {
|
||||
if (!relationInfo.value) return '';
|
||||
|
||||
if (props.userLanguage) {
|
||||
const user = useUserStore();
|
||||
item =
|
||||
props.value.find((val) => val?.[relation.value.field]?.[langPkField] === user.currentUser?.language) ?? item;
|
||||
}
|
||||
return item ?? {};
|
||||
});
|
||||
const primaryKeyField = relationInfo.value.junctionPrimaryKeyField.field;
|
||||
const collectionDisplayTemplate = relationInfo.value.junctionCollection?.meta?.display_template;
|
||||
|
||||
const writableFields = computed(() =>
|
||||
junctionFields.value.filter(
|
||||
(field) => field.type !== 'alias' && field.meta?.hidden === false && field.meta.readonly === false
|
||||
)
|
||||
);
|
||||
return props.template || collectionDisplayTemplate || `{{ ${primaryKeyField} }}`;
|
||||
});
|
||||
|
||||
const translations = computed(() => {
|
||||
return props.value.map((item) => {
|
||||
const filledFields = writableFields.value.filter((field) => {
|
||||
return field.field in item && !isNil(item?.[field.field]);
|
||||
}).length;
|
||||
const displayItem = computed(() => {
|
||||
if (!relationInfo.value) return {};
|
||||
|
||||
return {
|
||||
id: item?.[primaryKeyField.value?.field ?? 'id'],
|
||||
lang: item?.[relation.value.field]?.[props.languageField ?? relationPrimaryKeyField.value?.field],
|
||||
progress: Math.round((filledFields / writableFields.value.length) * 100),
|
||||
item,
|
||||
};
|
||||
});
|
||||
});
|
||||
const langPkField = relationInfo.value.relatedPrimaryKeyField.field;
|
||||
const langField = relationInfo.value.junctionField.field;
|
||||
|
||||
return { primaryKeyField, internalTemplate, junctionCollection, displayItem, translations };
|
||||
},
|
||||
let item = props.value.find((val) => val?.[langField]?.[langPkField] === props.defaultLanguage) ?? props.value[0];
|
||||
|
||||
if (props.userLanguage) {
|
||||
const user = useUserStore();
|
||||
item = props.value.find((val) => val?.[langField]?.[langPkField] === user.currentUser?.language) ?? item;
|
||||
}
|
||||
return item ?? {};
|
||||
});
|
||||
|
||||
const writableFields = computed(() => {
|
||||
if (!relationInfo.value) return [];
|
||||
|
||||
const junctionFields = fieldsStore.getFieldsForCollection(relationInfo.value.junctionCollection.collection);
|
||||
|
||||
return junctionFields.filter(
|
||||
(field) => field.type !== 'alias' && field.meta?.hidden === false && field.meta.readonly === false
|
||||
);
|
||||
});
|
||||
|
||||
const translations = computed(() => {
|
||||
if (!relationInfo.value) return [];
|
||||
|
||||
const primaryKeyField = relationInfo.value.junctionPrimaryKeyField.field;
|
||||
const langPkField = relationInfo.value.relatedPrimaryKeyField.field;
|
||||
const langField = relationInfo.value.junctionField.field;
|
||||
|
||||
return props.value.map((item) => {
|
||||
const filledFields = writableFields.value.filter((field) => {
|
||||
return field.field in item && !isNil(item?.[field.field]);
|
||||
}).length;
|
||||
|
||||
return {
|
||||
id: item?.[primaryKeyField ?? 'id'],
|
||||
lang: item?.[langField]?.[props.languageField ?? langPkField],
|
||||
progress: Math.round((filledFields / writableFields.value.length) * 100),
|
||||
item,
|
||||
};
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useFieldsStore } from '@/stores/fields';
|
||||
import { useCollectionsStore } from '@/stores/collections';
|
||||
import panel from '@directus-extensions-panel';
|
||||
import { useFieldsStore } from '@/stores/fields';
|
||||
import { PanelQuery } from '@directus/shared/types';
|
||||
import { definePanel } from '@directus/shared/utils';
|
||||
import { computed } from 'vue';
|
||||
|
||||
Reference in New Issue
Block a user