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:
Harikrushna
2021-12-11 01:39:36 +05:30
committed by GitHub
parent 63ade9b42f
commit 8f8f0e5c12
4 changed files with 27 additions and 19 deletions

View File

@@ -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 {

View File

@@ -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.

View File

@@ -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;

View File

@@ -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,
},
};
});