@rulab/adminjs-components 0.2.0 → 0.2.2
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/README.md +32 -2
- package/dist/components/ColorStatus/ColorStatusEdit.js +7 -3
- package/dist/components/ColorStatus/ColorStatusFeature.d.ts +1 -0
- package/dist/components/ColorStatus/ColorStatusFeature.js +8 -2
- package/dist/components/Editor/config.d.ts +1 -0
- package/dist/components/Editor/config.js +3 -0
- package/dist/components/StringList/StringList.js +5 -4
- package/dist/components/StringList/StringListFeature.d.ts +1 -0
- package/dist/components/StringList/StringListFeature.js +2 -1
- package/dist/components/StringList/StringListShow.js +6 -4
- package/dist/utils/parseHtml.js +9 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# adminjs-components
|
|
2
2
|
|
|
3
|
+
<a id="top"></a>
|
|
4
|
+
|
|
3
5
|
Prebuilt AdminJS components and features for common UI needs: colored status
|
|
4
6
|
badges, slug and UUID generation, Editor.js content, sortable string lists, tabs
|
|
5
7
|
layout, and record preview.
|
|
@@ -46,9 +48,19 @@ You can also pass `componentLoader` into every feature instead of calling
|
|
|
46
48
|
|
|
47
49
|
## Components and features
|
|
48
50
|
|
|
51
|
+
- [ColorStatus](#colorstatus)
|
|
52
|
+
- [Slug](#slug)
|
|
53
|
+
- [UUID](#uuid)
|
|
54
|
+
- [Editor](#editor)
|
|
55
|
+
- [StringList](#stringlist)
|
|
56
|
+
- [Tabs](#tabs)
|
|
57
|
+
- [Preview](#preview)
|
|
58
|
+
|
|
49
59
|
### ColorStatus
|
|
50
60
|
|
|
51
61
|
Renders a colored badge in edit/list/show based on a list of available values.
|
|
62
|
+
By default (`nullable: false`) the first option is auto-selected in new records.
|
|
63
|
+
Set `nullable: true` to allow an empty value.
|
|
52
64
|
|
|
53
65
|
```ts
|
|
54
66
|
import { ColorStatusFeature } from "@rulab/adminjs-components";
|
|
@@ -56,6 +68,7 @@ import { ColorStatusFeature } from "@rulab/adminjs-components";
|
|
|
56
68
|
features: [
|
|
57
69
|
ColorStatusFeature({
|
|
58
70
|
key: "status",
|
|
71
|
+
nullable: false, // optional, default false
|
|
59
72
|
availableValues: [
|
|
60
73
|
{ value: "draft", label: "Draft", color: "#64748b" },
|
|
61
74
|
{ value: "review", label: "In review", color: "#f59e0b" },
|
|
@@ -65,6 +78,8 @@ features: [
|
|
|
65
78
|
]
|
|
66
79
|
```
|
|
67
80
|
|
|
81
|
+
[Back to top](#top)
|
|
82
|
+
|
|
68
83
|
### Slug
|
|
69
84
|
|
|
70
85
|
Generates a slug from another field and stores it in the target property.
|
|
@@ -82,6 +97,8 @@ features: [
|
|
|
82
97
|
]
|
|
83
98
|
```
|
|
84
99
|
|
|
100
|
+
[Back to top](#top)
|
|
101
|
+
|
|
85
102
|
### UUID
|
|
86
103
|
|
|
87
104
|
Adds a UUID field with a "Generate UUID" button in edit view.
|
|
@@ -98,10 +115,12 @@ features: [
|
|
|
98
115
|
]
|
|
99
116
|
```
|
|
100
117
|
|
|
118
|
+
[Back to top](#top)
|
|
119
|
+
|
|
101
120
|
### Editor
|
|
102
121
|
|
|
103
122
|
Editor.js field for rich content. Supports optional image upload via
|
|
104
|
-
`@adminjs/upload` provider.
|
|
123
|
+
`@adminjs/upload` provider, plus built-in audio and video blocks.
|
|
105
124
|
|
|
106
125
|
```ts
|
|
107
126
|
import { EditorFeature } from "@rulab/adminjs-components";
|
|
@@ -120,9 +139,12 @@ features: [
|
|
|
120
139
|
]
|
|
121
140
|
```
|
|
122
141
|
|
|
142
|
+
[Back to top](#top)
|
|
143
|
+
|
|
123
144
|
### StringList
|
|
124
145
|
|
|
125
146
|
Sortable list stored as a single string (comma-separated by default).
|
|
147
|
+
Use `separator` to override the delimiter used for storing and rendering values.
|
|
126
148
|
|
|
127
149
|
```ts
|
|
128
150
|
import { StringListFeature } from "@rulab/adminjs-components";
|
|
@@ -130,21 +152,25 @@ import { StringListFeature } from "@rulab/adminjs-components";
|
|
|
130
152
|
features: [
|
|
131
153
|
StringListFeature({
|
|
132
154
|
key: "facts",
|
|
155
|
+
separator: "|", // optional, default "|"
|
|
133
156
|
}),
|
|
134
157
|
]
|
|
135
158
|
```
|
|
136
159
|
|
|
160
|
+
[Back to top](#top)
|
|
161
|
+
|
|
137
162
|
### Tabs
|
|
138
163
|
|
|
139
164
|
Groups edit/show fields into tabs based on property `props.tab` or
|
|
140
165
|
`custom.tab`. Fields without a tab go to a common group.
|
|
166
|
+
`commonTabLabel` is optional and defaults to `"Common"`.
|
|
141
167
|
|
|
142
168
|
```ts
|
|
143
169
|
import { TabsFeature } from "@rulab/adminjs-components";
|
|
144
170
|
|
|
145
171
|
features: [
|
|
146
172
|
TabsFeature({
|
|
147
|
-
commonTabLabel: "Common"
|
|
173
|
+
commonTabLabel: "General", // optional, default "Common"
|
|
148
174
|
}),
|
|
149
175
|
]
|
|
150
176
|
|
|
@@ -157,6 +183,8 @@ properties: {
|
|
|
157
183
|
},
|
|
158
184
|
```
|
|
159
185
|
|
|
186
|
+
[Back to top](#top)
|
|
187
|
+
|
|
160
188
|
### Preview
|
|
161
189
|
|
|
162
190
|
Adds a record action that renders an iframe preview. The `url` can include
|
|
@@ -173,6 +201,8 @@ features: [
|
|
|
173
201
|
]
|
|
174
202
|
```
|
|
175
203
|
|
|
204
|
+
[Back to top](#top)
|
|
205
|
+
|
|
176
206
|
## Utilities
|
|
177
207
|
|
|
178
208
|
- `setComponentLoader(loader)` and `getComponentLoader()` to reuse a single
|
|
@@ -43,8 +43,12 @@ const colorStyles = {
|
|
|
43
43
|
};
|
|
44
44
|
export const ColorStatusEdit = ({ property, record, onChange, }) => {
|
|
45
45
|
const availableValues = property.availableValues;
|
|
46
|
-
const
|
|
47
|
-
const
|
|
46
|
+
const nullable = Boolean(property.custom?.nullable);
|
|
47
|
+
const isNewRecord = !record.id;
|
|
48
|
+
const currentValue = record.params[property.path];
|
|
49
|
+
const currentOption = availableValues.find((item) => item.value === currentValue);
|
|
50
|
+
const initialOption = currentOption ?? (!nullable && isNewRecord ? availableValues[0] : null);
|
|
51
|
+
const [selectOption, setCurrentOption] = useState(initialOption);
|
|
48
52
|
const handleSelectChange = (option) => {
|
|
49
53
|
setCurrentOption(option);
|
|
50
54
|
};
|
|
@@ -53,6 +57,6 @@ export const ColorStatusEdit = ({ property, record, onChange, }) => {
|
|
|
53
57
|
}, [selectOption]);
|
|
54
58
|
return (React.createElement(ColorStatusWrapper, null,
|
|
55
59
|
React.createElement(Label, null, property.label ?? property.path),
|
|
56
|
-
React.createElement(Select, { className: "basic-single", classNamePrefix: "select",
|
|
60
|
+
React.createElement(Select, { className: "basic-single", classNamePrefix: "select", value: selectOption, onChange: handleSelectChange, isClearable: nullable, name: "color", options: availableValues, styles: colorStyles })));
|
|
57
61
|
};
|
|
58
62
|
export default ColorStatusEdit;
|
|
@@ -4,6 +4,7 @@ type ColorStatusOptions = {
|
|
|
4
4
|
componentLoader?: ComponentLoader;
|
|
5
5
|
key: string;
|
|
6
6
|
availableValues?: AvailableValueType[];
|
|
7
|
+
nullable?: boolean;
|
|
7
8
|
};
|
|
8
9
|
export declare const ColorStatusFeature: (config: ColorStatusOptions) => FeatureType;
|
|
9
10
|
export default ColorStatusFeature;
|
|
@@ -2,7 +2,10 @@ import { buildFeature } from "adminjs";
|
|
|
2
2
|
import { bundleComponent } from "../../utils/bundle-component.js";
|
|
3
3
|
const COMPONENT_NAME = "ColorStatus";
|
|
4
4
|
export const ColorStatusFeature = (config) => {
|
|
5
|
-
const { componentLoader, key, availableValues = [] } = config;
|
|
5
|
+
const { componentLoader, key, availableValues = [], nullable = false } = config;
|
|
6
|
+
const values = nullable
|
|
7
|
+
? [{ value: null, label: "", color: "#ffffff" }, ...availableValues]
|
|
8
|
+
: availableValues;
|
|
6
9
|
const editComponent = bundleComponent(componentLoader, COMPONENT_NAME, "ColorStatusEdit.js");
|
|
7
10
|
const listComponent = bundleComponent(componentLoader, COMPONENT_NAME, "ColorStatusList.js");
|
|
8
11
|
const showComponent = bundleComponent(componentLoader, COMPONENT_NAME, "ColorStatusShow.js");
|
|
@@ -10,7 +13,10 @@ export const ColorStatusFeature = (config) => {
|
|
|
10
13
|
properties: {
|
|
11
14
|
[key]: {
|
|
12
15
|
isVisible: { filter: true, show: true, edit: true, list: true },
|
|
13
|
-
availableValues,
|
|
16
|
+
availableValues: values,
|
|
17
|
+
custom: {
|
|
18
|
+
nullable,
|
|
19
|
+
},
|
|
14
20
|
components: {
|
|
15
21
|
edit: editComponent,
|
|
16
22
|
list: listComponent,
|
|
@@ -5,6 +5,8 @@ import Quote from "@editorjs/quote";
|
|
|
5
5
|
import Table from "@editorjs/table";
|
|
6
6
|
// @ts-ignore
|
|
7
7
|
import AudioPlayer from "editorjs-audio-player";
|
|
8
|
+
// @ts-ignore
|
|
9
|
+
import SimpleVideo from "simple-video-editorjs";
|
|
8
10
|
export const EDITOR_TOOLS = {
|
|
9
11
|
paragraph: {
|
|
10
12
|
class: Paragraph,
|
|
@@ -31,4 +33,5 @@ export const EDITOR_TOOLS = {
|
|
|
31
33
|
inlineToolbar: true,
|
|
32
34
|
},
|
|
33
35
|
audioPlayer: AudioPlayer,
|
|
36
|
+
video: SimpleVideo,
|
|
34
37
|
};
|
|
@@ -3,8 +3,9 @@ import React, { useEffect, useState, } from "react";
|
|
|
3
3
|
import { ThemeProvider } from "styled-components";
|
|
4
4
|
import { StyledCustomInput, StyledInputWrapper, StyledLabel, StyledListWrapper, StyledWrapper, } from "./styles.js";
|
|
5
5
|
import { SortableList } from "./SortableList/SortableList.js";
|
|
6
|
-
|
|
7
|
-
export const StringList = ({ record, onChange, property, stringListSeparator =
|
|
6
|
+
const DEFAULT_SEPARATOR = "|";
|
|
7
|
+
export const StringList = ({ record, onChange, property, stringListSeparator = DEFAULT_SEPARATOR, }) => {
|
|
8
|
+
const separatorValue = property.props?.stringListSeparator ?? stringListSeparator;
|
|
8
9
|
const stringListValue = record.params?.[property.path] ?? property.props.value ?? "";
|
|
9
10
|
const initialList = stringListValue
|
|
10
11
|
? prepareDataForList(stringListValue)
|
|
@@ -45,10 +46,10 @@ export const StringList = ({ record, onChange, property, stringListSeparator = s
|
|
|
45
46
|
setList(newData);
|
|
46
47
|
}
|
|
47
48
|
function prepareDataForDatabase(list) {
|
|
48
|
-
return list.map(({ value }) => value).join(
|
|
49
|
+
return list.map(({ value }) => value).join(separatorValue);
|
|
49
50
|
}
|
|
50
51
|
function prepareDataForList(str) {
|
|
51
|
-
return str.split(
|
|
52
|
+
return str.split(separatorValue).map((item) => createListObject(item));
|
|
52
53
|
}
|
|
53
54
|
function createListObject(value) {
|
|
54
55
|
return {
|
|
@@ -2,6 +2,7 @@ import { ComponentLoader, FeatureType } from "adminjs";
|
|
|
2
2
|
type StringListOptions = {
|
|
3
3
|
componentLoader?: ComponentLoader;
|
|
4
4
|
key: string;
|
|
5
|
+
separator?: string;
|
|
5
6
|
};
|
|
6
7
|
export declare const StringListFeature: (config: StringListOptions) => FeatureType;
|
|
7
8
|
export default StringListFeature;
|
|
@@ -2,13 +2,14 @@ import { buildFeature } from "adminjs";
|
|
|
2
2
|
import { bundleComponent } from "../../utils/bundle-component.js";
|
|
3
3
|
const COMPONENT_NAME = "StringList";
|
|
4
4
|
export const StringListFeature = (config) => {
|
|
5
|
-
const { componentLoader, key } = config;
|
|
5
|
+
const { componentLoader, key, separator } = config;
|
|
6
6
|
const editComponent = bundleComponent(componentLoader, COMPONENT_NAME, "StringList.js");
|
|
7
7
|
const showComponent = bundleComponent(componentLoader, COMPONENT_NAME, "StringListShow.js");
|
|
8
8
|
return buildFeature({
|
|
9
9
|
properties: {
|
|
10
10
|
[key]: {
|
|
11
11
|
isVisible: { filter: true, show: true, edit: true, list: true },
|
|
12
|
+
props: separator ? { stringListSeparator: separator } : undefined,
|
|
12
13
|
components: {
|
|
13
14
|
edit: editComponent,
|
|
14
15
|
show: showComponent,
|
|
@@ -2,13 +2,15 @@ import React from "react";
|
|
|
2
2
|
import { ThemeProvider } from "styled-components";
|
|
3
3
|
import { theme } from "@adminjs/design-system";
|
|
4
4
|
import { StyledShowLabel, StyledShowWrapper, StyledListItem } from "./styles.js";
|
|
5
|
-
|
|
6
|
-
export const StringListShow = ({ property, record, stringListSeparator =
|
|
5
|
+
const DEFAULT_SEPARATOR = "|";
|
|
6
|
+
export const StringListShow = ({ property, record, stringListSeparator = DEFAULT_SEPARATOR, }) => {
|
|
7
|
+
const separatorValue = property.props?.stringListSeparator ?? stringListSeparator;
|
|
8
|
+
const value = record.params[property.path];
|
|
7
9
|
return (React.createElement(ThemeProvider, { theme: theme },
|
|
8
10
|
React.createElement(StyledShowWrapper, null,
|
|
9
11
|
React.createElement(StyledShowLabel, null, property.label ?? property.path),
|
|
10
|
-
|
|
11
|
-
.split(
|
|
12
|
+
value && (React.createElement("ul", null, value
|
|
13
|
+
.split(separatorValue)
|
|
12
14
|
.map((item, index) => (React.createElement(StyledListItem, { key: index }, `- ${item}`))))))));
|
|
13
15
|
};
|
|
14
16
|
export default StringListShow;
|
package/dist/utils/parseHtml.js
CHANGED
|
@@ -20,12 +20,20 @@ const tableParser = (block) => {
|
|
|
20
20
|
}
|
|
21
21
|
};
|
|
22
22
|
const audioPlayerParser = (block) => {
|
|
23
|
-
return `<audio controls src=
|
|
23
|
+
return `<audio controls src="${block.data.src}"></audio>`;
|
|
24
|
+
};
|
|
25
|
+
const videoParser = (block) => {
|
|
26
|
+
const controls = block.data.controls === false ? "" : " controls";
|
|
27
|
+
const autoplay = block.data.autoplay ? " autoplay" : "";
|
|
28
|
+
const muted = block.data.muted ? " muted" : "";
|
|
29
|
+
const caption = block.data.caption ? `<figcaption>${block.data.caption}</figcaption>` : "";
|
|
30
|
+
return `<figure><video src="${block.data.url}"${controls}${autoplay}${muted}></video>${caption}</figure>`;
|
|
24
31
|
};
|
|
25
32
|
export const parseHtml = (jsonData) => {
|
|
26
33
|
const edjsParser = edjsHTML({
|
|
27
34
|
table: tableParser,
|
|
28
35
|
audioPlayer: audioPlayerParser,
|
|
36
|
+
video: videoParser,
|
|
29
37
|
});
|
|
30
38
|
try {
|
|
31
39
|
const data = edjsParser.parse(JSON.parse(jsonData));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rulab/adminjs-components",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Prebuilt AdminJS features for common UI needs.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
"editorjs-audio-player": "~0.0.3",
|
|
52
52
|
"editorjs-html": "~3.4.3",
|
|
53
53
|
"react-select": "^5.8.0",
|
|
54
|
+
"simple-video-editorjs": "~1.4.9",
|
|
54
55
|
"slugify": "^1.6.6"
|
|
55
56
|
},
|
|
56
57
|
"peerDependencies": {
|