From dd344b9a8eb49b9ba4eb9d1f370e796b0ea0e253 Mon Sep 17 00:00:00 2001 From: Andrew Scott Date: Fri, 17 May 2024 09:53:40 -0700 Subject: [PATCH] fix: #385 display doesn't handle many-to-many collections --- src/coalesce-vue/src/model.ts | 13 +++++++++++-- src/coalesce-vue/test/model.display.spec.ts | 19 +++++++++++++++++++ src/coalesce-vue/vitest.config.ts | 4 ++++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/coalesce-vue/src/model.ts b/src/coalesce-vue/src/model.ts index 7e8c3092d..0ff469097 100644 --- a/src/coalesce-vue/src/model.ts +++ b/src/coalesce-vue/src/model.ts @@ -21,6 +21,7 @@ import type { BooleanValue, NumberValue, StringValue, + ModelCollectionNavigationProperty, } from "./metadata.js"; import { resolvePropMeta } from "./metadata.js"; import { @@ -743,7 +744,7 @@ class DisplayVisitor extends Visitor< protected visitCollection( value: any[] | null, - meta: CollectionValue + meta: CollectionValue | ModelCollectionNavigationProperty ): string | null { if (value == null) return null; value = parseValue(value, meta); @@ -756,9 +757,17 @@ class DisplayVisitor extends Visitor< this.options?.collection ?? {}; if (value.length <= enumeratedItemsMax) { + let itemMeta = meta.itemType; + if ("manyToMany" in meta) { + itemMeta = meta.manyToMany!.farNavigationProp; + value = value.map( + (i) => i[meta.manyToMany!.farNavigationProp.name as any] + ); + } + return value .map( - (childItem) => this.visitValue(childItem, meta.itemType) || "???" // TODO: what should this be for un-displayable members of a collection? + (childItem) => this.visitValue(childItem, itemMeta) || "???" // TODO: what should this be for un-displayable members of a collection? ) .join(enumeratedItemsSeparator); } diff --git a/src/coalesce-vue/test/model.display.spec.ts b/src/coalesce-vue/test/model.display.spec.ts index 92ac338de..db6a3e0f9 100644 --- a/src/coalesce-vue/test/model.display.spec.ts +++ b/src/coalesce-vue/test/model.display.spec.ts @@ -5,6 +5,9 @@ import { shortStringify } from "./test-utils"; import { format, subYears } from "date-fns"; import { toDate } from "date-fns-tz"; +import { Case as CaseMeta } from "@test-targets/metadata.g"; +import { Case } from "@test-targets/models.g"; + const studentProps = $metadata.Student.props; const basicStudent = { @@ -203,6 +206,22 @@ describe.each([ }, ...undisplayable(studentProps.courses, "abc", 123, {}, true, new Date()), + // Many-to-many collection + { + meta: CaseMeta.props.caseProducts, + model: new Case({ + caseProducts: ["Foo", "Bar", "Baz"].map((name) => { + return { + product: { + name, + }, + }; + }), + }).caseProducts, + display: "Foo, Bar, Baz", + }, + + // Model/Object { meta: studentProps.advisor, model: null, display: null }, { meta: studentProps.advisor, diff --git a/src/coalesce-vue/vitest.config.ts b/src/coalesce-vue/vitest.config.ts index a33c5fd3b..fd0080628 100644 --- a/src/coalesce-vue/vitest.config.ts +++ b/src/coalesce-vue/vitest.config.ts @@ -15,6 +15,10 @@ export default defineConfig({ alias: [ // Imports inside the generated test targets: { find: "coalesce-vue/lib", replacement: path.resolve(__dirname, "src") }, + { + find: "@test-targets", + replacement: path.resolve(__dirname, "../test-targets"), + }, ], }, }) as UserConfig;