From 4eb2b6f8309cb9de33c751cf23780496a947c28e Mon Sep 17 00:00:00 2001 From: Piotr Gulbis Date: Mon, 9 Dec 2024 08:28:19 +0100 Subject: [PATCH 01/23] chore: update demo to latest comet starter --- demo/admin/src/common/MasterMenu.tsx | 10 + demo/admin/src/footer/EditFooterPage.tsx | 192 +++ .../src/footer/blocks/FooterContentBlock.tsx | 35 + demo/api/block-meta.json | 1484 +++++++++++++---- demo/api/schema.gql | 19 +- demo/api/src/comet-config.json | 13 +- .../src/common/blocks/accordion-item.block.ts | 61 + demo/api/src/common/blocks/accordion.block.ts | 4 + .../blocks/call-to-action-list.block.ts | 4 + .../src/common/blocks/call-to-action.block.ts | 43 + demo/api/src/common/blocks/heading.block.ts | 52 + .../blocks/{linkBlock => }/link.block.ts | 6 +- .../common/blocks/media-gallery-item.block.ts | 38 + .../src/common/blocks/media-gallery.block.ts | 40 + demo/api/src/common/blocks/media.block.ts | 13 + demo/api/src/common/blocks/rich-text.block.ts | 3 +- demo/api/src/common/blocks/space.block.ts | 22 +- .../standalone-call-to-action-list.block.ts | 44 + .../common/blocks/standalone-heading.block.ts | 43 + .../common/blocks/standalone-media.block.ts | 39 + demo/api/src/common/blocks/text-link.block.ts | 5 +- demo/api/src/config/config.ts | 2 +- demo/api/src/db/fixtures/fixtures.console.ts | 2 + .../generators/blocks/space.generator.ts | 2 +- .../db/fixtures/generators/links.generator.ts | 2 +- .../many-images-test-page-fixture.service.ts | 1 + .../db/migrations/Migration20220127092535.ts | 6 +- .../db/migrations/Migration20220127092750.ts | 2 +- .../src/footer/blocks/footer-content.block.ts | 62 +- .../footer-scope.ts} | 6 +- demo/api/src/footer/entities/footer.entity.ts | 29 +- demo/api/src/footer/footer.module.ts | 6 +- .../src/footer/generated/footer.resolver.ts | 8 +- demo/api/src/links/dto/link.input.ts | 2 +- demo/api/src/links/entities/link.entity.ts | 2 +- .../api/src/pages/blocks/basic-stage.block.ts | 71 + .../pages/blocks/billboard-teaser.block.ts | 59 + demo/api/src/pages/blocks/columns.block.ts | 29 +- .../src/pages/blocks/content-group.block.ts | 73 + demo/api/src/pages/blocks/image-link.block.ts | 2 +- .../src/pages/blocks/key-facts-item.block.ts | 50 + demo/api/src/pages/blocks/key-facts.block.ts | 5 + demo/api/src/pages/blocks/stage.block.ts | 6 + .../api/src/pages/blocks/teaser-item.block.ts | 50 + demo/api/src/pages/blocks/teaser.block.ts | 59 +- demo/api/src/pages/dto/page.input.ts | 6 + demo/api/src/pages/entities/page.entity.ts | 6 + demo/api/src/pages/pages.resolver.ts | 1 + demo/api/src/util/mediaAspectRatios.ts | 13 + .../documents/pages/blocks/TeaserBlock.tsx | 31 - demo/site/package.json | 2 +- .../[domain]/[language]/footer/page.tsx | 46 + demo/site/src/blocks/RichTextBlock.tsx | 144 +- .../components/common/HiddenIfInvalidLink.tsx | 35 + .../site/src/components/common/Typography.tsx | 214 +++ .../pages/blocks/FooterContentBlock.tsx | 154 ++ demo/site/src/layout/PageLayout.tsx | 23 + demo/site/src/redraft.d.ts | 9 +- demo/site/src/theme.ts | 121 +- demo/site/src/util/graphQLClient.ts | 22 +- pnpm-lock.yaml | 2 +- 61 files changed, 2869 insertions(+), 666 deletions(-) create mode 100644 demo/admin/src/footer/EditFooterPage.tsx create mode 100644 demo/admin/src/footer/blocks/FooterContentBlock.tsx create mode 100644 demo/api/src/common/blocks/accordion-item.block.ts create mode 100644 demo/api/src/common/blocks/accordion.block.ts create mode 100644 demo/api/src/common/blocks/call-to-action-list.block.ts create mode 100644 demo/api/src/common/blocks/call-to-action.block.ts create mode 100644 demo/api/src/common/blocks/heading.block.ts rename demo/api/src/common/blocks/{linkBlock => }/link.block.ts (100%) create mode 100644 demo/api/src/common/blocks/media-gallery-item.block.ts create mode 100644 demo/api/src/common/blocks/media-gallery.block.ts create mode 100644 demo/api/src/common/blocks/media.block.ts create mode 100644 demo/api/src/common/blocks/standalone-call-to-action-list.block.ts create mode 100644 demo/api/src/common/blocks/standalone-heading.block.ts create mode 100644 demo/api/src/common/blocks/standalone-media.block.ts rename demo/api/src/footer/{entities/footer-content-scope.entity.ts => dto/footer-scope.ts} (78%) create mode 100644 demo/api/src/pages/blocks/basic-stage.block.ts create mode 100644 demo/api/src/pages/blocks/billboard-teaser.block.ts create mode 100644 demo/api/src/pages/blocks/content-group.block.ts create mode 100644 demo/api/src/pages/blocks/key-facts-item.block.ts create mode 100644 demo/api/src/pages/blocks/key-facts.block.ts create mode 100644 demo/api/src/pages/blocks/stage.block.ts create mode 100644 demo/api/src/pages/blocks/teaser-item.block.ts create mode 100644 demo/api/src/util/mediaAspectRatios.ts delete mode 100644 demo/site-pages/src/documents/pages/blocks/TeaserBlock.tsx create mode 100644 demo/site/src/app/block-preview/[domain]/[language]/footer/page.tsx create mode 100644 demo/site/src/components/common/HiddenIfInvalidLink.tsx create mode 100644 demo/site/src/components/common/Typography.tsx create mode 100644 demo/site/src/documents/pages/blocks/FooterContentBlock.tsx create mode 100644 demo/site/src/layout/PageLayout.tsx diff --git a/demo/admin/src/common/MasterMenu.tsx b/demo/admin/src/common/MasterMenu.tsx index a31cba476e..b91157f307 100644 --- a/demo/admin/src/common/MasterMenu.tsx +++ b/demo/admin/src/common/MasterMenu.tsx @@ -16,6 +16,7 @@ import { ContentScope } from "@src/common/ContentScopeProvider"; import { ImportFromUnsplash } from "@src/dam/ImportFromUnsplash"; import Dashboard from "@src/dashboard/Dashboard"; import { PredefinedPage } from "@src/documents/predefinedPages/PredefinedPage"; +import { EditFooterPage } from "@src/footer/EditFooterPage"; import { GQLPageTreeNodeCategory } from "@src/graphql.generated"; import { Link } from "@src/links/Link"; import { NewsLinkBlock } from "@src/news/blocks/NewsLinkBlock"; @@ -141,6 +142,15 @@ export const masterMenuData: MasterMenuData = [ component: MainMenu, }, }, + { + type: "route", + primary: , + route: { + path: "/project-snips/footer", + component: EditFooterPage, + }, + requiredPermission: "pageTree", + }, ], requiredPermission: "pageTree", }, diff --git a/demo/admin/src/footer/EditFooterPage.tsx b/demo/admin/src/footer/EditFooterPage.tsx new file mode 100644 index 0000000000..0d7fbe6c25 --- /dev/null +++ b/demo/admin/src/footer/EditFooterPage.tsx @@ -0,0 +1,192 @@ +import { gql, useMutation, useQuery } from "@apollo/client"; +import { MainContent, messages, SaveButton, Stack, StackToolbar, ToolbarActions, ToolbarFillSpace, ToolbarTitleItem } from "@comet/admin"; +import { Save } from "@comet/admin-icons"; +import { AdminComponentRoot, BlockState } from "@comet/blocks-admin"; +import { + BlockPreviewWithTabs, + ContentScopeIndicator, + resolveHasSaveConflict, + useBlockPreview, + useCmsBlockContext, + useContentScopeConfig, + useSaveConflictQuery, + useSiteConfig, +} from "@comet/cms-admin"; +import { FooterContentBlockInput } from "@src/blocks.generated"; +import { useContentScope } from "@src/common/ContentScopeProvider"; +import isEqual from "lodash.isequal"; +import { useEffect, useState } from "react"; +import { FormattedMessage } from "react-intl"; +import { useRouteMatch } from "react-router"; + +import { FooterContentBlock } from "./blocks/FooterContentBlock"; +import { + GQLCheckForChangesFooterQuery, + GQLCheckForChangesFooterQueryVariables, + GQLFooterQuery, + GQLFooterQueryVariables, + GQLSaveFooterMutation, + GQLSaveFooterMutationVariables, + namedOperations, +} from "./EditFooterPage.generated"; + +export const EditFooterPage = () => { + const { scope } = useContentScope(); + const siteConfig = useSiteConfig({ scope }); + const [footerState, setFooterState] = useState>(FooterContentBlock.defaultValues()); + const [hasChanges, setHasChanges] = useState(false); + const [referenceContent, setReferenceContent] = useState(null); + const match = useRouteMatch(); + const previewApi = useBlockPreview(); + const blockContext = useCmsBlockContext(); + + useContentScopeConfig({ redirectPathAfterChange: "/project-snips/footer" }); + + const { data, refetch, loading } = useQuery(footerQuery, { + variables: { + scope, + }, + }); + + const saveConflict = useSaveConflictQuery( + checkForChangesQuery, + { + variables: { + scope, + }, + resolveHasConflict: (checkForChangesData) => { + return resolveHasSaveConflict(data?.footer?.updatedAt, checkForChangesData?.footer?.updatedAt); + }, + }, + { + hasChanges, + loadLatestVersion: async () => { + await refetch(); + }, + onDiscardButtonPressed: async () => { + await refetch(); + }, + }, + ); + + const [update, { loading: saving, error: hasSaveErrors }] = useMutation( + saveFooterMutation, + { refetchQueries: !data?.footer ? [namedOperations.Query.Footer] : [] }, + ); + + useEffect(() => { + if (data) { + if (data.footer) { + const content = FooterContentBlock.input2State(data.footer.content); + setFooterState(content); + setReferenceContent(FooterContentBlock.state2Output(content)); + } else { + const state = FooterContentBlock.defaultValues(); + setFooterState(state); + setReferenceContent(FooterContentBlock.state2Output(state)); + } + } + }, [data]); + + useEffect(() => { + const equal = isEqual(referenceContent, footerState ? FooterContentBlock.state2Output(footerState) : null); + setHasChanges(!equal); + }, [footerState, referenceContent]); + + if (loading) { + return null; + } + + const handleSavePage = async () => { + const hasSaveConflict = await saveConflict.checkForConflicts(); + if (hasSaveConflict) { + return; // dialogs open for the user to handle the conflict + } + + const input = { + content: FooterContentBlock.state2Output(footerState), + }; + return update({ + variables: { input, scope }, + }); + }; + + const tabs = [ + { + key: "content", + label: , + content: ( + + + + ), + }, + ]; + + const previewState = FooterContentBlock.createPreviewState(footerState, { + ...blockContext, + parentUrl: match.url, + showVisibleOnly: previewApi.showOnlyVisible, + }); + + return ( + + }> + + + + + + } + > + + + + + + + {tabs} + + + {saveConflict.dialogs} + + ); +}; + +const footerQuery = gql` + query Footer($scope: FooterScopeInput!) { + footer(scope: $scope) { + id + content + scope { + domain + } + updatedAt + } + } +`; + +const saveFooterMutation = gql` + mutation SaveFooter($input: FooterInput!, $scope: FooterScopeInput!) { + saveFooter(input: $input, scope: $scope) { + id + content + updatedAt + } + } +`; + +const checkForChangesQuery = gql` + query CheckForChangesFooter($scope: FooterScopeInput!) { + footer(scope: $scope) { + updatedAt + } + } +`; diff --git a/demo/admin/src/footer/blocks/FooterContentBlock.tsx b/demo/admin/src/footer/blocks/FooterContentBlock.tsx new file mode 100644 index 0000000000..571f86e530 --- /dev/null +++ b/demo/admin/src/footer/blocks/FooterContentBlock.tsx @@ -0,0 +1,35 @@ +import { createCompositeBlock, createCompositeBlockTextField } from "@comet/blocks-admin"; +import { DamImageBlock } from "@comet/cms-admin"; +import { LinkListBlock } from "@src/common/blocks/LinkListBlock"; +import { RichTextBlock } from "@src/common/blocks/RichTextBlock"; +import { FormattedMessage } from "react-intl"; + +export const FooterContentBlock = createCompositeBlock({ + name: "FooterContent", + displayName: null, + blocks: { + text: { + block: RichTextBlock, + title: , + hiddenInSubroute: true, + }, + image: { + block: DamImageBlock, + title: , + hiddenInSubroute: true, + }, + linkList: { + block: LinkListBlock, + title: , + }, + copyrightNotice: { + block: createCompositeBlockTextField({ + fieldProps: { + label: , + fullWidth: true, + }, + }), + hiddenInSubroute: true, + }, + }, +}); diff --git a/demo/api/block-meta.json b/demo/api/block-meta.json index 2537a8a4df..e6066b82c8 100644 --- a/demo/api/block-meta.json +++ b/demo/api/block-meta.json @@ -1,4 +1,177 @@ [ + { + "name": "Accordion", + "fields": [ + { + "name": "blocks", + "kind": "NestedObjectList", + "object": { + "fields": [ + { + "name": "key", + "kind": "String", + "nullable": false + }, + { + "name": "visible", + "kind": "Boolean", + "nullable": false + }, + { + "name": "props", + "kind": "Block", + "block": "AccordionItem", + "nullable": false + } + ] + }, + "nullable": false + } + ], + "inputFields": [ + { + "name": "blocks", + "kind": "NestedObjectList", + "object": { + "fields": [ + { + "name": "key", + "kind": "String", + "nullable": false + }, + { + "name": "visible", + "kind": "Boolean", + "nullable": false + }, + { + "name": "props", + "kind": "Block", + "block": "AccordionItem", + "nullable": false + } + ] + }, + "nullable": false + } + ] + }, + { + "name": "AccordionContent", + "fields": [ + { + "name": "blocks", + "kind": "NestedObjectList", + "object": { + "fields": [ + { + "name": "key", + "kind": "String", + "nullable": false + }, + { + "name": "visible", + "kind": "Boolean", + "nullable": false + }, + { + "name": "type", + "kind": "String", + "nullable": false + }, + { + "name": "props", + "kind": "OneOfBlocks", + "blocks": { + "richtext": "RichText", + "heading": "StandaloneHeading", + "space": "Space", + "callToActionList": "StandaloneCallToActionList" + }, + "nullable": false + } + ] + }, + "nullable": false + } + ], + "inputFields": [ + { + "name": "blocks", + "kind": "NestedObjectList", + "object": { + "fields": [ + { + "name": "key", + "kind": "String", + "nullable": false + }, + { + "name": "visible", + "kind": "Boolean", + "nullable": false + }, + { + "name": "type", + "kind": "String", + "nullable": false + }, + { + "name": "props", + "kind": "OneOfBlocks", + "blocks": { + "richtext": "RichText", + "heading": "StandaloneHeading", + "space": "Space", + "callToActionList": "StandaloneCallToActionList" + }, + "nullable": false + } + ] + }, + "nullable": false + } + ] + }, + { + "name": "AccordionItem", + "fields": [ + { + "name": "title", + "kind": "String", + "nullable": true + }, + { + "name": "content", + "kind": "Block", + "block": "AccordionContent", + "nullable": false + }, + { + "name": "openByDefault", + "kind": "Boolean", + "nullable": false + } + ], + "inputFields": [ + { + "name": "title", + "kind": "String", + "nullable": true + }, + { + "name": "content", + "kind": "Block", + "block": "AccordionContent", + "nullable": false + }, + { + "name": "openByDefault", + "kind": "Boolean", + "nullable": false + } + ] + }, { "name": "Anchor", "fields": [ @@ -16,6 +189,185 @@ } ] }, + { + "name": "BasicStage", + "fields": [ + { + "name": "media", + "kind": "Block", + "block": "Media", + "nullable": false + }, + { + "name": "heading", + "kind": "Block", + "block": "Heading", + "nullable": false + }, + { + "name": "text", + "kind": "Block", + "block": "RichText", + "nullable": false + }, + { + "name": "overlay", + "kind": "Number", + "nullable": false + }, + { + "name": "alignment", + "kind": "Enum", + "enum": [ + "left", + "center" + ], + "nullable": false + }, + { + "name": "callToActionList", + "kind": "Block", + "block": "CallToActionList", + "nullable": false + } + ], + "inputFields": [ + { + "name": "media", + "kind": "Block", + "block": "Media", + "nullable": false + }, + { + "name": "heading", + "kind": "Block", + "block": "Heading", + "nullable": false + }, + { + "name": "text", + "kind": "Block", + "block": "RichText", + "nullable": false + }, + { + "name": "overlay", + "kind": "Number", + "nullable": false + }, + { + "name": "alignment", + "kind": "Enum", + "enum": [ + "left", + "center" + ], + "nullable": false + }, + { + "name": "callToActionList", + "kind": "Block", + "block": "CallToActionList", + "nullable": false + } + ] + }, + { + "name": "CallToAction", + "fields": [ + { + "name": "textLink", + "kind": "Block", + "block": "TextLink", + "nullable": false + }, + { + "name": "variant", + "kind": "Enum", + "enum": [ + "Contained", + "Outlined", + "Text" + ], + "nullable": false + } + ], + "inputFields": [ + { + "name": "textLink", + "kind": "Block", + "block": "TextLink", + "nullable": false + }, + { + "name": "variant", + "kind": "Enum", + "enum": [ + "Contained", + "Outlined", + "Text" + ], + "nullable": false + } + ] + }, + { + "name": "CallToActionList", + "fields": [ + { + "name": "blocks", + "kind": "NestedObjectList", + "object": { + "fields": [ + { + "name": "key", + "kind": "String", + "nullable": false + }, + { + "name": "visible", + "kind": "Boolean", + "nullable": false + }, + { + "name": "props", + "kind": "Block", + "block": "CallToAction", + "nullable": false + } + ] + }, + "nullable": false + } + ], + "inputFields": [ + { + "name": "blocks", + "kind": "NestedObjectList", + "object": { + "fields": [ + { + "name": "key", + "kind": "String", + "nullable": false + }, + { + "name": "visible", + "kind": "Boolean", + "nullable": false + }, + { + "name": "props", + "kind": "Block", + "block": "CallToAction", + "nullable": false + } + ] + }, + "nullable": false + } + ] + }, { "name": "Columns", "fields": [ @@ -110,11 +462,17 @@ "name": "props", "kind": "OneOfBlocks", "blocks": { - "space": "Space", - "richtext": "RichText", + "accordion": "Accordion", + "anchor": "Anchor", + "callToActionList": "StandaloneCallToActionList", + "heading": "StandaloneHeading", "headline": "Headline", "image": "DamImage", - "linkList": "LinkList" + "linkList": "LinkList", + "media": "StandaloneMedia", + "mediaGallery": "MediaGallery", + "richtext": "RichText", + "space": "Space" }, "nullable": false } @@ -148,11 +506,17 @@ "name": "props", "kind": "OneOfBlocks", "blocks": { - "space": "Space", - "richtext": "RichText", + "accordion": "Accordion", + "anchor": "Anchor", + "callToActionList": "StandaloneCallToActionList", + "heading": "StandaloneHeading", "headline": "Headline", "image": "DamImage", - "linkList": "LinkList" + "linkList": "LinkList", + "media": "StandaloneMedia", + "mediaGallery": "MediaGallery", + "richtext": "RichText", + "space": "Space" }, "nullable": false } @@ -402,76 +766,6 @@ } ] }, - { - "name": "DemoSpace", - "fields": [ - { - "name": "spacing", - "kind": "Enum", - "enum": [ - "d150", - "d200", - "d250", - "d300", - "d350", - "d400", - "d450", - "d500", - "d550", - "d600" - ], - "nullable": false - } - ], - "inputFields": [ - { - "name": "spacing", - "kind": "Enum", - "enum": [ - "d150", - "d200", - "d250", - "d300", - "d350", - "d400", - "d450", - "d500", - "d550", - "d600" - ], - "nullable": false - } - ] - }, - { - "name": "DemoTextLink", - "fields": [ - { - "name": "text", - "kind": "String", - "nullable": false - }, - { - "name": "link", - "kind": "Block", - "block": "Link", - "nullable": false - } - ], - "inputFields": [ - { - "name": "text", - "kind": "String", - "nullable": false - }, - { - "name": "link", - "kind": "Block", - "block": "Link", - "nullable": false - } - ] - }, { "name": "EmailLink", "fields": [ @@ -520,19 +814,19 @@ "name": "FooterContent", "fields": [ { - "name": "popularTopicsLinks", + "name": "text", "kind": "Block", - "block": "LinkList", + "block": "RichText", "nullable": false }, { - "name": "aboutLinks", + "name": "image", "kind": "Block", - "block": "LinkList", + "block": "DamImage", "nullable": false }, { - "name": "bottomLinks", + "name": "linkList", "kind": "Block", "block": "LinkList", "nullable": false @@ -541,33 +835,23 @@ "name": "copyrightNotice", "kind": "String", "nullable": false - }, - { - "name": "location", - "kind": "String", - "nullable": false - }, - { - "name": "contactUs", - "kind": "String", - "nullable": false } ], "inputFields": [ { - "name": "popularTopicsLinks", + "name": "text", "kind": "Block", - "block": "LinkList", + "block": "RichText", "nullable": false }, { - "name": "aboutLinks", + "name": "image", "kind": "Block", - "block": "LinkList", + "block": "DamImage", "nullable": false }, { - "name": "bottomLinks", + "name": "linkList", "kind": "Block", "block": "LinkList", "nullable": false @@ -576,132 +860,93 @@ "name": "copyrightNotice", "kind": "String", "nullable": false - }, - { - "name": "location", - "kind": "String", - "nullable": false - }, - { - "name": "contactUs", - "kind": "String", - "nullable": false } ] }, { - "name": "FooterLinkSection", + "name": "FullWidthImage", "fields": [ { - "name": "title", - "kind": "String", - "nullable": false - }, - { - "name": "links", + "name": "image", "kind": "Block", - "block": "LinkList", - "nullable": false - } - ], - "inputFields": [ - { - "name": "title", - "kind": "String", + "block": "DamImage", "nullable": false }, { - "name": "links", + "name": "content", "kind": "Block", - "block": "LinkList", - "nullable": false - } - ] - }, - { - "name": "FooterTopLinks", - "fields": [ - { - "name": "blocks", - "kind": "NestedObjectList", - "object": { - "fields": [ - { - "name": "key", - "kind": "String", - "nullable": false - }, - { - "name": "visible", - "kind": "Boolean", - "nullable": false - }, - { - "name": "props", - "kind": "Block", - "block": "FooterLinkSection", - "nullable": false - } - ] - }, + "block": "OptionalRichText", "nullable": false } ], "inputFields": [ { - "name": "blocks", - "kind": "NestedObjectList", - "object": { - "fields": [ - { - "name": "key", - "kind": "String", - "nullable": false - }, - { - "name": "visible", - "kind": "Boolean", - "nullable": false - }, - { - "name": "props", - "kind": "Block", - "block": "FooterLinkSection", - "nullable": false - } - ] - }, + "name": "image", + "kind": "Block", + "block": "DamImage", + "nullable": false + }, + { + "name": "content", + "kind": "Block", + "block": "OptionalRichText", "nullable": false } ] }, { - "name": "FullWidthImage", + "name": "Heading", "fields": [ { - "name": "image", + "name": "eyebrow", "kind": "Block", - "block": "DamImage", + "block": "RichText", "nullable": false }, { - "name": "content", + "name": "headline", "kind": "Block", - "block": "OptionalRichText", + "block": "RichText", + "nullable": false + }, + { + "name": "htmlTag", + "kind": "Enum", + "enum": [ + "H1", + "H2", + "H3", + "H4", + "H5", + "H6" + ], "nullable": false } ], "inputFields": [ { - "name": "image", + "name": "eyebrow", "kind": "Block", - "block": "DamImage", + "block": "RichText", "nullable": false }, { - "name": "content", + "name": "headline", "kind": "Block", - "block": "OptionalRichText", + "block": "RichText", + "nullable": false + }, + { + "name": "htmlTag", + "kind": "Enum", + "enum": [ + "H1", + "H2", + "H3", + "H4", + "H5", + "H6" + ], "nullable": false } ] @@ -953,12 +1198,12 @@ "name": "props", "kind": "OneOfBlocks", "blocks": { - "internal": "InternalLink", + "damFileDownload": "DamFileDownloadLink", + "email": "EmailLink", "external": "ExternalLink", + "internal": "InternalLink", "news": "NewsLink", - "damFileDownload": "DamFileDownloadLink", - "phone": "PhoneLink", - "email": "EmailLink" + "phone": "PhoneLink" }, "nullable": false } @@ -985,12 +1230,12 @@ "name": "props", "kind": "OneOfBlocks", "blocks": { - "internal": "InternalLink", + "damFileDownload": "DamFileDownloadLink", + "email": "EmailLink", "external": "ExternalLink", + "internal": "InternalLink", "news": "NewsLink", - "damFileDownload": "DamFileDownloadLink", - "phone": "PhoneLink", - "email": "EmailLink" + "phone": "PhoneLink" }, "nullable": false } @@ -1033,7 +1278,44 @@ { "name": "props", "kind": "Block", - "block": "DemoTextLink", + "block": "TextLink", + "nullable": false + }, + { + "name": "userGroup", + "kind": "Enum", + "enum": [ + "All", + "Admin", + "User" + ], + "nullable": false + } + ] + }, + "nullable": false + } + ], + "inputFields": [ + { + "name": "blocks", + "kind": "NestedObjectList", + "object": { + "fields": [ + { + "name": "key", + "kind": "String", + "nullable": false + }, + { + "name": "visible", + "kind": "Boolean", + "nullable": false + }, + { + "name": "props", + "kind": "Block", + "block": "TextLink", "nullable": false }, { @@ -1050,8 +1332,227 @@ }, "nullable": false } - ], - "inputFields": [ + ] + }, + { + "name": "Media", + "fields": [ + { + "name": "attachedBlocks", + "kind": "NestedObjectList", + "object": { + "fields": [ + { + "name": "type", + "kind": "String", + "nullable": false + }, + { + "name": "props", + "kind": "OneOfBlocks", + "blocks": { + "image": "DamImage", + "damVideo": "DamVideo", + "youTubeVideo": "YouTubeVideo", + "vimeoVideo": "VimeoVideo" + }, + "nullable": false + } + ] + }, + "nullable": false + }, + { + "name": "activeType", + "kind": "String", + "nullable": true + }, + { + "name": "block", + "kind": "NestedObject", + "object": { + "fields": [ + { + "name": "type", + "kind": "String", + "nullable": false + }, + { + "name": "props", + "kind": "OneOfBlocks", + "blocks": { + "image": "DamImage", + "damVideo": "DamVideo", + "youTubeVideo": "YouTubeVideo", + "vimeoVideo": "VimeoVideo" + }, + "nullable": false + } + ] + }, + "nullable": true + } + ], + "inputFields": [ + { + "name": "activeType", + "kind": "String", + "nullable": true + } + ] + }, + { + "name": "Media", + "fields": [ + { + "name": "attachedBlocks", + "kind": "NestedObjectList", + "object": { + "fields": [ + { + "name": "type", + "kind": "String", + "nullable": false + }, + { + "name": "props", + "kind": "OneOfBlocks", + "blocks": { + "image": "DamImage", + "damVideo": "DamVideo", + "youTubeVideo": "YouTubeVideo" + }, + "nullable": false + } + ] + }, + "nullable": false + }, + { + "name": "activeType", + "kind": "String", + "nullable": true + }, + { + "name": "block", + "kind": "NestedObject", + "object": { + "fields": [ + { + "name": "type", + "kind": "String", + "nullable": false + }, + { + "name": "props", + "kind": "OneOfBlocks", + "blocks": { + "image": "DamImage", + "damVideo": "DamVideo", + "youTubeVideo": "YouTubeVideo" + }, + "nullable": false + } + ] + }, + "nullable": true + } + ], + "inputFields": [ + { + "name": "activeType", + "kind": "String", + "nullable": true + } + ] + }, + { + "name": "MediaGallery", + "fields": [ + { + "name": "items", + "kind": "Block", + "block": "MediaGalleryList", + "nullable": false + }, + { + "name": "aspectRatio", + "kind": "Enum", + "enum": [ + "16x9", + "4x3", + "3x2", + "3x1", + "2x1", + "1x1", + "1x2", + "1x3", + "2x3", + "3x4", + "9x16" + ], + "nullable": false + } + ], + "inputFields": [ + { + "name": "items", + "kind": "Block", + "block": "MediaGalleryList", + "nullable": false + }, + { + "name": "aspectRatio", + "kind": "Enum", + "enum": [ + "16x9", + "4x3", + "3x2", + "3x1", + "2x1", + "1x1", + "1x2", + "1x3", + "2x3", + "3x4", + "9x16" + ], + "nullable": false + } + ] + }, + { + "name": "MediaGalleryItem", + "fields": [ + { + "name": "media", + "kind": "Block", + "block": "Media", + "nullable": false + }, + { + "name": "caption", + "kind": "String", + "nullable": true + } + ], + "inputFields": [ + { + "name": "media", + "kind": "Block", + "block": "Media", + "nullable": false + }, + { + "name": "caption", + "kind": "String", + "nullable": true + } + ] + }, + { + "name": "MediaGalleryList", + "fields": [ { "name": "blocks", "kind": "NestedObjectList", @@ -1070,89 +1571,39 @@ { "name": "props", "kind": "Block", - "block": "DemoTextLink", - "nullable": false - }, - { - "name": "userGroup", - "kind": "Enum", - "enum": [ - "All", - "Admin", - "User" - ], + "block": "MediaGalleryItem", "nullable": false } ] }, "nullable": false } - ] - }, - { - "name": "Media", - "fields": [ + ], + "inputFields": [ { - "name": "attachedBlocks", + "name": "blocks", "kind": "NestedObjectList", "object": { "fields": [ { - "name": "type", + "name": "key", "kind": "String", "nullable": false }, { - "name": "props", - "kind": "OneOfBlocks", - "blocks": { - "image": "DamImage", - "damVideo": "DamVideo", - "youTubeVideo": "YouTubeVideo", - "vimeoVideo": "VimeoVideo" - }, - "nullable": false - } - ] - }, - "nullable": false - }, - { - "name": "activeType", - "kind": "String", - "nullable": true - }, - { - "name": "block", - "kind": "NestedObject", - "object": { - "fields": [ - { - "name": "type", - "kind": "String", + "name": "visible", + "kind": "Boolean", "nullable": false }, { "name": "props", - "kind": "OneOfBlocks", - "blocks": { - "image": "DamImage", - "damVideo": "DamVideo", - "youTubeVideo": "YouTubeVideo", - "vimeoVideo": "VimeoVideo" - }, + "kind": "Block", + "block": "MediaGalleryItem", "nullable": false } ] }, - "nullable": true - } - ], - "inputFields": [ - { - "name": "activeType", - "kind": "String", - "nullable": true + "nullable": false } ] }, @@ -1409,7 +1860,7 @@ "name": "props", "kind": "OneOfBlocks", "blocks": { - "space": "DemoSpace", + "space": "Space", "richtext": "RichText", "headline": "Headline", "image": "DamImage", @@ -1468,7 +1919,7 @@ "name": "props", "kind": "OneOfBlocks", "blocks": { - "space": "DemoSpace", + "space": "Space", "richtext": "RichText", "headline": "Headline", "image": "DamImage", @@ -1905,133 +2356,362 @@ "nullable": true }, { - "name": "alternativeLinks", + "name": "alternativeLinks", + "kind": "NestedObjectList", + "object": { + "fields": [ + { + "name": "code", + "kind": "String", + "nullable": true + }, + { + "name": "url", + "kind": "String", + "nullable": true + } + ] + }, + "nullable": false + } + ], + "inputFields": [ + { + "name": "htmlTitle", + "kind": "String", + "nullable": true + }, + { + "name": "metaDescription", + "kind": "String", + "nullable": true + }, + { + "name": "openGraphTitle", + "kind": "String", + "nullable": true + }, + { + "name": "openGraphDescription", + "kind": "String", + "nullable": true + }, + { + "name": "openGraphImage", + "kind": "Block", + "block": "OptionalPixelImage", + "nullable": false + }, + { + "name": "structuredData", + "kind": "String", + "nullable": true + }, + { + "name": "noIndex", + "kind": "Boolean", + "nullable": false + }, + { + "name": "priority", + "kind": "Enum", + "enum": [ + "0_0", + "0_1", + "0_2", + "0_3", + "0_4", + "0_5", + "0_6", + "0_7", + "0_8", + "0_9", + "1_0" + ], + "nullable": false + }, + { + "name": "changeFrequency", + "kind": "Enum", + "enum": [ + "always", + "hourly", + "daily", + "weekly", + "monthly", + "yearly", + "never" + ], + "nullable": false + }, + { + "name": "canonicalUrl", + "kind": "String", + "nullable": true + }, + { + "name": "alternativeLinks", + "kind": "NestedObjectList", + "object": { + "fields": [ + { + "name": "code", + "kind": "String", + "nullable": true + }, + { + "name": "url", + "kind": "String", + "nullable": true + } + ] + }, + "nullable": false + } + ] + }, + { + "name": "Space", + "fields": [ + { + "name": "height", + "kind": "Number", + "nullable": false + } + ], + "inputFields": [ + { + "name": "height", + "kind": "Number", + "nullable": false + } + ] + }, + { + "name": "Space", + "fields": [ + { + "name": "spacing", + "kind": "Enum", + "enum": [ + "D100", + "D200", + "D300", + "D400", + "S100", + "S200", + "S300", + "S400", + "S500", + "S600" + ], + "nullable": false + } + ], + "inputFields": [ + { + "name": "spacing", + "kind": "Enum", + "enum": [ + "D100", + "D200", + "D300", + "D400", + "S100", + "S200", + "S300", + "S400", + "S500", + "S600" + ], + "nullable": false + } + ] + }, + { + "name": "Stage", + "fields": [ + { + "name": "blocks", + "kind": "NestedObjectList", + "object": { + "fields": [ + { + "name": "key", + "kind": "String", + "nullable": false + }, + { + "name": "visible", + "kind": "Boolean", + "nullable": false + }, + { + "name": "props", + "kind": "Block", + "block": "BasicStage", + "nullable": false + } + ] + }, + "nullable": false + } + ], + "inputFields": [ + { + "name": "blocks", "kind": "NestedObjectList", "object": { "fields": [ { - "name": "code", + "name": "key", "kind": "String", - "nullable": true + "nullable": false }, { - "name": "url", - "kind": "String", - "nullable": true + "name": "visible", + "kind": "Boolean", + "nullable": false + }, + { + "name": "props", + "kind": "Block", + "block": "BasicStage", + "nullable": false } ] }, "nullable": false } - ], - "inputFields": [ - { - "name": "htmlTitle", - "kind": "String", - "nullable": true - }, - { - "name": "metaDescription", - "kind": "String", - "nullable": true - }, - { - "name": "openGraphTitle", - "kind": "String", - "nullable": true - }, - { - "name": "openGraphDescription", - "kind": "String", - "nullable": true - }, + ] + }, + { + "name": "StandaloneCallToActionList", + "fields": [ { - "name": "openGraphImage", + "name": "callToActionList", "kind": "Block", - "block": "OptionalPixelImage", + "block": "CallToActionList", "nullable": false }, { - "name": "structuredData", - "kind": "String", - "nullable": true - }, + "name": "alignment", + "kind": "Enum", + "enum": [ + "left", + "center", + "right" + ], + "nullable": false + } + ], + "inputFields": [ { - "name": "noIndex", - "kind": "Boolean", + "name": "callToActionList", + "kind": "Block", + "block": "CallToActionList", "nullable": false }, { - "name": "priority", + "name": "alignment", "kind": "Enum", "enum": [ - "0_0", - "0_1", - "0_2", - "0_3", - "0_4", - "0_5", - "0_6", - "0_7", - "0_8", - "0_9", - "1_0" + "left", + "center", + "right" ], "nullable": false + } + ] + }, + { + "name": "StandaloneHeading", + "fields": [ + { + "name": "heading", + "kind": "Block", + "block": "Heading", + "nullable": false }, { - "name": "changeFrequency", + "name": "textAlignment", "kind": "Enum", "enum": [ - "always", - "hourly", - "daily", - "weekly", - "monthly", - "yearly", - "never" + "left", + "center" ], "nullable": false - }, + } + ], + "inputFields": [ { - "name": "canonicalUrl", - "kind": "String", - "nullable": true + "name": "heading", + "kind": "Block", + "block": "Heading", + "nullable": false }, { - "name": "alternativeLinks", - "kind": "NestedObjectList", - "object": { - "fields": [ - { - "name": "code", - "kind": "String", - "nullable": true - }, - { - "name": "url", - "kind": "String", - "nullable": true - } - ] - }, + "name": "textAlignment", + "kind": "Enum", + "enum": [ + "left", + "center" + ], "nullable": false } ] }, { - "name": "Space", + "name": "StandaloneMedia", "fields": [ { - "name": "height", - "kind": "Number", + "name": "media", + "kind": "Block", + "block": "Media", + "nullable": false + }, + { + "name": "aspectRatio", + "kind": "Enum", + "enum": [ + "16x9", + "4x3", + "3x2", + "3x1", + "2x1", + "1x1", + "1x2", + "1x3", + "2x3", + "3x4", + "9x16" + ], "nullable": false } ], "inputFields": [ { - "name": "height", - "kind": "Number", + "name": "media", + "kind": "Block", + "block": "Media", + "nullable": false + }, + { + "name": "aspectRatio", + "kind": "Enum", + "enum": [ + "16x9", + "4x3", + "3x2", + "3x1", + "2x1", + "1x1", + "1x2", + "1x3", + "2x3", + "3x4", + "9x16" + ], "nullable": false } ] @@ -2111,65 +2791,108 @@ "name": "Teaser", "fields": [ { - "name": "headline", - "kind": "Block", - "block": "Headline", + "name": "blocks", + "kind": "NestedObjectList", + "object": { + "fields": [ + { + "name": "key", + "kind": "String", + "nullable": false + }, + { + "name": "visible", + "kind": "Boolean", + "nullable": false + }, + { + "name": "props", + "kind": "Block", + "block": "TeaserItem", + "nullable": false + } + ] + }, "nullable": false - }, + } + ], + "inputFields": [ { - "name": "image", + "name": "blocks", + "kind": "NestedObjectList", + "object": { + "fields": [ + { + "name": "key", + "kind": "String", + "nullable": false + }, + { + "name": "visible", + "kind": "Boolean", + "nullable": false + }, + { + "name": "props", + "kind": "Block", + "block": "TeaserItem", + "nullable": false + } + ] + }, + "nullable": false + } + ] + }, + { + "name": "TeaserItem", + "fields": [ + { + "name": "media", "kind": "Block", - "block": "DamImage", + "block": "Media", "nullable": false }, { - "name": "links", - "kind": "Block", - "block": "LinkList", + "name": "title", + "kind": "String", "nullable": false }, { - "name": "buttons", + "name": "description", "kind": "Block", - "block": "LinkList", + "block": "RichText", "nullable": false }, { - "name": "columns", + "name": "link", "kind": "Block", - "block": "Columns", + "block": "TextLink", "nullable": false } ], "inputFields": [ { - "name": "headline", - "kind": "Block", - "block": "Headline", - "nullable": false - }, - { - "name": "image", + "name": "media", "kind": "Block", - "block": "DamImage", + "block": "Media", "nullable": false }, { - "name": "links", - "kind": "Block", - "block": "LinkList", + "name": "title", + "kind": "String", "nullable": false }, { - "name": "buttons", + "name": "description", "kind": "Block", - "block": "LinkList", + "block": "RichText", "nullable": false }, { - "name": "columns", + "name": "link", "kind": "Block", - "block": "Columns", + "block": "TextLink", "nullable": false } ] @@ -2233,6 +2956,35 @@ } ] }, + { + "name": "TextLink", + "fields": [ + { + "name": "text", + "kind": "String", + "nullable": false + }, + { + "name": "link", + "kind": "Block", + "block": "Link", + "nullable": false + } + ], + "inputFields": [ + { + "name": "text", + "kind": "String", + "nullable": false + }, + { + "name": "link", + "kind": "Block", + "block": "Link", + "nullable": false + } + ] + }, { "name": "TwoLists", "fields": [ diff --git a/demo/api/schema.gql b/demo/api/schema.gql index e25e197c96..2a52d9e0d9 100644 --- a/demo/api/schema.gql +++ b/demo/api/schema.gql @@ -347,18 +347,17 @@ enum PredefinedPageType { News } -type FooterContentScope { +type FooterScope { domain: String! - language: String! + project: String! } -type Footer { +type Footer implements DocumentInterface { id: ID! + updatedAt: DateTime! content: FooterContentBlockData! - scope: FooterContentScope! + scope: FooterScope! createdAt: DateTime! - updatedAt: DateTime! - dependencies(offset: Int! = 0, limit: Int! = 25, filter: DependencyFilter, forceRefresh: Boolean! = false): PaginatedDependencies! } """FooterContent root block data""" @@ -691,9 +690,9 @@ input DamScopeInput { domain: String! } -input FooterContentScopeInput { +input FooterScopeInput { domain: String! - language: String! + project: String! } input NewsContentScopeInput { @@ -794,7 +793,7 @@ type Query { mainMenu(scope: PageTreeNodeScopeInput!): MainMenu! topMenu(scope: PageTreeNodeScopeInput!): [PageTreeNode!]! mainMenuItem(pageTreeNodeId: ID!): MainMenuItem! - footer(scope: FooterContentScopeInput!): Footer + footer(scope: FooterScopeInput!): Footer predefinedPage(id: ID!): PredefinedPage! kubernetesCronJobs: [KubernetesCronJob!]! kubernetesCronJob(name: String!): KubernetesCronJob! @@ -1218,7 +1217,7 @@ type Mutation { updateNewsComment(id: ID!, input: NewsCommentInput!): NewsComment! deleteNewsComment(id: ID!): Boolean! updateMainMenuItem(pageTreeNodeId: ID!, input: MainMenuItemInput!, lastUpdatedAt: DateTime): MainMenuItem! - saveFooter(scope: FooterContentScopeInput!, input: FooterInput!): Footer! + saveFooter(scope: FooterScopeInput!, input: FooterInput!): Footer! savePredefinedPage(id: ID!, input: PredefinedPageInput!, attachedPageTreeNodeId: ID!, lastUpdatedAt: DateTime): PredefinedPage! triggerKubernetesCronJob(name: String!): KubernetesJob! createProduct(input: ProductInput!): Product! diff --git a/demo/api/src/comet-config.json b/demo/api/src/comet-config.json index 5a88b97cf7..a307b09274 100644 --- a/demo/api/src/comet-config.json +++ b/demo/api/src/comet-config.json @@ -1,14 +1,15 @@ { + "dam": { + "allowedImageAspectRatios": ["16x9", "4x3", "3x2", "3x1", "2x1", "1x1", "1x2", "1x3", "2x3", "3x4", "9x16", "1200x630"], + "allowedImageSizes": [320, 420, 768, 1024, 1200, 2048], + "uploadsMaxFileSize": 500 + }, "fileUploads": { - "maxFileSize": 15 + "maxFileSize": 15, + "quality": 80 }, "imgproxy": { "maxSrcResolution": 70, "quality": 80 - }, - "dam": { - "uploadsMaxFileSize": 500, - "allowedImageSizes": [320, 420, 768, 1024, 1200, 2048], - "allowedImageAspectRatios": ["16x9", "4x3", "3x2", "3x1", "2x1", "1x1", "1x2", "1x3", "2x3", "3x4", "9x16", "1200x630"] } } diff --git a/demo/api/src/common/blocks/accordion-item.block.ts b/demo/api/src/common/blocks/accordion-item.block.ts new file mode 100644 index 0000000000..00e257ece5 --- /dev/null +++ b/demo/api/src/common/blocks/accordion-item.block.ts @@ -0,0 +1,61 @@ +import { + BlockData, + BlockDataInterface, + BlockField, + BlockInput, + ChildBlock, + ChildBlockInput, + createBlock, + createBlocksBlock, + ExtractBlockInput, + inputToData, +} from "@comet/blocks-api"; +import { IsUndefinable } from "@comet/cms-api"; +import { RichTextBlock } from "@src/common/blocks/rich-text.block"; +import { SpaceBlock } from "@src/common/blocks/space.block"; +import { StandaloneCallToActionListBlock } from "@src/common/blocks/standalone-call-to-action-list.block"; +import { StandaloneHeadingBlock } from "@src/common/blocks/standalone-heading.block"; +import { IsBoolean, IsString } from "class-validator"; + +const AccordionContentBlock = createBlocksBlock( + { + supportedBlocks: { + richtext: RichTextBlock, + heading: StandaloneHeadingBlock, + space: SpaceBlock, + callToActionList: StandaloneCallToActionListBlock, + }, + }, + "AccordionContent", +); + +class AccordionItemBlockData extends BlockData { + @BlockField({ nullable: true }) + title?: string; + + @ChildBlock(AccordionContentBlock) + content: BlockDataInterface; + + @BlockField() + openByDefault: boolean; +} + +class AccordionItemBlockInput extends BlockInput { + @IsUndefinable() + @BlockField({ nullable: true }) + @IsString() + title?: string; + + @ChildBlockInput(AccordionContentBlock) + content: ExtractBlockInput; + + @IsBoolean() + @BlockField() + openByDefault: boolean; + + transformToBlockData(): AccordionItemBlockData { + return inputToData(AccordionItemBlockData, this); + } +} + +export const AccordionItemBlock = createBlock(AccordionItemBlockData, AccordionItemBlockInput, "AccordionItem"); diff --git a/demo/api/src/common/blocks/accordion.block.ts b/demo/api/src/common/blocks/accordion.block.ts new file mode 100644 index 0000000000..8c093506a3 --- /dev/null +++ b/demo/api/src/common/blocks/accordion.block.ts @@ -0,0 +1,4 @@ +import { createListBlock } from "@comet/blocks-api"; +import { AccordionItemBlock } from "@src/common/blocks/accordion-item.block"; + +export const AccordionBlock = createListBlock({ block: AccordionItemBlock }, "Accordion"); diff --git a/demo/api/src/common/blocks/call-to-action-list.block.ts b/demo/api/src/common/blocks/call-to-action-list.block.ts new file mode 100644 index 0000000000..8d4a05d95f --- /dev/null +++ b/demo/api/src/common/blocks/call-to-action-list.block.ts @@ -0,0 +1,4 @@ +import { createListBlock } from "@comet/blocks-api"; +import { CallToActionBlock } from "@src/common/blocks/call-to-action.block"; + +export const CallToActionListBlock = createListBlock({ block: CallToActionBlock }, "CallToActionList"); diff --git a/demo/api/src/common/blocks/call-to-action.block.ts b/demo/api/src/common/blocks/call-to-action.block.ts new file mode 100644 index 0000000000..9f147ab38b --- /dev/null +++ b/demo/api/src/common/blocks/call-to-action.block.ts @@ -0,0 +1,43 @@ +import { + BlockData, + BlockDataInterface, + BlockField, + BlockInput, + ChildBlock, + ChildBlockInput, + createBlock, + ExtractBlockInput, + inputToData, +} from "@comet/blocks-api"; +import { IsEnum } from "class-validator"; + +import { TextLinkBlock } from "./text-link.block"; + +enum Variant { + Contained = "Contained", + Outlined = "Outlined", + Text = "Text", +} + +class CallToActionBlockData extends BlockData { + @ChildBlock(TextLinkBlock) + textLink: BlockDataInterface; + + @BlockField({ type: "enum", enum: Variant }) + variant: Variant; +} + +class CallToActionBlockInput extends BlockInput { + @ChildBlockInput(TextLinkBlock) + textLink: ExtractBlockInput; + + @IsEnum(Variant) + @BlockField({ type: "enum", enum: Variant }) + variant: Variant; + + transformToBlockData(): CallToActionBlockData { + return inputToData(CallToActionBlockData, this); + } +} + +export const CallToActionBlock = createBlock(CallToActionBlockData, CallToActionBlockInput, "CallToAction"); diff --git a/demo/api/src/common/blocks/heading.block.ts b/demo/api/src/common/blocks/heading.block.ts new file mode 100644 index 0000000000..6061ca48e9 --- /dev/null +++ b/demo/api/src/common/blocks/heading.block.ts @@ -0,0 +1,52 @@ +import { + BlockData, + BlockDataInterface, + BlockField, + BlockInput, + ChildBlock, + ChildBlockInput, + createBlock, + ExtractBlockInput, + inputToData, +} from "@comet/blocks-api"; +import { IsEnum } from "class-validator"; + +import { RichTextBlock } from "./rich-text.block"; + +enum HeadlineTag { + H1 = "H1", + H2 = "H2", + H3 = "H3", + H4 = "H4", + H5 = "H5", + H6 = "H6", +} + +class HeadingBlockData extends BlockData { + @ChildBlock(RichTextBlock) + eyebrow: BlockDataInterface; + + @ChildBlock(RichTextBlock) + headline: BlockDataInterface; + + @BlockField({ type: "enum", enum: HeadlineTag }) + htmlTag: HeadlineTag; +} + +class HeadingBlockInput extends BlockInput { + @ChildBlockInput(RichTextBlock) + eyebrow: ExtractBlockInput; + + @ChildBlockInput(RichTextBlock) + headline: ExtractBlockInput; + + @IsEnum(HeadlineTag) + @BlockField({ type: "enum", enum: HeadlineTag }) + htmlTag: HeadlineTag; + + transformToBlockData(): HeadingBlockData { + return inputToData(HeadingBlockData, this); + } +} + +export const HeadingBlock = createBlock(HeadingBlockData, HeadingBlockInput, "Heading"); diff --git a/demo/api/src/common/blocks/linkBlock/link.block.ts b/demo/api/src/common/blocks/link.block.ts similarity index 100% rename from demo/api/src/common/blocks/linkBlock/link.block.ts rename to demo/api/src/common/blocks/link.block.ts index 1e1aaa320a..cfab83e4fc 100644 --- a/demo/api/src/common/blocks/linkBlock/link.block.ts +++ b/demo/api/src/common/blocks/link.block.ts @@ -4,11 +4,11 @@ import { NewsLinkBlock } from "@src/news/blocks/news-link.block"; export const LinkBlock = createLinkBlock({ supportedBlocks: { - internal: InternalLinkBlock, + damFileDownload: DamFileDownloadLinkBlock, + email: EmailLinkBlock, external: ExternalLinkBlock, + internal: InternalLinkBlock, news: NewsLinkBlock, - damFileDownload: DamFileDownloadLinkBlock, phone: PhoneLinkBlock, - email: EmailLinkBlock, }, }); diff --git a/demo/api/src/common/blocks/media-gallery-item.block.ts b/demo/api/src/common/blocks/media-gallery-item.block.ts new file mode 100644 index 0000000000..6d2241ae1c --- /dev/null +++ b/demo/api/src/common/blocks/media-gallery-item.block.ts @@ -0,0 +1,38 @@ +import { + BlockData, + BlockDataInterface, + BlockField, + BlockInput, + ChildBlock, + ChildBlockInput, + createBlock, + ExtractBlockInput, + inputToData, +} from "@comet/blocks-api"; +import { IsUndefinable } from "@comet/cms-api"; +import { MediaBlock } from "@src/common/blocks/media.block"; +import { IsString } from "class-validator"; + +class MediaGalleryItemBlockData extends BlockData { + @ChildBlock(MediaBlock) + media: BlockDataInterface; + + @BlockField({ nullable: true }) + caption?: string; +} + +class MediaGalleryItemBlockInput extends BlockInput { + @ChildBlockInput(MediaBlock) + media: ExtractBlockInput; + + @IsUndefinable() + @BlockField({ nullable: true }) + @IsString() + caption?: string; + + transformToBlockData(): MediaGalleryItemBlockData { + return inputToData(MediaGalleryItemBlockData, this); + } +} + +export const MediaGalleryItemBlock = createBlock(MediaGalleryItemBlockData, MediaGalleryItemBlockInput, "MediaGalleryItem"); diff --git a/demo/api/src/common/blocks/media-gallery.block.ts b/demo/api/src/common/blocks/media-gallery.block.ts new file mode 100644 index 0000000000..986fece41a --- /dev/null +++ b/demo/api/src/common/blocks/media-gallery.block.ts @@ -0,0 +1,40 @@ +import { + BlockData, + BlockDataInterface, + BlockField, + BlockInput, + ChildBlock, + ChildBlockInput, + createBlock, + createListBlock, + ExtractBlockInput, + inputToData, +} from "@comet/blocks-api"; +import { MediaGalleryItemBlock } from "@src/common/blocks/media-gallery-item.block"; +import { MediaAspectRatios } from "@src/util/mediaAspectRatios"; +import { IsEnum } from "class-validator"; + +const MediaGalleryListBlock = createListBlock({ block: MediaGalleryItemBlock }, "MediaGalleryList"); + +class MediaGalleryBlockData extends BlockData { + @ChildBlock(MediaGalleryListBlock) + items: BlockDataInterface; + + @BlockField({ type: "enum", enum: MediaAspectRatios }) + aspectRatio: MediaAspectRatios; +} + +class MediaGalleryBlockInput extends BlockInput { + @ChildBlockInput(MediaGalleryListBlock) + items: ExtractBlockInput; + + @IsEnum(MediaAspectRatios) + @BlockField({ type: "enum", enum: MediaAspectRatios }) + aspectRatio: MediaAspectRatios; + + transformToBlockData(): MediaGalleryBlockData { + return inputToData(MediaGalleryBlockData, this); + } +} + +export const MediaGalleryBlock = createBlock(MediaGalleryBlockData, MediaGalleryBlockInput, "MediaGallery"); diff --git a/demo/api/src/common/blocks/media.block.ts b/demo/api/src/common/blocks/media.block.ts new file mode 100644 index 0000000000..0bac94446f --- /dev/null +++ b/demo/api/src/common/blocks/media.block.ts @@ -0,0 +1,13 @@ +import { createOneOfBlock } from "@comet/blocks-api"; +import { DamImageBlock, DamVideoBlock, YouTubeVideoBlock } from "@comet/cms-api"; + +export const MediaBlock = createOneOfBlock( + { + supportedBlocks: { + image: DamImageBlock, + damVideo: DamVideoBlock, + youTubeVideo: YouTubeVideoBlock, + }, + }, + "Media", +); diff --git a/demo/api/src/common/blocks/rich-text.block.ts b/demo/api/src/common/blocks/rich-text.block.ts index 81a1cd9fb7..8c9a2086b1 100644 --- a/demo/api/src/common/blocks/rich-text.block.ts +++ b/demo/api/src/common/blocks/rich-text.block.ts @@ -1,5 +1,4 @@ import { createRichTextBlock } from "@comet/blocks-api"; - -import { LinkBlock } from "./linkBlock/link.block"; +import { LinkBlock } from "@src/common/blocks/link.block"; export const RichTextBlock = createRichTextBlock({ link: LinkBlock }); diff --git a/demo/api/src/common/blocks/space.block.ts b/demo/api/src/common/blocks/space.block.ts index 13919f1d01..c56ade8485 100644 --- a/demo/api/src/common/blocks/space.block.ts +++ b/demo/api/src/common/blocks/space.block.ts @@ -1,16 +1,16 @@ import { createSpaceBlock } from "@comet/blocks-api"; export enum Spacing { - d150 = "d150", - d200 = "d200", - d250 = "d250", - d300 = "d300", - d350 = "d350", - d400 = "d400", - d450 = "d450", - d500 = "d500", - d550 = "d550", - d600 = "d600", + D100 = "D100", + D200 = "D200", + D300 = "D300", + D400 = "D400", + S100 = "S100", + S200 = "S200", + S300 = "S300", + S400 = "S400", + S500 = "S500", + S600 = "S600", } -export const SpaceBlock = createSpaceBlock({ spacing: Spacing }, "DemoSpace"); +export const SpaceBlock = createSpaceBlock({ spacing: Spacing }); diff --git a/demo/api/src/common/blocks/standalone-call-to-action-list.block.ts b/demo/api/src/common/blocks/standalone-call-to-action-list.block.ts new file mode 100644 index 0000000000..d947f96536 --- /dev/null +++ b/demo/api/src/common/blocks/standalone-call-to-action-list.block.ts @@ -0,0 +1,44 @@ +import { + BlockData, + BlockDataInterface, + BlockField, + BlockInput, + ChildBlock, + ChildBlockInput, + createBlock, + ExtractBlockInput, + inputToData, +} from "@comet/blocks-api"; +import { CallToActionListBlock } from "@src/common/blocks/call-to-action-list.block"; +import { IsEnum } from "class-validator"; + +enum Alignment { + left = "left", + center = "center", + right = "right", +} + +class StandaloneCallToActionListBlockData extends BlockData { + @ChildBlock(CallToActionListBlock) + callToActionList: BlockDataInterface; + + @BlockField({ type: "enum", enum: Alignment }) + alignment: Alignment; +} + +class StandaloneCallToActionListBlockInput extends BlockInput { + @ChildBlockInput(CallToActionListBlock) + callToActionList: ExtractBlockInput; + + @IsEnum(Alignment) + @BlockField({ type: "enum", enum: Alignment }) + alignment: Alignment; + + transformToBlockData(): StandaloneCallToActionListBlockData { + return inputToData(StandaloneCallToActionListBlockData, this); + } +} + +export const StandaloneCallToActionListBlock = createBlock(StandaloneCallToActionListBlockData, StandaloneCallToActionListBlockInput, { + name: "StandaloneCallToActionList", +}); diff --git a/demo/api/src/common/blocks/standalone-heading.block.ts b/demo/api/src/common/blocks/standalone-heading.block.ts new file mode 100644 index 0000000000..92d4b33e13 --- /dev/null +++ b/demo/api/src/common/blocks/standalone-heading.block.ts @@ -0,0 +1,43 @@ +import { + BlockData, + BlockDataInterface, + BlockField, + BlockInput, + ChildBlock, + ChildBlockInput, + createBlock, + ExtractBlockInput, + inputToData, +} from "@comet/blocks-api"; +import { HeadingBlock } from "@src/common/blocks/heading.block"; +import { IsEnum } from "class-validator"; + +enum TextAlignment { + left = "left", + center = "center", +} + +class StandaloneHeadingBlockData extends BlockData { + @ChildBlock(HeadingBlock) + heading: BlockDataInterface; + + @BlockField({ type: "enum", enum: TextAlignment }) + textAlignment: TextAlignment; +} + +class StandaloneHeadingBlockInput extends BlockInput { + @ChildBlockInput(HeadingBlock) + heading: ExtractBlockInput; + + @IsEnum(TextAlignment) + @BlockField({ type: "enum", enum: TextAlignment }) + textAlignment: TextAlignment; + + transformToBlockData(): StandaloneHeadingBlockData { + return inputToData(StandaloneHeadingBlockData, this); + } +} + +export const StandaloneHeadingBlock = createBlock(StandaloneHeadingBlockData, StandaloneHeadingBlockInput, { + name: "StandaloneHeading", +}); diff --git a/demo/api/src/common/blocks/standalone-media.block.ts b/demo/api/src/common/blocks/standalone-media.block.ts new file mode 100644 index 0000000000..60f16c14a0 --- /dev/null +++ b/demo/api/src/common/blocks/standalone-media.block.ts @@ -0,0 +1,39 @@ +import { + BlockData, + BlockDataInterface, + BlockField, + BlockInput, + ChildBlock, + ChildBlockInput, + createBlock, + ExtractBlockInput, + inputToData, +} from "@comet/blocks-api"; +import { MediaBlock } from "@src/common/blocks/media.block"; +import { MediaAspectRatios } from "@src/util/mediaAspectRatios"; +import { IsEnum } from "class-validator"; + +class StandaloneMediaBlockData extends BlockData { + @ChildBlock(MediaBlock) + media: BlockDataInterface; + + @BlockField({ type: "enum", enum: MediaAspectRatios }) + aspectRatio: MediaAspectRatios; +} + +class StandaloneMediaBlockInput extends BlockInput { + @ChildBlockInput(MediaBlock) + media: ExtractBlockInput; + + @IsEnum(MediaAspectRatios) + @BlockField({ type: "enum", enum: MediaAspectRatios }) + aspectRatio: MediaAspectRatios; + + transformToBlockData(): StandaloneMediaBlockData { + return inputToData(StandaloneMediaBlockData, this); + } +} + +export const StandaloneMediaBlock = createBlock(StandaloneMediaBlockData, StandaloneMediaBlockInput, { + name: "StandaloneMedia", +}); diff --git a/demo/api/src/common/blocks/text-link.block.ts b/demo/api/src/common/blocks/text-link.block.ts index 6cbe812a91..34c0af20a0 100644 --- a/demo/api/src/common/blocks/text-link.block.ts +++ b/demo/api/src/common/blocks/text-link.block.ts @@ -1,5 +1,4 @@ import { createTextLinkBlock } from "@comet/blocks-api"; +import { LinkBlock } from "@src/common/blocks/link.block"; -import { LinkBlock } from "./linkBlock/link.block"; - -export const TextLinkBlock = createTextLinkBlock({ link: LinkBlock }, "DemoTextLink"); +export const TextLinkBlock = createTextLinkBlock({ link: LinkBlock }); diff --git a/demo/api/src/config/config.ts b/demo/api/src/config/config.ts index 99ba6cb1ec..87e22a5402 100644 --- a/demo/api/src/config/config.ts +++ b/demo/api/src/config/config.ts @@ -19,7 +19,7 @@ export function createConfig(processEnv: NodeJS.ProcessEnv) { envVars.AZURE_OPEN_AI_CONTENT_GENERATION_DEPLOYMENT_ID ) { contentGeneration = { - apiKey: envVars.AZURE_OPEN_AI_CONTENT_GENERATION_API_KEY, + apiKey: envVars.AZURE_OPEN_AI_CONTENT_GENERATION_API_KEY ?? "", apiUrl: envVars.AZURE_OPEN_AI_CONTENT_GENERATION_API_URL, deploymentId: envVars.AZURE_OPEN_AI_CONTENT_GENERATION_DEPLOYMENT_ID, }; diff --git a/demo/api/src/db/fixtures/fixtures.console.ts b/demo/api/src/db/fixtures/fixtures.console.ts index 7249befe7f..b250f6a41a 100644 --- a/demo/api/src/db/fixtures/fixtures.console.ts +++ b/demo/api/src/db/fixtures/fixtures.console.ts @@ -209,6 +209,7 @@ export class FixturesConsole { updatedAt: new Date(), content: pageInput.content.transformToBlockData(), seo: pageInput.seo.transformToBlockData(), + stage: pageInput.stage.transformToBlockData(), }), ); } @@ -261,6 +262,7 @@ export class FixturesConsole { id: pageId, content: pageInput.content.transformToBlockData(), seo: pageInput.seo.transformToBlockData(), + stage: pageInput.stage.transformToBlockData(), }), ); await this.pageTreeService.attachDocument({ id: pageId, type: "Page" }, page.id); diff --git a/demo/api/src/db/fixtures/generators/blocks/space.generator.ts b/demo/api/src/db/fixtures/generators/blocks/space.generator.ts index a83c17b228..c02583f19f 100644 --- a/demo/api/src/db/fixtures/generators/blocks/space.generator.ts +++ b/demo/api/src/db/fixtures/generators/blocks/space.generator.ts @@ -1,4 +1,4 @@ import { ExtractBlockInputFactoryProps } from "@comet/blocks-api"; import { SpaceBlock, Spacing } from "@src/common/blocks/space.block"; -export const generateSpaceBlock = (): ExtractBlockInputFactoryProps => ({ spacing: Spacing.d200 }); +export const generateSpaceBlock = (): ExtractBlockInputFactoryProps => ({ spacing: Spacing.D200 }); diff --git a/demo/api/src/db/fixtures/generators/links.generator.ts b/demo/api/src/db/fixtures/generators/links.generator.ts index b5322270e0..bc7d04389b 100644 --- a/demo/api/src/db/fixtures/generators/links.generator.ts +++ b/demo/api/src/db/fixtures/generators/links.generator.ts @@ -1,6 +1,6 @@ import { InternalLinkBlock } from "@comet/cms-api"; import { EntityRepository } from "@mikro-orm/postgresql"; -import { LinkBlock } from "@src/common/blocks/linkBlock/link.block"; +import { LinkBlock } from "@src/common/blocks/link.block"; import { PageTreeNodesFixtures } from "@src/db/fixtures/fixtures.console"; import { Link } from "@src/links/entities/link.entity"; diff --git a/demo/api/src/db/fixtures/generators/many-images-test-page-fixture.service.ts b/demo/api/src/db/fixtures/generators/many-images-test-page-fixture.service.ts index b70d2bd231..05101ee564 100644 --- a/demo/api/src/db/fixtures/generators/many-images-test-page-fixture.service.ts +++ b/demo/api/src/db/fixtures/generators/many-images-test-page-fixture.service.ts @@ -82,6 +82,7 @@ export class ManyImagesTestPageFixtureService { seo: pageInput.seo.transformToBlockData(), createdAt: new Date(), updatedAt: new Date(), + stage: pageInput.stage.transformToBlockData(), }), ); } diff --git a/demo/api/src/db/migrations/Migration20220127092535.ts b/demo/api/src/db/migrations/Migration20220127092535.ts index 2777bfa27f..8ceb024a14 100644 --- a/demo/api/src/db/migrations/Migration20220127092535.ts +++ b/demo/api/src/db/migrations/Migration20220127092535.ts @@ -3,11 +3,11 @@ import { Migration } from "@mikro-orm/migrations"; export class Migration20220127092535 extends Migration { async up(): Promise { this.addSql( - 'alter table "PageTreeNode" add column "scope_domain" text not null, add column "scope_language" text not null, add column "parent" uuid null, add column "category" text check ("category" in (\'main-navigation\')) not null default \'main-navigation\';', + 'alter table "PageTreeNode" add column "scope_domain" text not null, add column "scope_language" text not null, add column "category" text check ("category" in (\'MainNavigation\')) not null default \'MainNavigation\';', ); - this.addSql('create index "PageTreeNode_parent_index" on "PageTreeNode" ("parent");'); this.addSql( - 'alter table "PageTreeNode" add constraint "PageTreeNode_parent_foreign" foreign key ("parent") references "PageTreeNode" ("id") on update cascade on delete set null;', + 'alter table "PageTreeNode" add constraint "PageTreeNode_parentId_foreign" foreign key ("parentId") references "PageTreeNode" ("id") on update cascade on delete set null;', ); + this.addSql('create index "PageTreeNode_parentId_index" on "PageTreeNode" ("parentId");'); } } diff --git a/demo/api/src/db/migrations/Migration20220127092750.ts b/demo/api/src/db/migrations/Migration20220127092750.ts index e5602c6713..62f4970edd 100644 --- a/demo/api/src/db/migrations/Migration20220127092750.ts +++ b/demo/api/src/db/migrations/Migration20220127092750.ts @@ -3,7 +3,7 @@ import { Migration } from "@mikro-orm/migrations"; export class Migration20220127092750 extends Migration { async up(): Promise { this.addSql( - 'create table "Page" ("id" uuid not null, "content" json not null, "seo" json not null, "createdAt" timestamp with time zone not null, "updatedAt" timestamp with time zone not null);', + 'create table "Page" ("id" uuid not null, "content" json not null, "stage" json not null, "seo" json not null, "createdAt" timestamp with time zone not null, "updatedAt" timestamp with time zone not null);', ); this.addSql('alter table "Page" add constraint "Page_pkey" primary key ("id");'); } diff --git a/demo/api/src/footer/blocks/footer-content.block.ts b/demo/api/src/footer/blocks/footer-content.block.ts index b45cbb7eef..9921c32b54 100644 --- a/demo/api/src/footer/blocks/footer-content.block.ts +++ b/demo/api/src/footer/blocks/footer-content.block.ts @@ -6,65 +6,47 @@ import { ChildBlock, ChildBlockInput, createBlock, - createListBlock, ExtractBlockInput, inputToData, } from "@comet/blocks-api"; +import { DamImageBlock } from "@comet/cms-api"; import { LinkListBlock } from "@src/common/blocks/link-list.block"; -import { IsOptional, IsString } from "class-validator"; +import { RichTextBlock } from "@src/common/blocks/rich-text.block"; +import { IsString } from "class-validator"; -import { FooterLinkSectionBlock } from "./footer-link-section.block"; +class FooterContentBlockData extends BlockData { + @ChildBlock(RichTextBlock) + text: ExtractBlockInput; -export const FooterTopLinksBlock = createListBlock({ block: FooterLinkSectionBlock }, "FooterTopLinks"); + @ChildBlock(DamImageBlock) + image: BlockDataInterface; -class FooterBlockData extends BlockData { @ChildBlock(LinkListBlock) - popularTopicsLinks: BlockDataInterface; - - @ChildBlock(LinkListBlock) - aboutLinks: BlockDataInterface; - - @ChildBlock(LinkListBlock) - bottomLinks: BlockDataInterface; - - @BlockField() - copyrightNotice?: string; - - @BlockField() - location?: string; + linkList: BlockDataInterface; @BlockField() - contactUs?: string; + copyrightNotice: string; } -class FooterBlockInput extends BlockInput { - @ChildBlockInput(LinkListBlock) - popularTopicsLinks: ExtractBlockInput; +class FooterContentBlockInput extends BlockInput { + @ChildBlockInput(RichTextBlock) + text: ExtractBlockInput; - @ChildBlockInput(LinkListBlock) - aboutLinks: ExtractBlockInput; + @ChildBlockInput(DamImageBlock) + image: ExtractBlockInput; @ChildBlockInput(LinkListBlock) - bottomLinks: ExtractBlockInput; - - @BlockField() - @IsOptional() - @IsString() - copyrightNotice?: string; - - @BlockField() - @IsOptional() - @IsString() - location?: string; + linkList: ExtractBlockInput; @BlockField() - @IsOptional() @IsString() - contactUs?: string; + copyrightNotice: string; - transformToBlockData(): FooterBlockData { - return inputToData(FooterBlockData, this); + transformToBlockData(): FooterContentBlockData { + return inputToData(FooterContentBlockData, this); } } -export const FooterContentBlock = createBlock(FooterBlockData, FooterBlockInput, "FooterContent"); +export const FooterContentBlock = createBlock(FooterContentBlockData, FooterContentBlockInput, { + name: "FooterContent", +}); diff --git a/demo/api/src/footer/entities/footer-content-scope.entity.ts b/demo/api/src/footer/dto/footer-scope.ts similarity index 78% rename from demo/api/src/footer/entities/footer-content-scope.entity.ts rename to demo/api/src/footer/dto/footer-scope.ts index 5eaf1d17a9..d6c52dff31 100644 --- a/demo/api/src/footer/entities/footer-content-scope.entity.ts +++ b/demo/api/src/footer/dto/footer-scope.ts @@ -4,8 +4,8 @@ import { IsString } from "class-validator"; @Embeddable() @ObjectType() -@InputType("FooterContentScopeInput") -export class FooterContentScope { +@InputType("FooterScopeInput") +export class FooterScope { @Property({ columnType: "text" }) @Field() @IsString() @@ -14,5 +14,5 @@ export class FooterContentScope { @Property({ columnType: "text" }) @Field() @IsString() - language: string; + project: string; } diff --git a/demo/api/src/footer/entities/footer.entity.ts b/demo/api/src/footer/entities/footer.entity.ts index c98fbaf730..3c35dee8a2 100644 --- a/demo/api/src/footer/entities/footer.entity.ts +++ b/demo/api/src/footer/entities/footer.entity.ts @@ -1,30 +1,33 @@ -import { BlockDataInterface, RootBlock, RootBlockEntity } from "@comet/blocks-api"; -import { CrudSingleGenerator, RootBlockDataScalar, RootBlockType } from "@comet/cms-api"; +import { ExtractBlockData, RootBlock, RootBlockEntity } from "@comet/blocks-api"; +import { CrudSingleGenerator, DocumentInterface, RootBlockDataScalar, RootBlockType } from "@comet/cms-api"; import { BaseEntity, Embedded, Entity, OptionalProps, PrimaryKey, Property } from "@mikro-orm/core"; import { Field, ID, ObjectType } from "@nestjs/graphql"; -import { v4 as uuid } from "uuid"; +import { v4 } from "uuid"; import { FooterContentBlock } from "../blocks/footer-content.block"; -import { FooterContentScope } from "./footer-content-scope.entity"; +import { FooterScope } from "../dto/footer-scope"; @Entity() -@ObjectType() +@ObjectType({ + implements: () => [DocumentInterface], +}) @RootBlockEntity() -@CrudSingleGenerator({ targetDirectory: `${__dirname}/../generated/`, requiredPermission: ["pageTree"] }) -export class Footer extends BaseEntity { +@CrudSingleGenerator({ targetDirectory: `${__dirname}/../generated/` }) +export class Footer extends BaseEntity implements DocumentInterface { [OptionalProps]?: "createdAt" | "updatedAt"; - @PrimaryKey({ columnType: "uuid" }) + @PrimaryKey({ type: "uuid" }) @Field(() => ID) - id: string = uuid(); + id: string = v4(); + @RootBlock(FooterContentBlock) @Property({ customType: new RootBlockType(FooterContentBlock) }) @Field(() => RootBlockDataScalar(FooterContentBlock)) - content: BlockDataInterface; + content: ExtractBlockData; - @Embedded(() => FooterContentScope) - @Field(() => FooterContentScope) - scope: FooterContentScope; + @Embedded(() => FooterScope) + @Field(() => FooterScope) + scope: FooterScope; @Property({ columnType: "timestamp with time zone" }) @Field() diff --git a/demo/api/src/footer/footer.module.ts b/demo/api/src/footer/footer.module.ts index 29d4c23118..4eb2c7b64f 100644 --- a/demo/api/src/footer/footer.module.ts +++ b/demo/api/src/footer/footer.module.ts @@ -1,14 +1,12 @@ -import { DependenciesResolverFactory } from "@comet/cms-api"; import { MikroOrmModule } from "@mikro-orm/nestjs"; import { Module } from "@nestjs/common"; import { Footer } from "./entities/footer.entity"; -import { FooterContentScope } from "./entities/footer-content-scope.entity"; import { FooterResolver } from "./generated/footer.resolver"; import { FootersService } from "./generated/footers.service"; @Module({ - imports: [MikroOrmModule.forFeature([Footer, FooterContentScope])], - providers: [FooterResolver, FootersService, DependenciesResolverFactory.create(Footer)], + imports: [MikroOrmModule.forFeature([Footer])], + providers: [FootersService, FooterResolver], }) export class FooterModule {} diff --git a/demo/api/src/footer/generated/footer.resolver.ts b/demo/api/src/footer/generated/footer.resolver.ts index 83787f2d09..64d2831ba7 100644 --- a/demo/api/src/footer/generated/footer.resolver.ts +++ b/demo/api/src/footer/generated/footer.resolver.ts @@ -5,13 +5,13 @@ import { InjectRepository } from "@mikro-orm/nestjs"; import { EntityManager, EntityRepository } from "@mikro-orm/postgresql"; import { Args, Mutation, Query, Resolver } from "@nestjs/graphql"; +import { FooterScope } from "../dto/footer-scope"; import { Footer } from "../entities/footer.entity"; -import { FooterContentScope } from "../entities/footer-content-scope.entity"; import { FooterInput } from "./dto/footer.input"; import { FootersService } from "./footers.service"; @Resolver(() => Footer) -@RequiredPermission(["pageTree"]) +@RequiredPermission(["footers"]) export class FooterResolver { constructor( private readonly entityManager: EntityManager, @@ -20,7 +20,7 @@ export class FooterResolver { ) {} @Query(() => Footer, { nullable: true }) - async footer(@Args("scope", { type: () => FooterContentScope }) scope: FooterContentScope): Promise