diff --git a/core/src/interface.ts b/core/src/interface.ts
index 176078fd..6c391b40 100644
--- a/core/src/interface.ts
+++ b/core/src/interface.ts
@@ -520,8 +520,6 @@ export interface BaseField {
hint?: string;
pattern?: [string, string];
i18n?: boolean | 'translate' | 'duplicate' | 'none';
- media_folder?: string;
- public_folder?: string;
comment?: string;
}
@@ -559,7 +557,7 @@ export interface DateTimeField extends BaseField {
format?: string;
date_format?: boolean | string;
time_format?: boolean | string;
- picker_utc?: boolean; // TODO Reimplement
+ picker_utc?: boolean;
}
export interface FileOrImageField extends BaseField {
@@ -567,6 +565,8 @@ export interface FileOrImageField extends BaseField {
default?: string;
media_library?: MediaLibrary;
+ media_folder?: string;
+ public_folder?: string;
private?: boolean;
}
diff --git a/core/src/lib/util/media.util.ts b/core/src/lib/util/media.util.ts
index 6a81e781..b6203c59 100644
--- a/core/src/lib/util/media.util.ts
+++ b/core/src/lib/util/media.util.ts
@@ -5,7 +5,17 @@ import { folderFormatter } from '../formatters';
import { joinUrlPath } from '../urlHelper';
import { basename, isAbsolutePath } from '.';
-import type { Config, Field, Collection, CollectionFile, Entry } from '../../interface';
+import type {
+ Config,
+ Field,
+ Collection,
+ CollectionFile,
+ Entry,
+ FileOrImageField,
+ MarkdownField,
+ ListField,
+ ObjectField,
+} from '../../interface';
export const DRAFT_MEDIA_FILES = 'DRAFT_MEDIA_FILES';
@@ -14,17 +24,28 @@ function getFileField(collectionFiles: CollectionFile[], slug: string | undefine
return file;
}
+function isMediaField(
+ folderKey: 'media_folder' | 'public_folder',
+ field: Field | undefined,
+): field is FileOrImageField | MarkdownField {
+ return Boolean(field && folderKey in field);
+}
+
function hasCustomFolder(
folderKey: 'media_folder' | 'public_folder',
collection: Collection | undefined | null,
slug: string | undefined,
field: Field | undefined,
-) {
+): field is FileOrImageField | MarkdownField {
if (!collection) {
return false;
}
- if (field && field[folderKey]) {
+ if (!isMediaField(folderKey, field)) {
+ return false;
+ }
+
+ if (field[folderKey]) {
return true;
}
@@ -47,7 +68,7 @@ function evaluateFolder(
config: Config,
c: Collection,
entryMap: Entry | undefined,
- field: Field | undefined,
+ field: FileOrImageField | MarkdownField,
) {
let currentFolder = config[folderKey]!;
@@ -140,12 +161,17 @@ function traverseFields(
config: Config,
collection: Collection,
entryMap: Entry | undefined,
- field: Field,
+ field: FileOrImageField | MarkdownField | ListField | ObjectField,
fields: Field[],
currentFolder: string,
): string | null {
- const matchedField = fields.filter(f => f === field)[0];
- if (matchedField) {
+ const matchedField = fields.filter(f => f === field)[0] as
+ | FileOrImageField
+ | MarkdownField
+ | ListField
+ | ObjectField
+ | undefined;
+ if (matchedField && isMediaField(folderKey, matchedField)) {
return folderFormatter(
matchedField[folderKey] ? matchedField[folderKey]! : `{{${folderKey}}}`,
entryMap,
@@ -157,13 +183,13 @@ function traverseFields(
}
for (const f of fields) {
- const field = { ...f };
- if (!field[folderKey]) {
+ const childField: Field = { ...f };
+ if (isMediaField(folderKey, childField) && !childField[folderKey]) {
// add identity template if doesn't exist
- field[folderKey] = `{{${folderKey}}}`;
+ childField[folderKey] = `{{${folderKey}}}`;
}
const folder = folderFormatter(
- field[folderKey]!,
+ isMediaField(folderKey, childField) ? childField[folderKey] ?? '' : '',
entryMap,
collection,
currentFolder,
@@ -171,24 +197,24 @@ function traverseFields(
config.slug,
);
let fieldFolder = null;
- if ('fields' in field && field.fields) {
+ if ('fields' in childField && childField.fields) {
fieldFolder = traverseFields(
folderKey,
config,
collection,
entryMap,
- field,
- field.fields,
+ childField,
+ childField.fields,
folder,
);
- } else if ('types' in field && field.types) {
+ } else if ('types' in childField && childField.types) {
fieldFolder = traverseFields(
folderKey,
config,
collection,
entryMap,
- field,
- field.types,
+ childField,
+ childField.types,
folder,
);
}
@@ -209,9 +235,7 @@ export function selectMediaFolder(
const name = 'media_folder';
let mediaFolder = config[name];
- const customFolder = hasCustomFolder(name, collection, entryMap?.slug, field);
-
- if (customFolder) {
+ if (hasCustomFolder(name, collection, entryMap?.slug, field)) {
const folder = evaluateFolder(name, config, collection!, entryMap, field);
if (folder.startsWith('/')) {
// return absolute paths as is
diff --git a/core/src/widgets/datetime/DateTimeControl.tsx b/core/src/widgets/datetime/DateTimeControl.tsx
index 7eab1af6..1a4ebcec 100644
--- a/core/src/widgets/datetime/DateTimeControl.tsx
+++ b/core/src/widgets/datetime/DateTimeControl.tsx
@@ -64,12 +64,9 @@ const DateTimeControl = ({
const format = field.format;
// dateFormat and timeFormat are strictly for modifying input field with the date/time pickers
- const dateFormat: string | boolean = field.date_format ?? false;
+ const dateFormat: string | boolean = field.date_format ?? true;
// show time-picker? false hides it, true shows it using default format
- let timeFormat: string | boolean = field.time_format ?? false;
- if (typeof timeFormat === 'undefined') {
- timeFormat = true;
- }
+ const timeFormat: string | boolean = field.time_format ?? true;
return {
format,
diff --git a/website/content/docs/azure-backend.mdx b/website/content/docs/azure-backend.mdx
index 9e0d28d5..12b597c4 100644
--- a/website/content/docs/azure-backend.mdx
+++ b/website/content/docs/azure-backend.mdx
@@ -3,9 +3,10 @@ group: Accounts
title: Azure
weight: 20
---
-
For repositories stored on Azure, the `azure` backend allows CMS users to log in directly with their Azure account. Note that all users must have write access to your content repository for this to work.
+## Authentication
+
In order to get Static CMS working with Azure DevOps, you need a Tenant Id and an Application Id.
1. If you do not have an Azure account, [create one here](https://azure.microsoft.com/en-us/free/?WT.mc_id=A261C142F) and make sure to have a credit card linked to the account.
diff --git a/website/content/docs/bitbucket-backend.mdx b/website/content/docs/bitbucket-backend.mdx
index dfd19001..a26aaefc 100644
--- a/website/content/docs/bitbucket-backend.mdx
+++ b/website/content/docs/bitbucket-backend.mdx
@@ -5,7 +5,9 @@ weight: 20
---
For repositories stored on Bitbucket, the `bitbucket` backend allows CMS users to log in directly with their Bitbucket account. Note that all users must have write access to your content repository for this to work.
-To enable it:
+## Authentication
+
+To enable Bitbucket authentication it:
1. Follow the authentication provider setup steps in the [Netlify docs](https://www.netlify.com/docs/authentication-providers/#using-an-authentication-provider).
2. Add the following lines to your Static CMS `config.yml` file:
diff --git a/website/content/docs/github-backend.mdx b/website/content/docs/github-backend.mdx
index f86d3a92..2daee030 100644
--- a/website/content/docs/github-backend.mdx
+++ b/website/content/docs/github-backend.mdx
@@ -5,6 +5,8 @@ weight: 30
---
For repositories stored on GitHub, the `github` backend allows CMS users to log in directly with their GitHub account. Note that all users must have push access to your content repository for this to work.
+## Authentication
+
Because Github requires a server for authentication, Netlify facilitates basic GitHub authentication.
To enable basic GitHub authentication:
diff --git a/website/content/docs/gitlab-backend.mdx b/website/content/docs/gitlab-backend.mdx
index b649d129..28e451ae 100644
--- a/website/content/docs/gitlab-backend.mdx
+++ b/website/content/docs/gitlab-backend.mdx
@@ -7,7 +7,7 @@ For repositories stored on GitLab, the `gitlab` backend allows CMS users to log
**Note:** GitLab default branch is protected by default, thus typically requires `maintainer` permissions in order for users to have push access.
-## Authorization
+## Authentication
With GitLab's PKCE authorization, users can authenticate with GitLab directly from the client. To do this:
diff --git a/website/content/docs/widget-boolean.mdx b/website/content/docs/widget-boolean.mdx
index 39f7e049..1ad4d795 100644
--- a/website/content/docs/widget-boolean.mdx
+++ b/website/content/docs/widget-boolean.mdx
@@ -6,12 +6,19 @@ weight: 10
The boolean widget translates a toggle switch input to a true/false value.
-- **Name:** `boolean`
-- **UI:** toggle switch
-- **Data type:** boolean
-- **Options:**
- - `default`: accepts `true` or `false`; defaults to `false` when `required` is set to `false`
-- **Example:**
- ```yaml
- - {label: "Draft", title: "draft", widget: "boolean", default: true}
- ```
+## Widget options
+
+For common options, see [Common widget options](/docs/widgets#common-widget-options).
+
+|Name|Type|Default|Description|
+|----|----|-------|-----------|
+|default|boolean|`false`|_Optional_. The default value for the field|
+
+## Example
+
+```yaml
+name: draft
+label: Draft
+widget: boolean
+default: true
+```
diff --git a/website/content/docs/widget-code.mdx b/website/content/docs/widget-code.mdx
index 26d2f1c6..a8cdee56 100644
--- a/website/content/docs/widget-code.mdx
+++ b/website/content/docs/widget-code.mdx
@@ -6,18 +6,21 @@ weight: 11
The code widget provides a code editor (powered by [Codemirror](https://codemirror.net)) with optional syntax awareness. Can output the raw code value or an object with the selected language and the raw code value.
-- **Name:** `code`
-- **UI:** code editor
-- **Data type:** string
-- **Options:**
- - `default_language`: optional; default language to use
- - `allow_language_selection`: optional; defaults to `false`: allows syntax to be changed
- - `keys`: optional; sets key names for code and lang if outputting an object; defaults to `{ code: 'code', lang: 'lang' }`
- - `output_code_only`: set to `true` to output the string value only, defaults to `false`
+## Widget options
-- **Example:**
- ```yaml
- - label: 'Code'
- title: 'code'
- widget: 'code'
- ```
+For common options, see [Common widget options](/docs/widgets#common-widget-options).
+
+| Name | Type | Default | Description |
+| ------------------------ | ------- | -------------------------------- | -------------------------------------------------------------------- |
+| default_language | string | | _Optional_. Default language to use |
+| allow_language_selection | boolean | `false` | _Optional_. Allows language syntax to be changed |
+| keys | boolean | `{ code: 'code', lang: 'lang' }` | _Optional_. Sets key names for code and lang if outputting an object |
+| output_code_only | string | `true` | _Optional_. Set to `true` to output the string value only |
+
+## Example
+
+```yaml
+name: code
+label: Code
+widget: code
+```
diff --git a/website/content/docs/widget-color.mdx b/website/content/docs/widget-color.mdx
index 0e216004..9cbefc46 100644
--- a/website/content/docs/widget-color.mdx
+++ b/website/content/docs/widget-color.mdx
@@ -6,18 +6,31 @@ weight: 12
The color widget translates a color picker to a color string.
-- **Name:** `color`
-- **UI:** color picker
-- **Data type:** string
-- **Options:**
- - `default`: accepts a string; defaults to an empty string. Sets the default value
- - `allow_input`: accepts a boolean, defaults to `false`. Allows manual editing of the color input value
- - `enable_alpha`: accepts a boolean, defaults to `false`. Enables Alpha editing
-- **Example:**
- ```yaml
- - { label: 'Color', title: 'color', widget: 'color' }
- ```
-- **Example:**
- ```yaml
- - { label: 'Color', title: 'color', widget: 'color', enable_alpha: true, allow_input: true }
- ```
+## Widget options
+
+For common options, see [Common widget options](/docs/widgets#common-widget-options).
+
+| Name | Type | Default | Description |
+| ------------ | ------- | ------- | ---------------------------------------------------------- |
+| default | string | `''` | _Optional_. The default value for the field |
+| allow_input | boolean | `false` | _Optional_. Allows manual editing of the color input value |
+| enable_alpha | boolean | `false` | _Optional_. Enables Alpha editing |
+
+## Examples
+
+### Basic
+```yaml
+name: color
+label: Color
+widget: color
+```
+
+### Kitchen Sink
+
+```yaml
+name: color
+label: Color
+widget: color
+enable_alpha: true
+allow_input: true
+```
diff --git a/website/content/docs/widget-datetime.mdx b/website/content/docs/widget-datetime.mdx
index 0c71972e..5e164302 100644
--- a/website/content/docs/widget-datetime.mdx
+++ b/website/content/docs/widget-datetime.mdx
@@ -6,23 +6,49 @@ weight: 13
The datetime widget translates a datetime picker to a datetime string.
-- **Name:** `datetime`
-- **UI:** datetime picker
-- **Data type:** Moment.js-formatted datetime string
-- **Options:**
- - `default`: accepts a datetime string, or an empty string to accept blank input; otherwise defaults to current datetime
- - `format`: sets storage format; accepts Moment.js [tokens](https://momentjs.com/docs/#/parsing/string-format/); defaults to raw Date object (if supported by output format)
- - `date_format`: sets date display format in UI; boolean or Moment.js [tokens](https://momentjs.com/docs/#/parsing/string-format/). If `true` use default locale format.
- - `time_format`: sets time display format in UI; boolean or Moment.js [tokens](https://momentjs.com/docs/#/parsing/string-format/). If `true` use default locale format, `false` hides time-picker.
- - `picker_utc`: _(default: `false`)_ when set to `true`, the datetime picker will display times in UTC. When `false`, the datetime picker will display times in the user's local timezone. When using date-only formats, it can be helpful to set this to `true` so users in all timezones will see the same date in the datetime picker.
-- **Example:**
- ```yaml
- - label: "Start time"
- title: "start"
- widget: "datetime"
- default: ""
- date_format: "DD.MM.YYYY" # e.g. 24.12.2021
- time_format: "HH:mm" # e.g. 21:07
- format: "LLL"
- picker_utc: false
- ```
+## Widget options
+
+For common options, see [Common widget options](/docs/widgets#common-widget-options).
+
+| Name | Type | Default | Description |
+| ----------- | ---------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| default | string | `Current Date and Time` | _Optional_. The default value for the field. Accepts a datetime string, or an empty string to accept blank input. |
+| format | string | `yyyy-MM-dd'T'HH:mm:ss.SSSXXX` | _Optional_. Sets storage format. Accepts [date-fns tokens](https://date-fns.org/v2.29.3/docs/format) |
+| date_format | string
\| boolean | `true` | _Optional_. Sets date display format in UI.