@picked/client 0.0.72-next.1 → 0.0.72-next.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -1
- package/dist/{api-B9DDtylO.cjs → api-B4qxWoQN.cjs} +1 -1
- package/dist/{api-BmzHzzpu.js → api-DNvaLWw_.js} +1 -1
- package/dist/cjs/index.js +2 -2
- package/dist/cjs/plugins/dynamic-experiences/index.js +1 -1
- package/dist/cjs/server/index.js +1 -1
- package/dist/docs/explanation/content-references.md +99 -0
- package/dist/docs/explanation/how-picked-works.md +25 -3
- package/dist/docs/explanation/the-content-model.md +38 -28
- package/dist/docs/how-to/create-a-content-entry.md +48 -0
- package/dist/docs/how-to/define-a-page-layout.md +12 -5
- package/dist/docs/how-to/point-one-entry-at-another.md +61 -0
- package/dist/docs/how-to/read-a-referenced-entry.md +111 -0
- package/dist/docs/how-to/reuse-a-section.md +26 -10
- package/dist/docs/index.md +1 -1
- package/dist/docs/reference/dashboard/content/blocks.mdx +57 -0
- package/dist/docs/reference/dashboard/content/content-entries.mdx +61 -10
- package/dist/docs/reference/dashboard/content/models.mdx +108 -0
- package/dist/docs/reference/dashboard/content/pages.mdx +4 -3
- package/dist/docs/reference/dashboard/fields.mdx +1 -1
- package/dist/docs/reference/dashboard/steps.mdx +2 -2
- package/dist/docs/reference/delivery-api/experience-content.md +68 -13
- package/dist/docs/reference/glossary.md +13 -5
- package/dist/docs/reference/management-api/error-handling.md +2 -2
- package/dist/docs/reference/sdk/content.md +216 -0
- package/dist/docs/reference/sdk/plugins/dynamic-experiences.md +51 -3
- package/dist/docs/reference/sdk/ssr/serialize.md +6 -3
- package/dist/docs/reference/tools/vite-plugin.md +90 -8
- package/dist/docs/tutorials/first-api-call.md +1 -1
- package/dist/docs/tutorials/first-server-rendered-page.mdx +1 -1
- package/dist/esm/index.js +484 -429
- package/dist/esm/plugins/dynamic-experiences/index.js +4 -3
- package/dist/esm/server/index.js +43 -46
- package/dist/plugin-DkSWIASL.cjs +1 -0
- package/dist/plugin-DviILBha.js +153 -0
- package/dist/provider-Bskcgd6U.js +68 -0
- package/dist/provider-Bv5nM3So.cjs +1 -0
- package/dist/registry-BMXsAEbZ.cjs +1 -0
- package/dist/registry-DjBZ8upD.js +74 -0
- package/dist/types/data-source/api.d.ts +60 -0
- package/dist/types/data-source/api.d.ts.map +1 -0
- package/dist/types/data-source/provider.d.ts +90 -0
- package/dist/types/data-source/provider.d.ts.map +1 -0
- package/dist/types/data-source/registry.d.ts +26 -0
- package/dist/types/data-source/registry.d.ts.map +1 -0
- package/dist/types/data-source/virtual-data.d.ts +19 -0
- package/dist/types/data-source/virtual-data.d.ts.map +1 -0
- package/dist/types/entities/content/reference.d.ts +101 -0
- package/dist/types/entities/content/reference.d.ts.map +1 -0
- package/dist/types/exports.d.ts +2 -0
- package/dist/types/exports.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/picked.d.ts +65 -1
- package/dist/types/picked.d.ts.map +1 -1
- package/dist/types/plugins/dynamic-experiences/index.d.ts +1 -0
- package/dist/types/plugins/dynamic-experiences/index.d.ts.map +1 -1
- package/dist/types/plugins/dynamic-experiences/plugin.d.ts +9 -40
- package/dist/types/plugins/dynamic-experiences/plugin.d.ts.map +1 -1
- package/dist/types/plugins/dynamic-experiences/types.d.ts +25 -23
- package/dist/types/plugins/dynamic-experiences/types.d.ts.map +1 -1
- package/dist/types/server/index.d.ts +1 -1
- package/dist/types/server/index.d.ts.map +1 -1
- package/dist/types/server/serialize.d.ts +27 -34
- package/dist/types/server/serialize.d.ts.map +1 -1
- package/package.json +3 -3
- package/dist/docs/reference/dashboard/content/layouts.mdx +0 -62
- package/dist/docs/reference/dashboard/content/sections.mdx +0 -28
- package/dist/plugin-CZN0_kqv.js +0 -252
- package/dist/plugin-SFx511s_.cjs +0 -1
|
@@ -5,52 +5,61 @@ layout: docs
|
|
|
5
5
|
|
|
6
6
|
# About the content model
|
|
7
7
|
|
|
8
|
-
Picked splits your content into three pieces: a
|
|
8
|
+
Picked splits your content into three pieces: a Model, a Block, and a content entry.
|
|
9
9
|
Why three, when a page editor needs only one?
|
|
10
10
|
|
|
11
11
|
## Schema and data are separate
|
|
12
12
|
|
|
13
|
-
A **
|
|
13
|
+
A **Model** is a schema. It sets which fields a piece of content can hold, and it holds
|
|
14
14
|
no data itself. A **content entry** is one instance of that schema, filled with real
|
|
15
15
|
values.
|
|
16
16
|
|
|
17
|
-
One
|
|
17
|
+
One Model backs many entries. Describe a campaign page one time, then make many pages
|
|
18
18
|
from it. Each entry carries its own title, its own body, and its own image, but they all
|
|
19
19
|
share the shape.
|
|
20
20
|
|
|
21
21
|
That split is also what lets your code depend on content that it never saw. Your component
|
|
22
|
-
reads `content.title` because the
|
|
23
|
-
comes from that
|
|
22
|
+
reads `content.title` because the Model promises a `title`. It works for every entry that
|
|
23
|
+
comes from that Model.
|
|
24
24
|
|
|
25
|
-
## A
|
|
25
|
+
## A category gives a Model a role
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
| Layout | It gives shape to | Who renders it |
|
|
31
|
-
| --- | --- | --- |
|
|
32
|
-
| Page layout | A standalone [Page](/reference/dashboard/content/pages). | The SDK renders the entry on your server. |
|
|
33
|
-
| Step layout | One [Step](/reference/dashboard/steps) inside a Flow. | The Step renders the entry in the browser. |
|
|
27
|
+
A Model can carry a **category**, and the category decides what the Model gives its shape
|
|
28
|
+
to. A **page layout** backs a standalone Page. A **step layout** backs one Step inside a
|
|
29
|
+
Flow.
|
|
34
30
|
|
|
35
31
|
The category is fixed because it decides where the SDK renders the entry. That is not a
|
|
36
|
-
property you can change under an entry that exists already.
|
|
37
|
-
|
|
32
|
+
property that you can change under an entry that exists already.
|
|
33
|
+
|
|
34
|
+
A Model can also carry no category. Such a Model has no layout role, and nothing renders
|
|
35
|
+
its entries directly. It holds the content that other content points at, such as a
|
|
36
|
+
product or a category of your own. See
|
|
37
|
+
[About content references](/explanation/content-references).
|
|
38
|
+
|
|
39
|
+
The three roles are one machine. A layout is a Model with a job in the render path. A
|
|
40
|
+
Model with no category is the same machine with no such job.
|
|
38
41
|
|
|
39
|
-
## A
|
|
42
|
+
## A Block is a schema fragment
|
|
40
43
|
|
|
41
|
-
A
|
|
42
|
-
inside one or more
|
|
44
|
+
A Model gives shape to a whole page or a whole step. A **Block** is a part that you put
|
|
45
|
+
inside one or more Models.
|
|
43
46
|
|
|
44
|
-
Define a hero one time as a
|
|
45
|
-
|
|
47
|
+
Define a hero one time as a Block, then point at it from every Model that needs one.
|
|
48
|
+
Change the Block and every Model that holds it changes with it.
|
|
46
49
|
|
|
47
|
-
This is the reason
|
|
48
|
-
structure again in each
|
|
50
|
+
This is the reason Blocks exist at all. Without them you must describe a common
|
|
51
|
+
structure again in each Model, and the copies then become different. It is the same
|
|
49
52
|
argument for one fact in one place that runs through the rest of this documentation.
|
|
50
53
|
|
|
54
|
+
A Block sits **inside** the entry that embeds it. It has no entry of its own, and no id
|
|
55
|
+
that you can point at.
|
|
56
|
+
|
|
57
|
+
That is the difference between a Block and a reference. A Block is a shape that many
|
|
58
|
+
entries hold. A reference is a pointer at one entry that many entries share.
|
|
59
|
+
|
|
51
60
|
## Why a schema change does not migrate your data
|
|
52
61
|
|
|
53
|
-
Change a
|
|
62
|
+
Change a Model or a Block, and Picked does not rewrite the entries behind it. An entry
|
|
54
63
|
that no longer matches its schema becomes invalid, and the dashboard shows an error on
|
|
55
64
|
each field that does not fit.
|
|
56
65
|
|
|
@@ -58,20 +67,21 @@ That is deliberate. An automatic change must decide what a new required field ho
|
|
|
58
67
|
every entry that came before it. Any value that it chooses is content that nobody wrote.
|
|
59
68
|
Picked reports the error instead, and you correct it.
|
|
60
69
|
|
|
61
|
-
The cost is real. After a schema change, check every entry that uses that
|
|
70
|
+
The cost is real. After a schema change, check every entry that uses that Model and fix
|
|
62
71
|
each error before you publish. Picked serves valid content only, so an entry with an error
|
|
63
72
|
does not reach a visitor.
|
|
64
73
|
|
|
65
74
|
## An error points at the exact field
|
|
66
75
|
|
|
67
76
|
A validation error carries a path in JSON style, such as `sections[0].data.title`. The
|
|
68
|
-
path holds through nested groups, repeated fields, and
|
|
77
|
+
path holds through nested groups, repeated fields, and Blocks. An error inside a
|
|
69
78
|
repeated group therefore tells you which item in that group holds it.
|
|
70
79
|
|
|
71
80
|
## Related
|
|
72
81
|
|
|
73
|
-
- [
|
|
74
|
-
- [
|
|
82
|
+
- [Models](/reference/dashboard/content/models) — every field type.
|
|
83
|
+
- [Blocks](/reference/dashboard/content/blocks) — the reusable fragments.
|
|
75
84
|
- [Content entries](/reference/dashboard/content/content-entries) — the editor and the
|
|
76
85
|
validation.
|
|
77
|
-
- [About
|
|
86
|
+
- [About content references](/explanation/content-references) — how one entry points at another.
|
|
87
|
+
- [About pages and flows](/explanation/pages-and-flows) — which category you need.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: how-to
|
|
3
|
+
layout: docs
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# How to create a content entry
|
|
7
|
+
|
|
8
|
+
This guide shows you how to make one instance of a Model and fill it with data. You need
|
|
9
|
+
a Model first. See [How to define a page layout](/how-to/define-a-page-layout).
|
|
10
|
+
|
|
11
|
+
A Page makes its own entry when you create the page. Use this guide for the content that
|
|
12
|
+
no Page and no Step owns, such as an author or a product.
|
|
13
|
+
|
|
14
|
+
## 1. Open the entries list
|
|
15
|
+
|
|
16
|
+
1. Open your workspace.
|
|
17
|
+
2. Click **CMS** in the sidebar.
|
|
18
|
+
3. Click **Content entries**.
|
|
19
|
+
|
|
20
|
+
## 2. Create the entry
|
|
21
|
+
|
|
22
|
+
1. Click **New content**.
|
|
23
|
+
2. Choose the **Model** for the entry.
|
|
24
|
+
3. Fill in each field. The form comes from the schema of the Model.
|
|
25
|
+
4. Click **Create entry**.
|
|
26
|
+
|
|
27
|
+
The Model is fixed when you create the entry. To move content to another Model, make a
|
|
28
|
+
new entry and copy the values across.
|
|
29
|
+
|
|
30
|
+
## 3. Correct every error
|
|
31
|
+
|
|
32
|
+
An invalid field shows an error next to it while you edit. The error carries the path to
|
|
33
|
+
the exact field. Correct each one before you publish, because Picked serves valid content
|
|
34
|
+
only.
|
|
35
|
+
|
|
36
|
+
## Find an entry again
|
|
37
|
+
|
|
38
|
+
The entries list shows a title for each entry. The title is the first single-line text
|
|
39
|
+
field of the entry. It shows the entry id when no such field holds a value.
|
|
40
|
+
|
|
41
|
+
Use the **Model** filter to narrow the list to one Model.
|
|
42
|
+
|
|
43
|
+
## Related
|
|
44
|
+
|
|
45
|
+
- [Content entries](/reference/dashboard/content/content-entries) — the editor reference.
|
|
46
|
+
- [Models](/reference/dashboard/content/models) — every field type.
|
|
47
|
+
- [How to point one entry at another](/how-to/point-one-entry-at-another)
|
|
48
|
+
- [How to publish a workspace](/how-to/publish-a-workspace)
|
|
@@ -5,8 +5,8 @@ layout: docs
|
|
|
5
5
|
|
|
6
6
|
# How to define a page layout
|
|
7
7
|
|
|
8
|
-
This guide shows you how to define the shape of a page. A layout sets which fields a
|
|
9
|
-
can hold, and it holds no data itself.
|
|
8
|
+
This guide shows you how to define the shape of a page. A page layout sets which fields a
|
|
9
|
+
page can hold, and it holds no data itself.
|
|
10
10
|
|
|
11
11
|
## Steps
|
|
12
12
|
|
|
@@ -19,7 +19,7 @@ can hold, and it holds no data itself.
|
|
|
19
19
|
6. Add your fields. Choose a type for each one.
|
|
20
20
|
7. Click **Create model**.
|
|
21
21
|
|
|
22
|
-
The category is fixed when you create the
|
|
22
|
+
The category is fixed when you create the Model. You cannot change it later.
|
|
23
23
|
|
|
24
24
|
## Make a field repeatable
|
|
25
25
|
|
|
@@ -31,9 +31,16 @@ for a gallery, or for a list of features.
|
|
|
31
31
|
Add a **Group** field to hold a set of fields under one key. Make the group repeatable to
|
|
32
32
|
describe a list of objects, such as a list of feature cards.
|
|
33
33
|
|
|
34
|
+
## Define content with no layout role
|
|
35
|
+
|
|
36
|
+
A Model needs no category. Leave **Category** as **None (general content)** for content
|
|
37
|
+
that no Page and no Step renders, such as an author or a product. Reach such a Model
|
|
38
|
+
under **CMS** in the sidebar, and point at its entries with a **Reference** field.
|
|
39
|
+
|
|
34
40
|
## Related
|
|
35
41
|
|
|
36
42
|
- [About the content model](/explanation/the-content-model) — why the schema and the data
|
|
37
43
|
are separate.
|
|
38
|
-
- [
|
|
39
|
-
- [How to reuse a section](/how-to/reuse-a-section)
|
|
44
|
+
- [Models](/reference/dashboard/content/models) — every field type.
|
|
45
|
+
- [How to reuse a section](/how-to/reuse-a-section)
|
|
46
|
+
- [How to point one entry at another](/how-to/point-one-entry-at-another)
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: how-to
|
|
3
|
+
layout: docs
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# How to point one entry at another
|
|
7
|
+
|
|
8
|
+
This guide shows you how to point one content entry at another, such as a product at its
|
|
9
|
+
category. You need two Models: the one that holds the pointer, and the one that the
|
|
10
|
+
pointer reaches.
|
|
11
|
+
|
|
12
|
+
## 1. Create the target Model
|
|
13
|
+
|
|
14
|
+
1. Click **CMS** in the sidebar, then **Models**.
|
|
15
|
+
2. Click **New model**.
|
|
16
|
+
3. Enter a **Name** and a **Key**, such as `category`.
|
|
17
|
+
4. Leave **Category** as **None (general content)**.
|
|
18
|
+
5. Add your fields.
|
|
19
|
+
6. Click **Create model**.
|
|
20
|
+
|
|
21
|
+
## 2. Add a Reference field
|
|
22
|
+
|
|
23
|
+
1. Open the Model that holds the pointer.
|
|
24
|
+
2. Drag a **Reference** property onto the schema.
|
|
25
|
+
3. Enter a **Name** and a **Key**, such as `category`.
|
|
26
|
+
4. Set **Target Model** to the Model from step 1.
|
|
27
|
+
5. Click **Save**.
|
|
28
|
+
|
|
29
|
+
Turn on **repeatable** for a field that points at more than one entry. Leave **Target
|
|
30
|
+
Model** as **Any Model** to accept an entry of any Model in the workspace.
|
|
31
|
+
|
|
32
|
+
## 3. Choose a target on an entry
|
|
33
|
+
|
|
34
|
+
1. Open a content entry that uses the Model.
|
|
35
|
+
2. Find your Reference field.
|
|
36
|
+
3. Click **Choose entry**.
|
|
37
|
+
4. Search for the entry.
|
|
38
|
+
5. Choose the entry.
|
|
39
|
+
6. Click **Save**.
|
|
40
|
+
|
|
41
|
+
Use **Change entry** to point the field somewhere else. Use **Clear** to remove the
|
|
42
|
+
pointer. **Clear** deletes no content.
|
|
43
|
+
|
|
44
|
+
## Delete a target
|
|
45
|
+
|
|
46
|
+
Picked does not delete an entry while another entry points at it. Clear the reference on
|
|
47
|
+
each entry that points at the target, then delete the target.
|
|
48
|
+
|
|
49
|
+
The same rule holds for a Model. Remove the Reference field that holds it as its **Target
|
|
50
|
+
Model** first.
|
|
51
|
+
|
|
52
|
+
## Read it in your code
|
|
53
|
+
|
|
54
|
+
The pointer and the entry travel separately. See
|
|
55
|
+
[How to read a referenced entry](/how-to/read-a-referenced-entry).
|
|
56
|
+
|
|
57
|
+
## Related
|
|
58
|
+
|
|
59
|
+
- [About content references](/explanation/content-references) — why a reference is a pointer.
|
|
60
|
+
- [Models](/reference/dashboard/content/models) — the field and its options.
|
|
61
|
+
- [Content entries](/reference/dashboard/content/content-entries) — the editor reference.
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: how-to
|
|
3
|
+
layout: docs
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# How to read a referenced entry
|
|
7
|
+
|
|
8
|
+
This guide shows you how to read the content that a
|
|
9
|
+
[Reference field](/reference/dashboard/content/models#reference-fields) points at. You
|
|
10
|
+
need a component that renders a step first. See
|
|
11
|
+
[How to render a step form](/how-to/render-a-step-form).
|
|
12
|
+
|
|
13
|
+
A Reference field holds a pointer, and not the content. The entry travels beside the
|
|
14
|
+
content of the step, so you resolve the pointer against the content of the client.
|
|
15
|
+
|
|
16
|
+
## 1. Resolve a single reference
|
|
17
|
+
|
|
18
|
+
Pass the raw field value to `useReference()` in React, or to `getReference()` in Svelte.
|
|
19
|
+
|
|
20
|
+
:::code-group
|
|
21
|
+
|
|
22
|
+
```tsx [React]
|
|
23
|
+
import { useUnit } from 'effector-react'
|
|
24
|
+
import { useReference, useStepContent } from '@picked/react/hooks'
|
|
25
|
+
|
|
26
|
+
export function ProductCategory() {
|
|
27
|
+
const content = useStepContent()
|
|
28
|
+
const category = useUnit(useReference(content?.category))
|
|
29
|
+
|
|
30
|
+
if (!category) return null
|
|
31
|
+
|
|
32
|
+
return <span>{String(category.data.name ?? '')}</span>
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
```svelte [Svelte]
|
|
37
|
+
<script lang="ts">
|
|
38
|
+
import { getStepContent, getReference } from '@picked/svelte/hooks'
|
|
39
|
+
|
|
40
|
+
const content = getStepContent()
|
|
41
|
+
const category = getReference(content.map((c) => c?.category ?? null, { skipVoid: false }))
|
|
42
|
+
</script>
|
|
43
|
+
|
|
44
|
+
{#if $category}
|
|
45
|
+
<span>{$category.data.name ?? ''}</span>
|
|
46
|
+
{/if}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
:::
|
|
50
|
+
|
|
51
|
+
In Svelte, pass a store and not a plain value. Content arrives after the component
|
|
52
|
+
starts. A plain value therefore holds the result at "not set".
|
|
53
|
+
|
|
54
|
+
## 2. Resolve a repeatable reference
|
|
55
|
+
|
|
56
|
+
Use `useReferences()` or `getReferences()`. They give a list in field order.
|
|
57
|
+
|
|
58
|
+
:::code-group
|
|
59
|
+
|
|
60
|
+
```tsx [React]
|
|
61
|
+
import { useUnit } from 'effector-react'
|
|
62
|
+
import { useReferences, useStepContent } from '@picked/react/hooks'
|
|
63
|
+
|
|
64
|
+
export function ProductCategories() {
|
|
65
|
+
const content = useStepContent()
|
|
66
|
+
const categories = useUnit(useReferences(content?.categories))
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
<ul>
|
|
70
|
+
{categories.map((category) => (
|
|
71
|
+
<li key={category.id}>{String(category.data.name ?? '')}</li>
|
|
72
|
+
))}
|
|
73
|
+
</ul>
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
```svelte [Svelte]
|
|
79
|
+
<script lang="ts">
|
|
80
|
+
import { getStepContent, getReferences } from '@picked/svelte/hooks'
|
|
81
|
+
|
|
82
|
+
const content = getStepContent()
|
|
83
|
+
const categories = getReferences(content.map((c) => c?.categories ?? null, { skipVoid: false }))
|
|
84
|
+
</script>
|
|
85
|
+
|
|
86
|
+
<ul>
|
|
87
|
+
{#each $categories as category (category.id)}
|
|
88
|
+
<li>{category.data.name ?? ''}</li>
|
|
89
|
+
{/each}
|
|
90
|
+
</ul>
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
:::
|
|
94
|
+
|
|
95
|
+
The list holds no empty places, so you need no check for each item.
|
|
96
|
+
|
|
97
|
+
## Handle a target that does not resolve
|
|
98
|
+
|
|
99
|
+
A single reference gives an empty result when Picked cannot resolve the target. A
|
|
100
|
+
repeatable reference leaves the item out of the list.
|
|
101
|
+
|
|
102
|
+
This happens when somebody deleted the target, when the target belongs to another
|
|
103
|
+
workspace, or when the chain of references is deeper than the limit.
|
|
104
|
+
|
|
105
|
+
Render something else for the empty case, as the React example above does.
|
|
106
|
+
|
|
107
|
+
## Related
|
|
108
|
+
|
|
109
|
+
- [Content](/reference/sdk/content) — every hook and its return type.
|
|
110
|
+
- [About content references](/explanation/content-references) — why the entry travels separately.
|
|
111
|
+
- [How to point one entry at another](/how-to/point-one-entry-at-another) — the dashboard side.
|
|
@@ -6,27 +6,42 @@ layout: docs
|
|
|
6
6
|
# How to reuse a section
|
|
7
7
|
|
|
8
8
|
This guide shows you how to define a common structure one time and use it in more than
|
|
9
|
-
one
|
|
9
|
+
one Model.
|
|
10
10
|
|
|
11
|
-
## Create
|
|
11
|
+
## 1. Create the section
|
|
12
12
|
|
|
13
|
-
1.
|
|
14
|
-
2. Click **
|
|
13
|
+
1. Click **Pages** in the sidebar.
|
|
14
|
+
2. Click **Page Sections**.
|
|
15
15
|
3. Click **New block**.
|
|
16
16
|
4. Enter a **Name** and a **Key**.
|
|
17
17
|
5. Add your fields.
|
|
18
18
|
6. Click **Create block**.
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
The **Category** is **Section** already, because you opened the list from **Page
|
|
21
|
+
Sections**.
|
|
22
|
+
|
|
23
|
+
## 2. Accept the section in a Model
|
|
21
24
|
|
|
22
25
|
1. Open a page layout or a step layout.
|
|
23
|
-
2. Add a **
|
|
24
|
-
3.
|
|
26
|
+
2. Add a **Page Sections** field to the schema.
|
|
27
|
+
3. Click **Save**.
|
|
28
|
+
|
|
29
|
+
The field now accepts any Block of the Section category. Make the field repeatable to
|
|
30
|
+
build a page from a list of sections.
|
|
31
|
+
|
|
32
|
+
If you want one section at a fixed place instead of a list, add a **Content block** field.
|
|
33
|
+
Set its **Block category** to the **Section** category.
|
|
34
|
+
|
|
35
|
+
## 3. Choose the section in an entry
|
|
25
36
|
|
|
26
|
-
|
|
37
|
+
1. Open a content entry that uses the Model.
|
|
38
|
+
2. Find the field that you added.
|
|
39
|
+
3. Choose your Block.
|
|
40
|
+
4. Fill in the fields of the Block.
|
|
41
|
+
5. Click **Save**.
|
|
27
42
|
|
|
28
43
|
:::warning
|
|
29
|
-
An edit to a
|
|
44
|
+
An edit to a Block does not migrate the entries that use it. Check each affected content
|
|
30
45
|
entry again, and correct every field error before you publish.
|
|
31
46
|
:::
|
|
32
47
|
|
|
@@ -34,4 +49,5 @@ entry again, and correct every field error before you publish.
|
|
|
34
49
|
|
|
35
50
|
- [About the content model](/explanation/the-content-model) — why a schema change does not
|
|
36
51
|
migrate your data.
|
|
37
|
-
- [
|
|
52
|
+
- [Blocks](/reference/dashboard/content/blocks) — the reference.
|
|
53
|
+
- [Models](/reference/dashboard/content/models) — every field type.
|
package/dist/docs/index.md
CHANGED
|
@@ -25,7 +25,7 @@ Then:
|
|
|
25
25
|
|
|
26
26
|
- **[Build](/how-to/create-an-experience)** — experiences, flows, conditions, and A/B
|
|
27
27
|
tests.
|
|
28
|
-
- **[Content](/how-to/define-a-page-layout)** —
|
|
28
|
+
- **[Content](/how-to/define-a-page-layout)** — Models, Blocks, entries, pages, and assets.
|
|
29
29
|
- **[Publish](/how-to/publish-a-workspace)** — preview, publish, and roll back.
|
|
30
30
|
- **[Administer and measure](/how-to/invite-and-remove-members)** — members, API keys,
|
|
31
31
|
analytics, and the tools that connect Picked to Google Tag Manager and to an AI tool.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: reference
|
|
3
|
+
layout: docs
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
import { Screenshot } from '../../../../../components/Screenshot'
|
|
7
|
+
|
|
8
|
+
# Blocks
|
|
9
|
+
|
|
10
|
+
A Block is a reusable schema fragment that you embed inside a Model, so that a common structure is defined one time.
|
|
11
|
+
|
|
12
|
+
<Screenshot
|
|
13
|
+
route="/{orgSlug}/{projectId}/workspaces/{workspaceId}/blocks"
|
|
14
|
+
alt="The blocks list in the schema builder on the Picked dashboard"
|
|
15
|
+
/>
|
|
16
|
+
|
|
17
|
+
## What a Block is
|
|
18
|
+
|
|
19
|
+
A Block is a schema fragment with its own **Key**. A
|
|
20
|
+
[Model](/reference/dashboard/content/models) gives its shape to a whole Page or Step. A
|
|
21
|
+
Block is a part that you put into one or more Models. Define the shape one time, then
|
|
22
|
+
reuse it everywhere.
|
|
23
|
+
|
|
24
|
+
A Block holds no data of its own. The content that fills a Block sits inside the entry
|
|
25
|
+
of the Model that embeds it.
|
|
26
|
+
|
|
27
|
+
## Where a Block appears
|
|
28
|
+
|
|
29
|
+
**CMS** in the sidebar holds **Blocks**, and that list shows every Block in the
|
|
30
|
+
workspace. **Pages** holds **Page Sections**, which is the same list limited to the
|
|
31
|
+
Section category.
|
|
32
|
+
|
|
33
|
+
## Category
|
|
34
|
+
|
|
35
|
+
| Category | What it does |
|
|
36
|
+
| --- | --- |
|
|
37
|
+
| **Section** | Marks the Block as a page section. A **Page Sections** field accepts it. |
|
|
38
|
+
| **None (general content)** | Gives the Block no layout role. |
|
|
39
|
+
|
|
40
|
+
The category is fixed when you create the Block. You cannot change it later.
|
|
41
|
+
|
|
42
|
+
A **Content block** field holds the category of the Blocks that it accepts. Give that
|
|
43
|
+
field the **Section** category to build a page section list.
|
|
44
|
+
|
|
45
|
+
A field set to **Any category** accepts every Block in the workspace. This is the only
|
|
46
|
+
kind of field that can hold a Block with no category.
|
|
47
|
+
|
|
48
|
+
## Field types
|
|
49
|
+
|
|
50
|
+
A Block holds the same field types as a Model. See
|
|
51
|
+
[Field types](/reference/dashboard/content/models#field-types).
|
|
52
|
+
|
|
53
|
+
## Related
|
|
54
|
+
|
|
55
|
+
- [About the content model](/explanation/the-content-model) — why Blocks exist.
|
|
56
|
+
- [How to reuse a section](/how-to/reuse-a-section)
|
|
57
|
+
- [Models](/reference/dashboard/content/models)
|
|
@@ -7,7 +7,7 @@ import { Screenshot } from '../../../../../components/Screenshot'
|
|
|
7
7
|
|
|
8
8
|
# Content Entries
|
|
9
9
|
|
|
10
|
-
A
|
|
10
|
+
A content entry is one instance of a Model, filled with real data. A Page renders one entry, and a Flow Step can render one too.
|
|
11
11
|
|
|
12
12
|
<Screenshot
|
|
13
13
|
route="/{orgSlug}/{projectId}/workspaces/{workspaceId}/content"
|
|
@@ -16,29 +16,80 @@ A Content Entry is an instance of a layout filled with real data. A Page renders
|
|
|
16
16
|
|
|
17
17
|
## What a content entry is
|
|
18
18
|
|
|
19
|
-
A
|
|
19
|
+
A content entry is an instance of the schema of a
|
|
20
|
+
[Model](/reference/dashboard/content/models). The Model sets the fields, and the entry
|
|
21
|
+
holds the values. One Model backs many entries, and each entry holds its own data.
|
|
22
|
+
|
|
23
|
+
The Model of an entry is fixed when you create the entry.
|
|
24
|
+
|
|
25
|
+
## The entries list
|
|
26
|
+
|
|
27
|
+
**CMS** in the sidebar holds **Content entries**, with a count of every entry in the
|
|
28
|
+
workspace.
|
|
29
|
+
|
|
30
|
+
| Column | What it shows |
|
|
31
|
+
| --- | --- |
|
|
32
|
+
| Title | The value of the first single-line text field of the entry. It falls back to the entry id when no such field holds a value. |
|
|
33
|
+
| Model | The Model that the entry belongs to. |
|
|
34
|
+
| Entry ID | The stable id of the entry. |
|
|
35
|
+
| Last updated | When somebody last saved the entry. |
|
|
36
|
+
|
|
37
|
+
The **Model** filter narrows the list to one Model. The list has no search, because the
|
|
38
|
+
title is derived at read time and is not a column that Picked can search.
|
|
20
39
|
|
|
21
40
|
## How entries bind to pages and steps
|
|
22
41
|
|
|
23
|
-
A [Page](/reference/dashboard/content/pages) has a single Step, and that Step links to
|
|
42
|
+
A [Page](/reference/dashboard/content/pages) has a single Step, and that Step links to
|
|
43
|
+
its entry through the layout content link. A Flow [Step](/reference/dashboard/steps)
|
|
44
|
+
with a Step Layout binds an entry the same way. When the SDK renders the Page or the
|
|
45
|
+
Step, it resolves the linked entry and gives the data to your component.
|
|
24
46
|
|
|
25
47
|
## Edit entry data
|
|
26
48
|
|
|
27
|
-
The entry editor renders a form from the
|
|
28
|
-
field, in the order that the schema sets. A repeatable field
|
|
49
|
+
The entry editor renders a form from the schema of the Model. There is one input for
|
|
50
|
+
each field, in the order that the schema sets. A repeatable field shows as a sortable
|
|
29
51
|
list. You can add to that list and put it into a new order. A group field holds its
|
|
30
52
|
inputs under one heading.
|
|
31
53
|
|
|
54
|
+
## Reference fields
|
|
55
|
+
|
|
56
|
+
A [Reference field](/reference/dashboard/content/models#reference-fields) holds a pointer
|
|
57
|
+
at another entry, and not a copy of it.
|
|
58
|
+
|
|
59
|
+
| Control | What it does |
|
|
60
|
+
| --- | --- |
|
|
61
|
+
| **Choose entry** | Opens the entry picker. |
|
|
62
|
+
| **Change entry** | Opens the entry picker on a field that holds a target already. |
|
|
63
|
+
| **Clear** | Removes the pointer. It does not delete the entry. |
|
|
64
|
+
|
|
65
|
+
The entry picker lists the entries that the **Target Model** of the field allows, and it
|
|
66
|
+
has a search box. **Open model** opens the Model of an entry in a new tab.
|
|
67
|
+
|
|
32
68
|
## Validation
|
|
33
69
|
|
|
34
|
-
Invalid data
|
|
35
|
-
|
|
36
|
-
|
|
70
|
+
Invalid data shows as an error on each field. The error carries a path in the JSON style,
|
|
71
|
+
and it points at the exact place in the entry, for example `sections[0].data.title`.
|
|
72
|
+
|
|
73
|
+
A reference field reports an error when its target does not exist, or when the target
|
|
74
|
+
belongs to the wrong Model. Fix every error before you publish, because Picked serves
|
|
37
75
|
valid content only.
|
|
38
76
|
|
|
77
|
+
## Delete rules
|
|
78
|
+
|
|
79
|
+
Picked does not delete an entry while something still points at it.
|
|
80
|
+
|
|
81
|
+
| Condition | Result |
|
|
82
|
+
| --- | --- |
|
|
83
|
+
| A Step uses the entry as its layout | The delete stops. |
|
|
84
|
+
| Another entry points at it through a Reference field | The delete stops. |
|
|
85
|
+
|
|
86
|
+
Clear the reference on the other entry first, then delete the target.
|
|
87
|
+
|
|
39
88
|
## Related
|
|
40
89
|
|
|
41
90
|
- [About the content model](/explanation/the-content-model) — why the schema and the data
|
|
42
91
|
are separate.
|
|
43
|
-
- [
|
|
44
|
-
- [
|
|
92
|
+
- [About content references](/explanation/content-references) — why a delete stops.
|
|
93
|
+
- [How to create a content entry](/how-to/create-a-content-entry)
|
|
94
|
+
- [How to point one entry at another](/how-to/point-one-entry-at-another)
|
|
95
|
+
- [Models](/reference/dashboard/content/models)
|