From 607424b4a7d6984d36adc6cf18c6e13194de8fa1 Mon Sep 17 00:00:00 2001 From: Xavier Rutayisire Date: Tue, 10 Oct 2023 18:02:49 +0200 Subject: [PATCH 01/16] fix(init): Missing reason in init errors (#1162) --- .../prismicRepository/PrismicRepositoryManager.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/manager/src/managers/prismicRepository/PrismicRepositoryManager.ts b/packages/manager/src/managers/prismicRepository/PrismicRepositoryManager.ts index 2df01a0c03..a5ab911759 100644 --- a/packages/manager/src/managers/prismicRepository/PrismicRepositoryManager.ts +++ b/packages/manager/src/managers/prismicRepository/PrismicRepositoryManager.ts @@ -174,10 +174,10 @@ export class PrismicRepositoryManager extends BaseManager { const text = await res.text(); // Endpoint returns repository name on success, which must be more than 4 characters and less than 30 - // if (!res.ok) { - if (!res.ok || text.length < 4 || text.length > 30) { + // Even when there is an error, we get a 200 success and so we have to check the name thanks to that + if (!res.ok || text.length < 4 || text.length > 63) { throw new Error(`Failed to create repository \`${args.domain}\``, { - cause: res, + cause: text, }); } } @@ -244,7 +244,7 @@ export class PrismicRepositoryManager extends BaseManager { throw new Error( `Failed to push documents to repository \`${args.domain}\`, repository is not empty`, { - cause: res, + cause: reason, }, ); } @@ -252,7 +252,7 @@ export class PrismicRepositoryManager extends BaseManager { throw new Error( `Failed to push documents to repository \`${args.domain}\`, ${res.status} ${res.statusText}`, { - cause: res, + cause: reason, }, ); } From fa863af9042b234c1a05a3db1c67ab1d0547220b Mon Sep 17 00:00:00 2001 From: xrutayisire Date: Tue, 10 Oct 2023 16:05:31 +0000 Subject: [PATCH 02/16] Publish - cimsirp@1.16.1-dev-next-release.0 - sveltekit@1.16.1-dev-next-release.0 - @slicemachine/adapter-next@0.3.20-dev-next-release.0 - @slicemachine/adapter-nuxt@0.3.20-dev-next-release.0 - @slicemachine/adapter-nuxt2@0.3.20-dev-next-release.0 - @slicemachine/adapter-sveltekit@0.3.20-dev-next-release.0 - @slicemachine/init@2.7.3-dev-next-release.0 - @slicemachine/manager@0.13.1-dev-next-release.0 - @slicemachine/plugin-kit@0.4.20-dev-next-release.0 - slice-machine-ui@1.16.1-dev-next-release.0 - start-slicemachine@0.11.10-dev-next-release.0 --- e2e-projects/next/package.json | 2 +- e2e-projects/sveltekit/package.json | 2 +- packages/adapter-next/package.json | 2 +- packages/adapter-nuxt/package.json | 2 +- packages/adapter-nuxt2/package.json | 2 +- packages/adapter-sveltekit/package.json | 2 +- packages/init/package.json | 2 +- packages/manager/package.json | 2 +- packages/plugin-kit/package.json | 2 +- packages/slice-machine/package.json | 2 +- packages/start-slicemachine/package.json | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/e2e-projects/next/package.json b/e2e-projects/next/package.json index 908eaade0a..609fbd0ed9 100644 --- a/e2e-projects/next/package.json +++ b/e2e-projects/next/package.json @@ -1,6 +1,6 @@ { "name": "cimsirp", - "version": "1.16.0", + "version": "1.16.1-dev-next-release.0", "private": true, "scripts": { "dev": "next dev", diff --git a/e2e-projects/sveltekit/package.json b/e2e-projects/sveltekit/package.json index 939b96ded9..3a6f037c8e 100644 --- a/e2e-projects/sveltekit/package.json +++ b/e2e-projects/sveltekit/package.json @@ -1,6 +1,6 @@ { "name": "sveltekit", - "version": "1.16.0", + "version": "1.16.1-dev-next-release.0", "private": true, "scripts": { "dev": "vite dev", diff --git a/packages/adapter-next/package.json b/packages/adapter-next/package.json index 5ee827b9a6..d9a0fb99d7 100644 --- a/packages/adapter-next/package.json +++ b/packages/adapter-next/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/adapter-next", - "version": "0.3.19", + "version": "0.3.20-dev-next-release.0", "description": "Slice Machine adapter for Next.js.", "keywords": [ "typescript", diff --git a/packages/adapter-nuxt/package.json b/packages/adapter-nuxt/package.json index 83b947e9e0..42f253fe56 100644 --- a/packages/adapter-nuxt/package.json +++ b/packages/adapter-nuxt/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/adapter-nuxt", - "version": "0.3.19", + "version": "0.3.20-dev-next-release.0", "description": "Slice Machine adapter for Nuxt 3.", "keywords": [ "typescript", diff --git a/packages/adapter-nuxt2/package.json b/packages/adapter-nuxt2/package.json index 9c66c2de73..651a2737fd 100644 --- a/packages/adapter-nuxt2/package.json +++ b/packages/adapter-nuxt2/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/adapter-nuxt2", - "version": "0.3.19", + "version": "0.3.20-dev-next-release.0", "description": "Slice Machine adapter for Nuxt 2.", "keywords": [ "typescript", diff --git a/packages/adapter-sveltekit/package.json b/packages/adapter-sveltekit/package.json index 9ecb49bb8e..7831e492e9 100644 --- a/packages/adapter-sveltekit/package.json +++ b/packages/adapter-sveltekit/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/adapter-sveltekit", - "version": "0.3.19", + "version": "0.3.20-dev-next-release.0", "description": "Slice Machine adapter for SvelteKit.", "keywords": [ "typescript", diff --git a/packages/init/package.json b/packages/init/package.json index 1bf6924c77..861a4fbb8e 100644 --- a/packages/init/package.json +++ b/packages/init/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/init", - "version": "2.7.2", + "version": "2.7.3-dev-next-release.0", "description": "Init Prismic Slice Machine in your project", "keywords": [ "typescript", diff --git a/packages/manager/package.json b/packages/manager/package.json index ac790b819b..9a0da738e8 100644 --- a/packages/manager/package.json +++ b/packages/manager/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/manager", - "version": "0.13.0", + "version": "0.13.1-dev-next-release.0", "description": "Manage all aspects of a Slice Machine project.", "repository": { "type": "git", diff --git a/packages/plugin-kit/package.json b/packages/plugin-kit/package.json index b74f1536b8..0bba20c24a 100644 --- a/packages/plugin-kit/package.json +++ b/packages/plugin-kit/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/plugin-kit", - "version": "0.4.19", + "version": "0.4.20-dev-next-release.0", "description": "A set of helpers to develop and run Slice Machine plugins", "keywords": [ "typescript", diff --git a/packages/slice-machine/package.json b/packages/slice-machine/package.json index 11f3705626..796eb3faeb 100644 --- a/packages/slice-machine/package.json +++ b/packages/slice-machine/package.json @@ -1,6 +1,6 @@ { "name": "slice-machine-ui", - "version": "1.16.0", + "version": "1.16.1-dev-next-release.0", "license": "MIT", "description": "A visual builder for your Slice Models with all the tools you need to generate data models and mock CMS content locally.", "repository": { diff --git a/packages/start-slicemachine/package.json b/packages/start-slicemachine/package.json index e94d75bc86..28fd476c07 100644 --- a/packages/start-slicemachine/package.json +++ b/packages/start-slicemachine/package.json @@ -1,6 +1,6 @@ { "name": "start-slicemachine", - "version": "0.11.9", + "version": "0.11.10-dev-next-release.0", "description": "Start Slice Machine from within a project.", "repository": { "type": "git", From 6165aa18b6b7cd2c9ccba74397082a7301e01cbc Mon Sep 17 00:00:00 2001 From: Lucie <25330882+lihbr@users.noreply.github.com> Date: Wed, 11 Oct 2023 10:01:36 +0200 Subject: [PATCH 03/16] feat(init,manager,slice-machine): convert composite and legacy slices flow (DT-1660) (#1138) Co-authored-by: lihbr Co-authored-by: Baptiste Morelle --- e2e-projects/next-upgrade/README.md | 34 + .../app/api/exit-preview/route.ts | 5 + .../next-upgrade/app/api/preview/route.ts | 13 + .../next-upgrade/app/api/revalidate/route.ts | 8 + e2e-projects/next-upgrade/app/layout.tsx | 22 + e2e-projects/next-upgrade/app/page.tsx | 7 + .../next-upgrade/app/slice-simulator/page.tsx | 14 + .../customtypes/kitchen_sink/index.json | 123 +++ .../customtypes/kitchen_sink_2/index.json | 83 ++ .../customtypes/kitchen_sink_3/index.json | 52 ++ .../customtypes/kitchen_sink_4/index.json | 44 + .../customtypes/kitchen_sink_5/index.json | 44 + .../customtypes/kitchen_sink_6/index.json | 46 + .../next-upgrade/customtypes/page/index.json | 90 ++ .../customtypes/partials/index.json | 93 ++ e2e-projects/next-upgrade/next-env.d.ts | 5 + e2e-projects/next-upgrade/next.config.js | 8 + e2e-projects/next-upgrade/package.json | 28 + .../next-upgrade/prismicio-types.d.ts | 859 ++++++++++++++++++ e2e-projects/next-upgrade/prismicio.ts | 54 ++ .../next-upgrade/slicemachine.config.json | 8 + e2e-projects/next-upgrade/tsconfig.json | 27 + package.json | 1 + packages/init/src/SliceMachineInitProcess.ts | 54 +- ...neInitProcess-syncDataWithPrismic.test.ts} | 177 +++- .../src/managers/slices/SlicesManager.ts | 129 ++- .../manager/src/managers/telemetry/types.ts | 17 + ...es-convertLegacySliceToSharedSlice.test.ts | 485 ++++++++++ .../CustomTypeBuilder/SliceZone/List.tsx | 19 +- .../CustomTypeBuilder/SliceZone/index.tsx | 26 +- packages/slice-machine/src/domain/slice.ts | 54 +- .../ConvertLegacySliceAsNewSliceDialog.tsx | 151 +++ ...ConvertLegacySliceAsNewVariationDialog.tsx | 233 +++++ .../ConvertLegacySliceButton.css.ts | 15 + .../ConvertLegacySliceButton.tsx | 268 ++++++ ...ertLegacySliceMergeWithIdenticalDialog.tsx | 106 +++ .../slices/convertLegacySlice/types.ts | 37 + .../sliceCards/NonSharedSliceViewCard.tsx | 23 +- yarn.lock | 230 ++++- 39 files changed, 3611 insertions(+), 81 deletions(-) create mode 100644 e2e-projects/next-upgrade/README.md create mode 100644 e2e-projects/next-upgrade/app/api/exit-preview/route.ts create mode 100644 e2e-projects/next-upgrade/app/api/preview/route.ts create mode 100644 e2e-projects/next-upgrade/app/api/revalidate/route.ts create mode 100644 e2e-projects/next-upgrade/app/layout.tsx create mode 100644 e2e-projects/next-upgrade/app/page.tsx create mode 100644 e2e-projects/next-upgrade/app/slice-simulator/page.tsx create mode 100644 e2e-projects/next-upgrade/customtypes/kitchen_sink/index.json create mode 100644 e2e-projects/next-upgrade/customtypes/kitchen_sink_2/index.json create mode 100644 e2e-projects/next-upgrade/customtypes/kitchen_sink_3/index.json create mode 100644 e2e-projects/next-upgrade/customtypes/kitchen_sink_4/index.json create mode 100644 e2e-projects/next-upgrade/customtypes/kitchen_sink_5/index.json create mode 100644 e2e-projects/next-upgrade/customtypes/kitchen_sink_6/index.json create mode 100644 e2e-projects/next-upgrade/customtypes/page/index.json create mode 100644 e2e-projects/next-upgrade/customtypes/partials/index.json create mode 100644 e2e-projects/next-upgrade/next-env.d.ts create mode 100644 e2e-projects/next-upgrade/next.config.js create mode 100644 e2e-projects/next-upgrade/package.json create mode 100644 e2e-projects/next-upgrade/prismicio-types.d.ts create mode 100644 e2e-projects/next-upgrade/prismicio.ts create mode 100644 e2e-projects/next-upgrade/slicemachine.config.json create mode 100644 e2e-projects/next-upgrade/tsconfig.json rename packages/init/test/{SliceMachineInitProcess-pushDataToPrismic.test.ts => SliceMachineInitProcess-syncDataWithPrismic.test.ts} (82%) create mode 100644 packages/manager/test/SliceMachineManager-slices-convertLegacySliceToSharedSlice.test.ts create mode 100644 packages/slice-machine/src/features/slices/convertLegacySlice/ConvertLegacySliceAsNewSliceDialog.tsx create mode 100644 packages/slice-machine/src/features/slices/convertLegacySlice/ConvertLegacySliceAsNewVariationDialog.tsx create mode 100644 packages/slice-machine/src/features/slices/convertLegacySlice/ConvertLegacySliceButton.css.ts create mode 100644 packages/slice-machine/src/features/slices/convertLegacySlice/ConvertLegacySliceButton.tsx create mode 100644 packages/slice-machine/src/features/slices/convertLegacySlice/ConvertLegacySliceMergeWithIdenticalDialog.tsx create mode 100644 packages/slice-machine/src/features/slices/convertLegacySlice/types.ts diff --git a/e2e-projects/next-upgrade/README.md b/e2e-projects/next-upgrade/README.md new file mode 100644 index 0000000000..f4da3c4c1c --- /dev/null +++ b/e2e-projects/next-upgrade/README.md @@ -0,0 +1,34 @@ +This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). + +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +# or +pnpm dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. + +This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/e2e-projects/next-upgrade/app/api/exit-preview/route.ts b/e2e-projects/next-upgrade/app/api/exit-preview/route.ts new file mode 100644 index 0000000000..ac1c84ca95 --- /dev/null +++ b/e2e-projects/next-upgrade/app/api/exit-preview/route.ts @@ -0,0 +1,5 @@ +import { exitPreview } from "@prismicio/next"; + +export async function GET(): Promise { + return await exitPreview(); +} diff --git a/e2e-projects/next-upgrade/app/api/preview/route.ts b/e2e-projects/next-upgrade/app/api/preview/route.ts new file mode 100644 index 0000000000..c89700f0d4 --- /dev/null +++ b/e2e-projects/next-upgrade/app/api/preview/route.ts @@ -0,0 +1,13 @@ +import { redirectToPreviewURL } from "@prismicio/next"; +import { draftMode } from "next/headers"; +import { NextRequest } from "next/server"; + +import { createClient } from "../../../prismicio"; + +export async function GET(request: NextRequest): Promise { + const client = createClient(); + + draftMode().enable(); + + await redirectToPreviewURL({ client, request }); +} diff --git a/e2e-projects/next-upgrade/app/api/revalidate/route.ts b/e2e-projects/next-upgrade/app/api/revalidate/route.ts new file mode 100644 index 0000000000..a4dbad4cc3 --- /dev/null +++ b/e2e-projects/next-upgrade/app/api/revalidate/route.ts @@ -0,0 +1,8 @@ +import { revalidateTag } from "next/cache"; +import { NextResponse } from "next/server"; + +export async function POST(): Promise { + revalidateTag("prismic"); + + return NextResponse.json({ revalidated: true, now: Date.now() }); +} diff --git a/e2e-projects/next-upgrade/app/layout.tsx b/e2e-projects/next-upgrade/app/layout.tsx new file mode 100644 index 0000000000..367c364e02 --- /dev/null +++ b/e2e-projects/next-upgrade/app/layout.tsx @@ -0,0 +1,22 @@ +import type { Metadata } from "next"; +import { Inter } from "next/font/google"; + +const inter = Inter({ subsets: ["latin"] }); + +// eslint-disable-next-line react-refresh/only-export-components +export const metadata: Metadata = { + title: "Create Next App", + description: "Generated by create next app", +}; + +export default function RootLayout({ + children, +}: { + children: React.ReactNode; +}): JSX.Element { + return ( + + {children} + + ); +} diff --git a/e2e-projects/next-upgrade/app/page.tsx b/e2e-projects/next-upgrade/app/page.tsx new file mode 100644 index 0000000000..90767140bb --- /dev/null +++ b/e2e-projects/next-upgrade/app/page.tsx @@ -0,0 +1,7 @@ +export default function Home(): JSX.Element { + return ( +
+ home +
+ ); +} diff --git a/e2e-projects/next-upgrade/app/slice-simulator/page.tsx b/e2e-projects/next-upgrade/app/slice-simulator/page.tsx new file mode 100644 index 0000000000..e7bda95112 --- /dev/null +++ b/e2e-projects/next-upgrade/app/slice-simulator/page.tsx @@ -0,0 +1,14 @@ +"use client"; + +import { SliceZone } from "@prismicio/react"; +import { SliceSimulator } from "@slicemachine/adapter-next/simulator"; + +import { components } from "../../slices"; + +export default function SliceSimulatorPage(): JSX.Element { + return ( + } + /> + ); +} diff --git a/e2e-projects/next-upgrade/customtypes/kitchen_sink/index.json b/e2e-projects/next-upgrade/customtypes/kitchen_sink/index.json new file mode 100644 index 0000000000..f714e47664 --- /dev/null +++ b/e2e-projects/next-upgrade/customtypes/kitchen_sink/index.json @@ -0,0 +1,123 @@ +{ + "id": "kitchen_sink", + "label": "Kitchen Sink", + "repeatable": true, + "json": { + "Main": { + "body": { + "type": "Slices", + "fieldset": "Slice zone", + "config": { + "labels": null, + "choices": { + "legacy_cta": { + "type": "Link", + "config": { + "allowTargetBlank": true, + "label": "CTA Link", + "select": null + } + }, + "quiet_cta": { + "type": "Slice", + "fieldset": "Quiet CTA", + "description": "Quiet CTA", + "icon": "account_balance", + "display": "list", + "non-repeat": { + "title": { + "type": "StructuredText", + "config": { + "single": "heading2", + "label": "Title" + } + }, + "cta_label": { + "type": "Text", + "config": { + "label": "CTA Label" + } + }, + "cta_link": { + "type": "Link", + "config": { + "allowTargetBlank": true, + "label": "CTA Link", + "select": null + } + } + }, + "repeat": {} + }, + "shouting_cta": { + "type": "Slice", + "fieldset": "Shouting CTA", + "description": "Shouting CTA", + "icon": "account_box", + "display": "list", + "non-repeat": { + "title": { + "type": "StructuredText", + "config": { + "single": "heading2", + "label": "Title" + } + } + }, + "repeat": { + "cta_label": { + "type": "Text", + "config": { + "label": "CTA Label" + } + }, + "cta_link": { + "type": "Link", + "config": { + "allowTargetBlank": true, + "label": "CTA Link", + "select": null + } + } + } + }, + "beautiful_cta": { + "type": "Slice", + "fieldset": "Beautiful CTA", + "description": "Beautiful CTA", + "icon": "adb", + "display": "grid", + "non-repeat": { + "title": { + "type": "StructuredText", + "config": { + "single": "heading2", + "label": "Title" + } + } + }, + "repeat": { + "cta_label": { + "type": "Text", + "config": { + "label": "CTA Label" + } + }, + "cta_link": { + "type": "Link", + "config": { + "allowTargetBlank": true, + "label": "CTA Link", + "select": null + } + } + } + } + } + } + } + } + }, + "status": true, + "format": "custom" +} \ No newline at end of file diff --git a/e2e-projects/next-upgrade/customtypes/kitchen_sink_2/index.json b/e2e-projects/next-upgrade/customtypes/kitchen_sink_2/index.json new file mode 100644 index 0000000000..4afbf841fd --- /dev/null +++ b/e2e-projects/next-upgrade/customtypes/kitchen_sink_2/index.json @@ -0,0 +1,83 @@ +{ + "id": "kitchen_sink_2", + "label": "Kitchen Sink 2", + "repeatable": true, + "json": { + "Main": { + "body": { + "type": "Slices", + "fieldset": "Slice zone", + "config": { + "labels": null, + "choices": { + "legacy_cta": { + "type": "Link", + "config": { + "allowTargetBlank": true, + "label": "CTA Link", + "select": null + } + }, + "quiet_cta": { + "type": "Slice", + "fieldset": "Quiet CTA", + "description": "Quiet CTA", + "icon": "account_balance", + "display": "list", + "non-repeat": { + "title": { + "type": "StructuredText", + "config": { + "single": "heading2", + "label": "Title" + } + }, + "cta_label": { + "type": "Text", + "config": { + "label": "CTA Label" + } + }, + "cta_link": { + "type": "Link", + "config": { + "allowTargetBlank": true, + "label": "CTA Link", + "select": null + } + } + }, + "repeat": {} + }, + "shouting_cta": { + "type": "Slice", + "fieldset": "Shouting CTA", + "description": "Shouting CTA", + "icon": "account_box", + "display": "list", + "non-repeat": { + "title": { + "type": "StructuredText", + "config": { + "single": "heading2", + "label": "Title" + } + } + }, + "repeat": { + "cta_label": { + "type": "Text", + "config": { + "label": "CTA Label" + } + } + } + } + } + } + } + } + }, + "status": true, + "format": "custom" +} \ No newline at end of file diff --git a/e2e-projects/next-upgrade/customtypes/kitchen_sink_3/index.json b/e2e-projects/next-upgrade/customtypes/kitchen_sink_3/index.json new file mode 100644 index 0000000000..9eb8c63166 --- /dev/null +++ b/e2e-projects/next-upgrade/customtypes/kitchen_sink_3/index.json @@ -0,0 +1,52 @@ +{ + "id": "kitchen_sink_3", + "label": "Kitchen Sink 3", + "repeatable": true, + "json": { + "Main": { + "body": { + "type": "Slices", + "fieldset": "Slice zone", + "config": { + "labels": {}, + "choices": { + "beautiful_cta": { + "type": "Slice", + "fieldset": "Beautiful CTA", + "description": "Beautiful CTA", + "icon": "adb", + "display": "grid", + "non-repeat": { + "title": { + "type": "StructuredText", + "config": { + "single": "heading2", + "label": "Title" + } + } + }, + "repeat": { + "cta_label": { + "type": "Text", + "config": { + "label": "CTA Label" + } + }, + "cta_link": { + "type": "Link", + "config": { + "allowTargetBlank": true, + "label": "CTA Link", + "select": null + } + } + } + } + } + } + } + } + }, + "status": true, + "format": "custom" +} diff --git a/e2e-projects/next-upgrade/customtypes/kitchen_sink_4/index.json b/e2e-projects/next-upgrade/customtypes/kitchen_sink_4/index.json new file mode 100644 index 0000000000..fce9589cb9 --- /dev/null +++ b/e2e-projects/next-upgrade/customtypes/kitchen_sink_4/index.json @@ -0,0 +1,44 @@ +{ + "id": "kitchen_sink_4", + "label": "Kitchen Sink 4", + "repeatable": true, + "json": { + "Main": { + "body": { + "type": "Slices", + "fieldset": "Slice zone", + "config": { + "labels": {}, + "choices": { + "beautiful_cta": { + "type": "Slice", + "fieldset": "Beautiful CTA", + "description": "Beautiful CTA", + "icon": "adb", + "display": "grid", + "non-repeat": { + "title": { + "type": "StructuredText", + "config": { + "single": "heading2", + "label": "Title" + } + } + }, + "repeat": { + "cta_label": { + "type": "Text", + "config": { + "label": "CTA Label" + } + } + } + } + } + } + } + } + }, + "status": true, + "format": "custom" +} diff --git a/e2e-projects/next-upgrade/customtypes/kitchen_sink_5/index.json b/e2e-projects/next-upgrade/customtypes/kitchen_sink_5/index.json new file mode 100644 index 0000000000..a98d8095e3 --- /dev/null +++ b/e2e-projects/next-upgrade/customtypes/kitchen_sink_5/index.json @@ -0,0 +1,44 @@ +{ + "id": "kitchen_sink_5", + "label": "Kitchen Sink 5", + "repeatable": true, + "json": { + "Main": { + "body": { + "type": "Slices", + "fieldset": "Slice zone", + "config": { + "labels": {}, + "choices": { + "beautiful_cta": { + "type": "Slice", + "fieldset": "Beautiful CTA", + "description": "Beautiful CTA", + "icon": "adb", + "display": "grid", + "non-repeat": { + "title": { + "type": "StructuredText", + "config": { + "single": "heading2", + "label": "Title" + } + } + }, + "repeat": { + "cta_label": { + "type": "Text", + "config": { + "label": "CTA Label" + } + } + } + } + } + } + } + } + }, + "status": true, + "format": "custom" +} diff --git a/e2e-projects/next-upgrade/customtypes/kitchen_sink_6/index.json b/e2e-projects/next-upgrade/customtypes/kitchen_sink_6/index.json new file mode 100644 index 0000000000..f41d8acdeb --- /dev/null +++ b/e2e-projects/next-upgrade/customtypes/kitchen_sink_6/index.json @@ -0,0 +1,46 @@ +{ + "id": "kitchen_sink_6", + "label": "Kitchen Sink 6", + "repeatable": true, + "json": { + "Main": { + "body": { + "type": "Slices", + "fieldset": "Slice zone", + "config": { + "labels": {}, + "choices": { + "beautiful_cta": { + "type": "Slice", + "fieldset": "Beautiful CTA", + "description": "Beautiful CTA", + "icon": "adb", + "display": "grid", + "non-repeat": { + "title": { + "type": "StructuredText", + "config": { + "single": "heading2", + "label": "Title" + } + } + }, + "repeat": { + "cta_link": { + "type": "Link", + "config": { + "allowTargetBlank": true, + "label": "CTA Link", + "select": null + } + } + } + } + } + } + } + } + }, + "status": true, + "format": "custom" +} diff --git a/e2e-projects/next-upgrade/customtypes/page/index.json b/e2e-projects/next-upgrade/customtypes/page/index.json new file mode 100644 index 0000000000..359b401829 --- /dev/null +++ b/e2e-projects/next-upgrade/customtypes/page/index.json @@ -0,0 +1,90 @@ +{ + "id": "page", + "label": "Page", + "repeatable": true, + "json": { + "Main": { + "uid": { + "type": "UID", + "config": { + "label": "UID", + "placeholder": "" + } + }, + "title": { + "type": "StructuredText", + "config": { + "label": "Title", + "placeholder": "", + "allowTargetBlank": true, + "single": "heading1" + } + }, + "slices": { + "type": "Slices", + "fieldset": "Slice Zone", + "config": { + "choices": { + "quiet_cta": { + "type": "Slice", + "fieldset": "Quiet CTA", + "description": "Quiet CTA", + "icon": "account_balance", + "display": "list", + "non-repeat": { + "title": { + "type": "StructuredText", + "config": { + "single": "heading2", + "label": "Title" + } + }, + "cta_label": { + "type": "Text", + "config": { + "label": "CTA Label" + } + }, + "cta_link": { + "type": "Link", + "config": { + "allowTargetBlank": true, + "label": "CTA Link", + "select": null + } + } + }, + "repeat": {} + }, + "shouting_cta": { + "type": "Slice", + "fieldset": "Shouting CTA", + "description": "Shouting CTA", + "icon": "account_box", + "display": "list", + "non-repeat": { + "title": { + "type": "StructuredText", + "config": { + "single": "heading2", + "label": "Title" + } + } + }, + "repeat": { + "cta_label": { + "type": "Text", + "config": { + "label": "CTA Label" + } + } + } + } + } + } + } + } + }, + "status": true, + "format": "custom" +} diff --git a/e2e-projects/next-upgrade/customtypes/partials/index.json b/e2e-projects/next-upgrade/customtypes/partials/index.json new file mode 100644 index 0000000000..8a2d430217 --- /dev/null +++ b/e2e-projects/next-upgrade/customtypes/partials/index.json @@ -0,0 +1,93 @@ +{ + "id": "partials", + "label": "Partials", + "repeatable": false, + "json": { + "Header": { + "nav": { + "type": "Group", + "config": { + "label": "Nav", + "fields": { + "label": { + "type": "Text", + "config": { + "label": "Label", + "placeholder": "" + } + }, + "link": { + "type": "Link", + "config": { + "label": "Link", + "placeholder": "", + "allowTargetBlank": true, + "select": null + } + }, + "cta": { + "type": "Boolean", + "config": { + "label": "Display as CTA", + "placeholder_false": "False", + "placeholder_true": "True", + "default_value": false + } + } + } + } + } + }, + "Footer": { + "socials": { + "type": "Group", + "config": { + "label": "Socials", + "fields": { + "label": { + "type": "Text", + "config": { + "label": "Label", + "placeholder": "" + } + }, + "link": { + "type": "Link", + "config": { + "label": "Link", + "placeholder": "", + "select": null + } + } + } + } + }, + "footer_nav": { + "type": "Group", + "config": { + "label": "Footer Nav", + "fields": { + "category": { + "type": "Text", + "config": { + "label": "Category", + "placeholder": "" + } + }, + "links": { + "type": "StructuredText", + "config": { + "label": "Links", + "placeholder": "", + "allowTargetBlank": true, + "single": "list-item,hyperlink" + } + } + } + } + } + } + }, + "status": true, + "format": "custom" +} diff --git a/e2e-projects/next-upgrade/next-env.d.ts b/e2e-projects/next-upgrade/next-env.d.ts new file mode 100644 index 0000000000..4f11a03dc6 --- /dev/null +++ b/e2e-projects/next-upgrade/next-env.d.ts @@ -0,0 +1,5 @@ +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/e2e-projects/next-upgrade/next.config.js b/e2e-projects/next-upgrade/next.config.js new file mode 100644 index 0000000000..7dcffb0028 --- /dev/null +++ b/e2e-projects/next-upgrade/next.config.js @@ -0,0 +1,8 @@ +/* eslint-disable tsdoc/syntax */ + +/** + * @type {import("next").NextConfig} + */ +const nextConfig = {}; + +module.exports = nextConfig; diff --git a/e2e-projects/next-upgrade/package.json b/e2e-projects/next-upgrade/package.json new file mode 100644 index 0000000000..b977d07d64 --- /dev/null +++ b/e2e-projects/next-upgrade/package.json @@ -0,0 +1,28 @@ +{ + "name": "next-upgrade", + "version": "1.14.1-dev-upgrade-legacy-3.1", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint", + "slicemachine": "NODE_ENV=development SM_ENV=staging start-slicemachine" + }, + "dependencies": { + "@prismicio/client": "^7.2.0", + "@prismicio/next": "^1.3.6", + "@prismicio/react": "^2.7.3", + "next": "^13.5.4", + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@slicemachine/adapter-next": "workspace:*", + "@types/node": "^20.8.3", + "@types/react": "^18.2.25", + "@types/react-dom": "^18.2.11", + "slice-machine-ui": "workspace:*", + "typescript": "^4.9.5" + } +} diff --git a/e2e-projects/next-upgrade/prismicio-types.d.ts b/e2e-projects/next-upgrade/prismicio-types.d.ts new file mode 100644 index 0000000000..b30ed7b95e --- /dev/null +++ b/e2e-projects/next-upgrade/prismicio-types.d.ts @@ -0,0 +1,859 @@ +// Code generated by Slice Machine. DO NOT EDIT. + +import type * as prismic from "@prismicio/client"; + +type Simplify = { [KeyType in keyof T]: T[KeyType] }; + +/** Primary content in _Kitchen Sink → Slice zone → Quiet CTA → Primary_ */ +export interface KitchenSinkDocumentDataBodyQuietCtaSlicePrimary { + /** + * Title field in _Kitchen Sink → Slice zone → Quiet CTA → Primary_ + * + * - **Field Type**: Title + * - **Placeholder**: _None_ + * - **API ID Path**: kitchen_sink.body[].quiet_cta.primary.title + * - **Documentation**: https://prismic.io/docs/field#rich-text-title + */ + title: prismic.TitleField; + + /** + * CTA Label field in _Kitchen Sink → Slice zone → Quiet CTA → Primary_ + * + * - **Field Type**: Text + * - **Placeholder**: _None_ + * - **API ID Path**: kitchen_sink.body[].quiet_cta.primary.cta_label + * - **Documentation**: https://prismic.io/docs/field#key-text + */ + cta_label: prismic.KeyTextField; + + /** + * CTA Link field in _Kitchen Sink → Slice zone → Quiet CTA → Primary_ + * + * - **Field Type**: Link + * - **Placeholder**: _None_ + * - **API ID Path**: kitchen_sink.body[].quiet_cta.primary.cta_link + * - **Documentation**: https://prismic.io/docs/field#link-content-relationship + */ + cta_link: prismic.LinkField; +} + +/** Slice for _Kitchen Sink → Slice zone_ */ +export type KitchenSinkDocumentDataBodyQuietCtaSlice = prismic.Slice< + "quiet_cta", + Simplify, + never +>; + +/** Primary content in _Kitchen Sink → Slice zone → Shouting CTA → Primary_ */ +export interface KitchenSinkDocumentDataBodyShoutingCtaSlicePrimary { + /** + * Title field in _Kitchen Sink → Slice zone → Shouting CTA → Primary_ + * + * - **Field Type**: Title + * - **Placeholder**: _None_ + * - **API ID Path**: kitchen_sink.body[].shouting_cta.primary.title + * - **Documentation**: https://prismic.io/docs/field#rich-text-title + */ + title: prismic.TitleField; +} + +/** Item content in _Kitchen Sink → Slice zone → Shouting CTA → Items_ */ +export interface KitchenSinkDocumentDataBodyShoutingCtaSliceItem { + /** + * CTA Label field in _Kitchen Sink → Slice zone → Shouting CTA → Items_ + * + * - **Field Type**: Text + * - **Placeholder**: _None_ + * - **API ID Path**: kitchen_sink.body[].shouting_cta.items.cta_label + * - **Documentation**: https://prismic.io/docs/field#key-text + */ + cta_label: prismic.KeyTextField; + + /** + * CTA Link field in _Kitchen Sink → Slice zone → Shouting CTA → Items_ + * + * - **Field Type**: Link + * - **Placeholder**: _None_ + * - **API ID Path**: kitchen_sink.body[].shouting_cta.items.cta_link + * - **Documentation**: https://prismic.io/docs/field#link-content-relationship + */ + cta_link: prismic.LinkField; +} + +/** Slice for _Kitchen Sink → Slice zone_ */ +export type KitchenSinkDocumentDataBodyShoutingCtaSlice = prismic.Slice< + "shouting_cta", + Simplify, + Simplify +>; + +/** Primary content in _Kitchen Sink → Slice zone → Beautiful CTA → Primary_ */ +export interface KitchenSinkDocumentDataBodyBeautifulCtaSlicePrimary { + /** + * Title field in _Kitchen Sink → Slice zone → Beautiful CTA → Primary_ + * + * - **Field Type**: Title + * - **Placeholder**: _None_ + * - **API ID Path**: kitchen_sink.body[].beautiful_cta.primary.title + * - **Documentation**: https://prismic.io/docs/field#rich-text-title + */ + title: prismic.TitleField; +} + +/** Item content in _Kitchen Sink → Slice zone → Beautiful CTA → Items_ */ +export interface KitchenSinkDocumentDataBodyBeautifulCtaSliceItem { + /** + * CTA Label field in _Kitchen Sink → Slice zone → Beautiful CTA → Items_ + * + * - **Field Type**: Text + * - **Placeholder**: _None_ + * - **API ID Path**: kitchen_sink.body[].beautiful_cta.items.cta_label + * - **Documentation**: https://prismic.io/docs/field#key-text + */ + cta_label: prismic.KeyTextField; + + /** + * CTA Link field in _Kitchen Sink → Slice zone → Beautiful CTA → Items_ + * + * - **Field Type**: Link + * - **Placeholder**: _None_ + * - **API ID Path**: kitchen_sink.body[].beautiful_cta.items.cta_link + * - **Documentation**: https://prismic.io/docs/field#link-content-relationship + */ + cta_link: prismic.LinkField; +} + +/** Slice for _Kitchen Sink → Slice zone_ */ +export type KitchenSinkDocumentDataBodyBeautifulCtaSlice = prismic.Slice< + "beautiful_cta", + Simplify, + Simplify +>; + +type KitchenSinkDocumentDataBodySlice = + | KitchenSinkDocumentDataBodyQuietCtaSlice + | KitchenSinkDocumentDataBodyShoutingCtaSlice + | KitchenSinkDocumentDataBodyBeautifulCtaSlice; + +/** Content for Kitchen Sink documents */ +interface KitchenSinkDocumentData { + /** + * Slice zone field in _Kitchen Sink_ + * + * - **Field Type**: Slice Zone + * - **Placeholder**: _None_ + * - **API ID Path**: kitchen_sink.body[] + * - **Tab**: Main + * - **Documentation**: https://prismic.io/docs/field#slices + */ + body: prismic.SliceZone; +} + +/** + * Kitchen Sink document from Prismic + * + * - **API ID**: `kitchen_sink` + * - **Repeatable**: `true` + * - **Documentation**: https://prismic.io/docs/custom-types + * + * @typeParam Lang - Language API ID of the document. + */ +export type KitchenSinkDocument = + prismic.PrismicDocumentWithoutUID< + Simplify, + "kitchen_sink", + Lang + >; + +/** Primary content in _Kitchen Sink 2 → Slice zone → Quiet CTA → Primary_ */ +export interface KitchenSink2DocumentDataBodyQuietCtaSlicePrimary { + /** + * Title field in _Kitchen Sink 2 → Slice zone → Quiet CTA → Primary_ + * + * - **Field Type**: Title + * - **Placeholder**: _None_ + * - **API ID Path**: kitchen_sink_2.body[].quiet_cta.primary.title + * - **Documentation**: https://prismic.io/docs/field#rich-text-title + */ + title: prismic.TitleField; + + /** + * CTA Label field in _Kitchen Sink 2 → Slice zone → Quiet CTA → Primary_ + * + * - **Field Type**: Text + * - **Placeholder**: _None_ + * - **API ID Path**: kitchen_sink_2.body[].quiet_cta.primary.cta_label + * - **Documentation**: https://prismic.io/docs/field#key-text + */ + cta_label: prismic.KeyTextField; + + /** + * CTA Link field in _Kitchen Sink 2 → Slice zone → Quiet CTA → Primary_ + * + * - **Field Type**: Link + * - **Placeholder**: _None_ + * - **API ID Path**: kitchen_sink_2.body[].quiet_cta.primary.cta_link + * - **Documentation**: https://prismic.io/docs/field#link-content-relationship + */ + cta_link: prismic.LinkField; +} + +/** Slice for _Kitchen Sink 2 → Slice zone_ */ +export type KitchenSink2DocumentDataBodyQuietCtaSlice = prismic.Slice< + "quiet_cta", + Simplify, + never +>; + +/** Primary content in _Kitchen Sink 2 → Slice zone → Shouting CTA → Primary_ */ +export interface KitchenSink2DocumentDataBodyShoutingCtaSlicePrimary { + /** + * Title field in _Kitchen Sink 2 → Slice zone → Shouting CTA → Primary_ + * + * - **Field Type**: Title + * - **Placeholder**: _None_ + * - **API ID Path**: kitchen_sink_2.body[].shouting_cta.primary.title + * - **Documentation**: https://prismic.io/docs/field#rich-text-title + */ + title: prismic.TitleField; +} + +/** Item content in _Kitchen Sink 2 → Slice zone → Shouting CTA → Items_ */ +export interface KitchenSink2DocumentDataBodyShoutingCtaSliceItem { + /** + * CTA Label field in _Kitchen Sink 2 → Slice zone → Shouting CTA → Items_ + * + * - **Field Type**: Text + * - **Placeholder**: _None_ + * - **API ID Path**: kitchen_sink_2.body[].shouting_cta.items.cta_label + * - **Documentation**: https://prismic.io/docs/field#key-text + */ + cta_label: prismic.KeyTextField; +} + +/** Slice for _Kitchen Sink 2 → Slice zone_ */ +export type KitchenSink2DocumentDataBodyShoutingCtaSlice = prismic.Slice< + "shouting_cta", + Simplify, + Simplify +>; + +type KitchenSink2DocumentDataBodySlice = + | KitchenSink2DocumentDataBodyQuietCtaSlice + | KitchenSink2DocumentDataBodyShoutingCtaSlice; + +/** Content for Kitchen Sink 2 documents */ +interface KitchenSink2DocumentData { + /** + * Slice zone field in _Kitchen Sink 2_ + * + * - **Field Type**: Slice Zone + * - **Placeholder**: _None_ + * - **API ID Path**: kitchen_sink_2.body[] + * - **Tab**: Main + * - **Documentation**: https://prismic.io/docs/field#slices + */ + body: prismic.SliceZone; +} + +/** + * Kitchen Sink 2 document from Prismic + * + * - **API ID**: `kitchen_sink_2` + * - **Repeatable**: `true` + * - **Documentation**: https://prismic.io/docs/custom-types + * + * @typeParam Lang - Language API ID of the document. + */ +export type KitchenSink2Document = + prismic.PrismicDocumentWithoutUID< + Simplify, + "kitchen_sink_2", + Lang + >; + +/** Primary content in _Kitchen Sink 3 → Slice zone → Beautiful CTA → Primary_ */ +export interface KitchenSink3DocumentDataBodyBeautifulCtaSlicePrimary { + /** + * Title field in _Kitchen Sink 3 → Slice zone → Beautiful CTA → Primary_ + * + * - **Field Type**: Title + * - **Placeholder**: _None_ + * - **API ID Path**: kitchen_sink_3.body[].beautiful_cta.primary.title + * - **Documentation**: https://prismic.io/docs/field#rich-text-title + */ + title: prismic.TitleField; +} + +/** Item content in _Kitchen Sink 3 → Slice zone → Beautiful CTA → Items_ */ +export interface KitchenSink3DocumentDataBodyBeautifulCtaSliceItem { + /** + * CTA Label field in _Kitchen Sink 3 → Slice zone → Beautiful CTA → Items_ + * + * - **Field Type**: Text + * - **Placeholder**: _None_ + * - **API ID Path**: kitchen_sink_3.body[].beautiful_cta.items.cta_label + * - **Documentation**: https://prismic.io/docs/field#key-text + */ + cta_label: prismic.KeyTextField; + + /** + * CTA Link field in _Kitchen Sink 3 → Slice zone → Beautiful CTA → Items_ + * + * - **Field Type**: Link + * - **Placeholder**: _None_ + * - **API ID Path**: kitchen_sink_3.body[].beautiful_cta.items.cta_link + * - **Documentation**: https://prismic.io/docs/field#link-content-relationship + */ + cta_link: prismic.LinkField; +} + +/** Slice for _Kitchen Sink 3 → Slice zone_ */ +export type KitchenSink3DocumentDataBodyBeautifulCtaSlice = prismic.Slice< + "beautiful_cta", + Simplify, + Simplify +>; + +type KitchenSink3DocumentDataBodySlice = + KitchenSink3DocumentDataBodyBeautifulCtaSlice; + +/** Content for Kitchen Sink 3 documents */ +interface KitchenSink3DocumentData { + /** + * Slice zone field in _Kitchen Sink 3_ + * + * - **Field Type**: Slice Zone + * - **Placeholder**: _None_ + * - **API ID Path**: kitchen_sink_3.body[] + * - **Tab**: Main + * - **Documentation**: https://prismic.io/docs/field#slices + */ + body: prismic.SliceZone; +} + +/** + * Kitchen Sink 3 document from Prismic + * + * - **API ID**: `kitchen_sink_3` + * - **Repeatable**: `true` + * - **Documentation**: https://prismic.io/docs/custom-types + * + * @typeParam Lang - Language API ID of the document. + */ +export type KitchenSink3Document = + prismic.PrismicDocumentWithoutUID< + Simplify, + "kitchen_sink_3", + Lang + >; + +/** Primary content in _Kitchen Sink 4 → Slice zone → Beautiful CTA → Primary_ */ +export interface KitchenSink4DocumentDataBodyBeautifulCtaSlicePrimary { + /** + * Title field in _Kitchen Sink 4 → Slice zone → Beautiful CTA → Primary_ + * + * - **Field Type**: Title + * - **Placeholder**: _None_ + * - **API ID Path**: kitchen_sink_4.body[].beautiful_cta.primary.title + * - **Documentation**: https://prismic.io/docs/field#rich-text-title + */ + title: prismic.TitleField; +} + +/** Item content in _Kitchen Sink 4 → Slice zone → Beautiful CTA → Items_ */ +export interface KitchenSink4DocumentDataBodyBeautifulCtaSliceItem { + /** + * CTA Label field in _Kitchen Sink 4 → Slice zone → Beautiful CTA → Items_ + * + * - **Field Type**: Text + * - **Placeholder**: _None_ + * - **API ID Path**: kitchen_sink_4.body[].beautiful_cta.items.cta_label + * - **Documentation**: https://prismic.io/docs/field#key-text + */ + cta_label: prismic.KeyTextField; +} + +/** Slice for _Kitchen Sink 4 → Slice zone_ */ +export type KitchenSink4DocumentDataBodyBeautifulCtaSlice = prismic.Slice< + "beautiful_cta", + Simplify, + Simplify +>; + +type KitchenSink4DocumentDataBodySlice = + KitchenSink4DocumentDataBodyBeautifulCtaSlice; + +/** Content for Kitchen Sink 4 documents */ +interface KitchenSink4DocumentData { + /** + * Slice zone field in _Kitchen Sink 4_ + * + * - **Field Type**: Slice Zone + * - **Placeholder**: _None_ + * - **API ID Path**: kitchen_sink_4.body[] + * - **Tab**: Main + * - **Documentation**: https://prismic.io/docs/field#slices + */ + body: prismic.SliceZone; +} + +/** + * Kitchen Sink 4 document from Prismic + * + * - **API ID**: `kitchen_sink_4` + * - **Repeatable**: `true` + * - **Documentation**: https://prismic.io/docs/custom-types + * + * @typeParam Lang - Language API ID of the document. + */ +export type KitchenSink4Document = + prismic.PrismicDocumentWithoutUID< + Simplify, + "kitchen_sink_4", + Lang + >; + +/** Primary content in _Kitchen Sink 5 → Slice zone → Beautiful CTA → Primary_ */ +export interface KitchenSink5DocumentDataBodyBeautifulCtaSlicePrimary { + /** + * Title field in _Kitchen Sink 5 → Slice zone → Beautiful CTA → Primary_ + * + * - **Field Type**: Title + * - **Placeholder**: _None_ + * - **API ID Path**: kitchen_sink_5.body[].beautiful_cta.primary.title + * - **Documentation**: https://prismic.io/docs/field#rich-text-title + */ + title: prismic.TitleField; +} + +/** Item content in _Kitchen Sink 5 → Slice zone → Beautiful CTA → Items_ */ +export interface KitchenSink5DocumentDataBodyBeautifulCtaSliceItem { + /** + * CTA Label field in _Kitchen Sink 5 → Slice zone → Beautiful CTA → Items_ + * + * - **Field Type**: Text + * - **Placeholder**: _None_ + * - **API ID Path**: kitchen_sink_5.body[].beautiful_cta.items.cta_label + * - **Documentation**: https://prismic.io/docs/field#key-text + */ + cta_label: prismic.KeyTextField; +} + +/** Slice for _Kitchen Sink 5 → Slice zone_ */ +export type KitchenSink5DocumentDataBodyBeautifulCtaSlice = prismic.Slice< + "beautiful_cta", + Simplify, + Simplify +>; + +type KitchenSink5DocumentDataBodySlice = + KitchenSink5DocumentDataBodyBeautifulCtaSlice; + +/** Content for Kitchen Sink 5 documents */ +interface KitchenSink5DocumentData { + /** + * Slice zone field in _Kitchen Sink 5_ + * + * - **Field Type**: Slice Zone + * - **Placeholder**: _None_ + * - **API ID Path**: kitchen_sink_5.body[] + * - **Tab**: Main + * - **Documentation**: https://prismic.io/docs/field#slices + */ + body: prismic.SliceZone; +} + +/** + * Kitchen Sink 5 document from Prismic + * + * - **API ID**: `kitchen_sink_5` + * - **Repeatable**: `true` + * - **Documentation**: https://prismic.io/docs/custom-types + * + * @typeParam Lang - Language API ID of the document. + */ +export type KitchenSink5Document = + prismic.PrismicDocumentWithoutUID< + Simplify, + "kitchen_sink_5", + Lang + >; + +/** Primary content in _Kitchen Sink 6 → Slice zone → Beautiful CTA → Primary_ */ +export interface KitchenSink6DocumentDataBodyBeautifulCtaSlicePrimary { + /** + * Title field in _Kitchen Sink 6 → Slice zone → Beautiful CTA → Primary_ + * + * - **Field Type**: Title + * - **Placeholder**: _None_ + * - **API ID Path**: kitchen_sink_6.body[].beautiful_cta.primary.title + * - **Documentation**: https://prismic.io/docs/field#rich-text-title + */ + title: prismic.TitleField; +} + +/** Item content in _Kitchen Sink 6 → Slice zone → Beautiful CTA → Items_ */ +export interface KitchenSink6DocumentDataBodyBeautifulCtaSliceItem { + /** + * CTA Link field in _Kitchen Sink 6 → Slice zone → Beautiful CTA → Items_ + * + * - **Field Type**: Link + * - **Placeholder**: _None_ + * - **API ID Path**: kitchen_sink_6.body[].beautiful_cta.items.cta_link + * - **Documentation**: https://prismic.io/docs/field#link-content-relationship + */ + cta_link: prismic.LinkField; +} + +/** Slice for _Kitchen Sink 6 → Slice zone_ */ +export type KitchenSink6DocumentDataBodyBeautifulCtaSlice = prismic.Slice< + "beautiful_cta", + Simplify, + Simplify +>; + +type KitchenSink6DocumentDataBodySlice = + KitchenSink6DocumentDataBodyBeautifulCtaSlice; + +/** Content for Kitchen Sink 6 documents */ +interface KitchenSink6DocumentData { + /** + * Slice zone field in _Kitchen Sink 6_ + * + * - **Field Type**: Slice Zone + * - **Placeholder**: _None_ + * - **API ID Path**: kitchen_sink_6.body[] + * - **Tab**: Main + * - **Documentation**: https://prismic.io/docs/field#slices + */ + body: prismic.SliceZone; +} + +/** + * Kitchen Sink 6 document from Prismic + * + * - **API ID**: `kitchen_sink_6` + * - **Repeatable**: `true` + * - **Documentation**: https://prismic.io/docs/custom-types + * + * @typeParam Lang - Language API ID of the document. + */ +export type KitchenSink6Document = + prismic.PrismicDocumentWithoutUID< + Simplify, + "kitchen_sink_6", + Lang + >; + +/** Primary content in _Page → Slice Zone → Quiet CTA → Primary_ */ +export interface PageDocumentDataSlicesQuietCtaSlicePrimary { + /** + * Title field in _Page → Slice Zone → Quiet CTA → Primary_ + * + * - **Field Type**: Title + * - **Placeholder**: _None_ + * - **API ID Path**: page.slices[].quiet_cta.primary.title + * - **Documentation**: https://prismic.io/docs/field#rich-text-title + */ + title: prismic.TitleField; + + /** + * CTA Label field in _Page → Slice Zone → Quiet CTA → Primary_ + * + * - **Field Type**: Text + * - **Placeholder**: _None_ + * - **API ID Path**: page.slices[].quiet_cta.primary.cta_label + * - **Documentation**: https://prismic.io/docs/field#key-text + */ + cta_label: prismic.KeyTextField; + + /** + * CTA Link field in _Page → Slice Zone → Quiet CTA → Primary_ + * + * - **Field Type**: Link + * - **Placeholder**: _None_ + * - **API ID Path**: page.slices[].quiet_cta.primary.cta_link + * - **Documentation**: https://prismic.io/docs/field#link-content-relationship + */ + cta_link: prismic.LinkField; +} + +/** Slice for _Page → Slice Zone_ */ +export type PageDocumentDataSlicesQuietCtaSlice = prismic.Slice< + "quiet_cta", + Simplify, + never +>; + +/** Primary content in _Page → Slice Zone → Shouting CTA → Primary_ */ +export interface PageDocumentDataSlicesShoutingCtaSlicePrimary { + /** + * Title field in _Page → Slice Zone → Shouting CTA → Primary_ + * + * - **Field Type**: Title + * - **Placeholder**: _None_ + * - **API ID Path**: page.slices[].shouting_cta.primary.title + * - **Documentation**: https://prismic.io/docs/field#rich-text-title + */ + title: prismic.TitleField; +} + +/** Item content in _Page → Slice Zone → Shouting CTA → Items_ */ +export interface PageDocumentDataSlicesShoutingCtaSliceItem { + /** + * CTA Label field in _Page → Slice Zone → Shouting CTA → Items_ + * + * - **Field Type**: Text + * - **Placeholder**: _None_ + * - **API ID Path**: page.slices[].shouting_cta.items.cta_label + * - **Documentation**: https://prismic.io/docs/field#key-text + */ + cta_label: prismic.KeyTextField; +} + +/** Slice for _Page → Slice Zone_ */ +export type PageDocumentDataSlicesShoutingCtaSlice = prismic.Slice< + "shouting_cta", + Simplify, + Simplify +>; + +type PageDocumentDataSlicesSlice = + | PageDocumentDataSlicesQuietCtaSlice + | PageDocumentDataSlicesShoutingCtaSlice; + +/** Content for Page documents */ +interface PageDocumentData { + /** + * Title field in _Page_ + * + * - **Field Type**: Title + * - **Placeholder**: _None_ + * - **API ID Path**: page.title + * - **Tab**: Main + * - **Documentation**: https://prismic.io/docs/field#rich-text-title + */ + title: prismic.TitleField; + + /** + * Slice Zone field in _Page_ + * + * - **Field Type**: Slice Zone + * - **Placeholder**: _None_ + * - **API ID Path**: page.slices[] + * - **Tab**: Main + * - **Documentation**: https://prismic.io/docs/field#slices + */ + slices: prismic.SliceZone; +} + +/** + * Page document from Prismic + * + * - **API ID**: `page` + * - **Repeatable**: `true` + * - **Documentation**: https://prismic.io/docs/custom-types + * + * @typeParam Lang - Language API ID of the document. + */ +export type PageDocument = + prismic.PrismicDocumentWithUID, "page", Lang>; + +/** Item in _Partials → Nav_ */ +export interface PartialsDocumentDataNavItem { + /** + * Label field in _Partials → Nav_ + * + * - **Field Type**: Text + * - **Placeholder**: _None_ + * - **API ID Path**: partials.nav[].label + * - **Documentation**: https://prismic.io/docs/field#key-text + */ + label: prismic.KeyTextField; + + /** + * Link field in _Partials → Nav_ + * + * - **Field Type**: Link + * - **Placeholder**: _None_ + * - **API ID Path**: partials.nav[].link + * - **Documentation**: https://prismic.io/docs/field#link-content-relationship + */ + link: prismic.LinkField; + + /** + * Display as CTA field in _Partials → Nav_ + * + * - **Field Type**: Boolean + * - **Placeholder**: _None_ + * - **Default Value**: false + * - **API ID Path**: partials.nav[].cta + * - **Documentation**: https://prismic.io/docs/field#boolean + */ + cta: prismic.BooleanField; +} + +/** Item in _Partials → Socials_ */ +export interface PartialsDocumentDataSocialsItem { + /** + * Label field in _Partials → Socials_ + * + * - **Field Type**: Text + * - **Placeholder**: _None_ + * - **API ID Path**: partials.socials[].label + * - **Documentation**: https://prismic.io/docs/field#key-text + */ + label: prismic.KeyTextField; + + /** + * Link field in _Partials → Socials_ + * + * - **Field Type**: Link + * - **Placeholder**: _None_ + * - **API ID Path**: partials.socials[].link + * - **Documentation**: https://prismic.io/docs/field#link-content-relationship + */ + link: prismic.LinkField; +} + +/** Item in _Partials → Footer Nav_ */ +export interface PartialsDocumentDataFooterNavItem { + /** + * Category field in _Partials → Footer Nav_ + * + * - **Field Type**: Text + * - **Placeholder**: _None_ + * - **API ID Path**: partials.footer_nav[].category + * - **Documentation**: https://prismic.io/docs/field#key-text + */ + category: prismic.KeyTextField; + + /** + * Links field in _Partials → Footer Nav_ + * + * - **Field Type**: Rich Text + * - **Placeholder**: _None_ + * - **API ID Path**: partials.footer_nav[].links + * - **Documentation**: https://prismic.io/docs/field#rich-text-title + */ + links: prismic.RichTextField; +} + +/** Content for Partials documents */ +interface PartialsDocumentData { + /** + * Nav field in _Partials_ + * + * - **Field Type**: Group + * - **Placeholder**: _None_ + * - **API ID Path**: partials.nav[] + * - **Tab**: Header + * - **Documentation**: https://prismic.io/docs/field#group + */ + nav: prismic.GroupField> + /** + * Socials field in _Partials_ + * + * - **Field Type**: Group + * - **Placeholder**: _None_ + * - **API ID Path**: partials.socials[] + * - **Tab**: Footer + * - **Documentation**: https://prismic.io/docs/field#group + */; + socials: prismic.GroupField>; + + /** + * Footer Nav field in _Partials_ + * + * - **Field Type**: Group + * - **Placeholder**: _None_ + * - **API ID Path**: partials.footer_nav[] + * - **Tab**: Footer + * - **Documentation**: https://prismic.io/docs/field#group + */ + footer_nav: prismic.GroupField>; +} + +/** + * Partials document from Prismic + * + * - **API ID**: `partials` + * - **Repeatable**: `false` + * - **Documentation**: https://prismic.io/docs/custom-types + * + * @typeParam Lang - Language API ID of the document. + */ +export type PartialsDocument = + prismic.PrismicDocumentWithoutUID< + Simplify, + "partials", + Lang + >; + +export type AllDocumentTypes = + | KitchenSinkDocument + | KitchenSink2Document + | KitchenSink3Document + | KitchenSink4Document + | KitchenSink5Document + | KitchenSink6Document + | PageDocument + | PartialsDocument; + +declare module "@prismicio/client" { + interface CreateClient { + ( + repositoryNameOrEndpoint: string, + options?: prismic.ClientConfig + ): prismic.Client; + } + + namespace Content { + export type { + KitchenSinkDocument, + KitchenSinkDocumentData, + KitchenSinkDocumentDataBodyQuietCtaSlicePrimary, + KitchenSinkDocumentDataBodyShoutingCtaSlicePrimary, + KitchenSinkDocumentDataBodyShoutingCtaSliceItem, + KitchenSinkDocumentDataBodyBeautifulCtaSlicePrimary, + KitchenSinkDocumentDataBodyBeautifulCtaSliceItem, + KitchenSinkDocumentDataBodySlice, + KitchenSink2Document, + KitchenSink2DocumentData, + KitchenSink2DocumentDataBodyQuietCtaSlicePrimary, + KitchenSink2DocumentDataBodyShoutingCtaSlicePrimary, + KitchenSink2DocumentDataBodyShoutingCtaSliceItem, + KitchenSink2DocumentDataBodySlice, + KitchenSink3Document, + KitchenSink3DocumentData, + KitchenSink3DocumentDataBodyBeautifulCtaSlicePrimary, + KitchenSink3DocumentDataBodyBeautifulCtaSliceItem, + KitchenSink3DocumentDataBodySlice, + KitchenSink4Document, + KitchenSink4DocumentData, + KitchenSink4DocumentDataBodyBeautifulCtaSlicePrimary, + KitchenSink4DocumentDataBodyBeautifulCtaSliceItem, + KitchenSink4DocumentDataBodySlice, + KitchenSink5Document, + KitchenSink5DocumentData, + KitchenSink5DocumentDataBodyBeautifulCtaSlicePrimary, + KitchenSink5DocumentDataBodyBeautifulCtaSliceItem, + KitchenSink5DocumentDataBodySlice, + KitchenSink6Document, + KitchenSink6DocumentData, + KitchenSink6DocumentDataBodyBeautifulCtaSlicePrimary, + KitchenSink6DocumentDataBodyBeautifulCtaSliceItem, + KitchenSink6DocumentDataBodySlice, + PageDocument, + PageDocumentData, + PageDocumentDataSlicesQuietCtaSlicePrimary, + PageDocumentDataSlicesShoutingCtaSlicePrimary, + PageDocumentDataSlicesShoutingCtaSliceItem, + PageDocumentDataSlicesSlice, + PartialsDocument, + PartialsDocumentData, + AllDocumentTypes, + }; + } +} diff --git a/e2e-projects/next-upgrade/prismicio.ts b/e2e-projects/next-upgrade/prismicio.ts new file mode 100644 index 0000000000..a24d3ceb4d --- /dev/null +++ b/e2e-projects/next-upgrade/prismicio.ts @@ -0,0 +1,54 @@ +import * as prismic from "@prismicio/client"; +import * as prismicNext from "@prismicio/next"; + +import config from "./slicemachine.config.json"; + +/** + * The project's Prismic repository name. + */ +export const repositoryName = config.repositoryName; + +/** + * A list of Route Resolver objects that define how a document's `url` field is + * resolved. + * + * {@link https://prismic.io/docs/route-resolver#route-resolver} + */ +// TODO: Update the routes array to match your project's route structure. +const routes: prismic.ClientConfig["routes"] = [ + { + type: "homepage", + path: "/", + }, + { + type: "page", + path: "/:uid", + }, +]; + +/** + * Creates a Prismic client for the project's repository. The client is used to + * query content from the Prismic API. + * + * @param config - Configuration for the Prismic client. + */ +export const createClient = ( + config: prismicNext.CreateClientConfig = {}, +): prismic.Client => { + const client = prismic.createClient(repositoryName, { + routes, + fetchOptions: + process.env.NODE_ENV === "production" + ? { next: { tags: ["prismic"] }, cache: "force-cache" } + : { next: { revalidate: 5 } }, + ...config, + }); + + prismicNext.enableAutoPreviews({ + client, + previewData: config.previewData, + req: config.req, + }); + + return client; +}; diff --git a/e2e-projects/next-upgrade/slicemachine.config.json b/e2e-projects/next-upgrade/slicemachine.config.json new file mode 100644 index 0000000000..adcee3fd17 --- /dev/null +++ b/e2e-projects/next-upgrade/slicemachine.config.json @@ -0,0 +1,8 @@ +{ + "repositoryName": "upgrade-optimize-full-legacy", + "adapter": "@slicemachine/adapter-next", + "libraries": [ + "./slices" + ], + "localSliceSimulatorURL": "http://localhost:3000/slice-simulator" +} \ No newline at end of file diff --git a/e2e-projects/next-upgrade/tsconfig.json b/e2e-projects/next-upgrade/tsconfig.json new file mode 100644 index 0000000000..c714696378 --- /dev/null +++ b/e2e-projects/next-upgrade/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": ["./*"] + } + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "exclude": ["node_modules"] +} diff --git a/package.json b/package.json index b4fba75e8d..0f62b82f38 100644 --- a/package.json +++ b/package.json @@ -72,6 +72,7 @@ "workspaces": [ "e2e-projects/next", "e2e-projects/sveltekit", + "e2e-projects/next-upgrade", "packages/*" ] } diff --git a/packages/init/src/SliceMachineInitProcess.ts b/packages/init/src/SliceMachineInitProcess.ts index 54598b3622..db94907130 100644 --- a/packages/init/src/SliceMachineInitProcess.ts +++ b/packages/init/src/SliceMachineInitProcess.ts @@ -176,7 +176,7 @@ export class SliceMachineInitProcess { await this.createNewRepository(); } - await this.pushDataToPrismic(); + await this.syncDataWithPrismic(); await this.initializeProject(); await this.initializePlugins(); } catch (error) { @@ -320,6 +320,8 @@ export class SliceMachineInitProcess { this.manager.customTypes.readCustomTypeLibrary(), this.readDocuments(), ]); + + // If repository exists, and there's anything to push if ( slices.length > 0 || ctLibrary.ids.length > 0 || @@ -327,6 +329,11 @@ export class SliceMachineInitProcess { ) { return true; } + + // If repository exists, and there might be things to pull + if (ctLibrary.ids.length === 0) { + return true; + } } catch (e) { return true; } @@ -1110,10 +1117,10 @@ ${chalk.cyan("?")} Your Prismic repository name`.replace("\n", ""), return { signature, documents, directoryPath: documentsDirectoryPath }; } - protected pushDataToPrismic(): Promise { + protected syncDataWithPrismic(): Promise { return listrRun([ { - title: "Pushing data to Prismic...", + title: "Syncing data with Prismic...", task: (_, parentTask) => listr([ { @@ -1209,7 +1216,7 @@ ${chalk.cyan("?")} Your Prismic repository name`.replace("\n", ""), task: async (_, task) => { assertExists( this.context.repository, - "Repository selection must be available through context to run `pushDataToPrismic`", + "Repository selection must be available through context to run `syncDataWithPrismic`", ); try { @@ -1219,7 +1226,6 @@ ${chalk.cyan("?")} Your Prismic repository name`.replace("\n", ""), documentsRead === undefined || documentsRead.documents.length === 0 ) { - parentTask.title = "Pushed data to Prismic"; task.skip("No document to push"); return; @@ -1261,9 +1267,7 @@ ${chalk.cyan("?")} Your Prismic repository name`.replace("\n", ""), }); task.title = "Pushed all documents"; - parentTask.title = "Pushed data to Prismic"; } catch { - parentTask.title = "Pushed data to Prismic"; task.skip("No document to push"); return; @@ -1285,7 +1289,41 @@ ${chalk.cyan("?")} Your Prismic repository name`.replace("\n", ""), } task.title = "Cleaned up data push artifacts"; - parentTask.title = "Pushed data to Prismic"; + }, + }, + { + title: "Pulling existing types...", + task: async (_, task) => { + const { ids, errors } = + await this.manager.customTypes.readCustomTypeLibrary(); + + if (errors.length > 0) { + // TODO: Provide better error message. + throw new Error( + `Failed to read custom type libraries: ${errors.join( + ", ", + )}`, + ); + } + + if (ids && ids.length > 0) { + task.skip("Types already exist"); + parentTask.title = "Synced data with Prismic"; + + return; + } + + const remoteTypes = + await this.manager.customTypes.fetchRemoteCustomTypes(); + + await Promise.all( + remoteTypes.map(async (model) => { + await this.manager.customTypes.createCustomType({ model }); + }), + ); + + task.title = "Pulled existing types"; + parentTask.title = "Synced data with Prismic"; }, }, ]), diff --git a/packages/init/test/SliceMachineInitProcess-pushDataToPrismic.test.ts b/packages/init/test/SliceMachineInitProcess-syncDataWithPrismic.test.ts similarity index 82% rename from packages/init/test/SliceMachineInitProcess-pushDataToPrismic.test.ts rename to packages/init/test/SliceMachineInitProcess-syncDataWithPrismic.test.ts index 1c1c3ee79a..2692ace973 100644 --- a/packages/init/test/SliceMachineInitProcess-pushDataToPrismic.test.ts +++ b/packages/init/test/SliceMachineInitProcess-syncDataWithPrismic.test.ts @@ -74,6 +74,7 @@ const mockAdapter = async ( sliceReadHookHandler: Mock; customTypeLibraryReadHookHandler: Mock; customTypeReadHookHandler: Mock; + customTypeCreateHookHandler: Mock; }; }> => { const sharedSliceModel = ctx.mockPrismic.model.sharedSlice({ @@ -109,12 +110,14 @@ const mockAdapter = async ( const customTypeReadHookHandler = vi.fn(() => { return { model: customTypeModel }; }); + const customTypeCreateHookHandler = vi.fn(); const adapter = createTestPlugin({ setup: ({ hook }) => { hook("slice-library:read", sliceLibraryReadHookHandler); hook("slice:read", sliceReadHookHandler); hook("custom-type-library:read", customTypeLibraryReadHookHandler); hook("custom-type:read", customTypeReadHookHandler); + hook("custom-type:create", customTypeCreateHookHandler); }, }); injectTestAdapter({ initProcess, adapter }); @@ -135,6 +138,7 @@ const mockAdapter = async ( sliceReadHookHandler, customTypeLibraryReadHookHandler, customTypeReadHookHandler, + customTypeCreateHookHandler, }, }; }; @@ -147,6 +151,10 @@ type MockPrismicAPIsArgs = { // eslint-disable-next-line @typescript-eslint/no-explicit-any customTypeModel: any; }; + remoteModels?: { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + customTypeModel: any[]; + }; documents?: Record; }; @@ -181,6 +189,9 @@ const mockPrismicAPIs = async ( async onCustomTypeGet(_req, res, ctx) { return res(ctx.status(404)); }, + async onCustomTypeGetAll(_req, res, ctx) { + return res(ctx.json(args.remoteModels?.customTypeModel ?? [])); + }, async onCustomTypeInsert(req, res, ctx) { const want = args.models.customTypeModel; const got = await req.json(); @@ -243,13 +254,39 @@ it("pushes data to Prismic", async (ctx) => { const { stdout } = await watchStd(() => { // @ts-expect-error - Accessing protected method - return initProcess.pushDataToPrismic(); + return initProcess.syncDataWithPrismic(); }); expect(stdout).toMatch(/Pushed all slices/); expect(stdout).toMatch(/Pushed all types/); expect(stdout).toMatch(/Pushed all documents/); - expect(stdout).toMatch(/Pushed data to Prismic/); + expect(stdout).toMatch(/Types already exist/); + expect(stdout).toMatch(/Synced data with Prismic/); +}); + +it("pulls data from Prismic", async (ctx) => { + const { models } = await mockAdapter(ctx, initProcess, { + empty: ["slice-library:read", "custom-type-library:read"], + }); + await mockPrismicAPIs(ctx, { + initProcess, + models, + documents: {}, + remoteModels: { + customTypeModel: [models.customTypeModel], + }, + }); + + const { stdout } = await watchStd(() => { + // @ts-expect-error - Accessing protected method + return initProcess.syncDataWithPrismic(); + }); + + expect(stdout).toMatch(/No slice to push/); + expect(stdout).toMatch(/No custom type to push/); + expect(stdout).toMatch(/No document to push/); + expect(stdout).toMatch(/Pulled existing types/); + expect(stdout).toMatch(/Synced data with Prismic/); }); it("skips pushing anything to Prismic when no-push flag is set", async (ctx) => { @@ -268,7 +305,7 @@ it("skips pushing anything to Prismic when no-push flag is set", async (ctx) => await watchStd(() => { // @ts-expect-error - Accessing protected method - return initProcess.pushDataToPrismic(); + return initProcess.syncDataWithPrismic(); }); expect(spiedManager.slices.pushSlice).not.toHaveBeenCalled(); @@ -285,7 +322,7 @@ it("pushes slices to Prismic", async (ctx) => { const { stdout } = await watchStd(() => { // @ts-expect-error - Accessing protected method - return initProcess.pushDataToPrismic(); + return initProcess.syncDataWithPrismic(); }); expect(spiedHookHandlers.sliceLibraryReadHookHandler).toHaveBeenCalledOnce(); @@ -309,7 +346,7 @@ it("skips pushing slices to Prismic when no-push-slices flag is set", async (ctx await watchStd(() => { // @ts-expect-error - Accessing protected method - return initProcess.pushDataToPrismic(); + return initProcess.syncDataWithPrismic(); }); expect(spiedHookHandlers.sliceLibraryReadHookHandler).not.toHaveBeenCalled(); @@ -333,7 +370,7 @@ it("skips pushing slices to Prismic when no-push flag is set", async (ctx) => { await watchStd(() => { // @ts-expect-error - Accessing protected method - return initProcess.pushDataToPrismic(); + return initProcess.syncDataWithPrismic(); }); expect(spiedHookHandlers.sliceLibraryReadHookHandler).not.toHaveBeenCalled(); @@ -350,7 +387,7 @@ it("skips pushing slices to Prismic when no slices are available", async (ctx) = const { stdout } = await watchStd(() => { // @ts-expect-error - Accessing protected method - return initProcess.pushDataToPrismic(); + return initProcess.syncDataWithPrismic(); }); expect(spiedHookHandlers.sliceLibraryReadHookHandler).toHaveBeenCalledOnce(); @@ -368,7 +405,7 @@ it("throws when it fails to read slice libraries", async (ctx) => { await expect( watchStd(() => { // @ts-expect-error - Accessing protected method - return initProcess.pushDataToPrismic(); + return initProcess.syncDataWithPrismic(); }), ).rejects.toMatch(/Failed to read slice libraries/); }); @@ -382,12 +419,13 @@ it("pushes types to Prismic", async (ctx) => { const { stdout } = await watchStd(() => { // @ts-expect-error - Accessing protected method - return initProcess.pushDataToPrismic(); + return initProcess.syncDataWithPrismic(); }); + // One for push, one for pull expect( spiedHookHandlers.customTypeLibraryReadHookHandler, - ).toHaveBeenCalledOnce(); + ).toHaveBeenCalledTimes(2); expect(spiedHookHandlers.customTypeReadHookHandler).toHaveBeenCalledOnce(); expect(spiedManager.customTypes.pushCustomType).toHaveBeenCalledOnce(); expect(stdout).toMatch(/Pushed all types/); @@ -409,12 +447,13 @@ it("skips pushing types to Prismic when no-push-custom-types flag is set", async await watchStd(() => { // @ts-expect-error - Accessing protected method - return initProcess.pushDataToPrismic(); + return initProcess.syncDataWithPrismic(); }); + // One for pull expect( spiedHookHandlers.customTypeLibraryReadHookHandler, - ).not.toHaveBeenCalled(); + ).toHaveBeenCalledOnce(); expect(spiedHookHandlers.customTypeReadHookHandler).not.toHaveBeenCalled(); expect(spiedManager.customTypes.pushCustomType).not.toHaveBeenCalled(); }); @@ -435,12 +474,13 @@ it("skips pushing types to Prismic when no-push flag is set", async (ctx) => { await watchStd(() => { // @ts-expect-error - Accessing protected method - return initProcess.pushDataToPrismic(); + return initProcess.syncDataWithPrismic(); }); + // One for pull expect( spiedHookHandlers.customTypeLibraryReadHookHandler, - ).not.toHaveBeenCalled(); + ).toHaveBeenCalledOnce(); expect(spiedHookHandlers.customTypeReadHookHandler).not.toHaveBeenCalled(); expect(spiedManager.customTypes.pushCustomType).not.toHaveBeenCalled(); }); @@ -454,18 +494,19 @@ it("skips pushing types to Prismic when no types are available", async (ctx) => const { stdout } = await watchStd(() => { // @ts-expect-error - Accessing protected method - return initProcess.pushDataToPrismic(); + return initProcess.syncDataWithPrismic(); }); + // One for push, one for pull expect( spiedHookHandlers.customTypeLibraryReadHookHandler, - ).toHaveBeenCalledOnce(); + ).toHaveBeenCalledTimes(2); expect(spiedHookHandlers.customTypeReadHookHandler).not.toHaveBeenCalled(); expect(spiedManager.customTypes.pushCustomType).not.toHaveBeenCalled(); expect(stdout).toMatch(/No custom type to push/); }); -it("throws when it fails to read slice libraries", async (ctx) => { +it("throws when it fails to read custom type libraries", async (ctx) => { const { models } = await mockAdapter(ctx, initProcess, { throwsOn: ["custom-type-library:read"], }); @@ -474,7 +515,7 @@ it("throws when it fails to read slice libraries", async (ctx) => { await expect( watchStd(() => { // @ts-expect-error - Accessing protected method - return initProcess.pushDataToPrismic(); + return initProcess.syncDataWithPrismic(); }), ).rejects.toMatch(/Failed to read custom type libraries/); }); @@ -488,7 +529,7 @@ it("pushes documents to Prismic", async (ctx) => { const { stdout } = await watchStd(() => { // @ts-expect-error - Accessing protected method - return initProcess.pushDataToPrismic(); + return initProcess.syncDataWithPrismic(); }); expect(spiedManager.prismicRepository.pushDocuments).toHaveBeenCalledOnce(); @@ -519,7 +560,7 @@ it("skips documents that cannot be parsed", async (ctx) => { const { stdout } = await watchStd(() => { // @ts-expect-error - Accessing protected method - return initProcess.pushDataToPrismic(); + return initProcess.syncDataWithPrismic(); }); expect(spiedManager.prismicRepository.pushDocuments).toHaveBeenCalledOnce(); @@ -543,7 +584,7 @@ it("skips pushing documents to Prismic when no-push-documents flag is set", asyn await watchStd(() => { // @ts-expect-error - Accessing protected method - return initProcess.pushDataToPrismic(); + return initProcess.syncDataWithPrismic(); }); expect(spiedManager.prismicRepository.pushDocuments).not.toHaveBeenCalled(); @@ -565,7 +606,7 @@ it("skips pushing documents to Prismic when no-push flag is set", async (ctx) => await watchStd(() => { // @ts-expect-error - Accessing protected method - return initProcess.pushDataToPrismic(); + return initProcess.syncDataWithPrismic(); }); expect(spiedManager.prismicRepository.pushDocuments).not.toHaveBeenCalled(); @@ -582,7 +623,7 @@ it("skips pushing documents to Prismic when no documents directory is available" const { stdout } = await watchStd(() => { // @ts-expect-error - Accessing protected method - return initProcess.pushDataToPrismic(); + return initProcess.syncDataWithPrismic(); }); expect(spiedManager.prismicRepository.pushDocuments).not.toHaveBeenCalled(); @@ -606,7 +647,7 @@ it("skips pushing documents to Prismic when no documents are available", async ( const { stdout } = await watchStd(() => { // @ts-expect-error - Accessing protected method - return initProcess.pushDataToPrismic(); + return initProcess.syncDataWithPrismic(); }); expect(spiedManager.prismicRepository.pushDocuments).not.toHaveBeenCalled(); @@ -615,28 +656,13 @@ it("skips pushing documents to Prismic when no documents are available", async ( // Cleanup -it("pushes data to Prismic", async (ctx) => { - const { models } = await mockAdapter(ctx, initProcess); - await mockPrismicAPIs(ctx, { initProcess, models }); - - const { stdout } = await watchStd(() => { - // @ts-expect-error - Accessing protected method - return initProcess.pushDataToPrismic(); - }); - - expect(stdout).toMatch(/Pushed all slices/); - expect(stdout).toMatch(/Pushed all types/); - // expect(stdout).toMatch(/Pushed all documents/); - expect(stdout).toMatch(/Pushed data to Prismic/); -}); - it("cleans up documents directory", async (ctx) => { const { models } = await mockAdapter(ctx, initProcess); await mockPrismicAPIs(ctx, { initProcess, models }); const { stdout } = await watchStd(() => { // @ts-expect-error - Accessing protected method - return initProcess.pushDataToPrismic(); + return initProcess.syncDataWithPrismic(); }); expect( @@ -659,7 +685,7 @@ it("does not throw if process cannot clean up documents directory", async (ctx) const { stdout } = await watchStd(() => { // @ts-expect-error - Accessing protected method - return initProcess.pushDataToPrismic(); + return initProcess.syncDataWithPrismic(); }); expect(stdout).toMatch(/Cleaned up data push artifacts/); @@ -675,9 +701,74 @@ it("throws if context is missing repository", async (ctx) => { await expect( watchStd(() => { // @ts-expect-error - Accessing protected method - return initProcess.pushDataToPrismic(); + return initProcess.syncDataWithPrismic(); }), ).rejects.toThrowErrorMatchingInlineSnapshot( - '"Repository selection must be available through context to run `pushDataToPrismic`"', + '"Repository selection must be available through context to run `syncDataWithPrismic`"', ); }); + +// Pull + +it("pulls types from Prismic", async (ctx) => { + const { models, spiedHookHandlers } = await mockAdapter(ctx, initProcess, { + empty: ["slice-library:read", "custom-type-library:read"], + }); + await mockPrismicAPIs(ctx, { + initProcess, + models, + documents: {}, + remoteModels: { + customTypeModel: [models.customTypeModel], + }, + }); + const spiedManager = spyManager(initProcess); + + const { stdout } = await watchStd(() => { + // @ts-expect-error - Accessing protected method + return initProcess.syncDataWithPrismic(); + }); + + // One for push, one for pull + expect( + spiedHookHandlers.customTypeLibraryReadHookHandler, + ).toHaveBeenCalledTimes(2); + expect( + spiedHookHandlers.customTypeCreateHookHandler, + ).toHaveBeenLastCalledWith( + { model: models.customTypeModel }, + expect.any(Object), + ); + expect(spiedManager.customTypes.fetchRemoteCustomTypes).toHaveBeenCalled(); + expect(spiedManager.customTypes.pushCustomType).not.toHaveBeenCalled(); + expect(stdout).toMatch(/Pulled existing types/); +}); + +it("skips pulling types if types already exist locally", async (ctx) => { + const { models, spiedHookHandlers } = await mockAdapter(ctx, initProcess); + await mockPrismicAPIs(ctx, { + initProcess, + models, + documents: {}, + remoteModels: { + customTypeModel: [models.customTypeModel], + }, + }); + const spiedManager = spyManager(initProcess); + + const { stdout } = await watchStd(() => { + // @ts-expect-error - Accessing protected method + return initProcess.syncDataWithPrismic(); + }); + + // One for push, one for pull + expect( + spiedHookHandlers.customTypeLibraryReadHookHandler, + ).toHaveBeenCalledTimes(2); + expect(spiedHookHandlers.customTypeCreateHookHandler).not.toHaveBeenCalled(); + expect( + spiedManager.customTypes.fetchRemoteCustomTypes, + ).not.toHaveBeenCalled(); + expect(spiedManager.customTypes.pushCustomType).toHaveBeenCalled(); + expect(stdout).toMatch(/Types already exist/); +}); diff --git a/packages/manager/src/managers/slices/SlicesManager.ts b/packages/manager/src/managers/slices/SlicesManager.ts index b68bf42143..a4a115b4d7 100644 --- a/packages/manager/src/managers/slices/SlicesManager.ts +++ b/packages/manager/src/managers/slices/SlicesManager.ts @@ -2,7 +2,12 @@ import * as t from "io-ts"; import * as prismicCustomTypesClient from "@prismicio/custom-types-client"; import { SharedSliceContent } from "@prismicio/types-internal/lib/content"; import { SliceComparator } from "@prismicio/types-internal/lib/customtypes/diff"; -import { SharedSlice } from "@prismicio/types-internal/lib/customtypes"; +import { + CompositeSlice, + LegacySlice, + SharedSlice, + Variation, +} from "@prismicio/types-internal/lib/customtypes"; import { CallHookReturnType, HookError, @@ -146,6 +151,26 @@ type SliceMachineManagerDeleteSliceArgs = { sliceID: string; }; +type SliceMachineManagerConvertLegacySliceToSharedSliceArgs = { + model: CompositeSlice | LegacySlice; + src: { + customTypeID: string; + tabID: string; + sliceZoneID: string; + sliceID: string; + }; + dest: { + libraryID: string; + sliceID: string; + variationName: string; + variationID: string; + }; +}; + +type SliceMachineManagerConvertLegacySliceToSharedSliceReturnType = { + errors: (DecodeError | HookError)[]; +}; + type SliceMachineManagerDeleteSliceReturnType = { errors: (DecodeError | HookError)[]; }; @@ -404,6 +429,108 @@ export class SlicesManager extends BaseManager { } } + async convertLegacySliceToSharedSlice( + args: SliceMachineManagerConvertLegacySliceToSharedSliceArgs, + ): Promise { + const errors: (DecodeError | HookError)[] = []; + + const { model: maybeExistingSlice } = await this.readSlice({ + libraryID: args.dest.libraryID, + sliceID: args.dest.sliceID, + }); + + const legacySliceAsVariation: Variation = { + id: args.dest.variationID, + name: args.dest.variationName, + description: args.dest.variationName, + imageUrl: "", + docURL: "", + version: "initial", + primary: {}, + items: {}, + }; + + switch (args.model.type) { + case "Slice": + legacySliceAsVariation.primary = args.model["non-repeat"]; + legacySliceAsVariation.items = args.model.repeat; + break; + + case "Group": + legacySliceAsVariation.items = args.model.config?.fields ?? {}; + break; + + default: + legacySliceAsVariation.primary = { [args.src.sliceID]: args.model }; + break; + } + + // Convert as a slice variation, or merge against an existing slice variation + if (maybeExistingSlice) { + const maybeVariation = maybeExistingSlice.variations.find( + (variation) => variation.id === args.dest.variationID, + ); + + // If we're not merging against an existing slice variation, then we need to insert the new variation + if (!maybeVariation) { + maybeExistingSlice.variations = [ + ...maybeExistingSlice.variations, + legacySliceAsVariation, + ]; + } + + maybeExistingSlice.legacyPaths ||= {}; + maybeExistingSlice.legacyPaths[ + `${args.src.customTypeID}::${args.src.sliceZoneID}::${args.src.sliceID}` + ] = args.dest.variationID; + + await this.updateSlice({ + libraryID: args.dest.libraryID, + model: maybeExistingSlice, + }); + } else { + // Convert to new shared slice + await this.createSlice({ + libraryID: args.dest.libraryID, + model: { + id: args.dest.sliceID, + type: "SharedSlice", + name: args.dest.sliceID, + legacyPaths: { + [`${args.src.customTypeID}::${args.src.sliceZoneID}::${args.src.sliceID}`]: + args.dest.variationID, + }, + variations: [legacySliceAsVariation], + }, + }); + } + + // Update source custom type + const { model: customType, errors: customTypeReadErrors } = + await this.customTypes.readCustomType({ + id: args.src.customTypeID, + }); + errors.push(...customTypeReadErrors); + + if (customType) { + const field = customType.json[args.src.tabID][args.src.sliceZoneID]; + + // Convert legacy slice definition in slice zone to shared slice reference + if (field.type === "Slices" && field.config?.choices) { + delete field.config.choices[args.src.sliceID]; + field.config.choices[args.dest.sliceID] = { + type: "SharedSlice", + }; + } + + const { errors: customTypeUpdateErrors } = + await this.customTypes.updateCustomType({ model: customType }); + errors.push(...customTypeUpdateErrors); + } + + return { errors }; + } + /** * @returns Record of variation IDs mapped to uploaded screenshot URLs. */ diff --git a/packages/manager/src/managers/telemetry/types.ts b/packages/manager/src/managers/telemetry/types.ts index 38b3fa5517..a5aa65198a 100644 --- a/packages/manager/src/managers/telemetry/types.ts +++ b/packages/manager/src/managers/telemetry/types.ts @@ -18,6 +18,7 @@ export const SegmentEventType = { customType_openAddFromTemplates: "custom-type:open-add-from-templates", customType_saved: "custom-type:saved", slice_created: "slice:created", + legacySlice_converted: "legacy-slice:converted", screenshotTaken: "screenshot-taken", changes_pushed: "changes:pushed", changes_limitReach: "changes:limit-reach", @@ -50,6 +51,8 @@ export const HumanSegmentEventType = { "SliceMachine Open Add from templates", [SegmentEventType.customType_saved]: "SliceMachine Custom Type Saved", [SegmentEventType.slice_created]: "SliceMachine Slice Created", + [SegmentEventType.legacySlice_converted]: + "SliceMachine Legacy Slice Converted", [SegmentEventType.screenshotTaken]: "SliceMachine Screenshot Taken", [SegmentEventType.changes_pushed]: "SliceMachine Changes Pushed", [SegmentEventType.changes_limitReach]: "SliceMachine Changes Limit Reach", @@ -183,6 +186,19 @@ type SliceCreatedSegmentEvent = SegmentEvent< { id: string; name: string; library: string; sliceTemplate?: string } >; +type LegacySliceConvertedSegmentEvent = SegmentEvent< + typeof SegmentEventType.legacySlice_converted, + { + id: string; + variation: string; + library: string; + conversionType: + | "as_new_slice" + | "as_new_variation" + | "merge_with_identical"; + } +>; + type ScreenshotTakenSegmentEvent = SegmentEvent< typeof SegmentEventType.screenshotTaken, { @@ -233,6 +249,7 @@ export type SegmentEvents = | CustomTypeOpenAddFromTemplatesEvent | CustomTypeSavedSegmentEvent | SliceCreatedSegmentEvent + | LegacySliceConvertedSegmentEvent | ScreenshotTakenSegmentEvent | ChangesPushedSegmentEvent | ChangesLimitReachSegmentEvent diff --git a/packages/manager/test/SliceMachineManager-slices-convertLegacySliceToSharedSlice.test.ts b/packages/manager/test/SliceMachineManager-slices-convertLegacySliceToSharedSlice.test.ts new file mode 100644 index 0000000000..b7565a265c --- /dev/null +++ b/packages/manager/test/SliceMachineManager-slices-convertLegacySliceToSharedSlice.test.ts @@ -0,0 +1,485 @@ +import { TestContext, expect, it, vi } from "vitest"; + +import { + CompositeSlice, + CustomType, + LegacySlice, + SharedSliceRef, +} from "@prismicio/types-internal/lib/customtypes"; + +import { createTestPlugin } from "./__testutils__/createTestPlugin"; +import { createTestProject } from "./__testutils__/createTestProject"; +import { expectHookHandlerToHaveBeenCalledWithData } from "./__testutils__/expectHookHandlerToHaveBeenCalledWithData"; + +import { createSliceMachineManager } from "../src"; + +const baseSrc = { + customTypeID: "ct_foo", + tabID: "Main", + sliceZoneID: "sliceZone_bar", + sliceID: "slice_qux", +}; + +const baseDest = { + libraryID: "library_foo", + sliceID: "slice_bar", + variationName: "Default", + variationID: "default", +}; + +const mockCustomType = ({ + ctx, + model, + src, + extraSlices, +}: { + ctx: TestContext; + model: CompositeSlice | LegacySlice; + src: typeof baseSrc; + extraSlices?: Record; +}): CustomType => { + return ctx.mockPrismic.model.customType({ + id: src.customTypeID, + fields: { + [src.sliceZoneID]: ctx.mockPrismic.model.sliceZone({ + choices: { + // @prismicio/mock doesn't know about legacy slices + [src.sliceID]: model as CompositeSlice, + ...(extraSlices as Record), + }, + }), + }, + }); +}; + +it("converts non-repetable legacy slice as a new shared slice", async (ctx) => { + const model = ctx.mockPrismic.model.keyText(); + const src = { ...baseSrc }; + const dest = { ...baseDest }; + const customType = mockCustomType({ ctx, model, src }); + + const customTypeUpdateHookHandler = vi.fn(); + const sliceCreateHookHandler = vi.fn(); + const adapter = createTestPlugin({ + setup: ({ hook }) => { + hook( + "custom-type:read", + vi.fn().mockResolvedValue({ model: customType }), + ); + hook("custom-type:update", customTypeUpdateHookHandler); + hook("slice:read", vi.fn().mockResolvedValue({ error: [] })); + hook("slice:create", sliceCreateHookHandler); + hook("slice:asset:read", vi.fn()); + hook("slice:asset:update", vi.fn()); + }, + }); + const cwd = await createTestProject({ adapter }); + const manager = createSliceMachineManager({ + nativePlugins: { [adapter.meta.name]: adapter }, + cwd, + }); + + await manager.plugins.initPlugins(); + + const res = await manager.slices.convertLegacySliceToSharedSlice({ + model, + src, + dest, + }); + + expectHookHandlerToHaveBeenCalledWithData(sliceCreateHookHandler, { + libraryID: dest.libraryID, + model: expect.objectContaining({ + id: dest.sliceID, + type: "SharedSlice", + legacyPaths: { + [`${src.customTypeID}::${src.sliceZoneID}::${src.sliceID}`]: + dest.variationID, + }, + variations: [ + expect.objectContaining({ + id: dest.variationID, + primary: { [src.sliceID]: model }, + items: {}, + }), + ], + }), + }); + expectHookHandlerToHaveBeenCalledWithData(customTypeUpdateHookHandler, { + model: expect.objectContaining({ + id: src.customTypeID, + json: { + [src.tabID]: { + [src.sliceZoneID]: expect.objectContaining({ + config: expect.objectContaining({ + choices: { + [dest.sliceID]: { + type: "SharedSlice", + }, + }, + }), + }), + }, + }, + }), + }); + expect(res).toStrictEqual({ + errors: [], + }); +}); + +it("converts repetable legacy slice as a new shared slice", async (ctx) => { + const model = ctx.mockPrismic.model.group({ + fields: { + foo: ctx.mockPrismic.model.keyText(), + bar: ctx.mockPrismic.model.keyText(), + }, + }); + const src = { ...baseSrc }; + const dest = { ...baseDest }; + const customType = mockCustomType({ ctx, model, src }); + + const customTypeUpdateHookHandler = vi.fn(); + const sliceCreateHookHandler = vi.fn(); + const adapter = createTestPlugin({ + setup: ({ hook }) => { + hook( + "custom-type:read", + vi.fn().mockResolvedValue({ model: customType }), + ); + hook("custom-type:update", customTypeUpdateHookHandler); + hook("slice:read", vi.fn().mockResolvedValue({ error: [] })); + hook("slice:create", sliceCreateHookHandler); + hook("slice:asset:read", vi.fn()); + hook("slice:asset:update", vi.fn()); + }, + }); + const cwd = await createTestProject({ adapter }); + const manager = createSliceMachineManager({ + nativePlugins: { [adapter.meta.name]: adapter }, + cwd, + }); + + await manager.plugins.initPlugins(); + + const res = await manager.slices.convertLegacySliceToSharedSlice({ + model, + src, + dest, + }); + + expectHookHandlerToHaveBeenCalledWithData(sliceCreateHookHandler, { + libraryID: dest.libraryID, + model: expect.objectContaining({ + id: dest.sliceID, + type: "SharedSlice", + legacyPaths: { + [`${src.customTypeID}::${src.sliceZoneID}::${src.sliceID}`]: + dest.variationID, + }, + variations: [ + expect.objectContaining({ + id: dest.variationID, + primary: {}, + items: model.config?.fields, + }), + ], + }), + }); + expectHookHandlerToHaveBeenCalledWithData(customTypeUpdateHookHandler, { + model: expect.objectContaining({ + id: src.customTypeID, + json: { + [src.tabID]: { + [src.sliceZoneID]: expect.objectContaining({ + config: expect.objectContaining({ + choices: { + [dest.sliceID]: { + type: "SharedSlice", + }, + }, + }), + }), + }, + }, + }), + }); + expect(res).toStrictEqual({ + errors: [], + }); +}); + +it("converts composite slice as a new shared slice", async (ctx) => { + const model = ctx.mockPrismic.model.slice({ + nonRepeatFields: { foo: ctx.mockPrismic.model.keyText() }, + repeatFields: { bar: ctx.mockPrismic.model.keyText() }, + }); + const src = { ...baseSrc }; + const dest = { ...baseDest }; + const customType = mockCustomType({ ctx, model, src }); + + const customTypeUpdateHookHandler = vi.fn(); + const sliceCreateHookHandler = vi.fn(); + const adapter = createTestPlugin({ + setup: ({ hook }) => { + hook( + "custom-type:read", + vi.fn().mockResolvedValue({ model: customType }), + ); + hook("custom-type:update", customTypeUpdateHookHandler); + hook("slice:read", vi.fn().mockResolvedValue({ error: [] })); + hook("slice:create", sliceCreateHookHandler); + hook("slice:asset:read", vi.fn()); + hook("slice:asset:update", vi.fn()); + }, + }); + const cwd = await createTestProject({ adapter }); + const manager = createSliceMachineManager({ + nativePlugins: { [adapter.meta.name]: adapter }, + cwd, + }); + + await manager.plugins.initPlugins(); + + const res = await manager.slices.convertLegacySliceToSharedSlice({ + model, + src, + dest, + }); + + expectHookHandlerToHaveBeenCalledWithData(sliceCreateHookHandler, { + libraryID: dest.libraryID, + model: expect.objectContaining({ + id: dest.sliceID, + type: "SharedSlice", + legacyPaths: { + [`${src.customTypeID}::${src.sliceZoneID}::${src.sliceID}`]: + dest.variationID, + }, + variations: [ + expect.objectContaining({ + id: dest.variationID, + primary: model["non-repeat"], + items: model.repeat, + }), + ], + }), + }); + expectHookHandlerToHaveBeenCalledWithData(customTypeUpdateHookHandler, { + model: expect.objectContaining({ + id: src.customTypeID, + json: { + [src.tabID]: { + [src.sliceZoneID]: expect.objectContaining({ + config: expect.objectContaining({ + choices: { + [dest.sliceID]: { + type: "SharedSlice", + }, + }, + }), + }), + }, + }, + }), + }); + expect(res).toStrictEqual({ + errors: [], + }); +}); + +it("converts composite slice as a new variation of an existing shared slice", async (ctx) => { + const existingSharedSliceModel = ctx.mockPrismic.model.sharedSlice({ + variations: [ctx.mockPrismic.model.sharedSliceVariation()], + }); + const model = ctx.mockPrismic.model.slice({ + nonRepeatFields: { foo: ctx.mockPrismic.model.keyText() }, + repeatFields: { bar: ctx.mockPrismic.model.keyText() }, + }); + const src = { ...baseSrc }; + const dest = { ...baseDest, sliceID: existingSharedSliceModel.id }; + const customType = mockCustomType({ + ctx, + model, + src, + extraSlices: { + [existingSharedSliceModel.id]: existingSharedSliceModel, + }, + }); + + const customTypeUpdateHookHandler = vi.fn(); + const sliceUpdateHookHandler = vi.fn(); + const adapter = createTestPlugin({ + setup: ({ hook }) => { + hook( + "custom-type:read", + vi.fn().mockResolvedValue({ model: customType }), + ); + hook("custom-type:update", customTypeUpdateHookHandler); + hook( + "slice:read", + vi.fn().mockResolvedValue({ model: existingSharedSliceModel }), + ); + hook("slice:update", sliceUpdateHookHandler); + hook("slice:asset:read", vi.fn()); + hook("slice:asset:update", vi.fn()); + }, + }); + const cwd = await createTestProject({ adapter }); + const manager = createSliceMachineManager({ + nativePlugins: { [adapter.meta.name]: adapter }, + cwd, + }); + + await manager.plugins.initPlugins(); + + const res = await manager.slices.convertLegacySliceToSharedSlice({ + model, + src, + dest, + }); + + expectHookHandlerToHaveBeenCalledWithData(sliceUpdateHookHandler, { + libraryID: dest.libraryID, + model: expect.objectContaining({ + ...existingSharedSliceModel, + legacyPaths: { + [`${src.customTypeID}::${src.sliceZoneID}::${src.sliceID}`]: + dest.variationID, + }, + variations: [ + existingSharedSliceModel.variations[0], + expect.objectContaining({ + id: dest.variationID, + primary: model["non-repeat"], + items: model.repeat, + }), + ], + }), + }); + expectHookHandlerToHaveBeenCalledWithData(customTypeUpdateHookHandler, { + model: expect.objectContaining({ + id: src.customTypeID, + json: { + [src.tabID]: { + [src.sliceZoneID]: expect.objectContaining({ + config: expect.objectContaining({ + choices: { + [dest.sliceID]: { + type: "SharedSlice", + }, + }, + }), + }), + }, + }, + }), + }); + expect(res).toStrictEqual({ + errors: [], + }); +}); + +it("converts composite slice by merging it with an existing shared slice variation", async (ctx) => { + const existingSharedSliceModel = ctx.mockPrismic.model.sharedSlice({ + variations: [ + ctx.mockPrismic.model.sharedSliceVariation({ + primaryFields: { foo: ctx.mockPrismic.model.keyText() }, + itemsFields: { bar: ctx.mockPrismic.model.keyText() }, + }), + ], + }); + const model = ctx.mockPrismic.model.slice(); + const src = { ...baseSrc }; + const dest = { + ...baseDest, + sliceID: existingSharedSliceModel.id, + variationID: existingSharedSliceModel.variations[0].id, + }; + const customType = mockCustomType({ + ctx, + model, + src, + extraSlices: { + [existingSharedSliceModel.id]: existingSharedSliceModel, + }, + }); + + const customTypeUpdateHookHandler = vi.fn(); + const sliceUpdateHookHandler = vi.fn(); + const adapter = createTestPlugin({ + setup: ({ hook }) => { + hook( + "custom-type:read", + vi.fn().mockResolvedValue({ model: customType }), + ); + hook("custom-type:update", customTypeUpdateHookHandler); + hook( + "slice:read", + vi.fn().mockResolvedValue({ model: existingSharedSliceModel }), + ); + hook("slice:update", sliceUpdateHookHandler); + hook("slice:asset:read", vi.fn()); + hook("slice:asset:update", vi.fn()); + }, + }); + const cwd = await createTestProject({ adapter }); + const manager = createSliceMachineManager({ + nativePlugins: { [adapter.meta.name]: adapter }, + cwd, + }); + + await manager.plugins.initPlugins(); + + const res = await manager.slices.convertLegacySliceToSharedSlice({ + model, + src, + dest, + }); + + expectHookHandlerToHaveBeenCalledWithData(sliceUpdateHookHandler, { + libraryID: dest.libraryID, + model: { + ...existingSharedSliceModel, + legacyPaths: { + [`${src.customTypeID}::${src.sliceZoneID}::${src.sliceID}`]: + dest.variationID, + }, + variations: [existingSharedSliceModel.variations[0]], + }, + }); + expectHookHandlerToHaveBeenCalledWithData(customTypeUpdateHookHandler, { + model: expect.objectContaining({ + id: src.customTypeID, + json: { + [src.tabID]: { + [src.sliceZoneID]: expect.objectContaining({ + config: expect.objectContaining({ + choices: { + [dest.sliceID]: { + type: "SharedSlice", + }, + }, + }), + }), + }, + }, + }), + }); + expect(res).toStrictEqual({ + errors: [], + }); +}); + +it("throws if plugins have not been initialized", async (ctx) => { + const cwd = await createTestProject(); + const manager = createSliceMachineManager({ cwd }); + + await expect(async () => { + await manager.slices.convertLegacySliceToSharedSlice({ + model: ctx.mockPrismic.model.slice(), + src: baseSrc, + dest: baseDest, + }); + }).rejects.toThrow(/plugins have not been initialized/i); +}); diff --git a/packages/slice-machine/lib/builders/CustomTypeBuilder/SliceZone/List.tsx b/packages/slice-machine/lib/builders/CustomTypeBuilder/SliceZone/List.tsx index e194014af7..ca42250cea 100644 --- a/packages/slice-machine/lib/builders/CustomTypeBuilder/SliceZone/List.tsx +++ b/packages/slice-machine/lib/builders/CustomTypeBuilder/SliceZone/List.tsx @@ -16,12 +16,18 @@ import { SharedSliceViewCard } from "@src/features/slices/sliceCards/SharedSlice interface SlicesListProps { format: CustomTypeFormat; slices: ReadonlyArray; + path: { + customTypeID: string; + tabID: string; + sliceZoneID: string; + }; onRemoveSharedSlice: (sliceId: string) => void; } export const SlicesList: React.FC = ({ slices, format, + path, onRemoveSharedSlice, }) => { const hasLegacySlices = slices.some((slice) => slice.type !== "SharedSlice"); @@ -35,8 +41,8 @@ export const SlicesList: React.FC = ({ `This ${customTypesMessages.name({ start: false, plural: false, - })} contains Slices that are incompatible.`, - ToasterType.WARNING + })} contains legacy slices that can be upgraded.`, + ToasterType.INFO ); // eslint-disable-next-line react-hooks/exhaustive-deps }, [hasLegacySlices]); @@ -45,15 +51,14 @@ export const SlicesList: React.FC = ({ - slice.type === "Slice" + slice.type !== "SharedSlice" ? (slice.payload as NonSharedSliceInSliceZone).key : (slice.payload as ComponentUI).model.name } renderElem={(slice) => { - if (slice.type === "Slice") { - const nonSharedSlice = (slice.payload as NonSharedSliceInSliceZone) - .value; - return ; + if (slice.type !== "SharedSlice") { + const nonSharedSlice = slice.payload as NonSharedSliceInSliceZone; + return ; } else { const sharedSlice = slice.payload as ComponentUI; return ( diff --git a/packages/slice-machine/lib/builders/CustomTypeBuilder/SliceZone/index.tsx b/packages/slice-machine/lib/builders/CustomTypeBuilder/SliceZone/index.tsx index 3c3b5e541c..a98200827a 100644 --- a/packages/slice-machine/lib/builders/CustomTypeBuilder/SliceZone/index.tsx +++ b/packages/slice-machine/lib/builders/CustomTypeBuilder/SliceZone/index.tsx @@ -75,19 +75,15 @@ const mapAvailableAndSharedSlices = ( return { ...acc, notFound: [...acc.notFound, { key }] }; } - // Legacy Slice - else if (value.type === "Slice") { - return { - ...acc, - slicesInSliceZone: [ - ...acc.slicesInSliceZone, - { type: "Slice", payload: { key, value } }, - ], - }; - } - // Really old legacy Slice are ignored - return acc; + // Composite and legacy Slice + return { + ...acc, + slicesInSliceZone: [ + ...acc.slicesInSliceZone, + { type: "Slice", payload: { key, value } }, + ], + }; }, { slicesInSliceZone: [], notFound: [] } ); @@ -154,6 +150,7 @@ const SliceZone: React.FC = ({ .filter((e) => e.type === "SharedSlice") .map((e) => e.payload) as ReadonlyArray; + /* Preserve these keys in SliceZone */ const availableSlicesToAdd = availableSlices.filter( (slice) => !sharedSlicesInSliceZone.some( @@ -284,6 +281,11 @@ const SliceZone: React.FC = ({ diff --git a/packages/slice-machine/src/domain/slice.ts b/packages/slice-machine/src/domain/slice.ts index a437cb4e3d..acf2838db1 100644 --- a/packages/slice-machine/src/domain/slice.ts +++ b/packages/slice-machine/src/domain/slice.ts @@ -6,13 +6,13 @@ import type { import type { ComponentUI } from "@lib/models/common/ComponentUI"; import type { VariationSM } from "@lib/models/common/Slice"; -export type NonSharedSlice = CompositeSlice | LegacySlice; - export function countMissingScreenshots(slice: ComponentUI): number { return slice.model.variations.length - Object.keys(slice.screenshots).length; } -export function getNonSharedSliceLabel(slice: NonSharedSlice): string { +export function getNonSharedSliceLabel( + slice: CompositeSlice | LegacySlice +): string { return ( slice.config?.label ?? (slice.type === "Group" || @@ -30,3 +30,51 @@ export function getScreenshotUrl( ): string | undefined { return slice.screenshots[variation.id]?.url; } + +export function getFieldMappingFingerprint( + slice: LegacySlice | CompositeSlice | VariationSM, + sliceName: string +): { + primary: string; + items: string; +} { + const primary: Record = {}; + const items: Record = {}; + + if ("type" in slice) { + if (slice.type === "Slice") { + for (const key in slice["non-repeat"]) { + primary[key] = slice["non-repeat"][key].type; + } + for (const key in slice.repeat) { + items[key] = slice.repeat[key].type; + } + } else if (slice.type === "Group") { + for (const key in slice.config?.fields) { + items[key] = slice.config?.fields[key].type ?? ""; + } + } else { + primary[sliceName] = slice.type; + } + } else if ("id" in slice) { + for (const { key, value } of slice.primary ?? []) { + primary[key] = value.type; + } + for (const { key, value } of slice.items ?? []) { + items[key] = value.type; + } + } + + return { + primary: JSON.stringify( + Object.keys(primary) + .sort() + .map((key) => [key, primary[key]]) + ), + items: JSON.stringify( + Object.keys(items) + .sort() + .map((key) => [key, items[key]]) + ), + }; +} diff --git a/packages/slice-machine/src/features/slices/convertLegacySlice/ConvertLegacySliceAsNewSliceDialog.tsx b/packages/slice-machine/src/features/slices/convertLegacySlice/ConvertLegacySliceAsNewSliceDialog.tsx new file mode 100644 index 0000000000..92e5f25331 --- /dev/null +++ b/packages/slice-machine/src/features/slices/convertLegacySlice/ConvertLegacySliceAsNewSliceDialog.tsx @@ -0,0 +1,151 @@ +import type { FC } from "react"; +import { useSelector } from "react-redux"; +import { Formik } from "formik"; +import { + Box, + Dialog, + DialogActions, + DialogContent, + DialogHeader, + ScrollArea, + FormInput, + Text, + Select, + SelectItem, +} from "@prismicio/editor-ui"; + +import { SliceMachineStoreType } from "@src/redux/type"; +import { getRemoteSlices } from "@src/modules/slices"; +import { pascalize } from "@lib/utils/str"; +import { validateSliceModalValues as validateAsNewSliceValues } from "@components/Forms/formsValidator"; + +import * as styles from "./ConvertLegacySliceButton.css"; +import { DialogProps } from "./types"; + +export const ConvertLegacySliceAsNewSliceDialog: FC = ({ + isOpen, + close, + onSubmit, + isLoading, + slice, + libraries, +}) => { + const { remoteSlices } = useSelector((store: SliceMachineStoreType) => ({ + remoteSlices: getRemoteSlices(store), + })); + + return ( + !open && close()} + size={{ width: 448, height: "auto" }} + > + + + { + return validateAsNewSliceValues(values, libraries, remoteSlices); + }} + onSubmit={(values) => { + onSubmit({ libraryID: values.from, sliceID: values.sliceName }); + }} + > + {(formik) => { + return ( +
+ + + + This will create a new slice with the same fields. The new + slice will replace the legacy slice in all of your types, + and the existing slice content will be re-mapped to the + new slice. + + + This will not migrate your component. You will need to do + that manually. + + + + + void formik.setFieldValue( + "sliceName", + value.slice(0, 30) + ) + } + data-cy="slice-name-input" + /> + + A display name for the slice + + + + + + + The library where we'll store your slice + + + + void formik.submitForm(), + loading: isLoading, + disabled: !formik.isValid, + }} + cancel={{ text: "Cancel" }} + /> + +
+ ); + }} +
+
+
+ ); +}; diff --git a/packages/slice-machine/src/features/slices/convertLegacySlice/ConvertLegacySliceAsNewVariationDialog.tsx b/packages/slice-machine/src/features/slices/convertLegacySlice/ConvertLegacySliceAsNewVariationDialog.tsx new file mode 100644 index 0000000000..06f0a83090 --- /dev/null +++ b/packages/slice-machine/src/features/slices/convertLegacySlice/ConvertLegacySliceAsNewVariationDialog.tsx @@ -0,0 +1,233 @@ +import { useState, type FC } from "react"; +import { Formik } from "formik"; +import { + Box, + Dialog, + DialogActions, + DialogContent, + DialogHeader, + ScrollArea, + FormInput, + Text, + Select, + SelectItem, +} from "@prismicio/editor-ui"; + +import { Variation } from "@models/common/Variation"; +import { LibraryUI } from "@models/common/LibraryUI"; + +import * as styles from "./ConvertLegacySliceButton.css"; +import { DialogProps } from "./types"; + +type FormValues = { + libraryID: string; + sliceID: string; + variationID: string; + variationName: string; +}; + +export const ConvertLegacySliceAsNewVariationDialog: FC = ({ + isOpen, + close, + onSubmit, + isLoading, + slice, + sliceName, + libraries, + localSharedSlices, +}) => { + const [inferIDFromName, setInferIDFromName] = useState(true); + + return ( + !open && close()} + size={{ width: 448, height: "auto" }} + > + + + { + return validateAsNewVariationValues(values, libraries); + }} + onSubmit={(values) => { + onSubmit(values); + }} + > + {(formik) => { + return ( +
+ + + + If you have multiple slices that are similar, you can + combine them as variations of the same slice. + + + + + + Choose the slice to which you would like to add this + variation. + + + + + { + const values = { + ...formik.values, + variationName: value.slice(0, 30), + }; + + if (inferIDFromName) { + values.variationID = Variation.generateId( + values.variationName + ); + } + + formik.setValues(values, true); + }} + data-cy="variation-name-input" + /> + + + + { + setInferIDFromName(false); + void formik.setFieldValue( + "variationID", + Variation.generateId(value.slice(0, 30)) + ); + }} + data-cy="variation-id-input" + /> + + + void formik.submitForm(), + loading: isLoading, + disabled: !formik.isValid, + }} + cancel={{ text: "Cancel" }} + /> + +
+ ); + }} +
+
+
+ ); +}; + +const validateAsNewVariationValues = ( + values: FormValues, + libraries: readonly LibraryUI[] +): Partial> => { + const errors: Partial> = {}; + + if (!values.libraryID) { + errors.libraryID = "Cannot be empty."; + } + const library = libraries.find( + (library) => library.path === values.libraryID + ); + // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions + if (!errors.libraryID && !library) { + errors.libraryID = "Does not exist."; + } + + if (!values.sliceID) { + errors.sliceID = "Cannot be empty."; + } + const slice = library?.components.find( + (component) => component.model.id === values.sliceID + ); + // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions + if (!errors.sliceID && !slice) { + errors.sliceID = "Does not exist."; + } + + if (!values.variationName) { + errors.variationName = "Cannot be empty."; + } + + if (!values.variationID) { + errors.variationID = "Cannot be empty."; + } else { + const variationIDs = + slice?.model.variations.map((variation) => variation.id) ?? []; + + if (variationIDs.includes(values.variationID)) { + errors.variationID = "Slice variation ID is already taken."; + } + } + + return errors; +}; diff --git a/packages/slice-machine/src/features/slices/convertLegacySlice/ConvertLegacySliceButton.css.ts b/packages/slice-machine/src/features/slices/convertLegacySlice/ConvertLegacySliceButton.css.ts new file mode 100644 index 0000000000..cffaa4cbf8 --- /dev/null +++ b/packages/slice-machine/src/features/slices/convertLegacySlice/ConvertLegacySliceButton.css.ts @@ -0,0 +1,15 @@ +import { sprinkles } from "@prismicio/editor-ui"; + +export const scrollArea = sprinkles({ + height: "100%", + display: "flex", + gap: 8, + paddingInline: 16, + paddingBlock: 16, +}); + +export const label = sprinkles({ + display: "inline-flex", + alignItems: "center", + gap: 4, +}); diff --git a/packages/slice-machine/src/features/slices/convertLegacySlice/ConvertLegacySliceButton.tsx b/packages/slice-machine/src/features/slices/convertLegacySlice/ConvertLegacySliceButton.tsx new file mode 100644 index 0000000000..7ce788bbc9 --- /dev/null +++ b/packages/slice-machine/src/features/slices/convertLegacySlice/ConvertLegacySliceButton.tsx @@ -0,0 +1,268 @@ +import { useMemo, useState, type FC } from "react"; +import { useSelector } from "react-redux"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, + Icon, + Button, +} from "@prismicio/editor-ui"; + +import { NonSharedSliceInSliceZone } from "@models/common/CustomType/sliceZone"; +import { ComponentUI } from "@models/common/ComponentUI"; +import { CustomTypes } from "@models/common/CustomType"; +import { getLibraries } from "@src/modules/slices"; +import { SliceMachineStoreType } from "@src/redux/type"; +import { managerClient } from "@src/managerClient"; +import { getState, telemetry } from "@src/apiClient"; +import useSliceMachineActions from "@src/modules/useSliceMachineActions"; +import { ToasterType } from "@src/modules/toaster"; +import { getFieldMappingFingerprint } from "@src/domain/slice"; + +import { NonSharedSliceViewCardProps } from "../sliceCards/NonSharedSliceViewCard"; +import { ConvertLegacySliceAsNewSliceDialog } from "./ConvertLegacySliceAsNewSliceDialog"; +import { ConvertLegacySliceAsNewVariationDialog } from "./ConvertLegacySliceAsNewVariationDialog"; +import { ConvertLegacySliceMergeWithIdenticalDialog } from "./ConvertLegacySliceMergeWithIdenticalDialog"; +import { + ConvertLegacySliceAndTrackArgs, + IdenticalSlice, + LegacySliceConversionType, +} from "./types"; + +type ConvertLegacySliceButtonProps = NonSharedSliceViewCardProps; + +export const ConvertLegacySliceButton: FC = ({ + slice, + path, +}) => { + const { + refreshState, + openToaster, + initCustomTypeStore, + saveCustomTypeSuccess, + } = useSliceMachineActions(); + + const [isLoading, setIsLoading] = useState(false); + const [dialog, setDialog] = useState(); + + const { libraries: allLibraries } = useSelector( + (store: SliceMachineStoreType) => ({ + libraries: getLibraries(store), + }) + ); + + const sliceName = + slice.value.type === "Slice" + ? slice.value.fieldset ?? slice.key + : slice.key; + const libraries = allLibraries.filter((library) => library.isLocal); + const localSharedSlices = libraries + .map((library) => library.components) + .flat(); + const identicalSlices = useIdenticalSlices( + slice, + sliceName, + localSharedSlices + ); + + const convertLegacySliceAndTrack = async ( + args: ConvertLegacySliceAndTrackArgs + ) => { + if (!dialog) { + return; + } + + setIsLoading(true); + + void telemetry.track({ + event: "legacy-slice:converted", + id: args.sliceID, + variation: args.variationID ?? "default", + library: args.libraryID, + conversionType: dialog, + }); + + const { errors } = + await managerClient.slices.convertLegacySliceToSharedSlice({ + model: slice.value, + src: { + ...path, + sliceID: slice.key, + }, + dest: { + libraryID: args.libraryID, + sliceID: args.sliceID, + variationName: args.variationName ?? "Default", + variationID: args.variationID ?? "default", + }, + }); + + if (errors.length) { + console.error(`Could not convert slice \`${sliceName}\``, errors); + + openToaster( + `Could not convert slice \`${sliceName}\``, + ToasterType.ERROR + ); + + throw errors; + } + + const { model: customType, errors: customTypeReadErrors } = + await managerClient.customTypes.readCustomType({ + id: path.customTypeID, + }); + + if (customTypeReadErrors.length || !customType) { + console.error( + `Could not refresh custom type view \`${path.customTypeID}\``, + customTypeReadErrors + ); + + openToaster( + `Could not refresh custom type view \`${path.customTypeID}\``, + ToasterType.ERROR + ); + + return; + } + + // TODO(DT-1453): Remove the need of the global getState + const serverState = await getState(); + // Update Redux store + refreshState(serverState); + + setIsLoading(false); + setDialog(undefined); + switch (dialog) { + case "as_new_slice": + openToaster( + `${sliceName} has been upgraded to a new slice ${args.libraryID} > ${args.sliceID}`, + ToasterType.SUCCESS + ); + break; + + case "as_new_variation": + openToaster( + `${sliceName} has been converted as a variation of ${args.libraryID} > ${args.sliceID}`, + ToasterType.SUCCESS + ); + break; + + case "merge_with_identical": + default: + openToaster( + `${sliceName} has been merged with ${args.libraryID} > ${args.sliceID}`, + ToasterType.SUCCESS + ); + break; + } + + const customTypeSM = CustomTypes.toSM(customType); + initCustomTypeStore(customTypeSM, customTypeSM); + saveCustomTypeSuccess(customType); + }; + + const formProps = { + path, + slice, + sliceName, + libraries, + localSharedSlices, + identicalSlices, + close: () => setDialog(undefined), + onSubmit: convertLegacySliceAndTrack, + isLoading, + }; + + return ( + <> + + + + + + } + description="Use it with new types" + onSelect={() => setDialog("as_new_slice")} + > + Upgrade slice + + } + description="Add it to another slice" + onSelect={() => setDialog("as_new_variation")} + disabled={!localSharedSlices.length} + > + Convert to slice variation + + } + description="Combine identical slices" + onSelect={() => setDialog("merge_with_identical")} + disabled={!identicalSlices.length} + > + Merge with another slice + + + + + + + + ); +}; + +const useIdenticalSlices = ( + slice: NonSharedSliceInSliceZone, + sliceName: string, + localSharedSlices: ComponentUI[] +) => { + return useMemo(() => { + const results: IdenticalSlice[] = []; + + const sliceFields = getFieldMappingFingerprint(slice.value, sliceName); + + for (const sharedSlice of localSharedSlices) { + for (const variation of sharedSlice.model.variations) { + const variationFields = getFieldMappingFingerprint( + variation, + sharedSlice.model.name + ); + + if ( + sliceFields.primary === variationFields.primary && + sliceFields.items === variationFields.items + ) { + results.push({ + libraryID: sharedSlice.from, + sliceID: sharedSlice.model.id, + variationID: variation.id, + path: `${sharedSlice.from}::${sharedSlice.model.id}::${variation.id}`, + }); + } + } + } + + return results; + }, [slice, sliceName, localSharedSlices]); +}; diff --git a/packages/slice-machine/src/features/slices/convertLegacySlice/ConvertLegacySliceMergeWithIdenticalDialog.tsx b/packages/slice-machine/src/features/slices/convertLegacySlice/ConvertLegacySliceMergeWithIdenticalDialog.tsx new file mode 100644 index 0000000000..2a41dd873a --- /dev/null +++ b/packages/slice-machine/src/features/slices/convertLegacySlice/ConvertLegacySliceMergeWithIdenticalDialog.tsx @@ -0,0 +1,106 @@ +import type { FC } from "react"; +import { Formik } from "formik"; +import { + Box, + Dialog, + DialogActions, + DialogContent, + DialogHeader, + ScrollArea, + Text, + Select, + SelectItem, +} from "@prismicio/editor-ui"; + +import * as styles from "./ConvertLegacySliceButton.css"; +import { DialogProps } from "./types"; + +export const ConvertLegacySliceMergeWithIdenticalDialog: FC = ({ + isOpen, + close, + onSubmit, + isLoading, + identicalSlices, +}) => { + return ( + !open && close()} + size={{ width: 448, height: "auto" }} + > + + + { + if (!values.path) { + return { path: "Cannot be empty." }; + } + }} + onSubmit={(values) => { + const [libraryID, sliceID, variationID] = values.path.split("::"); + onSubmit({ libraryID, sliceID, variationID }); + }} + > + {(formik) => { + return ( +
+ + + + If you have multiple identical slices, you can merge them. + All of your content will be remapped to the target slice. + + + + + + Choose a slice that you would like to merge this into. + + + + void formik.submitForm(), + loading: isLoading, + disabled: !formik.isValid, + }} + cancel={{ text: "Cancel" }} + /> + +
+ ); + }} +
+
+
+ ); +}; diff --git a/packages/slice-machine/src/features/slices/convertLegacySlice/types.ts b/packages/slice-machine/src/features/slices/convertLegacySlice/types.ts new file mode 100644 index 0000000000..55884c0e28 --- /dev/null +++ b/packages/slice-machine/src/features/slices/convertLegacySlice/types.ts @@ -0,0 +1,37 @@ +import { LibraryUI } from "@models/common/LibraryUI"; +import { ComponentUI } from "@models/common/ComponentUI"; + +import { NonSharedSliceViewCardProps } from "../sliceCards/NonSharedSliceViewCard"; + +export type ConvertLegacySliceAndTrackArgs = { + libraryID: string; + sliceID: string; + variationID?: string; + variationName?: string; +}; + +const legacySliceConversionTypes = [ + "as_new_slice", + "as_new_variation", + "merge_with_identical", +] as const; +export type LegacySliceConversionType = + (typeof legacySliceConversionTypes)[number]; + +export type IdenticalSlice = { + libraryID: string; + sliceID: string; + variationID: string; + path: string; +}; + +export type DialogProps = { + isOpen: boolean; + close: () => void; + onSubmit: (args: ConvertLegacySliceAndTrackArgs) => void; + isLoading: boolean; + sliceName: string; + libraries: readonly LibraryUI[]; + localSharedSlices: ComponentUI[]; + identicalSlices: IdenticalSlice[]; +} & Pick; diff --git a/packages/slice-machine/src/features/slices/sliceCards/NonSharedSliceViewCard.tsx b/packages/slice-machine/src/features/slices/sliceCards/NonSharedSliceViewCard.tsx index 5eee804ef8..a726cf70f1 100644 --- a/packages/slice-machine/src/features/slices/sliceCards/NonSharedSliceViewCard.tsx +++ b/packages/slice-machine/src/features/slices/sliceCards/NonSharedSliceViewCard.tsx @@ -1,15 +1,24 @@ import { Badge, Box, Text, Tooltip } from "@prismicio/editor-ui"; import type { FC } from "react"; +import { type NonSharedSliceInSliceZone } from "@models/common/CustomType/sliceZone"; import { Card, CardActions, CardFooter, CardMedia } from "@src/components/Card"; -import { getNonSharedSliceLabel, type NonSharedSlice } from "@src/domain/slice"; +import { getNonSharedSliceLabel } from "@src/domain/slice"; -type NonSharedSliceViewCardProps = { - slice: NonSharedSlice; +import { ConvertLegacySliceButton } from "../convertLegacySlice/ConvertLegacySliceButton"; + +export type NonSharedSliceViewCardProps = { + slice: NonSharedSliceInSliceZone; + path: { + customTypeID: string; + tabID: string; + sliceZoneID: string; + }; }; export const NonSharedSliceViewCard: FC = ({ slice, + path, }) => ( @@ -21,12 +30,16 @@ export const NonSharedSliceViewCard: FC = ({ + - + ); diff --git a/yarn.lock b/yarn.lock index f83b3cf19d..5daab1a4fa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3761,6 +3761,13 @@ __metadata: languageName: node linkType: hard +"@next/env@npm:13.5.4": + version: 13.5.4 + resolution: "@next/env@npm:13.5.4" + checksum: 95ec7108bc88a01fed5389fb33e4b9eb34937908859d9f0aa87930c660f4395d90dafe10e54830faae5bc0a1b799be544c6455a2c8054499569d1e9296369076 + languageName: node + linkType: hard + "@next/eslint-plugin-next@npm:13.4.2": version: 13.4.2 resolution: "@next/eslint-plugin-next@npm:13.4.2" @@ -3798,6 +3805,13 @@ __metadata: languageName: node linkType: hard +"@next/swc-darwin-arm64@npm:13.5.4": + version: 13.5.4 + resolution: "@next/swc-darwin-arm64@npm:13.5.4" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + "@next/swc-darwin-x64@npm:12.3.4": version: 12.3.4 resolution: "@next/swc-darwin-x64@npm:12.3.4" @@ -3812,6 +3826,13 @@ __metadata: languageName: node linkType: hard +"@next/swc-darwin-x64@npm:13.5.4": + version: 13.5.4 + resolution: "@next/swc-darwin-x64@npm:13.5.4" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + "@next/swc-freebsd-x64@npm:12.3.4": version: 12.3.4 resolution: "@next/swc-freebsd-x64@npm:12.3.4" @@ -3840,6 +3861,13 @@ __metadata: languageName: node linkType: hard +"@next/swc-linux-arm64-gnu@npm:13.5.4": + version: 13.5.4 + resolution: "@next/swc-linux-arm64-gnu@npm:13.5.4" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + "@next/swc-linux-arm64-musl@npm:12.3.4": version: 12.3.4 resolution: "@next/swc-linux-arm64-musl@npm:12.3.4" @@ -3854,6 +3882,13 @@ __metadata: languageName: node linkType: hard +"@next/swc-linux-arm64-musl@npm:13.5.4": + version: 13.5.4 + resolution: "@next/swc-linux-arm64-musl@npm:13.5.4" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + "@next/swc-linux-x64-gnu@npm:12.3.4": version: 12.3.4 resolution: "@next/swc-linux-x64-gnu@npm:12.3.4" @@ -3868,6 +3903,13 @@ __metadata: languageName: node linkType: hard +"@next/swc-linux-x64-gnu@npm:13.5.4": + version: 13.5.4 + resolution: "@next/swc-linux-x64-gnu@npm:13.5.4" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + "@next/swc-linux-x64-musl@npm:12.3.4": version: 12.3.4 resolution: "@next/swc-linux-x64-musl@npm:12.3.4" @@ -3882,6 +3924,13 @@ __metadata: languageName: node linkType: hard +"@next/swc-linux-x64-musl@npm:13.5.4": + version: 13.5.4 + resolution: "@next/swc-linux-x64-musl@npm:13.5.4" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + "@next/swc-win32-arm64-msvc@npm:12.3.4": version: 12.3.4 resolution: "@next/swc-win32-arm64-msvc@npm:12.3.4" @@ -3896,6 +3945,13 @@ __metadata: languageName: node linkType: hard +"@next/swc-win32-arm64-msvc@npm:13.5.4": + version: 13.5.4 + resolution: "@next/swc-win32-arm64-msvc@npm:13.5.4" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + "@next/swc-win32-ia32-msvc@npm:12.3.4": version: 12.3.4 resolution: "@next/swc-win32-ia32-msvc@npm:12.3.4" @@ -3910,6 +3966,13 @@ __metadata: languageName: node linkType: hard +"@next/swc-win32-ia32-msvc@npm:13.5.4": + version: 13.5.4 + resolution: "@next/swc-win32-ia32-msvc@npm:13.5.4" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + "@next/swc-win32-x64-msvc@npm:12.3.4": version: 12.3.4 resolution: "@next/swc-win32-x64-msvc@npm:12.3.4" @@ -3924,6 +3987,13 @@ __metadata: languageName: node linkType: hard +"@next/swc-win32-x64-msvc@npm:13.5.4": + version: 13.5.4 + resolution: "@next/swc-win32-x64-msvc@npm:13.5.4" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@nodelib/fs.scandir@npm:2.1.5": version: 2.1.5 resolution: "@nodelib/fs.scandir@npm:2.1.5" @@ -4935,6 +5005,16 @@ __metadata: languageName: node linkType: hard +"@prismicio/client@npm:^7.2.0": + version: 7.2.0 + resolution: "@prismicio/client@npm:7.2.0" + dependencies: + "@prismicio/richtext": ^2.1.5 + imgix-url-builder: ^0.0.4 + checksum: 1f7d18df1a402880eb685513cb4796172778f90183f3e52a3edf52c59f81cc5ce088dce293377e8d060e09700f4ed4730b06cde02462d6d04c4317fcb7528a26 + languageName: node + linkType: hard + "@prismicio/custom-types-client@npm:^1.1.0": version: 1.1.0 resolution: "@prismicio/custom-types-client@npm:1.1.0" @@ -5127,6 +5207,19 @@ __metadata: languageName: node linkType: hard +"@prismicio/next@npm:^1.3.6": + version: 1.3.6 + resolution: "@prismicio/next@npm:1.3.6" + dependencies: + imgix-url-builder: ^0.0.4 + peerDependencies: + "@prismicio/client": ^6 || ^7 + next: ^13.4.5 + react: ^18 + checksum: b8f705350801b67199a4e9b4f512605e2c16acc0572a3bae4d629fb16856cc3bc9558d22dcb9dbb616057d45b6f35dfe62fa6009ea0c82727cd2606f22a5b534 + languageName: node + linkType: hard + "@prismicio/react@npm:^2.6.0": version: 2.7.0 resolution: "@prismicio/react@npm:2.7.0" @@ -5139,6 +5232,18 @@ __metadata: languageName: node linkType: hard +"@prismicio/react@npm:^2.7.3": + version: 2.7.3 + resolution: "@prismicio/react@npm:2.7.3" + dependencies: + "@prismicio/richtext": ^2.1.5 + peerDependencies: + "@prismicio/client": ^6 || ^7 + react: ^18 + checksum: eff143d3e5f6606fcb3cd7bfc404af8803e3f35f808d54988f1689fb4b3f2efa2ba4afa93716deb9eb37611eda845c01f0865cd7c9c552c17102e72ae6b944d5 + languageName: node + linkType: hard + "@prismicio/richtext@npm:2.1.1": version: 2.1.1 resolution: "@prismicio/richtext@npm:2.1.1" @@ -9398,6 +9503,15 @@ __metadata: languageName: node linkType: hard +"@swc/helpers@npm:0.5.2": + version: 0.5.2 + resolution: "@swc/helpers@npm:0.5.2" + dependencies: + tslib: ^2.4.0 + checksum: 51d7e3d8bd56818c49d6bfbd715f0dbeedc13cf723af41166e45c03e37f109336bbcb57a1f2020f4015957721aeb21e1a7fff281233d797ff7d3dd1f447fa258 + languageName: node + linkType: hard + "@swc/helpers@npm:^0.4.14": version: 0.4.14 resolution: "@swc/helpers@npm:0.4.14" @@ -10373,6 +10487,13 @@ __metadata: languageName: node linkType: hard +"@types/node@npm:^20.8.3": + version: 20.8.3 + resolution: "@types/node@npm:20.8.3" + checksum: bfb88b341faeb19f8fd37306a3bf433721b876c6491d10fcb0b13fd26601fa36ee45113dd82b1e1c23e3c957dff5b99f81a16493cefa03abe797e41a2487a4f7 + languageName: node + linkType: hard + "@types/nodemon@npm:1.19.2": version: 1.19.2 resolution: "@types/nodemon@npm:1.19.2" @@ -10494,6 +10615,15 @@ __metadata: languageName: node linkType: hard +"@types/react-dom@npm:^18.2.11": + version: 18.2.11 + resolution: "@types/react-dom@npm:18.2.11" + dependencies: + "@types/react": "*" + checksum: 70dbdd2f8836a797ab8a3771c773f51023aab187d4d88ed3733bb3f2cbc2146057788a0095a03637101aeab9a48fce0ea369f96a35fc07e785ef53b8ab870885 + languageName: node + linkType: hard + "@types/react-modal@npm:3.13.1": version: 3.13.1 resolution: "@types/react-modal@npm:3.13.1" @@ -10555,6 +10685,17 @@ __metadata: languageName: node linkType: hard +"@types/react@npm:^18.2.25": + version: 18.2.25 + resolution: "@types/react@npm:18.2.25" + dependencies: + "@types/prop-types": "*" + "@types/scheduler": "*" + csstype: ^3.0.2 + checksum: 177515cd44135d56191ec6c5c10edd490c96c175d37624d9c37bc2007c3abcf6cc2d2137d2a073d692cdc5129d5d5785bd60a6ddd315f695da5d8b989fa2afc5 + languageName: node + linkType: hard + "@types/resolve@npm:1.20.2": version: 1.20.2 resolution: "@types/resolve@npm:1.20.2" @@ -24384,6 +24525,25 @@ __metadata: languageName: node linkType: hard +"next-upgrade@workspace:e2e-projects/next-upgrade": + version: 0.0.0-use.local + resolution: "next-upgrade@workspace:e2e-projects/next-upgrade" + dependencies: + "@prismicio/client": ^7.2.0 + "@prismicio/next": ^1.3.6 + "@prismicio/react": ^2.7.3 + "@slicemachine/adapter-next": "workspace:*" + "@types/node": ^20.8.3 + "@types/react": ^18.2.25 + "@types/react-dom": ^18.2.11 + next: ^13.5.4 + react: ^18.2.0 + react-dom: ^18.2.0 + slice-machine-ui: "workspace:*" + typescript: ^4.9.5 + languageName: unknown + linkType: soft + "next@npm:12.3.4": version: 12.3.4 resolution: "next@npm:12.3.4" @@ -24512,6 +24672,61 @@ __metadata: languageName: node linkType: hard +"next@npm:^13.5.4": + version: 13.5.4 + resolution: "next@npm:13.5.4" + dependencies: + "@next/env": 13.5.4 + "@next/swc-darwin-arm64": 13.5.4 + "@next/swc-darwin-x64": 13.5.4 + "@next/swc-linux-arm64-gnu": 13.5.4 + "@next/swc-linux-arm64-musl": 13.5.4 + "@next/swc-linux-x64-gnu": 13.5.4 + "@next/swc-linux-x64-musl": 13.5.4 + "@next/swc-win32-arm64-msvc": 13.5.4 + "@next/swc-win32-ia32-msvc": 13.5.4 + "@next/swc-win32-x64-msvc": 13.5.4 + "@swc/helpers": 0.5.2 + busboy: 1.6.0 + caniuse-lite: ^1.0.30001406 + postcss: 8.4.31 + styled-jsx: 5.1.1 + watchpack: 2.4.0 + peerDependencies: + "@opentelemetry/api": ^1.1.0 + react: ^18.2.0 + react-dom: ^18.2.0 + sass: ^1.3.0 + dependenciesMeta: + "@next/swc-darwin-arm64": + optional: true + "@next/swc-darwin-x64": + optional: true + "@next/swc-linux-arm64-gnu": + optional: true + "@next/swc-linux-arm64-musl": + optional: true + "@next/swc-linux-x64-gnu": + optional: true + "@next/swc-linux-x64-musl": + optional: true + "@next/swc-win32-arm64-msvc": + optional: true + "@next/swc-win32-ia32-msvc": + optional: true + "@next/swc-win32-x64-msvc": + optional: true + peerDependenciesMeta: + "@opentelemetry/api": + optional: true + sass: + optional: true + bin: + next: dist/bin/next + checksum: f8e964ee9bbabd0303f9d807c9193833fcc47960be029c3721db9a5a35cc4ff690313e30fc6ee497f959a9141048957dddf6eb038b4a23c78c8762b0cd9d0ae0 + languageName: node + linkType: hard + "nitropack@npm:~2.3.2": version: 2.3.3 resolution: "nitropack@npm:2.3.3" @@ -27548,6 +27763,17 @@ __metadata: languageName: node linkType: hard +"postcss@npm:8.4.31": + version: 8.4.31 + resolution: "postcss@npm:8.4.31" + dependencies: + nanoid: ^3.3.6 + picocolors: ^1.0.0 + source-map-js: ^1.0.2 + checksum: 1d8611341b073143ad90486fcdfeab49edd243377b1f51834dc4f6d028e82ce5190e4f11bb2633276864503654fb7cab28e67abdc0fbf9d1f88cad4a0ff0beea + languageName: node + linkType: hard + "postcss@npm:^7.0.36": version: 7.0.39 resolution: "postcss@npm:7.0.39" @@ -32789,7 +33015,7 @@ __metadata: languageName: node linkType: hard -"typescript@npm:4.9.5": +"typescript@npm:4.9.5, typescript@npm:^4.9.5": version: 4.9.5 resolution: "typescript@npm:4.9.5" bin: @@ -32819,7 +33045,7 @@ __metadata: languageName: node linkType: hard -"typescript@patch:typescript@4.9.5#~builtin": +"typescript@patch:typescript@4.9.5#~builtin, typescript@patch:typescript@^4.9.5#~builtin": version: 4.9.5 resolution: "typescript@patch:typescript@npm%3A4.9.5#~builtin::version=4.9.5&hash=289587" bin: From 165397e0d03bf3851788874ff1ad35fee0ec1ee6 Mon Sep 17 00:00:00 2001 From: Angelo Ashmore Date: Tue, 10 Oct 2023 22:02:13 -1000 Subject: [PATCH 04/16] fix(adapter-next): prevent slice template hydration errors due to CSS (DT-1673) (#1163) --- .../public/AlternateGrid/javascript.jsx | 291 +++++++++--------- .../public/CallToAction/javascript.jsx | 163 +++++----- .../public/CustomerLogos/javascript.jsx | 147 ++++----- .../adapter-next/public/Hero/javascript.jsx | 134 ++++---- 4 files changed, 370 insertions(+), 365 deletions(-) diff --git a/packages/adapter-next/public/AlternateGrid/javascript.jsx b/packages/adapter-next/public/AlternateGrid/javascript.jsx index 1334293579..636b47e08c 100644 --- a/packages/adapter-next/public/AlternateGrid/javascript.jsx +++ b/packages/adapter-next/public/AlternateGrid/javascript.jsx @@ -78,158 +78,159 @@ const PascalNameToReplace = ({ slice }) => { )} + + .es-alternate-grid__image--left + div { + order: 2; + } + + .es-alternate-grid__image--right{ + order: 2; + } + + .es-alternate-grid__image--right + div { + order: 1; + } + + .es-alternate-grid__primary-content { + display: grid; + gap: 2rem; + } + + .es-alternate-grid__primary-content__intro { + display: grid; + gap: 0.5rem; + } + + .es-alternate-grid__primary-content__intro__eyebrow { + color: #8592e0; + font-size: 1.15rem; + font-weight: 500; + margin: 0; + } + + .es-alternate-grid__primary-content__intro__headline { + font-size: 1.625rem; + font-weight: 700; + } + + .es-alternate-grid__primary-content__intro__headline * { + margin: 0; + } + + @media (min-width: 640px) { + .es-alternate-grid__primary-content__intro__headline { + font-size: 2rem; + } + } + + @media (min-width: 1024px) { + .es-alternate-grid__primary-content__intro__headline { + font-size: 2.5rem; + } + } + + @media (min-width: 1200px) { + .es-alternate-grid__primary-content__intro__headline { + font-size: 2.75rem; + } + } + + .es-alternate-grid__primary-content__intro__description { + font-size: 1.15rem; + max-width: 38rem; + } + + .es-alternate-grid__primary-content__intro__description > p { + margin: 0; + } + + @media (min-width: 1200px) { + .es-alternate-grid__primary-content__intro__description { + font-size: 1.4rem; + } + } + + .es-alternate-grid__primary-content__items { + display: grid; + gap: 2rem; + } + + @media (min-width: 640px) { + .es-alternate-grid__primary-content__items { + grid-template-columns: repeat(2, 1fr); + } + } + + .es-alternate-grid__item { + display: grid; + align-content: start; + } + + .es-alternate-grid__item__heading { + font-weight: 700; + font-size: 1.17rem; + margin-top: 0; + margin-bottom: .5rem; + } + + .es-alternate-grid__item__heading * { + margin: 0; + } + + .es-alternate-grid__item__description { + font-size: 0.9rem; + } + + .es-alternate-grid__item__description * { + margin: 0; + } + `, + }} + /> ); }; diff --git a/packages/adapter-next/public/CallToAction/javascript.jsx b/packages/adapter-next/public/CallToAction/javascript.jsx index 6d19469b88..91de9a4058 100644 --- a/packages/adapter-next/public/CallToAction/javascript.jsx +++ b/packages/adapter-next/public/CallToAction/javascript.jsx @@ -46,89 +46,90 @@ const PascalNameToReplace = ({ slice }) => { )} + + @media screen and (min-width: 640px) { + .es-bounded__content { + max-width: 90%; + } + } + + @media screen and (min-width: 896px) { + .es-bounded__content { + max-width: 80%; + } + } + + @media screen and (min-width: 1280px) { + .es-bounded__content { + max-width: 75%; + } + } + + .es-call-to-action { + font-family: system-ui, sans-serif; + background-color: #fff; + color: #333; + } + + .es-call-to-action__image { + max-width: 14rem; + height: auto; + width: auto; + justify-self: ${alignment}; + } + + .es-call-to-action__content { + display: grid; + gap: 1rem; + justify-items: ${alignment}; + } + + .es-call-to-action__content__heading { + font-size: 2rem; + font-weight: 700; + text-align: ${alignment}; + } + + .es-call-to-action__content__heading * { + margin: 0; + } + + .es-call-to-action__content__paragraph { + font-size: 1.15rem; + max-width: 38rem; + text-align: ${alignment}; + } + + .es-call-to-action__button { + justify-self: ${alignment}; + border-radius: 0.25rem; + display: inline-block; + font-size: 0.875rem; + line-height: 1.3; + padding: 1rem 2.625rem; + text-align: ${alignment}; + transition: background-color 100ms linear; + background-color: #16745f; + color: #fff; + } + + .es-call-to-action__button:hover { + background-color: #0d5e4c; + } + `, + }} + /> ); }; diff --git a/packages/adapter-next/public/CustomerLogos/javascript.jsx b/packages/adapter-next/public/CustomerLogos/javascript.jsx index f7b069602b..8d32b035e0 100644 --- a/packages/adapter-next/public/CustomerLogos/javascript.jsx +++ b/packages/adapter-next/public/CustomerLogos/javascript.jsx @@ -48,83 +48,84 @@ const PascalNameToReplace = ({ slice }) => { {slice.primary.callToActionLabel || "Learn more..."} + + .es-customer-logos__heading { + color: #8592e0; + font-size: 1.5rem; + font-weight: 500; + text-align: center; + } + + .es-customer-logos__heading * { + margin: 0; + } + + .es-customer-logos__logos { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); + grid-column-gap: 1.25rem; + grid-row-gap: 2rem; + align-items: center; + list-style-type: none; + width: 100%; + } + + @media (min-width: 1200px) { + .es-customer-logos__logos { + margin-left: -3rem; + } + } + + .es-customer-logos__logo { + margin: 0; + display: flex; + justify-content: center; + } + + @media (min-width: 1200px) { + .es-customer-logos__logo { + margin-left: 3rem; + } + } + + .es-customer-logos__logo__link__image { + max-width: 10rem; + } + + .es-customer-logos__button { + justify-self: center; + text-decoration: underline; + } + `, + }} + /> ); }; diff --git a/packages/adapter-next/public/Hero/javascript.jsx b/packages/adapter-next/public/Hero/javascript.jsx index 5d3f2f919e..fc2293b9c5 100644 --- a/packages/adapter-next/public/Hero/javascript.jsx +++ b/packages/adapter-next/public/Hero/javascript.jsx @@ -64,56 +64,57 @@ const PascalNameToReplace = ({ slice }) => { - + } + `, + }} + /> ); }; From a3b0412c4480dcba4d6a1d3609442bdb2d7dbd99 Mon Sep 17 00:00:00 2001 From: bapmrl Date: Wed, 11 Oct 2023 08:06:16 +0000 Subject: [PATCH 05/16] Publish - cimsirp@1.16.1-dev-next-release.1 - next-upgrade@1.14.1-dev-next-release.0 - sveltekit@1.16.1-dev-next-release.1 - @slicemachine/adapter-next@0.3.20-dev-next-release.1 - @slicemachine/adapter-nuxt@0.3.20-dev-next-release.1 - @slicemachine/adapter-nuxt2@0.3.20-dev-next-release.1 - @slicemachine/adapter-sveltekit@0.3.20-dev-next-release.1 - @slicemachine/init@2.7.3-dev-next-release.1 - @slicemachine/manager@0.13.1-dev-next-release.1 - @slicemachine/plugin-kit@0.4.20-dev-next-release.1 - slice-machine-ui@1.16.1-dev-next-release.1 - start-slicemachine@0.11.10-dev-next-release.1 --- e2e-projects/next-upgrade/package.json | 2 +- e2e-projects/next/package.json | 2 +- e2e-projects/sveltekit/package.json | 2 +- packages/adapter-next/package.json | 2 +- packages/adapter-nuxt/package.json | 2 +- packages/adapter-nuxt2/package.json | 2 +- packages/adapter-sveltekit/package.json | 2 +- packages/init/package.json | 2 +- packages/manager/package.json | 2 +- packages/plugin-kit/package.json | 2 +- packages/slice-machine/package.json | 2 +- packages/start-slicemachine/package.json | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/e2e-projects/next-upgrade/package.json b/e2e-projects/next-upgrade/package.json index b977d07d64..c5a7fcfbd6 100644 --- a/e2e-projects/next-upgrade/package.json +++ b/e2e-projects/next-upgrade/package.json @@ -1,6 +1,6 @@ { "name": "next-upgrade", - "version": "1.14.1-dev-upgrade-legacy-3.1", + "version": "1.14.1-dev-next-release.0", "private": true, "scripts": { "dev": "next dev", diff --git a/e2e-projects/next/package.json b/e2e-projects/next/package.json index 609fbd0ed9..424fb399e6 100644 --- a/e2e-projects/next/package.json +++ b/e2e-projects/next/package.json @@ -1,6 +1,6 @@ { "name": "cimsirp", - "version": "1.16.1-dev-next-release.0", + "version": "1.16.1-dev-next-release.1", "private": true, "scripts": { "dev": "next dev", diff --git a/e2e-projects/sveltekit/package.json b/e2e-projects/sveltekit/package.json index 3a6f037c8e..055831f9e6 100644 --- a/e2e-projects/sveltekit/package.json +++ b/e2e-projects/sveltekit/package.json @@ -1,6 +1,6 @@ { "name": "sveltekit", - "version": "1.16.1-dev-next-release.0", + "version": "1.16.1-dev-next-release.1", "private": true, "scripts": { "dev": "vite dev", diff --git a/packages/adapter-next/package.json b/packages/adapter-next/package.json index d9a0fb99d7..0473f199e1 100644 --- a/packages/adapter-next/package.json +++ b/packages/adapter-next/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/adapter-next", - "version": "0.3.20-dev-next-release.0", + "version": "0.3.20-dev-next-release.1", "description": "Slice Machine adapter for Next.js.", "keywords": [ "typescript", diff --git a/packages/adapter-nuxt/package.json b/packages/adapter-nuxt/package.json index 42f253fe56..a06b04d438 100644 --- a/packages/adapter-nuxt/package.json +++ b/packages/adapter-nuxt/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/adapter-nuxt", - "version": "0.3.20-dev-next-release.0", + "version": "0.3.20-dev-next-release.1", "description": "Slice Machine adapter for Nuxt 3.", "keywords": [ "typescript", diff --git a/packages/adapter-nuxt2/package.json b/packages/adapter-nuxt2/package.json index 651a2737fd..b0a783f5b1 100644 --- a/packages/adapter-nuxt2/package.json +++ b/packages/adapter-nuxt2/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/adapter-nuxt2", - "version": "0.3.20-dev-next-release.0", + "version": "0.3.20-dev-next-release.1", "description": "Slice Machine adapter for Nuxt 2.", "keywords": [ "typescript", diff --git a/packages/adapter-sveltekit/package.json b/packages/adapter-sveltekit/package.json index 7831e492e9..3d03568e7f 100644 --- a/packages/adapter-sveltekit/package.json +++ b/packages/adapter-sveltekit/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/adapter-sveltekit", - "version": "0.3.20-dev-next-release.0", + "version": "0.3.20-dev-next-release.1", "description": "Slice Machine adapter for SvelteKit.", "keywords": [ "typescript", diff --git a/packages/init/package.json b/packages/init/package.json index 861a4fbb8e..c5dacea3d7 100644 --- a/packages/init/package.json +++ b/packages/init/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/init", - "version": "2.7.3-dev-next-release.0", + "version": "2.7.3-dev-next-release.1", "description": "Init Prismic Slice Machine in your project", "keywords": [ "typescript", diff --git a/packages/manager/package.json b/packages/manager/package.json index 9a0da738e8..7b0319042c 100644 --- a/packages/manager/package.json +++ b/packages/manager/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/manager", - "version": "0.13.1-dev-next-release.0", + "version": "0.13.1-dev-next-release.1", "description": "Manage all aspects of a Slice Machine project.", "repository": { "type": "git", diff --git a/packages/plugin-kit/package.json b/packages/plugin-kit/package.json index 0bba20c24a..d7eb070d41 100644 --- a/packages/plugin-kit/package.json +++ b/packages/plugin-kit/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/plugin-kit", - "version": "0.4.20-dev-next-release.0", + "version": "0.4.20-dev-next-release.1", "description": "A set of helpers to develop and run Slice Machine plugins", "keywords": [ "typescript", diff --git a/packages/slice-machine/package.json b/packages/slice-machine/package.json index 796eb3faeb..c6092594fd 100644 --- a/packages/slice-machine/package.json +++ b/packages/slice-machine/package.json @@ -1,6 +1,6 @@ { "name": "slice-machine-ui", - "version": "1.16.1-dev-next-release.0", + "version": "1.16.1-dev-next-release.1", "license": "MIT", "description": "A visual builder for your Slice Models with all the tools you need to generate data models and mock CMS content locally.", "repository": { diff --git a/packages/start-slicemachine/package.json b/packages/start-slicemachine/package.json index 28fd476c07..8f34321a33 100644 --- a/packages/start-slicemachine/package.json +++ b/packages/start-slicemachine/package.json @@ -1,6 +1,6 @@ { "name": "start-slicemachine", - "version": "0.11.10-dev-next-release.0", + "version": "0.11.10-dev-next-release.1", "description": "Start Slice Machine from within a project.", "repository": { "type": "git", From 6bddf7f5cf9e38b3eefacca37082f48be5e32859 Mon Sep 17 00:00:00 2001 From: Baptiste Morelle Date: Wed, 11 Oct 2023 11:16:31 +0200 Subject: [PATCH 06/16] feat(slice-machine-ui): hide ConvertLegacySliceButton --- .../slices/sliceCards/NonSharedSliceViewCard.tsx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/slice-machine/src/features/slices/sliceCards/NonSharedSliceViewCard.tsx b/packages/slice-machine/src/features/slices/sliceCards/NonSharedSliceViewCard.tsx index a726cf70f1..2ea782ba02 100644 --- a/packages/slice-machine/src/features/slices/sliceCards/NonSharedSliceViewCard.tsx +++ b/packages/slice-machine/src/features/slices/sliceCards/NonSharedSliceViewCard.tsx @@ -30,12 +30,17 @@ export const NonSharedSliceViewCard: FC = ({ - + {/* TODO(DT-1675): remove this `div` when the migration of Legacy Slices has been validated. */} +
+ +
Date: Wed, 11 Oct 2023 09:19:11 +0000 Subject: [PATCH 07/16] Publish - cimsirp@1.16.1-dev-next-release.2 - next-upgrade@1.14.1-dev-next-release.1 - sveltekit@1.16.1-dev-next-release.2 - @slicemachine/adapter-next@0.3.20-dev-next-release.2 - @slicemachine/adapter-nuxt@0.3.20-dev-next-release.2 - @slicemachine/adapter-nuxt2@0.3.20-dev-next-release.2 - @slicemachine/adapter-sveltekit@0.3.20-dev-next-release.2 - @slicemachine/init@2.7.3-dev-next-release.2 - @slicemachine/manager@0.13.1-dev-next-release.2 - @slicemachine/plugin-kit@0.4.20-dev-next-release.2 - slice-machine-ui@1.16.1-dev-next-release.2 - start-slicemachine@0.11.10-dev-next-release.2 --- e2e-projects/next-upgrade/package.json | 2 +- e2e-projects/next/package.json | 2 +- e2e-projects/sveltekit/package.json | 2 +- packages/adapter-next/package.json | 2 +- packages/adapter-nuxt/package.json | 2 +- packages/adapter-nuxt2/package.json | 2 +- packages/adapter-sveltekit/package.json | 2 +- packages/init/package.json | 2 +- packages/manager/package.json | 2 +- packages/plugin-kit/package.json | 2 +- packages/slice-machine/package.json | 2 +- packages/start-slicemachine/package.json | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/e2e-projects/next-upgrade/package.json b/e2e-projects/next-upgrade/package.json index c5a7fcfbd6..ad29b4fc4f 100644 --- a/e2e-projects/next-upgrade/package.json +++ b/e2e-projects/next-upgrade/package.json @@ -1,6 +1,6 @@ { "name": "next-upgrade", - "version": "1.14.1-dev-next-release.0", + "version": "1.14.1-dev-next-release.1", "private": true, "scripts": { "dev": "next dev", diff --git a/e2e-projects/next/package.json b/e2e-projects/next/package.json index 424fb399e6..ba1502f92d 100644 --- a/e2e-projects/next/package.json +++ b/e2e-projects/next/package.json @@ -1,6 +1,6 @@ { "name": "cimsirp", - "version": "1.16.1-dev-next-release.1", + "version": "1.16.1-dev-next-release.2", "private": true, "scripts": { "dev": "next dev", diff --git a/e2e-projects/sveltekit/package.json b/e2e-projects/sveltekit/package.json index 055831f9e6..46274b3bc8 100644 --- a/e2e-projects/sveltekit/package.json +++ b/e2e-projects/sveltekit/package.json @@ -1,6 +1,6 @@ { "name": "sveltekit", - "version": "1.16.1-dev-next-release.1", + "version": "1.16.1-dev-next-release.2", "private": true, "scripts": { "dev": "vite dev", diff --git a/packages/adapter-next/package.json b/packages/adapter-next/package.json index 0473f199e1..d305fa2654 100644 --- a/packages/adapter-next/package.json +++ b/packages/adapter-next/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/adapter-next", - "version": "0.3.20-dev-next-release.1", + "version": "0.3.20-dev-next-release.2", "description": "Slice Machine adapter for Next.js.", "keywords": [ "typescript", diff --git a/packages/adapter-nuxt/package.json b/packages/adapter-nuxt/package.json index a06b04d438..e7795ec577 100644 --- a/packages/adapter-nuxt/package.json +++ b/packages/adapter-nuxt/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/adapter-nuxt", - "version": "0.3.20-dev-next-release.1", + "version": "0.3.20-dev-next-release.2", "description": "Slice Machine adapter for Nuxt 3.", "keywords": [ "typescript", diff --git a/packages/adapter-nuxt2/package.json b/packages/adapter-nuxt2/package.json index b0a783f5b1..45323368d9 100644 --- a/packages/adapter-nuxt2/package.json +++ b/packages/adapter-nuxt2/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/adapter-nuxt2", - "version": "0.3.20-dev-next-release.1", + "version": "0.3.20-dev-next-release.2", "description": "Slice Machine adapter for Nuxt 2.", "keywords": [ "typescript", diff --git a/packages/adapter-sveltekit/package.json b/packages/adapter-sveltekit/package.json index 3d03568e7f..8e396c2310 100644 --- a/packages/adapter-sveltekit/package.json +++ b/packages/adapter-sveltekit/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/adapter-sveltekit", - "version": "0.3.20-dev-next-release.1", + "version": "0.3.20-dev-next-release.2", "description": "Slice Machine adapter for SvelteKit.", "keywords": [ "typescript", diff --git a/packages/init/package.json b/packages/init/package.json index c5dacea3d7..d477ead633 100644 --- a/packages/init/package.json +++ b/packages/init/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/init", - "version": "2.7.3-dev-next-release.1", + "version": "2.7.3-dev-next-release.2", "description": "Init Prismic Slice Machine in your project", "keywords": [ "typescript", diff --git a/packages/manager/package.json b/packages/manager/package.json index 7b0319042c..f1915b0b9d 100644 --- a/packages/manager/package.json +++ b/packages/manager/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/manager", - "version": "0.13.1-dev-next-release.1", + "version": "0.13.1-dev-next-release.2", "description": "Manage all aspects of a Slice Machine project.", "repository": { "type": "git", diff --git a/packages/plugin-kit/package.json b/packages/plugin-kit/package.json index d7eb070d41..e1060c5a27 100644 --- a/packages/plugin-kit/package.json +++ b/packages/plugin-kit/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/plugin-kit", - "version": "0.4.20-dev-next-release.1", + "version": "0.4.20-dev-next-release.2", "description": "A set of helpers to develop and run Slice Machine plugins", "keywords": [ "typescript", diff --git a/packages/slice-machine/package.json b/packages/slice-machine/package.json index c6092594fd..5c86b1582f 100644 --- a/packages/slice-machine/package.json +++ b/packages/slice-machine/package.json @@ -1,6 +1,6 @@ { "name": "slice-machine-ui", - "version": "1.16.1-dev-next-release.1", + "version": "1.16.1-dev-next-release.2", "license": "MIT", "description": "A visual builder for your Slice Models with all the tools you need to generate data models and mock CMS content locally.", "repository": { diff --git a/packages/start-slicemachine/package.json b/packages/start-slicemachine/package.json index 8f34321a33..66123806b8 100644 --- a/packages/start-slicemachine/package.json +++ b/packages/start-slicemachine/package.json @@ -1,6 +1,6 @@ { "name": "start-slicemachine", - "version": "0.11.10-dev-next-release.1", + "version": "0.11.10-dev-next-release.2", "description": "Start Slice Machine from within a project.", "repository": { "type": "git", From b118ed613d12a77f60e16a0ecc66b6a701c68808 Mon Sep 17 00:00:00 2001 From: Baptiste Morelle Date: Wed, 11 Oct 2023 14:33:24 +0200 Subject: [PATCH 08/16] fix(slice-machine-ui): inactive slices menu item (#1161) --- cypress/e2e/slices/00-create.cy.js | 4 +- cypress/e2e/updates/simulator-tooltip.cy.js | 6 +- cypress/helpers/slices.js | 2 +- cypress/pages/slices/sliceBuilder.js | 2 +- .../components/Navigation/ChangesListItem.tsx | 86 +++++++++---------- .../components/Navigation/VideoItem.tsx | 1 - .../components/Navigation/index.test.tsx | 2 +- .../components/Navigation/index.tsx | 57 ++++++------ .../lib/builders/SliceBuilder/links.ts | 4 +- .../[lib]/[sliceName]/[variation]/index.tsx | 0 .../[sliceName]/[variation]/screenshot.tsx | 0 .../[sliceName]/[variation]/simulator.tsx | 0 .../components/SideNav/SideNav.stories.tsx | 3 +- .../src/components/SideNav/SideNav.tsx | 59 +++++++------ .../src/features/slices/slicesConfig.ts | 10 +-- packages/slice-machine/test/__setup__.ts | 5 ++ .../test/pages/simulator.test.tsx | 4 +- .../src/lib/createSliceMachineExpressApp.ts | 15 ++-- 18 files changed, 124 insertions(+), 136 deletions(-) rename packages/slice-machine/pages/{ => slices}/[lib]/[sliceName]/[variation]/index.tsx (100%) rename packages/slice-machine/pages/{ => slices}/[lib]/[sliceName]/[variation]/screenshot.tsx (100%) rename packages/slice-machine/pages/{ => slices}/[lib]/[sliceName]/[variation]/simulator.tsx (100%) diff --git a/cypress/e2e/slices/00-create.cy.js b/cypress/e2e/slices/00-create.cy.js index 643204387c..4ad93c1394 100644 --- a/cypress/e2e/slices/00-create.cy.js +++ b/cypress/e2e/slices/00-create.cy.js @@ -57,13 +57,13 @@ describe("Create Slices", () => { cy.location("pathname", { timeout: 20000 }).should( "eq", - `/${lib}/${sliceName}/bar` + `/slices/${lib}/${sliceName}/bar` ); cy.get("button").contains("foo").click(); cy.contains("Default").click(); cy.location("pathname", { timeout: 20000 }).should( "eq", - `/${lib}/${sliceName}/default` + `/slices/${lib}/${sliceName}/default` ); cy.contains("Save").click(); diff --git a/cypress/e2e/updates/simulator-tooltip.cy.js b/cypress/e2e/updates/simulator-tooltip.cy.js index 23958b4108..1f1a92f5b1 100644 --- a/cypress/e2e/updates/simulator-tooltip.cy.js +++ b/cypress/e2e/updates/simulator-tooltip.cy.js @@ -13,7 +13,7 @@ describe("simulator tooltip", () => { cy.createSlice(lib, sliceId, sliceName); - cy.visit(`/${lib}/${sliceName}/default`); + cy.visit(`/slices/${lib}/${sliceName}/default`); // There is a 5 s timeout for displaying the tooltip. cy.wait(6_000); @@ -37,7 +37,7 @@ describe("simulator tooltip", () => { cy.createSlice(lib, sliceId, sliceName); - cy.visit(`/${lib}/${sliceName}/default`); + cy.visit(`/slices/${lib}/${sliceName}/default`); // There is a 5 s timeout for displaying the tooltip. cy.wait(6_000); @@ -50,7 +50,7 @@ describe("simulator tooltip", () => { cy.createSlice(lib, sliceId, sliceName); - cy.visit(`/${lib}/${sliceName}/default`); + cy.visit(`/slices/${lib}/${sliceName}/default`); // There is a 5 s timeout for displaying the tooltip. cy.wait(6_000); diff --git a/cypress/helpers/slices.js b/cypress/helpers/slices.js index 54a6ef6b37..4d0b12a745 100644 --- a/cypress/helpers/slices.js +++ b/cypress/helpers/slices.js @@ -24,7 +24,7 @@ export function createSlice(lib, id, name) { cy.location("pathname", { timeout: 20000 }).should( "eq", - `/${lib}/${name}/default` + `/slices/${lib}/${name}/default` ); cy.readFile(TYPES_FILE).should("contains", name); } diff --git a/cypress/pages/slices/sliceBuilder.js b/cypress/pages/slices/sliceBuilder.js index 85acef61a9..aeaafaff3f 100644 --- a/cypress/pages/slices/sliceBuilder.js +++ b/cypress/pages/slices/sliceBuilder.js @@ -44,7 +44,7 @@ class SliceBuilder extends BaseBuilder { } goTo(sliceLibrary, sliceName, variation = "default") { - cy.visit(`/${sliceLibrary}/${sliceName}/${variation}`); + cy.visit(`/slices/${sliceLibrary}/${sliceName}/${variation}`); this.saveButton.should("be.visible"); cy.contains(sliceName).should("be.visible"); return this; diff --git a/packages/slice-machine/components/Navigation/ChangesListItem.tsx b/packages/slice-machine/components/Navigation/ChangesListItem.tsx index 010b19da26..ef24e683d7 100644 --- a/packages/slice-machine/components/Navigation/ChangesListItem.tsx +++ b/packages/slice-machine/components/Navigation/ChangesListItem.tsx @@ -1,4 +1,5 @@ -import { MouseEventHandler, forwardRef, useState } from "react"; +import { type FC, useState } from "react"; +import Link from "next/link"; import { useRouter } from "next/router"; import { SliceMachineStoreType } from "@src/redux/type"; import { useSelector } from "react-redux"; @@ -22,53 +23,46 @@ import { import useSliceMachineActions from "@src/modules/useSliceMachineActions"; import { ChangesRightElement } from "./ChangesRightElement"; -type ChangesListItemProps = { - handleNavigation: MouseEventHandler; -}; - -export const ChangesListItem = forwardRef( - ({ handleNavigation }, ref) => { - const { setSeenChangesToolTip } = useSliceMachineActions(); - const open = useOpenChangesHoverCard(); - const router = useRouter(); - const currentPath = router.asPath; +export const ChangesListItem: FC = () => { + const { setSeenChangesToolTip } = useSliceMachineActions(); + const open = useOpenChangesHoverCard(); + const router = useRouter(); - const onClose = () => { - setSeenChangesToolTip(); - }; + const onClose = () => { + setSeenChangesToolTip(); + }; - return ( - - } - /> - - } - > - Push your changes - - - When you click Save, your changes are saved locally. Then, you can - push your models to Prismic from the Changes page. - - Got It - - ); - } -); + return ( + + } + /> + + } + > + Push your changes + + + When you click Save, your changes are saved locally. Then, you can push + your models to Prismic from the Changes page. + + Got It + + ); +}; const useOpenChangesHoverCard = () => { const { diff --git a/packages/slice-machine/components/Navigation/VideoItem.tsx b/packages/slice-machine/components/Navigation/VideoItem.tsx index 016d96301f..e7cc035796 100644 --- a/packages/slice-machine/components/Navigation/VideoItem.tsx +++ b/packages/slice-machine/components/Navigation/VideoItem.tsx @@ -53,7 +53,6 @@ export const VideoItem = forwardRef( event: "open-video-tutorials", video: videoUrl, }); - window.open(videoUrl, "_blank"); onClose(); }} /> diff --git a/packages/slice-machine/components/Navigation/index.test.tsx b/packages/slice-machine/components/Navigation/index.test.tsx index 28da97f02d..67b6f31a5a 100644 --- a/packages/slice-machine/components/Navigation/index.test.tsx +++ b/packages/slice-machine/components/Navigation/index.test.tsx @@ -128,7 +128,7 @@ describe("Side Navigation", () => { expect(element).toBeNull(); }); - test.each([ + test.skip.each([ ["Page types", "/"], ["Custom types", "/custom-types"], ["Changes", "/changes"], diff --git a/packages/slice-machine/components/Navigation/index.tsx b/packages/slice-machine/components/Navigation/index.tsx index d83f218f31..cd38554c7f 100644 --- a/packages/slice-machine/components/Navigation/index.tsx +++ b/packages/slice-machine/components/Navigation/index.tsx @@ -1,5 +1,6 @@ import { ErrorBoundary } from "@prismicio/editor-ui"; import { Suspense, type FC } from "react"; +import Link from "next/link"; import { useRouter } from "next/router"; import { useSelector } from "react-redux"; @@ -40,33 +41,12 @@ const Navigation: FC = () => { hasSeenTutorialsToolTip: userHasSeenTutorialsToolTip(store), })); const router = useRouter(); - const currentPath = router.asPath; const repoDomain = new URL(apiEndpoint).hostname.replace(".cdn", ""); const repoAddress = apiEndpoint.replace(".cdn.", ".").replace("/api/v2", ""); - const latestVersion = - changelog.sliceMachine.versions.length > 0 - ? changelog.sliceMachine.versions[0] - : null; + const { setUpdatesViewed, setSeenTutorialsToolTip } = useSliceMachineActions(); - const handleNavigation = ( - event: React.MouseEvent - ) => { - const href = event.currentTarget.getAttribute("href"); - if (href !== null && href) void router.push(href); - }; - - const handleChangeLogNavigationFromUpdateBox = ( - event: React.MouseEvent - ) => { - setUpdatesViewed({ - latest: latestVersion && latestVersion.versionNumber, - latestNonBreaking: changelog.sliceMachine.latestNonBreakingVersion, - }); - handleNavigation(event); - }; - return ( @@ -86,9 +66,9 @@ const Navigation: FC = () => { })} href={CUSTOM_TYPES_CONFIG["page"].tablePagePathname} active={CUSTOM_TYPES_CONFIG["page"].matchesTablePagePathname( - currentPath + router.asPath )} - onClick={handleNavigation} + component={Link} Icon={CUSTOM_TYPES_CONFIG.page.Icon} /> @@ -101,16 +81,16 @@ const Navigation: FC = () => { })} href={CUSTOM_TYPES_CONFIG["custom"].tablePagePathname} active={CUSTOM_TYPES_CONFIG["custom"].matchesTablePagePathname( - currentPath + router.asPath )} - onClick={handleNavigation} + component={Link} Icon={CUSTOM_TYPES_CONFIG.custom.Icon} /> - + @@ -119,8 +99,8 @@ const Navigation: FC = () => { title="Slices" href="/slices" Icon={FolderIcon} - active={currentPath.startsWith("/slices")} - onClick={handleNavigation} + active={router.asPath.startsWith("/slices")} + component={Link} /> @@ -129,7 +109,18 @@ const Navigation: FC = () => { changelog.adapter.updateAvailable) && ( { + const latestVersion = + changelog.sliceMachine.versions.length > 0 + ? changelog.sliceMachine.versions?.[0] + : null; + setUpdatesViewed({ + latest: latestVersion && latestVersion.versionNumber, + latestNonBreaking: + changelog.sliceMachine.latestNonBreakingVersion, + }); + }} + component={Link} /> )} @@ -142,8 +133,8 @@ const Navigation: FC = () => { void telemetry.track({ event: "users-invite-button-clicked", }); - window.open(`${repoAddress}/settings/users`, "_blank"); }} + target="_blank" /> @@ -160,8 +151,8 @@ const Navigation: FC = () => { title="Changelog" href="/changelog" Icon={(props) => } - active={currentPath.startsWith("/changelog")} - onClick={handleNavigation} + active={router.asPath.startsWith("/changelog")} + component={Link} RightElement={ {changelog.sliceMachine.currentVersion && diff --git a/packages/slice-machine/lib/builders/SliceBuilder/links.ts b/packages/slice-machine/lib/builders/SliceBuilder/links.ts index 579c006998..c4ddc1fcbe 100644 --- a/packages/slice-machine/lib/builders/SliceBuilder/links.ts +++ b/packages/slice-machine/lib/builders/SliceBuilder/links.ts @@ -16,11 +16,11 @@ export function variation({ options: object; all: [string, string, object]; } { - const href = `/[lib]/[sliceName]/[variation]${ + const href = `/slices/[lib]/[sliceName]/[variation]${ // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions isSimulator ? "/simulator" : "" }`; - const as = `/${lib}/${sliceName}/${variationId}${ + const as = `/slices/${lib}/${sliceName}/${variationId}${ // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions isSimulator ? "/simulator" : "" }`; diff --git a/packages/slice-machine/pages/[lib]/[sliceName]/[variation]/index.tsx b/packages/slice-machine/pages/slices/[lib]/[sliceName]/[variation]/index.tsx similarity index 100% rename from packages/slice-machine/pages/[lib]/[sliceName]/[variation]/index.tsx rename to packages/slice-machine/pages/slices/[lib]/[sliceName]/[variation]/index.tsx diff --git a/packages/slice-machine/pages/[lib]/[sliceName]/[variation]/screenshot.tsx b/packages/slice-machine/pages/slices/[lib]/[sliceName]/[variation]/screenshot.tsx similarity index 100% rename from packages/slice-machine/pages/[lib]/[sliceName]/[variation]/screenshot.tsx rename to packages/slice-machine/pages/slices/[lib]/[sliceName]/[variation]/screenshot.tsx diff --git a/packages/slice-machine/pages/[lib]/[sliceName]/[variation]/simulator.tsx b/packages/slice-machine/pages/slices/[lib]/[sliceName]/[variation]/simulator.tsx similarity index 100% rename from packages/slice-machine/pages/[lib]/[sliceName]/[variation]/simulator.tsx rename to packages/slice-machine/pages/slices/[lib]/[sliceName]/[variation]/simulator.tsx diff --git a/packages/slice-machine/src/components/SideNav/SideNav.stories.tsx b/packages/slice-machine/src/components/SideNav/SideNav.stories.tsx index d3c3f139e2..b54cfb282f 100644 --- a/packages/slice-machine/src/components/SideNav/SideNav.stories.tsx +++ b/packages/slice-machine/src/components/SideNav/SideNav.stories.tsx @@ -116,7 +116,7 @@ export const Default = { - void 0} /> + @@ -124,7 +124,6 @@ export const Default = { title="Changelog" href="/changelog" Icon={LightningIcon} - onClick={() => void 0} RightElement={v1.0.0} /> diff --git a/packages/slice-machine/src/components/SideNav/SideNav.tsx b/packages/slice-machine/src/components/SideNav/SideNav.tsx index 5eed4fad27..8fbdd499b4 100644 --- a/packages/slice-machine/src/components/SideNav/SideNav.tsx +++ b/packages/slice-machine/src/components/SideNav/SideNav.tsx @@ -2,15 +2,16 @@ import { HTMLAttributes, type CSSProperties, type FC, - type HTMLProps, type LiHTMLAttributes, type MouseEvent, type PropsWithChildren, type ReactNode, type SVGProps, + createElement, forwardRef, } from "react"; import clsx from "clsx"; +import type { UrlObject } from "node:url"; import LogoIcon from "@src/icons/LogoIcon"; import OpenIcon from "@src/icons/OpenIcon"; @@ -98,33 +99,33 @@ export type SideNavLinkProps = { Icon: FC>; target?: "_blank"; RightElement?: ReactNode; -} & HTMLProps; + component?: "a" | FC; + onClick?: (event: MouseEvent) => void; +}; + +type LinkProps = { + href: string | UrlObject; +}; export const SideNavLink: FC = ({ title, RightElement, Icon, active, - ...props -}) => { - return ( - { - event.preventDefault(); - props.disabled !== true && props.onClick && props.onClick(event); - }} - data-active={active} - > + component = "a", + ...otherProps +}) => + createElement( + component, + { ...otherProps, ...{ className: styles.link, "data-active": active } }, + <>
{title} {RightElement}
-
+ ); -}; type RightElementProps = PropsWithChildren< { @@ -151,13 +152,16 @@ export const RightElement: FC = ({ }; type UpdateInfoProps = { - onClick: ( - event: MouseEvent - ) => void; + onClick?: (event: MouseEvent) => void; href: string; + component?: "a" | FC; }; -export const UpdateInfo: FC = ({ href, onClick }) => ( +export const UpdateInfo: FC = ({ + href, + onClick, + component = "a", +}) => (

Updates Available

@@ -165,15 +169,10 @@ export const UpdateInfo: FC = ({ href, onClick }) => ( Some updates of Slice Machine are available.

- { - event.preventDefault(); - onClick(event); - }} - > - Learn more - + {createElement( + component, + { ...{ className: styles.updateInfoLink, onClick }, href }, + "Learn more" + )}
); diff --git a/packages/slice-machine/src/features/slices/slicesConfig.ts b/packages/slice-machine/src/features/slices/slicesConfig.ts index 2d31deeb26..43d77379ae 100644 --- a/packages/slice-machine/src/features/slices/slicesConfig.ts +++ b/packages/slice-machine/src/features/slices/slicesConfig.ts @@ -5,10 +5,8 @@ type GetBuilderPagePathnameArgs = { }; export const SLICES_CONFIG = { - getBuilderPagePathname: ({ - libraryName, - sliceName, - variationId, - }: GetBuilderPagePathnameArgs) => - `/${libraryName.replace(/\//g, "--")}/${sliceName}/${variationId}`, + getBuilderPagePathname: (args: GetBuilderPagePathnameArgs) => + `/slices/${args.libraryName.replaceAll("/", "--")}/${args.sliceName}/${ + args.variationId + }`, }; diff --git a/packages/slice-machine/test/__setup__.ts b/packages/slice-machine/test/__setup__.ts index d388062e4d..27c6c95960 100644 --- a/packages/slice-machine/test/__setup__.ts +++ b/packages/slice-machine/test/__setup__.ts @@ -119,6 +119,11 @@ vi.mock("analytics-node", () => { }; }); +// We have to manually set this environment variable as there's no equivalent of +// `next/jest` for Vitest. It means Vitest doesn't read Next.js's configuration +// file and (in our case) the `experimental.newNextLinkBehavior` setting. +vi.stubEnv("__NEXT_NEW_LINK_BEHAVIOR", "true"); + vi.stubGlobal("FormData", FormData); vi.stubGlobal("Blob", Blob); vi.stubGlobal("File", File); diff --git a/packages/slice-machine/test/pages/simulator.test.tsx b/packages/slice-machine/test/pages/simulator.test.tsx index 0cb5eb7916..e88583ee78 100644 --- a/packages/slice-machine/test/pages/simulator.test.tsx +++ b/packages/slice-machine/test/pages/simulator.test.tsx @@ -8,7 +8,7 @@ import { createDynamicRouteParser } from "next-router-mock/dynamic-routes"; import SegmentClient from "analytics-node"; import pkg from "../../package.json"; -import Simulator from "../../pages/[lib]/[sliceName]/[variation]/simulator"; +import Simulator from "../../pages/slices/[lib]/[sliceName]/[variation]/simulator"; import { SliceMachineStoreType } from "@src/redux/type"; import { createTestPlugin } from "test/__testutils__/createTestPlugin"; import { createTestProject } from "test/__testutils__/createTestProject"; @@ -18,7 +18,7 @@ import { createSliceMachineManagerMSWHandler } from "@slicemachine/manager/test" vi.mock("next/router", () => require("next-router-mock")); vi.mock("next/dist/client/router", () => require("next-router-mock")); mockRouter.useParser( - createDynamicRouteParser(["/[lib]/[sliceName]/[variation]/simulator"]) + createDynamicRouteParser(["/slices/[lib]/[sliceName]/[variation]/simulator"]) ); // mock simulator client, it would be nice not to have to do this :/ vi.mock("@prismicio/simulator", () => { diff --git a/packages/start-slicemachine/src/lib/createSliceMachineExpressApp.ts b/packages/start-slicemachine/src/lib/createSliceMachineExpressApp.ts index fcffb4931f..e4d5b307da 100644 --- a/packages/start-slicemachine/src/lib/createSliceMachineExpressApp.ts +++ b/packages/start-slicemachine/src/lib/createSliceMachineExpressApp.ts @@ -125,26 +125,29 @@ export const createSliceMachineExpressApp = async ( ); }); - app.get("/:lib/:sliceID/:variation", (_req, res) => { + app.get("/slices/:lib/:sliceID/:variation", (_req, res) => { res.sendFile( - path.join(sliceMachineOutDir, "[lib]/[sliceName]/[variation].html"), + path.join( + sliceMachineOutDir, + "slices/[lib]/[sliceName]/[variation].html", + ), ); }); - app.get("/:lib/:sliceID/:variation/simulator", (_req, res) => { + app.get("/slices/:lib/:sliceID/:variation/simulator", (_req, res) => { res.sendFile( path.join( sliceMachineOutDir, - "[lib]/[sliceName]/[variation]/simulator.html", + "slices/[lib]/[sliceName]/[variation]/simulator.html", ), ); }); - app.get("/:lib/:sliceID/:variation/screenshot", (_req, res) => { + app.get("/slices/:lib/:sliceID/:variation/screenshot", (_req, res) => { res.sendFile( path.join( sliceMachineOutDir, - "[lib]/[sliceName]/[variation]/screenshot.html", + "slices/[lib]/[sliceName]/[variation]/screenshot.html", ), ); }); From dae7aa4fb440fbbe75de113968c8c754c50f73f3 Mon Sep 17 00:00:00 2001 From: Baptiste Morelle Date: Wed, 11 Oct 2023 14:33:44 +0200 Subject: [PATCH 09/16] feat(slice-machine-ui): update Window and List colors (#1165) --- packages/slice-machine/src/components/List/List.css.ts | 4 ++-- .../slice-machine/src/components/List/List.stories.tsx | 6 +++++- .../slice-machine/src/components/Window/Window.css.ts | 10 +++++----- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/packages/slice-machine/src/components/List/List.css.ts b/packages/slice-machine/src/components/List/List.css.ts index 71188d201b..02f85e8a13 100644 --- a/packages/slice-machine/src/components/List/List.css.ts +++ b/packages/slice-machine/src/components/List/List.css.ts @@ -9,9 +9,9 @@ export const header = style([ flex, sprinkles({ alignItems: "center", - backgroundColor: colors.grey1, + backgroundColor: colors.grey2, borderBottomColor: colors.grey6, - borderBottomStyle: "dashed", + borderBottomStyle: "solid", borderBottomWidth: 1, boxSizing: "border-box", flexDirection: "row", diff --git a/packages/slice-machine/src/components/List/List.stories.tsx b/packages/slice-machine/src/components/List/List.stories.tsx index 182afe93b2..014d5b99e2 100644 --- a/packages/slice-machine/src/components/List/List.stories.tsx +++ b/packages/slice-machine/src/components/List/List.stories.tsx @@ -16,7 +16,11 @@ export const Default = { args: { children: ( Add} + actions={ + + } toggle={} > Zone diff --git a/packages/slice-machine/src/components/Window/Window.css.ts b/packages/slice-machine/src/components/Window/Window.css.ts index 3991e58579..bbef0d53ec 100644 --- a/packages/slice-machine/src/components/Window/Window.css.ts +++ b/packages/slice-machine/src/components/Window/Window.css.ts @@ -11,7 +11,7 @@ const row = style([flex, sprinkles({ flexDirection: "row" })]); export const root = style([ column, sprinkles({ - backgroundColor: colors.grey2, + backgroundColor: colors.grey3, borderColor: colors.grey6, borderRadius: 6, borderStyle: "solid", @@ -92,7 +92,7 @@ export const tabsTrigger = style([ color: vars.color.greyLight12, }, '&:is(:focus, :hover, [data-state="active"])::before': { - backgroundColor: vars.color.greyLight1, + backgroundColor: vars.color.greyLight2, borderBottomStyle: vars.borderStyle.none, borderColor: vars.color.greyLight6, borderLeftStyle: vars.borderStyle.solid, @@ -137,7 +137,7 @@ export const tabsTriggerMenu = style([ export const newTabButton = style([ tabsListChild, sprinkles({ - backgroundColor: colors.grey2, + backgroundColor: colors.grey3, paddingInline: 8, position: "sticky", right: 0, @@ -146,13 +146,13 @@ export const newTabButton = style([ boxShadow: `inset 0 ${calc.multiply(-1, vars.borderWidth[1])} 0 0 ${ vars.color.greyLight6 }, 0 ${calc.multiply(-1, vars.borderWidth[1])} 0 0 ${ - vars.color.greyLight2 + vars.color.greyLight3 }`, }, ]); export const tabsContent = sprinkles({ - backgroundColor: colors.grey1, + backgroundColor: colors.grey2, flexGrow: 1, outline: "none", }); From 653b17a3be1154321f345bedeec54c509ddc5527 Mon Sep 17 00:00:00 2001 From: bapmrl Date: Wed, 11 Oct 2023 12:42:41 +0000 Subject: [PATCH 10/16] Publish - cimsirp@1.16.1-dev-next-release.3 - next-upgrade@1.14.1-dev-next-release.2 - sveltekit@1.16.1-dev-next-release.3 - @slicemachine/adapter-next@0.3.20-dev-next-release.3 - @slicemachine/adapter-nuxt@0.3.20-dev-next-release.3 - @slicemachine/adapter-nuxt2@0.3.20-dev-next-release.3 - @slicemachine/adapter-sveltekit@0.3.20-dev-next-release.3 - @slicemachine/init@2.7.3-dev-next-release.3 - @slicemachine/manager@0.13.1-dev-next-release.3 - @slicemachine/plugin-kit@0.4.20-dev-next-release.3 - slice-machine-ui@1.16.1-dev-next-release.3 - start-slicemachine@0.11.10-dev-next-release.3 --- e2e-projects/next-upgrade/package.json | 2 +- e2e-projects/next/package.json | 2 +- e2e-projects/sveltekit/package.json | 2 +- packages/adapter-next/package.json | 2 +- packages/adapter-nuxt/package.json | 2 +- packages/adapter-nuxt2/package.json | 2 +- packages/adapter-sveltekit/package.json | 2 +- packages/init/package.json | 2 +- packages/manager/package.json | 2 +- packages/plugin-kit/package.json | 2 +- packages/slice-machine/package.json | 2 +- packages/start-slicemachine/package.json | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/e2e-projects/next-upgrade/package.json b/e2e-projects/next-upgrade/package.json index ad29b4fc4f..d147a55d31 100644 --- a/e2e-projects/next-upgrade/package.json +++ b/e2e-projects/next-upgrade/package.json @@ -1,6 +1,6 @@ { "name": "next-upgrade", - "version": "1.14.1-dev-next-release.1", + "version": "1.14.1-dev-next-release.2", "private": true, "scripts": { "dev": "next dev", diff --git a/e2e-projects/next/package.json b/e2e-projects/next/package.json index ba1502f92d..5e183912de 100644 --- a/e2e-projects/next/package.json +++ b/e2e-projects/next/package.json @@ -1,6 +1,6 @@ { "name": "cimsirp", - "version": "1.16.1-dev-next-release.2", + "version": "1.16.1-dev-next-release.3", "private": true, "scripts": { "dev": "next dev", diff --git a/e2e-projects/sveltekit/package.json b/e2e-projects/sveltekit/package.json index 46274b3bc8..d8f45b62c4 100644 --- a/e2e-projects/sveltekit/package.json +++ b/e2e-projects/sveltekit/package.json @@ -1,6 +1,6 @@ { "name": "sveltekit", - "version": "1.16.1-dev-next-release.2", + "version": "1.16.1-dev-next-release.3", "private": true, "scripts": { "dev": "vite dev", diff --git a/packages/adapter-next/package.json b/packages/adapter-next/package.json index d305fa2654..fe05e8f2b1 100644 --- a/packages/adapter-next/package.json +++ b/packages/adapter-next/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/adapter-next", - "version": "0.3.20-dev-next-release.2", + "version": "0.3.20-dev-next-release.3", "description": "Slice Machine adapter for Next.js.", "keywords": [ "typescript", diff --git a/packages/adapter-nuxt/package.json b/packages/adapter-nuxt/package.json index e7795ec577..f9a6052f2e 100644 --- a/packages/adapter-nuxt/package.json +++ b/packages/adapter-nuxt/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/adapter-nuxt", - "version": "0.3.20-dev-next-release.2", + "version": "0.3.20-dev-next-release.3", "description": "Slice Machine adapter for Nuxt 3.", "keywords": [ "typescript", diff --git a/packages/adapter-nuxt2/package.json b/packages/adapter-nuxt2/package.json index 45323368d9..7217070a6a 100644 --- a/packages/adapter-nuxt2/package.json +++ b/packages/adapter-nuxt2/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/adapter-nuxt2", - "version": "0.3.20-dev-next-release.2", + "version": "0.3.20-dev-next-release.3", "description": "Slice Machine adapter for Nuxt 2.", "keywords": [ "typescript", diff --git a/packages/adapter-sveltekit/package.json b/packages/adapter-sveltekit/package.json index 8e396c2310..328a1b3550 100644 --- a/packages/adapter-sveltekit/package.json +++ b/packages/adapter-sveltekit/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/adapter-sveltekit", - "version": "0.3.20-dev-next-release.2", + "version": "0.3.20-dev-next-release.3", "description": "Slice Machine adapter for SvelteKit.", "keywords": [ "typescript", diff --git a/packages/init/package.json b/packages/init/package.json index d477ead633..251dd4b14a 100644 --- a/packages/init/package.json +++ b/packages/init/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/init", - "version": "2.7.3-dev-next-release.2", + "version": "2.7.3-dev-next-release.3", "description": "Init Prismic Slice Machine in your project", "keywords": [ "typescript", diff --git a/packages/manager/package.json b/packages/manager/package.json index f1915b0b9d..d2897278b0 100644 --- a/packages/manager/package.json +++ b/packages/manager/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/manager", - "version": "0.13.1-dev-next-release.2", + "version": "0.13.1-dev-next-release.3", "description": "Manage all aspects of a Slice Machine project.", "repository": { "type": "git", diff --git a/packages/plugin-kit/package.json b/packages/plugin-kit/package.json index e1060c5a27..0ce0403397 100644 --- a/packages/plugin-kit/package.json +++ b/packages/plugin-kit/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/plugin-kit", - "version": "0.4.20-dev-next-release.2", + "version": "0.4.20-dev-next-release.3", "description": "A set of helpers to develop and run Slice Machine plugins", "keywords": [ "typescript", diff --git a/packages/slice-machine/package.json b/packages/slice-machine/package.json index 5c86b1582f..76d4bc3a01 100644 --- a/packages/slice-machine/package.json +++ b/packages/slice-machine/package.json @@ -1,6 +1,6 @@ { "name": "slice-machine-ui", - "version": "1.16.1-dev-next-release.2", + "version": "1.16.1-dev-next-release.3", "license": "MIT", "description": "A visual builder for your Slice Models with all the tools you need to generate data models and mock CMS content locally.", "repository": { diff --git a/packages/start-slicemachine/package.json b/packages/start-slicemachine/package.json index 66123806b8..e1d616c909 100644 --- a/packages/start-slicemachine/package.json +++ b/packages/start-slicemachine/package.json @@ -1,6 +1,6 @@ { "name": "start-slicemachine", - "version": "0.11.10-dev-next-release.2", + "version": "0.11.10-dev-next-release.3", "description": "Start Slice Machine from within a project.", "repository": { "type": "git", From 61ff872b2b34fa40ac60e69a82d37132a37c780c Mon Sep 17 00:00:00 2001 From: Lucie <25330882+lihbr@users.noreply.github.com> Date: Thu, 12 Oct 2023 12:00:58 +0200 Subject: [PATCH 11/16] feat(slice-machine): labs page (DT-1675) (#1166) Co-authored-by: lihbr Co-authored-by: Baptiste Morelle --- e2e-projects/next-upgrade/package.json | 2 +- .../next-upgrade/slicemachine.config.json | 6 +- e2e-projects/next/package.json | 2 +- e2e-projects/sveltekit/package.json | 2 +- packages/adapter-next/package.json | 2 +- packages/adapter-nuxt/package.json | 2 +- packages/adapter-nuxt2/package.json | 2 +- packages/adapter-sveltekit/package.json | 2 +- packages/init/package.json | 2 +- packages/manager/package.json | 2 +- .../src/lib/decodeSliceMachineConfig.ts | 1 + packages/manager/src/types.ts | 1 + packages/plugin-kit/package.json | 2 +- .../src/lib/decodeSliceMachineConfig.ts | 1 + packages/plugin-kit/src/types.ts | 1 + .../CustomTypeBuilder/SliceZone/List.tsx | 25 +++++-- packages/slice-machine/package.json | 2 +- packages/slice-machine/pages/labs.tsx | 1 + .../src/features/labs/labsList/LabsList.tsx | 70 +++++++++++++++++++ .../features/labs/labsList/LabsListItem.tsx | 36 ++++++++++ .../src/features/labs/labsList/LabsPage.tsx | 70 +++++++++++++++++++ .../src/features/labs/labsList/useLab.tsx | 32 +++++++++ .../sliceCards/NonSharedSliceViewCard.tsx | 61 ++++++++-------- .../src/hooks/useSliceMachineConfig.ts | 24 +++++++ packages/start-slicemachine/package.json | 2 +- .../src/lib/createSliceMachineExpressApp.ts | 4 ++ 26 files changed, 305 insertions(+), 52 deletions(-) create mode 100644 packages/slice-machine/pages/labs.tsx create mode 100644 packages/slice-machine/src/features/labs/labsList/LabsList.tsx create mode 100644 packages/slice-machine/src/features/labs/labsList/LabsListItem.tsx create mode 100644 packages/slice-machine/src/features/labs/labsList/LabsPage.tsx create mode 100644 packages/slice-machine/src/features/labs/labsList/useLab.tsx create mode 100644 packages/slice-machine/src/hooks/useSliceMachineConfig.ts diff --git a/e2e-projects/next-upgrade/package.json b/e2e-projects/next-upgrade/package.json index d147a55d31..ec97670bbf 100644 --- a/e2e-projects/next-upgrade/package.json +++ b/e2e-projects/next-upgrade/package.json @@ -1,6 +1,6 @@ { "name": "next-upgrade", - "version": "1.14.1-dev-next-release.2", + "version": "1.14.1-dev-labs.4", "private": true, "scripts": { "dev": "next dev", diff --git a/e2e-projects/next-upgrade/slicemachine.config.json b/e2e-projects/next-upgrade/slicemachine.config.json index adcee3fd17..811d4719a3 100644 --- a/e2e-projects/next-upgrade/slicemachine.config.json +++ b/e2e-projects/next-upgrade/slicemachine.config.json @@ -1,8 +1,6 @@ { "repositoryName": "upgrade-optimize-full-legacy", "adapter": "@slicemachine/adapter-next", - "libraries": [ - "./slices" - ], + "libraries": ["./slices"], "localSliceSimulatorURL": "http://localhost:3000/slice-simulator" -} \ No newline at end of file +} diff --git a/e2e-projects/next/package.json b/e2e-projects/next/package.json index 5e183912de..75a431a4a0 100644 --- a/e2e-projects/next/package.json +++ b/e2e-projects/next/package.json @@ -1,6 +1,6 @@ { "name": "cimsirp", - "version": "1.16.1-dev-next-release.3", + "version": "1.16.1-dev-labs.4", "private": true, "scripts": { "dev": "next dev", diff --git a/e2e-projects/sveltekit/package.json b/e2e-projects/sveltekit/package.json index d8f45b62c4..bb3b185dfa 100644 --- a/e2e-projects/sveltekit/package.json +++ b/e2e-projects/sveltekit/package.json @@ -1,6 +1,6 @@ { "name": "sveltekit", - "version": "1.16.1-dev-next-release.3", + "version": "1.16.1-dev-labs.4", "private": true, "scripts": { "dev": "vite dev", diff --git a/packages/adapter-next/package.json b/packages/adapter-next/package.json index fe05e8f2b1..b5864f4d75 100644 --- a/packages/adapter-next/package.json +++ b/packages/adapter-next/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/adapter-next", - "version": "0.3.20-dev-next-release.3", + "version": "0.3.20-dev-labs.4", "description": "Slice Machine adapter for Next.js.", "keywords": [ "typescript", diff --git a/packages/adapter-nuxt/package.json b/packages/adapter-nuxt/package.json index f9a6052f2e..532932fd16 100644 --- a/packages/adapter-nuxt/package.json +++ b/packages/adapter-nuxt/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/adapter-nuxt", - "version": "0.3.20-dev-next-release.3", + "version": "0.3.20-dev-labs.4", "description": "Slice Machine adapter for Nuxt 3.", "keywords": [ "typescript", diff --git a/packages/adapter-nuxt2/package.json b/packages/adapter-nuxt2/package.json index 7217070a6a..b9cb6f8497 100644 --- a/packages/adapter-nuxt2/package.json +++ b/packages/adapter-nuxt2/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/adapter-nuxt2", - "version": "0.3.20-dev-next-release.3", + "version": "0.3.20-dev-labs.4", "description": "Slice Machine adapter for Nuxt 2.", "keywords": [ "typescript", diff --git a/packages/adapter-sveltekit/package.json b/packages/adapter-sveltekit/package.json index 328a1b3550..195a13810d 100644 --- a/packages/adapter-sveltekit/package.json +++ b/packages/adapter-sveltekit/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/adapter-sveltekit", - "version": "0.3.20-dev-next-release.3", + "version": "0.3.20-dev-labs.4", "description": "Slice Machine adapter for SvelteKit.", "keywords": [ "typescript", diff --git a/packages/init/package.json b/packages/init/package.json index 251dd4b14a..f85f45539d 100644 --- a/packages/init/package.json +++ b/packages/init/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/init", - "version": "2.7.3-dev-next-release.3", + "version": "2.7.3-dev-labs.4", "description": "Init Prismic Slice Machine in your project", "keywords": [ "typescript", diff --git a/packages/manager/package.json b/packages/manager/package.json index d2897278b0..cef8244188 100644 --- a/packages/manager/package.json +++ b/packages/manager/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/manager", - "version": "0.13.1-dev-next-release.3", + "version": "0.13.1-dev-labs.4", "description": "Manage all aspects of a Slice Machine project.", "repository": { "type": "git", diff --git a/packages/manager/src/lib/decodeSliceMachineConfig.ts b/packages/manager/src/lib/decodeSliceMachineConfig.ts index fa67dea251..7704dcffbc 100644 --- a/packages/manager/src/lib/decodeSliceMachineConfig.ts +++ b/packages/manager/src/lib/decodeSliceMachineConfig.ts @@ -26,6 +26,7 @@ const SliceMachineConfigCodec = t.intersection([ libraries: t.array(t.string), localSliceSimulatorURL: t.string, plugins: t.array(SliceMachineConfigPluginRegistrationCodec), + labs: t.partial({ legacySliceUpgrader: t.boolean }), }), ]); diff --git a/packages/manager/src/types.ts b/packages/manager/src/types.ts index 4a94f574e0..3ee2dbce1e 100644 --- a/packages/manager/src/types.ts +++ b/packages/manager/src/types.ts @@ -30,6 +30,7 @@ export type SliceMachineConfig = { libraries?: string[]; adapter: SliceMachineConfigPluginRegistration; plugins?: SliceMachineConfigPluginRegistration[]; + labs?: { legacySliceUpgrader?: boolean }; }; export type OnlyHookErrors< diff --git a/packages/plugin-kit/package.json b/packages/plugin-kit/package.json index 0ce0403397..0602b27778 100644 --- a/packages/plugin-kit/package.json +++ b/packages/plugin-kit/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/plugin-kit", - "version": "0.4.20-dev-next-release.3", + "version": "0.4.20-dev-labs.4", "description": "A set of helpers to develop and run Slice Machine plugins", "keywords": [ "typescript", diff --git a/packages/plugin-kit/src/lib/decodeSliceMachineConfig.ts b/packages/plugin-kit/src/lib/decodeSliceMachineConfig.ts index fa67dea251..7704dcffbc 100644 --- a/packages/plugin-kit/src/lib/decodeSliceMachineConfig.ts +++ b/packages/plugin-kit/src/lib/decodeSliceMachineConfig.ts @@ -26,6 +26,7 @@ const SliceMachineConfigCodec = t.intersection([ libraries: t.array(t.string), localSliceSimulatorURL: t.string, plugins: t.array(SliceMachineConfigPluginRegistrationCodec), + labs: t.partial({ legacySliceUpgrader: t.boolean }), }), ]); diff --git a/packages/plugin-kit/src/types.ts b/packages/plugin-kit/src/types.ts index 4d3ed86f71..094be61647 100644 --- a/packages/plugin-kit/src/types.ts +++ b/packages/plugin-kit/src/types.ts @@ -68,6 +68,7 @@ export type SliceMachineConfig = { libraries?: string[]; adapter: SliceMachineConfigPluginRegistration; plugins?: SliceMachineConfigPluginRegistration[]; + labs?: { legacySliceUpgrader?: boolean }; }; /** diff --git a/packages/slice-machine/lib/builders/CustomTypeBuilder/SliceZone/List.tsx b/packages/slice-machine/lib/builders/CustomTypeBuilder/SliceZone/List.tsx index ca42250cea..50604f0564 100644 --- a/packages/slice-machine/lib/builders/CustomTypeBuilder/SliceZone/List.tsx +++ b/packages/slice-machine/lib/builders/CustomTypeBuilder/SliceZone/List.tsx @@ -12,6 +12,7 @@ import { CustomTypeFormat } from "@slicemachine/manager"; import { CUSTOM_TYPES_MESSAGES } from "@src/features/customTypes/customTypesMessages"; import { NonSharedSliceViewCard } from "@src/features/slices/sliceCards/NonSharedSliceViewCard"; import { SharedSliceViewCard } from "@src/features/slices/sliceCards/SharedSliceViewCard"; +import { useLab } from "@src/features/labs/labsList/useLab"; interface SlicesListProps { format: CustomTypeFormat; @@ -33,17 +34,27 @@ export const SlicesList: React.FC = ({ const hasLegacySlices = slices.some((slice) => slice.type !== "SharedSlice"); const customTypesMessages = CUSTOM_TYPES_MESSAGES[format]; + const [legacySliceUpgraderLab] = useLab("legacySliceUpgrader"); + const { openToaster } = useSliceMachineActions(); useEffect(() => { if (hasLegacySlices) - openToaster( - `This ${customTypesMessages.name({ - start: false, - plural: false, - })} contains legacy slices that can be upgraded.`, - ToasterType.INFO - ); + legacySliceUpgraderLab.enabled + ? openToaster( + `This ${customTypesMessages.name({ + start: false, + plural: false, + })} contains legacy slices that can be upgraded.`, + ToasterType.INFO + ) + : openToaster( + `This ${customTypesMessages.name({ + start: false, + plural: false, + })} contains slices that are incompatible.`, + ToasterType.WARNING + ); // eslint-disable-next-line react-hooks/exhaustive-deps }, [hasLegacySlices]); diff --git a/packages/slice-machine/package.json b/packages/slice-machine/package.json index 76d4bc3a01..e3cf4a4c5d 100644 --- a/packages/slice-machine/package.json +++ b/packages/slice-machine/package.json @@ -1,6 +1,6 @@ { "name": "slice-machine-ui", - "version": "1.16.1-dev-next-release.3", + "version": "1.16.1-dev-labs.4", "license": "MIT", "description": "A visual builder for your Slice Models with all the tools you need to generate data models and mock CMS content locally.", "repository": { diff --git a/packages/slice-machine/pages/labs.tsx b/packages/slice-machine/pages/labs.tsx new file mode 100644 index 0000000000..dc6a5c5f20 --- /dev/null +++ b/packages/slice-machine/pages/labs.tsx @@ -0,0 +1 @@ +export { LabsPage as default } from "@src/features/labs/labsList/LabsPage"; diff --git a/packages/slice-machine/src/features/labs/labsList/LabsList.tsx b/packages/slice-machine/src/features/labs/labsList/LabsList.tsx new file mode 100644 index 0000000000..19934a0efc --- /dev/null +++ b/packages/slice-machine/src/features/labs/labsList/LabsList.tsx @@ -0,0 +1,70 @@ +import type { FC } from "react"; +import { Box, Text } from "@prismicio/editor-ui"; + +import useSliceMachineActions from "@src/modules/useSliceMachineActions"; +import { ToasterType } from "@src/modules/toaster"; + +import { LabsListItem } from "./LabsListItem"; +import { type UseLabArgs, type UseLabReturnType, useLab } from "./useLab"; + +export const LabsList: FC = () => { + const [legacySliceUpgraderLab, setLegacySliceUpgraderLab] = useLabWithToast( + "legacySliceUpgrader", + "Legacy Slice Upgrader" + ); + + return ( + +
+ + Slice Machine Labs gives you early access to new features before + they're available to everyone. + + + Experimental features are works-in-progress and unstable, so you may + find some bugs along the way. + +
+ + void setLegacySliceUpgraderLab(enabled)} + > + The Legacy Slice Upgrader allows you to convert old slices (legacy and + composite slices) to slices managed by Slice Machine (shared slices). + This feature is experimental, we strongly encourage you testing it + through a Prismic environment first or you'll be at risk of losing + past content. + + +
+ ); +}; + +function useLabWithToast(key: UseLabArgs, name: string): UseLabReturnType { + const { openToaster } = useSliceMachineActions(); + const [lab, setLab] = useLab(key); + + const setLabWithToast = async (enabled: boolean) => { + try { + await setLab(enabled); + + openToaster( + enabled ? `Labs: enabled ${name}` : `Labs: disabled ${name}`, + ToasterType.SUCCESS + ); + } catch (error) { + console.error(error); + + openToaster( + enabled + ? `Labs: failed to enable ${name}` + : `Labs: failed to disable ${name}`, + ToasterType.ERROR + ); + } + }; + + return [lab, setLabWithToast]; +} diff --git a/packages/slice-machine/src/features/labs/labsList/LabsListItem.tsx b/packages/slice-machine/src/features/labs/labsList/LabsListItem.tsx new file mode 100644 index 0000000000..447a05c599 --- /dev/null +++ b/packages/slice-machine/src/features/labs/labsList/LabsListItem.tsx @@ -0,0 +1,36 @@ +import { type FC, type PropsWithChildren } from "react"; +import { Switch, Box, Card, Icon, Text } from "@prismicio/editor-ui"; + +type LabsListItemProps = PropsWithChildren<{ + title: string; + enabled: boolean; + onToggle: (enabled: boolean) => void; +}>; + +export const LabsListItem: FC = ({ + title, + enabled, + onToggle, + children, +}) => { + return ( + + + + + + + {title} + {children} + + + onToggle(checked)} + /> + + + + ); +}; diff --git a/packages/slice-machine/src/features/labs/labsList/LabsPage.tsx b/packages/slice-machine/src/features/labs/labsList/LabsPage.tsx new file mode 100644 index 0000000000..d4bd5b45f3 --- /dev/null +++ b/packages/slice-machine/src/features/labs/labsList/LabsPage.tsx @@ -0,0 +1,70 @@ +import { type FC, ReactNode, Suspense } from "react"; +import { + ErrorBoundary, + Box, + ProgressCircle, + DefaultErrorMessage, +} from "@prismicio/editor-ui"; +import Head from "next/head"; + +import { + AppLayout, + AppLayoutBreadcrumb, + AppLayoutContent, + AppLayoutHeader, +} from "@components/AppLayout"; + +import { LabsList } from "./LabsList"; + +export const LabsPage: FC = () => { + return ( + <> + + Labs - Slice Machine + + ( + + + + + + )} + > + + + + } + > + + + + + + + ); +}; + +type LabsPageLayoutProps = { + children: ReactNode; + withHeader?: boolean; +}; + +const LabsPageLayout: FC = ({ + children, + withHeader = false, +}) => ( + + {withHeader ? ( + + + + ) : null} + {children} + +); diff --git a/packages/slice-machine/src/features/labs/labsList/useLab.tsx b/packages/slice-machine/src/features/labs/labsList/useLab.tsx new file mode 100644 index 0000000000..8617fdfa82 --- /dev/null +++ b/packages/slice-machine/src/features/labs/labsList/useLab.tsx @@ -0,0 +1,32 @@ +import type { SliceMachineConfig } from "@slicemachine/manager"; + +import { useSliceMachineConfig } from "@src/hooks/useSliceMachineConfig"; + +export type UseLabArgs = keyof Required["labs"]; + +export type UseLabReturnType = [ + lab: { enabled: boolean }, + setLab: (enabled: boolean) => Promise +]; + +export function useLab(key: UseLabArgs): UseLabReturnType { + const [config, setConfig] = useSliceMachineConfig(); + + const setLab = async (enabled: boolean) => { + const updatedConfig = { ...config, labs: { ...config.labs } }; + + if (enabled) { + updatedConfig.labs[key] = enabled; + } else if (key in updatedConfig.labs) { + delete updatedConfig.labs[key]; + } + + if (Object.keys(updatedConfig.labs).length === 0) { + delete (updatedConfig as SliceMachineConfig).labs; + } + + await setConfig(updatedConfig); + }; + + return [{ enabled: config?.labs?.[key] ?? false }, setLab]; +} diff --git a/packages/slice-machine/src/features/slices/sliceCards/NonSharedSliceViewCard.tsx b/packages/slice-machine/src/features/slices/sliceCards/NonSharedSliceViewCard.tsx index 2ea782ba02..ca05533788 100644 --- a/packages/slice-machine/src/features/slices/sliceCards/NonSharedSliceViewCard.tsx +++ b/packages/slice-machine/src/features/slices/sliceCards/NonSharedSliceViewCard.tsx @@ -4,6 +4,7 @@ import type { FC } from "react"; import { type NonSharedSliceInSliceZone } from "@models/common/CustomType/sliceZone"; import { Card, CardActions, CardFooter, CardMedia } from "@src/components/Card"; import { getNonSharedSliceLabel } from "@src/domain/slice"; +import { useLab } from "@src/features/labs/labsList/useLab"; import { ConvertLegacySliceButton } from "../convertLegacySlice/ConvertLegacySliceButton"; @@ -19,32 +20,34 @@ export type NonSharedSliceViewCardProps = { export const NonSharedSliceViewCard: FC = ({ slice, path, -}) => ( - - - - - No screenshot available - - - - - - - - {/* TODO(DT-1675): remove this `div` when the migration of Legacy Slices has been validated. */} -
- -
-
- -
-); +}) => { + const [legacySliceUpgraderLab] = useLab("legacySliceUpgrader"); + + const tooltipContent = legacySliceUpgraderLab.enabled + ? "This Slice was created with the Legacy Builder. It needs to be converted first to be used within Slice Machine." + : "This Slice was created with the Legacy Builder, and is incompatible with Slice Machine. You cannot edit, push, or delete it in Slice Machine. In order to proceed, manually remove the Slice from your type model. Then create a new Slice with the same fields using Slice Machine."; + + return ( + + + + + No screenshot available + + + + + + + + {legacySliceUpgraderLab.enabled ? ( + + ) : null} + + + + ); +}; diff --git a/packages/slice-machine/src/hooks/useSliceMachineConfig.ts b/packages/slice-machine/src/hooks/useSliceMachineConfig.ts new file mode 100644 index 0000000000..3a4663c021 --- /dev/null +++ b/packages/slice-machine/src/hooks/useSliceMachineConfig.ts @@ -0,0 +1,24 @@ +import { useRequest, updateData } from "@prismicio/editor-support/Suspense"; +import type { SliceMachineConfig } from "@slicemachine/manager"; + +import { managerClient } from "@src/managerClient"; + +type UseSliceMachineConfigReturnType = [ + config: SliceMachineConfig, + setConfig: (config: SliceMachineConfig) => Promise +]; + +export function useSliceMachineConfig(): UseSliceMachineConfigReturnType { + const config = useRequest(readSliceMachineConfig, []); + + const setConfig = async (config: SliceMachineConfig) => { + await managerClient.project.writeSliceMachineConfig({ config }); + updateData(readSliceMachineConfig, [], config); + }; + + return [config, setConfig]; +} + +async function readSliceMachineConfig(): Promise { + return managerClient.project.getSliceMachineConfig(); +} diff --git a/packages/start-slicemachine/package.json b/packages/start-slicemachine/package.json index e1d616c909..fff1ef5e89 100644 --- a/packages/start-slicemachine/package.json +++ b/packages/start-slicemachine/package.json @@ -1,6 +1,6 @@ { "name": "start-slicemachine", - "version": "0.11.10-dev-next-release.3", + "version": "0.11.10-dev-labs.4", "description": "Start Slice Machine from within a project.", "repository": { "type": "git", diff --git a/packages/start-slicemachine/src/lib/createSliceMachineExpressApp.ts b/packages/start-slicemachine/src/lib/createSliceMachineExpressApp.ts index e4d5b307da..5d26bfa9aa 100644 --- a/packages/start-slicemachine/src/lib/createSliceMachineExpressApp.ts +++ b/packages/start-slicemachine/src/lib/createSliceMachineExpressApp.ts @@ -101,6 +101,10 @@ export const createSliceMachineExpressApp = async ( res.sendFile(path.join(sliceMachineOutDir, "changelog.html")); }); + app.get("/labs", (_req, res) => { + res.sendFile(path.join(sliceMachineOutDir, "labs.html")); + }); + app.get("/slices", (_req, res) => { res.sendFile(path.join(sliceMachineOutDir, "slices.html")); }); From c00e7744ca6521500d14415ae79b2f7017ab2597 Mon Sep 17 00:00:00 2001 From: Lucie <25330882+lihbr@users.noreply.github.com> Date: Thu, 12 Oct 2023 12:10:17 +0200 Subject: [PATCH 12/16] fix(slice-machine): convert legacy slice dialog overflow (DT-1677) (#1168) Co-authored-by: lihbr --- .../ConvertLegacySliceAsNewSliceDialog.tsx | 5 ++++- .../ConvertLegacySliceAsNewVariationDialog.tsx | 5 ++++- .../ConvertLegacySliceMergeWithIdenticalDialog.tsx | 5 ++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/slice-machine/src/features/slices/convertLegacySlice/ConvertLegacySliceAsNewSliceDialog.tsx b/packages/slice-machine/src/features/slices/convertLegacySlice/ConvertLegacySliceAsNewSliceDialog.tsx index 92e5f25331..3ed12ade6d 100644 --- a/packages/slice-machine/src/features/slices/convertLegacySlice/ConvertLegacySliceAsNewSliceDialog.tsx +++ b/packages/slice-machine/src/features/slices/convertLegacySlice/ConvertLegacySliceAsNewSliceDialog.tsx @@ -61,7 +61,10 @@ export const ConvertLegacySliceAsNewSliceDialog: FC = ({ return (
- + This will create a new slice with the same fields. The new slice will replace the legacy slice in all of your types, diff --git a/packages/slice-machine/src/features/slices/convertLegacySlice/ConvertLegacySliceAsNewVariationDialog.tsx b/packages/slice-machine/src/features/slices/convertLegacySlice/ConvertLegacySliceAsNewVariationDialog.tsx index 06f0a83090..a2b47c6f15 100644 --- a/packages/slice-machine/src/features/slices/convertLegacySlice/ConvertLegacySliceAsNewVariationDialog.tsx +++ b/packages/slice-machine/src/features/slices/convertLegacySlice/ConvertLegacySliceAsNewVariationDialog.tsx @@ -65,7 +65,10 @@ export const ConvertLegacySliceAsNewVariationDialog: FC = ({ return ( - + If you have multiple slices that are similar, you can combine them as variations of the same slice. diff --git a/packages/slice-machine/src/features/slices/convertLegacySlice/ConvertLegacySliceMergeWithIdenticalDialog.tsx b/packages/slice-machine/src/features/slices/convertLegacySlice/ConvertLegacySliceMergeWithIdenticalDialog.tsx index 2a41dd873a..cf78c80f4c 100644 --- a/packages/slice-machine/src/features/slices/convertLegacySlice/ConvertLegacySliceMergeWithIdenticalDialog.tsx +++ b/packages/slice-machine/src/features/slices/convertLegacySlice/ConvertLegacySliceMergeWithIdenticalDialog.tsx @@ -49,7 +49,10 @@ export const ConvertLegacySliceMergeWithIdenticalDialog: FC = ({ return ( - + If you have multiple identical slices, you can merge them. All of your content will be remapped to the target slice. From f7993f53edae10822338015c454b16d5e3fa962a Mon Sep 17 00:00:00 2001 From: Baptiste Morelle Date: Thu, 12 Oct 2023 12:19:13 +0200 Subject: [PATCH 13/16] chore: fix dev versions --- e2e-projects/next-upgrade/package.json | 2 +- e2e-projects/next/package.json | 2 +- e2e-projects/sveltekit/package.json | 2 +- packages/adapter-next/package.json | 2 +- packages/adapter-nuxt/package.json | 2 +- packages/adapter-nuxt2/package.json | 2 +- packages/adapter-sveltekit/package.json | 2 +- packages/init/package.json | 2 +- packages/manager/package.json | 2 +- packages/plugin-kit/package.json | 2 +- packages/slice-machine/package.json | 2 +- packages/start-slicemachine/package.json | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/e2e-projects/next-upgrade/package.json b/e2e-projects/next-upgrade/package.json index ec97670bbf..ebe4a4bc7d 100644 --- a/e2e-projects/next-upgrade/package.json +++ b/e2e-projects/next-upgrade/package.json @@ -1,6 +1,6 @@ { "name": "next-upgrade", - "version": "1.14.1-dev-labs.4", + "version": "1.14.1-dev-next-release.3", "private": true, "scripts": { "dev": "next dev", diff --git a/e2e-projects/next/package.json b/e2e-projects/next/package.json index 75a431a4a0..5e183912de 100644 --- a/e2e-projects/next/package.json +++ b/e2e-projects/next/package.json @@ -1,6 +1,6 @@ { "name": "cimsirp", - "version": "1.16.1-dev-labs.4", + "version": "1.16.1-dev-next-release.3", "private": true, "scripts": { "dev": "next dev", diff --git a/e2e-projects/sveltekit/package.json b/e2e-projects/sveltekit/package.json index bb3b185dfa..d8f45b62c4 100644 --- a/e2e-projects/sveltekit/package.json +++ b/e2e-projects/sveltekit/package.json @@ -1,6 +1,6 @@ { "name": "sveltekit", - "version": "1.16.1-dev-labs.4", + "version": "1.16.1-dev-next-release.3", "private": true, "scripts": { "dev": "vite dev", diff --git a/packages/adapter-next/package.json b/packages/adapter-next/package.json index b5864f4d75..fe05e8f2b1 100644 --- a/packages/adapter-next/package.json +++ b/packages/adapter-next/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/adapter-next", - "version": "0.3.20-dev-labs.4", + "version": "0.3.20-dev-next-release.3", "description": "Slice Machine adapter for Next.js.", "keywords": [ "typescript", diff --git a/packages/adapter-nuxt/package.json b/packages/adapter-nuxt/package.json index 532932fd16..f9a6052f2e 100644 --- a/packages/adapter-nuxt/package.json +++ b/packages/adapter-nuxt/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/adapter-nuxt", - "version": "0.3.20-dev-labs.4", + "version": "0.3.20-dev-next-release.3", "description": "Slice Machine adapter for Nuxt 3.", "keywords": [ "typescript", diff --git a/packages/adapter-nuxt2/package.json b/packages/adapter-nuxt2/package.json index b9cb6f8497..7217070a6a 100644 --- a/packages/adapter-nuxt2/package.json +++ b/packages/adapter-nuxt2/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/adapter-nuxt2", - "version": "0.3.20-dev-labs.4", + "version": "0.3.20-dev-next-release.3", "description": "Slice Machine adapter for Nuxt 2.", "keywords": [ "typescript", diff --git a/packages/adapter-sveltekit/package.json b/packages/adapter-sveltekit/package.json index 195a13810d..328a1b3550 100644 --- a/packages/adapter-sveltekit/package.json +++ b/packages/adapter-sveltekit/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/adapter-sveltekit", - "version": "0.3.20-dev-labs.4", + "version": "0.3.20-dev-next-release.3", "description": "Slice Machine adapter for SvelteKit.", "keywords": [ "typescript", diff --git a/packages/init/package.json b/packages/init/package.json index f85f45539d..251dd4b14a 100644 --- a/packages/init/package.json +++ b/packages/init/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/init", - "version": "2.7.3-dev-labs.4", + "version": "2.7.3-dev-next-release.3", "description": "Init Prismic Slice Machine in your project", "keywords": [ "typescript", diff --git a/packages/manager/package.json b/packages/manager/package.json index cef8244188..d2897278b0 100644 --- a/packages/manager/package.json +++ b/packages/manager/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/manager", - "version": "0.13.1-dev-labs.4", + "version": "0.13.1-dev-next-release.3", "description": "Manage all aspects of a Slice Machine project.", "repository": { "type": "git", diff --git a/packages/plugin-kit/package.json b/packages/plugin-kit/package.json index 0602b27778..0ce0403397 100644 --- a/packages/plugin-kit/package.json +++ b/packages/plugin-kit/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/plugin-kit", - "version": "0.4.20-dev-labs.4", + "version": "0.4.20-dev-next-release.3", "description": "A set of helpers to develop and run Slice Machine plugins", "keywords": [ "typescript", diff --git a/packages/slice-machine/package.json b/packages/slice-machine/package.json index e3cf4a4c5d..76d4bc3a01 100644 --- a/packages/slice-machine/package.json +++ b/packages/slice-machine/package.json @@ -1,6 +1,6 @@ { "name": "slice-machine-ui", - "version": "1.16.1-dev-labs.4", + "version": "1.16.1-dev-next-release.3", "license": "MIT", "description": "A visual builder for your Slice Models with all the tools you need to generate data models and mock CMS content locally.", "repository": { diff --git a/packages/start-slicemachine/package.json b/packages/start-slicemachine/package.json index fff1ef5e89..e1d616c909 100644 --- a/packages/start-slicemachine/package.json +++ b/packages/start-slicemachine/package.json @@ -1,6 +1,6 @@ { "name": "start-slicemachine", - "version": "0.11.10-dev-labs.4", + "version": "0.11.10-dev-next-release.3", "description": "Start Slice Machine from within a project.", "repository": { "type": "git", From 959e80832ac9d5e4c8951e2d6d2facb4edece7b6 Mon Sep 17 00:00:00 2001 From: bapmrl Date: Thu, 12 Oct 2023 10:22:22 +0000 Subject: [PATCH 14/16] Publish - cimsirp@1.16.1-dev-next-release.4 - next-upgrade@1.14.1-dev-next-release.4 - sveltekit@1.16.1-dev-next-release.4 - @slicemachine/adapter-next@0.3.20-dev-next-release.4 - @slicemachine/adapter-nuxt@0.3.20-dev-next-release.4 - @slicemachine/adapter-nuxt2@0.3.20-dev-next-release.4 - @slicemachine/adapter-sveltekit@0.3.20-dev-next-release.4 - @slicemachine/init@2.7.3-dev-next-release.4 - @slicemachine/manager@0.13.1-dev-next-release.4 - @slicemachine/plugin-kit@0.4.20-dev-next-release.4 - slice-machine-ui@1.16.1-dev-next-release.4 - start-slicemachine@0.11.10-dev-next-release.4 --- e2e-projects/next-upgrade/package.json | 2 +- e2e-projects/next/package.json | 2 +- e2e-projects/sveltekit/package.json | 2 +- packages/adapter-next/package.json | 2 +- packages/adapter-nuxt/package.json | 2 +- packages/adapter-nuxt2/package.json | 2 +- packages/adapter-sveltekit/package.json | 2 +- packages/init/package.json | 2 +- packages/manager/package.json | 2 +- packages/plugin-kit/package.json | 2 +- packages/slice-machine/package.json | 2 +- packages/start-slicemachine/package.json | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/e2e-projects/next-upgrade/package.json b/e2e-projects/next-upgrade/package.json index ebe4a4bc7d..780acf76bf 100644 --- a/e2e-projects/next-upgrade/package.json +++ b/e2e-projects/next-upgrade/package.json @@ -1,6 +1,6 @@ { "name": "next-upgrade", - "version": "1.14.1-dev-next-release.3", + "version": "1.14.1-dev-next-release.4", "private": true, "scripts": { "dev": "next dev", diff --git a/e2e-projects/next/package.json b/e2e-projects/next/package.json index 5e183912de..e0b91aba4b 100644 --- a/e2e-projects/next/package.json +++ b/e2e-projects/next/package.json @@ -1,6 +1,6 @@ { "name": "cimsirp", - "version": "1.16.1-dev-next-release.3", + "version": "1.16.1-dev-next-release.4", "private": true, "scripts": { "dev": "next dev", diff --git a/e2e-projects/sveltekit/package.json b/e2e-projects/sveltekit/package.json index d8f45b62c4..26991e3187 100644 --- a/e2e-projects/sveltekit/package.json +++ b/e2e-projects/sveltekit/package.json @@ -1,6 +1,6 @@ { "name": "sveltekit", - "version": "1.16.1-dev-next-release.3", + "version": "1.16.1-dev-next-release.4", "private": true, "scripts": { "dev": "vite dev", diff --git a/packages/adapter-next/package.json b/packages/adapter-next/package.json index fe05e8f2b1..5359b0c54a 100644 --- a/packages/adapter-next/package.json +++ b/packages/adapter-next/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/adapter-next", - "version": "0.3.20-dev-next-release.3", + "version": "0.3.20-dev-next-release.4", "description": "Slice Machine adapter for Next.js.", "keywords": [ "typescript", diff --git a/packages/adapter-nuxt/package.json b/packages/adapter-nuxt/package.json index f9a6052f2e..4f7a36bf02 100644 --- a/packages/adapter-nuxt/package.json +++ b/packages/adapter-nuxt/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/adapter-nuxt", - "version": "0.3.20-dev-next-release.3", + "version": "0.3.20-dev-next-release.4", "description": "Slice Machine adapter for Nuxt 3.", "keywords": [ "typescript", diff --git a/packages/adapter-nuxt2/package.json b/packages/adapter-nuxt2/package.json index 7217070a6a..35ffb0556f 100644 --- a/packages/adapter-nuxt2/package.json +++ b/packages/adapter-nuxt2/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/adapter-nuxt2", - "version": "0.3.20-dev-next-release.3", + "version": "0.3.20-dev-next-release.4", "description": "Slice Machine adapter for Nuxt 2.", "keywords": [ "typescript", diff --git a/packages/adapter-sveltekit/package.json b/packages/adapter-sveltekit/package.json index 328a1b3550..f01e8bb5c6 100644 --- a/packages/adapter-sveltekit/package.json +++ b/packages/adapter-sveltekit/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/adapter-sveltekit", - "version": "0.3.20-dev-next-release.3", + "version": "0.3.20-dev-next-release.4", "description": "Slice Machine adapter for SvelteKit.", "keywords": [ "typescript", diff --git a/packages/init/package.json b/packages/init/package.json index 251dd4b14a..2c71d5074c 100644 --- a/packages/init/package.json +++ b/packages/init/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/init", - "version": "2.7.3-dev-next-release.3", + "version": "2.7.3-dev-next-release.4", "description": "Init Prismic Slice Machine in your project", "keywords": [ "typescript", diff --git a/packages/manager/package.json b/packages/manager/package.json index d2897278b0..f4f1302150 100644 --- a/packages/manager/package.json +++ b/packages/manager/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/manager", - "version": "0.13.1-dev-next-release.3", + "version": "0.13.1-dev-next-release.4", "description": "Manage all aspects of a Slice Machine project.", "repository": { "type": "git", diff --git a/packages/plugin-kit/package.json b/packages/plugin-kit/package.json index 0ce0403397..7d1d85c816 100644 --- a/packages/plugin-kit/package.json +++ b/packages/plugin-kit/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/plugin-kit", - "version": "0.4.20-dev-next-release.3", + "version": "0.4.20-dev-next-release.4", "description": "A set of helpers to develop and run Slice Machine plugins", "keywords": [ "typescript", diff --git a/packages/slice-machine/package.json b/packages/slice-machine/package.json index 76d4bc3a01..5f8c4539d6 100644 --- a/packages/slice-machine/package.json +++ b/packages/slice-machine/package.json @@ -1,6 +1,6 @@ { "name": "slice-machine-ui", - "version": "1.16.1-dev-next-release.3", + "version": "1.16.1-dev-next-release.4", "license": "MIT", "description": "A visual builder for your Slice Models with all the tools you need to generate data models and mock CMS content locally.", "repository": { diff --git a/packages/start-slicemachine/package.json b/packages/start-slicemachine/package.json index e1d616c909..81ff0752e8 100644 --- a/packages/start-slicemachine/package.json +++ b/packages/start-slicemachine/package.json @@ -1,6 +1,6 @@ { "name": "start-slicemachine", - "version": "0.11.10-dev-next-release.3", + "version": "0.11.10-dev-next-release.4", "description": "Start Slice Machine from within a project.", "repository": { "type": "git", From bd09152239881196083bb9200557448c3d65b8f7 Mon Sep 17 00:00:00 2001 From: lihbr Date: Thu, 12 Oct 2023 15:21:36 +0200 Subject: [PATCH 15/16] refactor(slice-machine): update wording --- .../src/features/labs/labsList/LabsList.tsx | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/packages/slice-machine/src/features/labs/labsList/LabsList.tsx b/packages/slice-machine/src/features/labs/labsList/LabsList.tsx index 19934a0efc..b3ec954313 100644 --- a/packages/slice-machine/src/features/labs/labsList/LabsList.tsx +++ b/packages/slice-machine/src/features/labs/labsList/LabsList.tsx @@ -18,11 +18,9 @@ export const LabsList: FC = () => {
Slice Machine Labs gives you early access to new features before - they're available to everyone. - - - Experimental features are works-in-progress and unstable, so you may - find some bugs along the way. + they're widely released. Experimental features are works-in-progress + and potentially unstable, so you may find some bugs and breaking + changes along the way.
@@ -33,9 +31,12 @@ export const LabsList: FC = () => { > The Legacy Slice Upgrader allows you to convert old slices (legacy and composite slices) to slices managed by Slice Machine (shared slices). - This feature is experimental, we strongly encourage you testing it - through a Prismic environment first or you'll be at risk of losing - past content. + This feature is experimental, and we strongly recommend that you test + it with a{" "} + + Prismic environment + {" "} + or you'll be at risk of losing past content.
From b353a1ff208777e8131d13f8720e88de7f444b07 Mon Sep 17 00:00:00 2001 From: lihbr Date: Thu, 12 Oct 2023 13:25:28 +0000 Subject: [PATCH 16/16] Publish - cimsirp@1.16.1-dev-next-release.5 - next-upgrade@1.14.1-dev-next-release.5 - sveltekit@1.16.1-dev-next-release.5 - @slicemachine/adapter-next@0.3.20-dev-next-release.5 - @slicemachine/adapter-nuxt@0.3.20-dev-next-release.5 - @slicemachine/adapter-nuxt2@0.3.20-dev-next-release.5 - @slicemachine/adapter-sveltekit@0.3.20-dev-next-release.5 - @slicemachine/init@2.7.3-dev-next-release.5 - @slicemachine/manager@0.13.1-dev-next-release.5 - @slicemachine/plugin-kit@0.4.20-dev-next-release.5 - slice-machine-ui@1.16.1-dev-next-release.5 - start-slicemachine@0.11.10-dev-next-release.5 --- e2e-projects/next-upgrade/package.json | 2 +- e2e-projects/next/package.json | 2 +- e2e-projects/sveltekit/package.json | 2 +- packages/adapter-next/package.json | 2 +- packages/adapter-nuxt/package.json | 2 +- packages/adapter-nuxt2/package.json | 2 +- packages/adapter-sveltekit/package.json | 2 +- packages/init/package.json | 2 +- packages/manager/package.json | 2 +- packages/plugin-kit/package.json | 2 +- packages/slice-machine/package.json | 2 +- packages/start-slicemachine/package.json | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/e2e-projects/next-upgrade/package.json b/e2e-projects/next-upgrade/package.json index 780acf76bf..2056073046 100644 --- a/e2e-projects/next-upgrade/package.json +++ b/e2e-projects/next-upgrade/package.json @@ -1,6 +1,6 @@ { "name": "next-upgrade", - "version": "1.14.1-dev-next-release.4", + "version": "1.14.1-dev-next-release.5", "private": true, "scripts": { "dev": "next dev", diff --git a/e2e-projects/next/package.json b/e2e-projects/next/package.json index e0b91aba4b..01d6d7c195 100644 --- a/e2e-projects/next/package.json +++ b/e2e-projects/next/package.json @@ -1,6 +1,6 @@ { "name": "cimsirp", - "version": "1.16.1-dev-next-release.4", + "version": "1.16.1-dev-next-release.5", "private": true, "scripts": { "dev": "next dev", diff --git a/e2e-projects/sveltekit/package.json b/e2e-projects/sveltekit/package.json index 26991e3187..a1fcf8598e 100644 --- a/e2e-projects/sveltekit/package.json +++ b/e2e-projects/sveltekit/package.json @@ -1,6 +1,6 @@ { "name": "sveltekit", - "version": "1.16.1-dev-next-release.4", + "version": "1.16.1-dev-next-release.5", "private": true, "scripts": { "dev": "vite dev", diff --git a/packages/adapter-next/package.json b/packages/adapter-next/package.json index 5359b0c54a..f82319992f 100644 --- a/packages/adapter-next/package.json +++ b/packages/adapter-next/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/adapter-next", - "version": "0.3.20-dev-next-release.4", + "version": "0.3.20-dev-next-release.5", "description": "Slice Machine adapter for Next.js.", "keywords": [ "typescript", diff --git a/packages/adapter-nuxt/package.json b/packages/adapter-nuxt/package.json index 4f7a36bf02..a03f6d03ad 100644 --- a/packages/adapter-nuxt/package.json +++ b/packages/adapter-nuxt/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/adapter-nuxt", - "version": "0.3.20-dev-next-release.4", + "version": "0.3.20-dev-next-release.5", "description": "Slice Machine adapter for Nuxt 3.", "keywords": [ "typescript", diff --git a/packages/adapter-nuxt2/package.json b/packages/adapter-nuxt2/package.json index 35ffb0556f..e0bb2efed8 100644 --- a/packages/adapter-nuxt2/package.json +++ b/packages/adapter-nuxt2/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/adapter-nuxt2", - "version": "0.3.20-dev-next-release.4", + "version": "0.3.20-dev-next-release.5", "description": "Slice Machine adapter for Nuxt 2.", "keywords": [ "typescript", diff --git a/packages/adapter-sveltekit/package.json b/packages/adapter-sveltekit/package.json index f01e8bb5c6..bc0d2cae85 100644 --- a/packages/adapter-sveltekit/package.json +++ b/packages/adapter-sveltekit/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/adapter-sveltekit", - "version": "0.3.20-dev-next-release.4", + "version": "0.3.20-dev-next-release.5", "description": "Slice Machine adapter for SvelteKit.", "keywords": [ "typescript", diff --git a/packages/init/package.json b/packages/init/package.json index 2c71d5074c..92a9e38268 100644 --- a/packages/init/package.json +++ b/packages/init/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/init", - "version": "2.7.3-dev-next-release.4", + "version": "2.7.3-dev-next-release.5", "description": "Init Prismic Slice Machine in your project", "keywords": [ "typescript", diff --git a/packages/manager/package.json b/packages/manager/package.json index f4f1302150..f1c6faa9f9 100644 --- a/packages/manager/package.json +++ b/packages/manager/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/manager", - "version": "0.13.1-dev-next-release.4", + "version": "0.13.1-dev-next-release.5", "description": "Manage all aspects of a Slice Machine project.", "repository": { "type": "git", diff --git a/packages/plugin-kit/package.json b/packages/plugin-kit/package.json index 7d1d85c816..210e554a6f 100644 --- a/packages/plugin-kit/package.json +++ b/packages/plugin-kit/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/plugin-kit", - "version": "0.4.20-dev-next-release.4", + "version": "0.4.20-dev-next-release.5", "description": "A set of helpers to develop and run Slice Machine plugins", "keywords": [ "typescript", diff --git a/packages/slice-machine/package.json b/packages/slice-machine/package.json index 5f8c4539d6..ffa87aafa7 100644 --- a/packages/slice-machine/package.json +++ b/packages/slice-machine/package.json @@ -1,6 +1,6 @@ { "name": "slice-machine-ui", - "version": "1.16.1-dev-next-release.4", + "version": "1.16.1-dev-next-release.5", "license": "MIT", "description": "A visual builder for your Slice Models with all the tools you need to generate data models and mock CMS content locally.", "repository": { diff --git a/packages/start-slicemachine/package.json b/packages/start-slicemachine/package.json index 81ff0752e8..03972c20fb 100644 --- a/packages/start-slicemachine/package.json +++ b/packages/start-slicemachine/package.json @@ -1,6 +1,6 @@ { "name": "start-slicemachine", - "version": "0.11.10-dev-next-release.4", + "version": "0.11.10-dev-next-release.5", "description": "Start Slice Machine from within a project.", "repository": { "type": "git",