diff --git a/cms/components/PublishAction.tsx b/cms/components/PublishAction.tsx new file mode 100644 index 00000000..b7fecb2e --- /dev/null +++ b/cms/components/PublishAction.tsx @@ -0,0 +1,45 @@ +import { CheckmarkIcon as CheckIcon } from '@sanity/icons' +import { useDocumentOperation } from 'sanity' +import type { DocumentActionComponent } from 'sanity' + +export const PublishAction: DocumentActionComponent = props => { + const { publish } = useDocumentOperation(props.id, props.type) + const { patch } = useDocumentOperation(props.id, props.type) + + const document = props.draft || props.published + const isReady = document?.publishStatus === 'ready' + const isPublished = document?.publishStatus === 'published' + const hasResponse = (document?.posts as any[])?.length > 0 + + // Don't show the action if there's no response or if already published + if (!hasResponse || isPublished) { + return null + } + + return { + label: isReady ? 'Ready to publish ✓' : 'Mark as ready to publish', + icon: CheckIcon, + disabled: isReady, + tone: isReady ? 'positive' : 'primary', + shortcut: !isReady ? 'mod+shift+p' : undefined, + onHandle: () => { + if (isReady) return + + // Set the publish status to 'ready' + patch.execute([ + { + set: { + publishStatus: 'ready', + }, + }, + ]) + + // Publish the document to make the changes live + if (!publish.disabled) { + publish.execute() + } + + props.onComplete() + }, + } +} diff --git a/cms/package.json b/cms/package.json index d0da1981..c98038e1 100644 --- a/cms/package.json +++ b/cms/package.json @@ -11,6 +11,7 @@ "deploy-graphql": "sanity graphql deploy" }, "dependencies": { + "@sanity/icons": "^3.7.0", "@sanity/ui": "^2.15.18", "@sanity/vision": "^3.91.0", "modern-screenshot": "^4.6.0", diff --git a/cms/sanity.config.ts b/cms/sanity.config.ts index 5fba8f8a..05c04e81 100644 --- a/cms/sanity.config.ts +++ b/cms/sanity.config.ts @@ -2,6 +2,7 @@ import { defineConfig } from 'sanity' import { structureTool } from 'sanity/structure' import { visionTool } from '@sanity/vision' import { schemaTypes } from './schemaTypes' +import { PublishAction } from './components/PublishAction' export default defineConfig({ name: 'default', @@ -53,6 +54,17 @@ export default defineConfig({ visionTool(), ], + document: { + actions: (prev, context) => { + if (context.schemaType === 'ama') { + // Filter out the default publish action for AMA documents + const filteredActions = prev.filter(action => action.name !== 'publish') + return [PublishAction, ...filteredActions] + } + return prev + }, + }, + schema: { types: schemaTypes, }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d7522ed1..1d549994 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -236,6 +236,9 @@ importers: cms: dependencies: + '@sanity/icons': + specifier: ^3.7.0 + version: 3.7.0(react@18.3.1) '@sanity/ui': specifier: ^2.15.18 version: 2.15.18(@emotion/is-prop-valid@1.2.2)(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1)(styled-components@6.1.18(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) @@ -14053,16 +14056,16 @@ snapshots: '@poppinss/exception@1.2.1': {} - '@portabletext/block-tools@1.1.27(@sanity/types@3.91.0(@types/react@18.3.23))(@types/react@18.3.23)': + '@portabletext/block-tools@1.1.27(@sanity/types@3.91.0(@types/react@18.3.23)(debug@4.4.1))(@types/react@18.3.23)': dependencies: '@sanity/types': 3.91.0(@types/react@18.3.23)(debug@4.4.1) '@types/react': 18.3.23 get-random-values-esm: 1.0.2 lodash: 4.17.21 - '@portabletext/editor@1.50.6(@sanity/schema@3.91.0(@types/react@18.3.23))(@sanity/types@3.91.0(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rxjs@7.8.2)': + '@portabletext/editor@1.50.6(@sanity/schema@3.91.0(@types/react@18.3.23))(@sanity/types@3.91.0(@types/react@18.3.23)(debug@4.4.1))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rxjs@7.8.2)': dependencies: - '@portabletext/block-tools': 1.1.27(@sanity/types@3.91.0(@types/react@18.3.23))(@types/react@18.3.23) + '@portabletext/block-tools': 1.1.27(@sanity/types@3.91.0(@types/react@18.3.23)(debug@4.4.1))(@types/react@18.3.23) '@portabletext/patches': 1.1.3 '@portabletext/to-html': 2.0.14 '@sanity/schema': 3.91.0(@types/react@18.3.23)(debug@4.4.1) @@ -14491,7 +14494,7 @@ snapshots: - '@types/react' - supports-color - '@sanity/insert-menu@1.1.12(@emotion/is-prop-valid@1.2.2)(@sanity/types@3.91.0(@types/react@18.3.23))(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1)(styled-components@6.1.18(react-dom@18.3.1(react@18.3.1))(react@18.3.1))': + '@sanity/insert-menu@1.1.12(@emotion/is-prop-valid@1.2.2)(@sanity/types@3.91.0(@types/react@18.3.23)(debug@4.4.1))(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1)(styled-components@6.1.18(react-dom@18.3.1(react@18.3.1))(react@18.3.1))': dependencies: '@sanity/icons': 3.7.0(react@18.3.1) '@sanity/types': 3.91.0(@types/react@18.3.23)(debug@4.4.1) @@ -14575,11 +14578,19 @@ snapshots: transitivePeerDependencies: - '@sanity/types' + '@sanity/presentation-comlink@1.0.21(@sanity/client@7.4.0)(@sanity/types@3.91.0(@types/react@18.3.23)(debug@4.4.1))': + dependencies: + '@sanity/client': 7.4.0(debug@4.4.1) + '@sanity/comlink': 3.0.5 + '@sanity/visual-editing-types': 1.1.0(@sanity/client@7.4.0)(@sanity/types@3.91.0(@types/react@18.3.23)(debug@4.4.1)) + transitivePeerDependencies: + - '@sanity/types' + '@sanity/presentation-comlink@1.0.21(@sanity/client@7.4.0)(@sanity/types@3.91.0(@types/react@18.3.23))': dependencies: '@sanity/client': 7.4.0(debug@4.4.1) '@sanity/comlink': 3.0.5 - '@sanity/visual-editing-types': 1.1.0(@sanity/client@7.4.0)(@sanity/types@3.91.0(@types/react@18.3.23)) + '@sanity/visual-editing-types': 1.1.0(@sanity/client@7.4.0)(@sanity/types@3.91.0(@types/react@18.3.23)(debug@4.4.1)) transitivePeerDependencies: - '@sanity/types' @@ -14784,7 +14795,7 @@ snapshots: '@sanity/visual-editing-csm@2.0.17(@sanity/client@7.4.0)(@sanity/types@3.91.0(@types/react@18.3.23))(typescript@5.8.3)': dependencies: '@sanity/client': 7.4.0(debug@4.4.1) - '@sanity/visual-editing-types': 1.1.0(@sanity/client@7.4.0)(@sanity/types@3.91.0(@types/react@18.3.23)) + '@sanity/visual-editing-types': 1.1.0(@sanity/client@7.4.0)(@sanity/types@3.91.0(@types/react@18.3.23)(debug@4.4.1)) valibot: 1.1.0(typescript@5.8.3) transitivePeerDependencies: - '@sanity/types' @@ -14796,7 +14807,7 @@ snapshots: optionalDependencies: '@sanity/types': 3.91.0(@types/react@18.3.23)(debug@4.4.1) - '@sanity/visual-editing-types@1.1.0(@sanity/client@7.4.0)(@sanity/types@3.91.0(@types/react@18.3.23))': + '@sanity/visual-editing-types@1.1.0(@sanity/client@7.4.0)(@sanity/types@3.91.0(@types/react@18.3.23)(debug@4.4.1))': dependencies: '@sanity/client': 7.4.0(debug@4.4.1) optionalDependencies: @@ -14806,7 +14817,7 @@ snapshots: dependencies: '@sanity/comlink': 3.0.5 '@sanity/icons': 3.7.0(react@18.3.1) - '@sanity/insert-menu': 1.1.12(@emotion/is-prop-valid@1.2.2)(@sanity/types@3.91.0(@types/react@18.3.23))(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1)(styled-components@6.1.18(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) + '@sanity/insert-menu': 1.1.12(@emotion/is-prop-valid@1.2.2)(@sanity/types@3.91.0(@types/react@18.3.23)(debug@4.4.1))(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1)(styled-components@6.1.18(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) '@sanity/mutate': 0.11.0-canary.4(xstate@5.19.3) '@sanity/presentation-comlink': 1.0.21(@sanity/client@6.29.1)(@sanity/types@3.91.0(@types/react@18.3.23)) '@sanity/preview-url-secret': 2.1.11(@sanity/client@6.29.1) @@ -22062,8 +22073,8 @@ snapshots: '@dnd-kit/sortable': 7.0.2(@dnd-kit/core@6.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) '@dnd-kit/utilities': 3.2.2(react@18.3.1) '@juggle/resize-observer': 3.4.0 - '@portabletext/block-tools': 1.1.27(@sanity/types@3.91.0(@types/react@18.3.23))(@types/react@18.3.23) - '@portabletext/editor': 1.50.6(@sanity/schema@3.91.0(@types/react@18.3.23))(@sanity/types@3.91.0(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rxjs@7.8.2) + '@portabletext/block-tools': 1.1.27(@sanity/types@3.91.0(@types/react@18.3.23)(debug@4.4.1))(@types/react@18.3.23) + '@portabletext/editor': 1.50.6(@sanity/schema@3.91.0(@types/react@18.3.23))(@sanity/types@3.91.0(@types/react@18.3.23)(debug@4.4.1))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rxjs@7.8.2) '@portabletext/react': 3.2.1(react@18.3.1) '@portabletext/toolkit': 2.0.17 '@rexxars/react-json-inspector': 9.0.1(react@18.3.1) @@ -22082,12 +22093,12 @@ snapshots: '@sanity/id-utils': 1.0.0 '@sanity/image-url': 1.1.0 '@sanity/import': 3.38.2(@types/react@18.3.23) - '@sanity/insert-menu': 1.1.12(@emotion/is-prop-valid@1.2.2)(@sanity/types@3.91.0(@types/react@18.3.23))(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1)(styled-components@6.1.18(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) + '@sanity/insert-menu': 1.1.12(@emotion/is-prop-valid@1.2.2)(@sanity/types@3.91.0(@types/react@18.3.23)(debug@4.4.1))(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1)(styled-components@6.1.18(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) '@sanity/logos': 2.2.0(@sanity/color@3.0.6)(react@18.3.1) '@sanity/message-protocol': 0.13.3 '@sanity/migrate': 3.91.0(@types/react@18.3.23) '@sanity/mutator': 3.91.0(@types/react@18.3.23) - '@sanity/presentation-comlink': 1.0.21(@sanity/client@7.4.0)(@sanity/types@3.91.0(@types/react@18.3.23)) + '@sanity/presentation-comlink': 1.0.21(@sanity/client@7.4.0)(@sanity/types@3.91.0(@types/react@18.3.23)(debug@4.4.1)) '@sanity/preview-url-secret': 2.1.11(@sanity/client@7.4.0) '@sanity/schema': 3.91.0(@types/react@18.3.23)(debug@4.4.1) '@sanity/sdk': 0.0.0-alpha.25(@types/react@18.3.23)(debug@4.4.1)(immer@10.1.1)(react@18.3.1)(use-sync-external-store@1.5.0(react@18.3.1))