-
Notifications
You must be signed in to change notification settings - Fork 9
Setup Storybook for HTML mails in Demo-API #4954
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| { | ||
| "presets": ["@comet/admin-babel-preset"] | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| import { type Decorator } from "@storybook/react-webpack5"; | ||
| import { de, enUS } from "date-fns/locale"; | ||
| import { IntlProvider } from "react-intl"; | ||
|
|
||
| enum LocaleOption { | ||
| German = "de", | ||
| English = "en", | ||
| } | ||
|
|
||
| function isLocaleOption(value: any): value is LocaleOption { | ||
| return value === "de" || value === "en"; | ||
| } | ||
|
|
||
| type DateFnsLocale = typeof de; | ||
| const dateFnsLocales: Record<LocaleOption, DateFnsLocale> = { | ||
| [LocaleOption.German]: de, | ||
| [LocaleOption.English]: enUS, | ||
| }; | ||
|
|
||
| // @TODO: use messages from lang-package | ||
| const messages: Record<LocaleOption, Record<string, string>> = { | ||
| en: { | ||
| "comet.core.deleteMutation.promptDelete": "Delete data?", | ||
| "comet.core.deleteMutation.yes": "Yes", | ||
| "comet.core.deleteMutation.no": "No", | ||
| "comet.core.dirtyHandler.discardChanges": "Discard unsaved changes?", | ||
| "comet.core.editDialog.edit": "Edit", | ||
| "comet.core.editDialog.add": "Add", | ||
| "comet.core.editDialog.cancel": "Cancel", | ||
| "comet.core.editDialog.save": "Save", | ||
| "comet.core.finalForm.abort": "Cancel", | ||
| "comet.core.finalForm.save": "Save", | ||
| "comet.core.router.confirmationDialog.confirm": "OK", | ||
| "comet.core.router.confirmationDialog.abort": "Cancel", | ||
| "comet.core.stack.stack.back": "Back", | ||
| "comet.core.table.addButton": "Add", | ||
| "comet.core.table.excelExportButton": "Export", | ||
| "comet.core.table.deleteButton": "Delete", | ||
| "comet.core.table.pagination.pageInfo": "Page {current} of {total}", | ||
| "comet.core.table.localChangesToolbar.save": "Save", | ||
| "comet.core.table.localChangesToolbar.unsavedItems": | ||
| "{count, plural, =0 {no unsaved changes} one {# unsaved change} other {# unsaved changes}}", | ||
| "comet.core.table.tableFilterFinalForm.resetButton": "Reset Filter", | ||
| "comet.core.table.tableQuery.error": "Error :( {error}", | ||
|
Comment on lines
+23
to
+44
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These are the Admin messages. Could we just provide empty objects for now?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I just copied this from the existing storybook configurations 😅 |
||
| }, | ||
| de: { | ||
| "comet.core.table.localChangesToolbar.unsavedItems": | ||
| "{count, plural, =0 {keine ungespeicherten Änderungen} one {# ungespeicherte Änderung} other {# ungespeicherte Änderungen}}", | ||
| "comet.core.table.tableQuery.error": "Fehler :( {error}", | ||
| }, | ||
| }; | ||
|
|
||
| export const IntlDecorator: Decorator = (fn, context) => { | ||
| const { locale: selectedLocale = LocaleOption.English } = context.globals; | ||
| const selecteDateFnsLocale = isLocaleOption(selectedLocale) ? dateFnsLocales[selectedLocale] : dateFnsLocales.en; | ||
|
|
||
| return ( | ||
| <IntlProvider | ||
| locale={selectedLocale} | ||
| messages={isLocaleOption(selectedLocale) ? messages[selectedLocale] : {}} | ||
| onError={() => { | ||
| // disable error logging | ||
| }} | ||
| > | ||
| {fn()} | ||
| </IntlProvider> | ||
| ); | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| import type { StorybookConfig } from "@storybook/react-webpack5"; | ||
|
|
||
| const config: StorybookConfig = { | ||
| stories: ["../src/**/*.mdx", "../src/**/__stories__/*.stories.@(js|jsx|mjs|ts|tsx)"], | ||
| staticDirs: ["./public"], | ||
|
|
||
| addons: ["@storybook/addon-docs", "storybook-addon-tag-badges", "@storybook/addon-webpack5-compiler-babel"], | ||
| framework: "@storybook/react-webpack5", | ||
| }; | ||
| export default config; |
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will be deploy this to Netlify or Chromatic? If Chromatic, then we can remove this badge.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't really see the need to deploy this for now, I'll remove it. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| <link rel="shortcut icon" href="/favicon.ico" /> | ||
| <script type="text/javascript"> | ||
| document.addEventListener("DOMContentLoaded", function () { | ||
| var badge = document.createElement("div"); | ||
| badge.style.position = "fixed"; | ||
| badge.style.right = "5px"; | ||
| badge.style.bottom = "5px"; | ||
| badge.style.zIndex = "10"; | ||
| badge.innerHTML = | ||
| '<a href="https://www.netlify.com"><img src="https://www.netlify.com/img/global/badges/netlify-color-accent.svg" alt="Deploys by Netlify" /></a>'; | ||
|
|
||
| document.body.appendChild(badge); | ||
| }); | ||
| </script> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| import { addons } from "storybook/manager-api"; | ||
|
|
||
| import theme from "./theme"; | ||
|
|
||
| addons.setConfig({ | ||
| theme, | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| export default function middleware(router) { | ||
| router.use((req, res, next) => { | ||
| const origin = req.headers.origin; | ||
|
|
||
| if (origin?.startsWith("http://localhost:")) { | ||
| res.setHeader("Access-Control-Allow-Origin", origin); | ||
| res.setHeader("Access-Control-Allow-Credentials", "true"); | ||
| } | ||
|
|
||
| next(); | ||
| }); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| <title>Comet</title> | ||
| <style> | ||
| body { | ||
| font-family: "Lato", "Helvetica Neue", "Helvetica", "Arial", sans-serif; | ||
| font-size: 14px; | ||
| line-height: 1.4; | ||
| -webkit-font-smoothing: antialiased; | ||
| } | ||
|
|
||
| #root pre:not(.prismjs) { | ||
| background-color: #efefef; | ||
| font-size: 10px; | ||
| padding: 15px; | ||
| } | ||
|
|
||
| #root code { | ||
| font-size: 10px; | ||
| } | ||
| </style> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| import type { Preview } from "@storybook/react-webpack5"; | ||
|
|
||
| import { IntlDecorator } from "./decorators/IntlProvider.decorator"; | ||
|
|
||
| const preview: Preview = { | ||
| tags: ["autodocs"], | ||
| decorators: [IntlDecorator], | ||
|
|
||
| parameters: { | ||
| docs: { | ||
| codePanel: true, | ||
| }, | ||
| controls: { | ||
| matchers: { | ||
| color: /(background|color)$/i, | ||
| date: /Date$/i, | ||
| }, | ||
| }, | ||
| }, | ||
| }; | ||
|
|
||
| export default preview; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| import { create, type ThemeVars } from "storybook/theming"; | ||
|
|
||
| import CometLogo from "./public/comet-logo-header.svg"; | ||
|
|
||
| export default create({ | ||
| base: "light", | ||
| brandTitle: "Comet", | ||
| brandUrl: "https://github.com/vivid-planet/comet", | ||
| brandImage: CometLogo, | ||
| }) as ThemeVars; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| { | ||
| "compilerOptions": { | ||
| "jsx": "react-jsx", | ||
| "module": "ESNext", | ||
| "moduleResolution": "Bundler", | ||
| "noEmit": true | ||
| }, | ||
| "exclude": ["../dist"], | ||
| "extends": "../tsconfig.json", | ||
| "include": ["../src/**/*.stories.ts", "../src/**/*.stories.tsx"] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,11 +1,13 @@ | ||
| import eslintConfigNestJs from "@comet/eslint-config/future/nestjs.js"; | ||
| import storybook from "eslint-plugin-storybook"; | ||
|
|
||
| /** @type {import('eslint')} */ | ||
| const config = [ | ||
| { | ||
| ignores: ["src/db/migrations/**", "dist/**", "src/**/*.generated.ts", "src/**/generated/**"], | ||
| }, | ||
| ...eslintConfigNestJs, | ||
| ...storybook.configs["flat/recommended"], | ||
| ]; | ||
|
|
||
| export default config; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -29,6 +29,7 @@ | |
| "lint:tsc": "tsc --project ./tsconfig.lint.json", | ||
| "mikro-orm": "dotenv -e .env.secrets -e .env.local -e .env -e .env.site-configs -- mikro-orm", | ||
| "repl": "pnpm run start --entryFile repl", | ||
| "storybook": "storybook dev -p 4004 --no-open", | ||
| "start": "pnpm clean && pnpm intl:compile && dotenv -e .env.secrets -e .env.local -e .env -e .env.site-configs -- nest start --debug --watch --preserveWatchOutput", | ||
| "start:dev": "pnpm check-node-version && run-p dev:*", | ||
| "start:prod": "node dist/main" | ||
|
|
@@ -74,7 +75,8 @@ | |
| "rimraf": "^6.1.2", | ||
| "rxjs": "^7.8.2", | ||
| "slugify": "^1.6.6", | ||
| "uuid": "^11.1.0" | ||
| "uuid": "^11.1.0", | ||
| "react": "^18.3.1" | ||
| }, | ||
| "devDependencies": { | ||
| "@comet/api-generator": "workspace:*", | ||
|
|
@@ -84,12 +86,17 @@ | |
| "@nestjs/schematics": "^11.0.9", | ||
| "@types/cli-progress": "^3.11.6", | ||
| "@types/compression": "^1.8.1", | ||
| "react-intl": "^7.1.11", | ||
| "@types/cookie-parser": "^1.4.10", | ||
| "@types/express": "^5.0.3", | ||
| "@types/inquirer": "^8.2.12", | ||
| "@types/node": "^24.9.1", | ||
| "@types/react": "^18.3.1", | ||
| "@types/response-time": "^2.3.9", | ||
| "check-node-version": "^4.2.1", | ||
| "@storybook/addon-docs": "^9.1.10", | ||
| "@storybook/addon-webpack5-compiler-babel": "^3.0.6", | ||
| "@storybook/react-webpack5": "^9.1.10", | ||
| "chokidar-cli": "^3.0.0", | ||
| "dotenv-cli": "^9.0.0", | ||
| "eslint": "^9.30.1", | ||
|
|
@@ -98,6 +105,9 @@ | |
| "rimraf": "^6.1.2", | ||
| "ts-node": "^10.9.2", | ||
| "tsconfig-paths": "^3.15.0", | ||
| "eslint-plugin-storybook": "^9.1.10", | ||
| "storybook": "^9.1.10", | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Storybook V10 is already available. Should we update to the latest version?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wanted to keep it the same as in the other packages to:
|
||
| "storybook-addon-tag-badges": "^2.0.1", | ||
| "typescript": "5.9.3" | ||
| }, | ||
| "mikro-orm": { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| import { type Meta, type StoryObj } from "@storybook/react-webpack5"; | ||
| import React from "react"; | ||
|
|
||
| const config: Meta = { | ||
| title: "products/ProductPublishedMail", | ||
| }; | ||
|
|
||
| export default config; | ||
|
|
||
| export const ProductPublishedMailStory: StoryObj = { | ||
| render: () => ( | ||
| <> | ||
| <h1>ProductPublishedMail</h1> | ||
| <p>In the future, this story will render the (currently non-existing) ProductPublishedMail component, built with MJML and React</p> | ||
| </> | ||
| ), | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -227,5 +227,10 @@ export default defineConfig({ | |
| group: ["storybook", "docs"], | ||
| waitOn: waitOnPackages("@comet/admin"), | ||
| }, | ||
| { | ||
| name: "storybook-demo-api", | ||
| script: "pnpm --filter comet-demo-api run storybook", | ||
| group: ["storybook", "docs"], | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't this be in the demo-api group instead? IMO it doesn't make sense to add this to the global Storybook as it's a Demo API specific feature.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point, will change this |
||
| }, | ||
| ], | ||
| }); | ||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,6 @@ | ||
| import type { StorybookConfig } from "@storybook/react-webpack5"; | ||
| import remarkGfm from "remark-gfm"; | ||
| import { type StorybookConfigRaw } from "storybook/internal/types"; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using an internal type is risky. Could we instead use something from Storybook's public API? |
||
|
|
||
| const config: StorybookConfig = { | ||
| framework: "@storybook/react-webpack5", | ||
|
|
@@ -24,12 +25,21 @@ const config: StorybookConfig = { | |
| }), | ||
| staticDirs: ["../public"], | ||
| refs: (config, { configType }) => { | ||
| return { | ||
| const refs: StorybookConfigRaw["refs"] = { | ||
| "@comet/admin": { | ||
| title: "@comet/admin", | ||
| url: configType === "DEVELOPMENT" ? "http://localhost:26646/" : "https://main--68e7b70f15b8f51dac492af6.chromatic.com", // TODO: support pull request previews, | ||
| }, | ||
| }; | ||
|
|
||
| if (configType === "DEVELOPMENT") { | ||
| refs["demo/api"] = { | ||
| title: "demo/api", | ||
| url: "http://localhost:4004/", | ||
| }; | ||
| } | ||
|
Comment on lines
+35
to
+40
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we add this Storybook to the global Storybook?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point, maybe this is unnecessary 🤔 |
||
|
|
||
| return refs; | ||
| }, | ||
| }; | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems wrong, why is this necesssary?