mirror of
https://github.com/directus/directus.git
synced 2026-01-29 01:48:23 -05:00
Relations: fix M2M related primary key (#10368)
* correction in m2m relation filed name * prevent m2m reload on form change * rely on junction PK instead of relation PK When relation PK is a manually entered string, we cannot rely on relation PK. * prevent m2a reload on form change Co-authored-by: Jose Varela <joselcvarela@gmail.com> Co-authored-by: rijkvanzanten <rijkvanzanten@me.com>
This commit is contained in:
@@ -148,7 +148,7 @@ import DrawerItem from '@/views/private/components/drawer-item/';
|
||||
import api from '@/api';
|
||||
import { unexpectedError } from '@/utils/unexpected-error';
|
||||
import { getFieldsFromTemplate } from '@directus/shared/utils';
|
||||
import { isPlainObject, cloneDeep } from 'lodash';
|
||||
import { isPlainObject, cloneDeep, isEqual } from 'lodash';
|
||||
import { getEndpoint } from '@/utils/get-endpoint';
|
||||
import { hideDragImage } from '@/utils/hide-drag-image';
|
||||
import Draggable from 'vuedraggable';
|
||||
@@ -378,9 +378,11 @@ export default defineComponent({
|
||||
relatedItemValues,
|
||||
};
|
||||
|
||||
async function fetchValues() {
|
||||
async function fetchValues(newVal: any, oldVal: any) {
|
||||
if (props.value === null) return;
|
||||
|
||||
if (isEqual(newVal, oldVal)) return;
|
||||
|
||||
loading.value = true;
|
||||
|
||||
try {
|
||||
|
||||
@@ -44,22 +44,26 @@ export default function useActions(
|
||||
|
||||
// Returns all items that do not have an existing junction and related item.
|
||||
function getNewItems() {
|
||||
const { junctionField, relationPkField } = relation.value;
|
||||
const { junctionPkField } = relation.value;
|
||||
|
||||
if (value.value === null || junctionField === null) return [];
|
||||
if (value.value === null || junctionPkField === null) return [];
|
||||
|
||||
return value.value.filter(
|
||||
(item) => typeof get(item, junctionField) === 'object' && has(item, [junctionField, relationPkField]) === false
|
||||
) as Record<string, any>[];
|
||||
return value.value.filter((item: any) => typeof item === 'object' && !item?.[junctionPkField]) as Record<
|
||||
string,
|
||||
any
|
||||
>[];
|
||||
}
|
||||
|
||||
// Returns a list of items which related or junction item does exist but had changes.
|
||||
function getUpdatedItems() {
|
||||
const { junctionField, relationPkField } = relation.value;
|
||||
const { junctionPkField } = relation.value;
|
||||
|
||||
if (value.value === null || junctionField === null) return [];
|
||||
if (value.value === null || junctionPkField === null) return [];
|
||||
|
||||
return value.value.filter((item) => has(item, [junctionField, relationPkField])) as Record<string, any>[];
|
||||
return value.value.filter((item: any) => typeof item === 'object' && item?.[junctionPkField]) as Record<
|
||||
string,
|
||||
any
|
||||
>[];
|
||||
}
|
||||
|
||||
// Returns only items that do not have any changes what so ever.
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Header } from '@/components/v-table/types';
|
||||
import { useFieldsStore } from '@/stores/';
|
||||
import { Field } from '@directus/shared/types';
|
||||
import { addRelatedPrimaryKeyToFields } from '@/utils/add-related-primary-key-to-fields';
|
||||
import { cloneDeep, get, merge } from 'lodash';
|
||||
import { cloneDeep, get, merge, isEqual } from 'lodash';
|
||||
import { Ref, ref, watch } from 'vue';
|
||||
import { RelationInfo } from '@/composables/use-m2m';
|
||||
import { getEndpoint } from '@/utils/get-endpoint';
|
||||
@@ -37,12 +37,14 @@ export default function usePreview(
|
||||
|
||||
watch(
|
||||
() => value.value,
|
||||
async (newVal) => {
|
||||
async (newVal, oldVal) => {
|
||||
if (newVal === null) {
|
||||
items.value = [];
|
||||
return;
|
||||
}
|
||||
|
||||
if (isEqual(newVal, oldVal)) return;
|
||||
|
||||
loading.value = true;
|
||||
const { junctionField, relationPkField, junctionPkField, relationCollection } = relation.value;
|
||||
if (junctionField === null) return;
|
||||
@@ -87,7 +89,7 @@ export default function usePreview(
|
||||
.map((item) => {
|
||||
const updatedItem = updatedItems.find(
|
||||
(updated) =>
|
||||
get(updated, [junctionField, junctionPkField]) === get(item, [junctionField, junctionPkField])
|
||||
get(updated, [junctionField, relationPkField]) === get(item, [junctionField, relationPkField])
|
||||
);
|
||||
if (updatedItem !== undefined) return merge(item, updatedItem);
|
||||
return item;
|
||||
|
||||
@@ -31,19 +31,19 @@ export default function useSelection(
|
||||
});
|
||||
|
||||
function stageSelection(newSelection: (number | string)[]) {
|
||||
const { junctionField, junctionPkField } = relation.value;
|
||||
const { junctionField, relationPkField } = relation.value;
|
||||
|
||||
const selection = newSelection.map((item) => {
|
||||
const initial = initialItems.value.find((existent) => existent[junctionField][junctionPkField] === item);
|
||||
const draft = items.value.find((draft) => draft[junctionField][junctionPkField] === item);
|
||||
const initial = initialItems.value.find((existent) => existent[junctionField][relationPkField] === item);
|
||||
const draft = items.value.find((draft) => draft[junctionField][relationPkField] === item);
|
||||
|
||||
return {
|
||||
...initial,
|
||||
...draft,
|
||||
[junctionField]: {
|
||||
...initial?.[junctionPkField],
|
||||
...draft?.[junctionPkField],
|
||||
[junctionPkField]: item,
|
||||
...initial?.[relationPkField],
|
||||
...draft?.[relationPkField],
|
||||
[relationPkField]: item,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user