diff --git a/dev-test/backends/default-workflow-status/config.yml b/dev-test/backends/default-workflow-status/config.yml
new file mode 100644
index 000000000000..5b44c1177ead
--- /dev/null
+++ b/dev-test/backends/default-workflow-status/config.yml
@@ -0,0 +1,62 @@
+backend:
+ name: test-repo
+
+publish_mode: editorial_workflow
+default_workflow_status: pending_publish
+media_folder: static/media
+public_folder: /media
+collections:
+ - name: posts
+ label: Posts
+ label_singular: 'Post'
+ folder: content/posts
+ create: true
+ slug: '{{year}}-{{month}}-{{day}}-{{slug}}'
+ fields:
+ - label: Template
+ name: template
+ widget: hidden
+ default: post
+ - label: Title
+ name: title
+ widget: string
+ - label: 'Cover Image'
+ name: 'image'
+ widget: 'image'
+ required: false
+ - label: Publish Date
+ name: date
+ widget: datetime
+ - label: Description
+ name: description
+ widget: text
+ - label: Category
+ name: category
+ widget: string
+ - label: Body
+ name: body
+ widget: markdown
+ - label: Tags
+ name: tags
+ widget: list
+ - name: pages
+ label: Pages
+ label_singular: 'Page'
+ folder: content/pages
+ create: true
+ slug: '{{slug}}'
+ fields:
+ - label: Template
+ name: template
+ widget: hidden
+ default: page
+ - label: Title
+ name: title
+ widget: string
+ - label: Draft
+ name: draft
+ widget: boolean
+ default: true
+ - label: Body
+ name: body
+ widget: markdown
diff --git a/dev-test/backends/default-workflow-status/index.html b/dev-test/backends/default-workflow-status/index.html
new file mode 100644
index 000000000000..103dbb272d68
--- /dev/null
+++ b/dev-test/backends/default-workflow-status/index.html
@@ -0,0 +1,41 @@
+
+
+
+
+
+ Netlify CMS Development Test
+
+
+
+
+
+
diff --git a/packages/decap-cms-core/index.d.ts b/packages/decap-cms-core/index.d.ts
index 9eb5e7f9855e..49fbcae7a769 100644
--- a/packages/decap-cms-core/index.d.ts
+++ b/packages/decap-cms-core/index.d.ts
@@ -43,6 +43,8 @@ declare module 'decap-cms-core' {
export type CmsPublishMode = 'simple' | 'editorial_workflow' | '';
+ export type CmsPublishWorkflowStatus = 'draft' | 'pending_review' | 'pending_publish';
+
export type CmsSlugEncoding = 'unicode' | 'ascii';
export interface CmsI18nConfig {
@@ -388,6 +390,7 @@ declare module 'decap-cms-core' {
media_folder_relative?: boolean;
media_library?: CmsMediaLibrary;
publish_mode?: CmsPublishMode;
+ default_workflow_status?: CmsPublishWorkflowStatus;
load_config_file?: boolean;
integrations?: {
hooks: string[];
diff --git a/packages/decap-cms-core/src/actions/__tests__/config.spec.js b/packages/decap-cms-core/src/actions/__tests__/config.spec.js
index 119345517ea8..6f6eecae02dc 100644
--- a/packages/decap-cms-core/src/actions/__tests__/config.spec.js
+++ b/packages/decap-cms-core/src/actions/__tests__/config.spec.js
@@ -9,6 +9,7 @@ import {
detectProxyServer,
handleLocalBackend,
} from '../config';
+import { Statues } from '../../constants/publishModes';
jest.spyOn(console, 'log').mockImplementation(() => {});
jest.spyOn(console, 'warn').mockImplementation(() => {});
@@ -44,6 +45,7 @@ describe('config', () => {
local_backend: true
site_url: https://www.decapcms.org
publish_mode: editorial_workflow
+ default_workflow_status: pending_publish
media_folder: website/static/img
public_folder: img
docs_collection: &docs_collection
@@ -69,6 +71,7 @@ describe('config', () => {
local_backend: true,
site_url: 'https://www.decapcms.org',
publish_mode: 'editorial_workflow',
+ default_workflow_status: 'pending_publish',
media_folder: 'website/static/img',
public_folder: 'img',
docs_collection: {
@@ -120,6 +123,31 @@ describe('config', () => {
});
});
+ describe('default_workflow_status', () => {
+ it('should set default_workflow_status to "draft" by default if publish_mode is "editorial_workflow"', () => {
+ const config = {
+ publish_mode: 'editorial_workflow',
+ };
+ expect(applyDefaults(config).default_workflow_status).toEqual(Statues.DRAFT);
+ });
+
+ it('should set default_workflow_status to "draft" if the given one is unknown', () => {
+ const config = {
+ publish_mode: 'editorial_workflow',
+ default_workflow_status: 'unknown',
+ };
+ expect(applyDefaults(config).default_workflow_status).toEqual(Statues.DRAFT);
+ });
+
+ it('should set default_workflow_status from config', () => {
+ const config = {
+ publish_mode: 'editorial_workflow',
+ default_workflow_status: Statues.PENDING_REVIEW,
+ };
+ expect(applyDefaults(config).default_workflow_status).toEqual(Statues.PENDING_REVIEW);
+ });
+ });
+
describe('public_folder', () => {
it('should set public_folder based on media_folder if not set', () => {
expect(
diff --git a/packages/decap-cms-core/src/actions/config.ts b/packages/decap-cms-core/src/actions/config.ts
index 66062a50a1ee..e20c8eccd957 100644
--- a/packages/decap-cms-core/src/actions/config.ts
+++ b/packages/decap-cms-core/src/actions/config.ts
@@ -4,7 +4,11 @@ import deepmerge from 'deepmerge';
import { produce } from 'immer';
import { trimStart, trim, isEmpty } from 'lodash';
-import { SIMPLE as SIMPLE_PUBLISH_MODE } from '../constants/publishModes';
+import {
+ EDITORIAL_WORKFLOW,
+ SIMPLE as SIMPLE_PUBLISH_MODE,
+ Statues,
+} from '../constants/publishModes';
import { validateConfig } from '../constants/configSchema';
import { selectDefaultSortableFields } from '../reducers/collections';
import { getIntegrations, selectIntegration } from '../reducers/integrations';
@@ -210,6 +214,14 @@ export function applyDefaults(originalConfig: CmsConfig) {
config.slug = config.slug || {};
config.collections = config.collections || [];
+ if (config.publish_mode === EDITORIAL_WORKFLOW) {
+ config.default_workflow_status =
+ config.default_workflow_status &&
+ Object.values(Statues).includes(config.default_workflow_status)
+ ? config.default_workflow_status
+ : Statues.DRAFT;
+ }
+
// Use `site_url` as default `display_url`.
if (!config.display_url && config.site_url) {
config.display_url = config.site_url;
diff --git a/packages/decap-cms-core/src/backend.ts b/packages/decap-cms-core/src/backend.ts
index bcb8881de045..9447d5a82f62 100644
--- a/packages/decap-cms-core/src/backend.ts
+++ b/packages/decap-cms-core/src/backend.ts
@@ -14,7 +14,7 @@ import { basename, join, extname, dirname } from 'path';
import { stringTemplate } from 'decap-cms-lib-widgets';
import { resolveFormat } from './formats/formats';
-import { selectUseWorkflow } from './reducers/config';
+import { selectUseWorkflow, selectDefaultWorkflowStatus } from './reducers/config';
import { selectMediaFilePath, selectEntry } from './reducers/entries';
import { selectIntegration } from './reducers/integrations';
import {
@@ -33,7 +33,6 @@ import { createEntry } from './valueObjects/Entry';
import { sanitizeChar } from './lib/urlHelper';
import { getBackend, invokeEvent } from './lib/registry';
import { commitMessageFormatter, slugFormatter, previewUrlFormatter } from './lib/formatters';
-import { status } from './constants/publishModes';
import { FOLDER, FILES } from './constants/collectionTypes';
import { selectCustomPath } from './reducers/entryDraft';
import {
@@ -354,7 +353,7 @@ export class Backend {
this.implementation = implementation.init(this.config, {
useWorkflow: selectUseWorkflow(this.config),
updateUserCredentials: this.updateUserCredentials,
- initialWorkflowStatus: status.first(),
+ initialWorkflowStatus: selectDefaultWorkflowStatus(this.config),
});
this.backendName = backendName;
this.authStore = authStore;
diff --git a/packages/decap-cms-core/src/constants/configSchema.js b/packages/decap-cms-core/src/constants/configSchema.js
index 5efd2cd4c172..7dd1e8bdd73d 100644
--- a/packages/decap-cms-core/src/constants/configSchema.js
+++ b/packages/decap-cms-core/src/constants/configSchema.js
@@ -8,6 +8,7 @@ import {
import ajvErrors from 'ajv-errors';
import { v4 as uuid } from 'uuid';
+import { Statues } from './publishModes';
import { frontmatterFormats, extensionFormatters } from '../formats/formats';
import { getWidgets } from '../lib/registry';
import { I18N_STRUCTURE, I18N_FIELD } from '../lib/i18n';
@@ -178,6 +179,11 @@ function getConfigSchema() {
enum: ['simple', 'editorial_workflow', ''],
examples: ['editorial_workflow'],
},
+ default_workflow_status: {
+ type: 'string',
+ enum: Object.values(Statues),
+ examples: [Statues.PENDING_PUBLISH],
+ },
slug: {
type: 'object',
properties: {
diff --git a/packages/decap-cms-core/src/constants/publishModes.ts b/packages/decap-cms-core/src/constants/publishModes.ts
index 56fba78ffb3d..7ac9ad5fba84 100644
--- a/packages/decap-cms-core/src/constants/publishModes.ts
+++ b/packages/decap-cms-core/src/constants/publishModes.ts
@@ -8,7 +8,7 @@ export const Statues = {
DRAFT: 'draft',
PENDING_REVIEW: 'pending_review',
PENDING_PUBLISH: 'pending_publish',
-};
+} as const;
// Available status
export const status = OrderedMap(Statues);
@@ -20,3 +20,4 @@ export const statusDescriptions = Map({
});
export type Status = keyof typeof Statues;
+export type StatusValues = (typeof Statues)[Status];
diff --git a/packages/decap-cms-core/src/reducers/config.ts b/packages/decap-cms-core/src/reducers/config.ts
index d98546a48c1a..3553dbba6cca 100644
--- a/packages/decap-cms-core/src/reducers/config.ts
+++ b/packages/decap-cms-core/src/reducers/config.ts
@@ -1,7 +1,7 @@
import { produce } from 'immer';
import { CONFIG_REQUEST, CONFIG_SUCCESS, CONFIG_FAILURE } from '../actions/config';
-import { EDITORIAL_WORKFLOW } from '../constants/publishModes';
+import { EDITORIAL_WORKFLOW, status } from '../constants/publishModes';
import type { ConfigAction } from '../actions/config';
import type { CmsConfig } from '../types/redux';
@@ -35,4 +35,8 @@ export function selectUseWorkflow(state: CmsConfig) {
return state.publish_mode === EDITORIAL_WORKFLOW;
}
+export function selectDefaultWorkflowStatus(state: CmsConfig) {
+ return state.default_workflow_status || status.first();
+}
+
export default config;
diff --git a/packages/decap-cms-core/src/types/redux.ts b/packages/decap-cms-core/src/types/redux.ts
index b69a82311532..3b212aa89084 100644
--- a/packages/decap-cms-core/src/types/redux.ts
+++ b/packages/decap-cms-core/src/types/redux.ts
@@ -11,6 +11,7 @@ import type { Search } from '../reducers/search';
import type { GlobalUI } from '../reducers/globalUI';
import type { NotificationsState } from '../reducers/notifications';
import type { formatExtensions } from '../formats/formats';
+import type { StatusValues as PublishStatusValues } from '../constants/publishModes';
export type CmsBackendType =
| 'azure'
@@ -402,6 +403,7 @@ export interface CmsConfig {
media_folder_relative?: boolean;
media_library?: CmsMediaLibrary;
publish_mode?: CmsPublishMode;
+ default_workflow_status?: PublishStatusValues;
load_config_file?: boolean;
integrations?: {
hooks: string[];
@@ -457,6 +459,7 @@ export type Config = StaticallyTypedRecord<{
media_folder: string;
public_folder: string;
publish_mode?: string;
+ default_workflow_status?: string;
media_library: StaticallyTypedRecord<{ name: string }> & { name: string };
locale?: string;
slug: SlugConfig;