@firecms/collection_editor 3.0.0 → 3.1.0-canary.02232f4

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.
Files changed (119) hide show
  1. package/dist/ConfigControllerProvider.d.ts +6 -0
  2. package/dist/api/generateCollectionApi.d.ts +71 -0
  3. package/dist/api/index.d.ts +1 -0
  4. package/dist/index.d.ts +5 -1
  5. package/dist/index.es.js +15234 -8138
  6. package/dist/index.es.js.map +1 -1
  7. package/dist/index.umd.js +15199 -8103
  8. package/dist/index.umd.js.map +1 -1
  9. package/dist/locales/de.d.ts +120 -0
  10. package/dist/locales/en.d.ts +120 -0
  11. package/dist/locales/es.d.ts +120 -0
  12. package/dist/locales/fr.d.ts +120 -0
  13. package/dist/locales/hi.d.ts +120 -0
  14. package/dist/locales/it.d.ts +120 -0
  15. package/dist/locales/pt.d.ts +120 -0
  16. package/dist/types/collection_editor_controller.d.ts +14 -0
  17. package/dist/types/collection_inference.d.ts +8 -2
  18. package/dist/types/config_controller.d.ts +31 -1
  19. package/dist/ui/AddKanbanColumnAction.d.ts +11 -0
  20. package/dist/ui/KanbanSetupAction.d.ts +10 -0
  21. package/dist/ui/collection_editor/AICollectionGeneratorPopover.d.ts +37 -0
  22. package/dist/ui/collection_editor/AIModifiedPathsContext.d.ts +20 -0
  23. package/dist/ui/collection_editor/CollectionDetailsForm.d.ts +2 -3
  24. package/dist/ui/collection_editor/CollectionEditorDialog.d.ts +24 -0
  25. package/dist/ui/collection_editor/CollectionEditorWelcomeView.d.ts +4 -1
  26. package/dist/ui/collection_editor/CollectionJsonImportDialog.d.ts +7 -0
  27. package/dist/ui/collection_editor/CollectionYupValidation.d.ts +9 -13
  28. package/dist/ui/collection_editor/DisplaySettingsForm.d.ts +3 -0
  29. package/dist/ui/collection_editor/EntityActionsEditTab.d.ts +2 -1
  30. package/dist/ui/collection_editor/ExtendSettingsForm.d.ts +14 -0
  31. package/dist/ui/collection_editor/GeneralSettingsForm.d.ts +7 -0
  32. package/dist/ui/collection_editor/KanbanConfigSection.d.ts +4 -0
  33. package/dist/ui/collection_editor/PropertyEditView.d.ts +6 -1
  34. package/dist/ui/collection_editor/PropertyTree.d.ts +2 -1
  35. package/dist/ui/collection_editor/SubcollectionsEditTab.d.ts +2 -1
  36. package/dist/ui/collection_editor/ViewModeSwitch.d.ts +6 -0
  37. package/dist/ui/collection_editor/properties/EnumPropertyField.d.ts +2 -1
  38. package/dist/ui/collection_editor/properties/conditions/ConditionsEditor.d.ts +10 -0
  39. package/dist/ui/collection_editor/properties/conditions/ConditionsPanel.d.ts +2 -0
  40. package/dist/ui/collection_editor/properties/conditions/EnumConditionsEditor.d.ts +6 -0
  41. package/dist/ui/collection_editor/properties/conditions/index.d.ts +6 -0
  42. package/dist/ui/collection_editor/properties/conditions/property_paths.d.ts +19 -0
  43. package/dist/useCollectionEditorPlugin.d.ts +7 -1
  44. package/dist/utils/validateCollectionJson.d.ts +22 -0
  45. package/package.json +15 -15
  46. package/src/ConfigControllerProvider.tsx +82 -47
  47. package/src/api/generateCollectionApi.ts +119 -0
  48. package/src/api/index.ts +1 -0
  49. package/src/index.ts +28 -1
  50. package/src/locales/de.ts +125 -0
  51. package/src/locales/en.ts +145 -0
  52. package/src/locales/es.ts +125 -0
  53. package/src/locales/fr.ts +125 -0
  54. package/src/locales/hi.ts +125 -0
  55. package/src/locales/it.ts +125 -0
  56. package/src/locales/pt.ts +125 -0
  57. package/src/types/collection_editor_controller.tsx +16 -3
  58. package/src/types/collection_inference.ts +15 -2
  59. package/src/types/config_controller.tsx +37 -1
  60. package/src/ui/AddKanbanColumnAction.tsx +203 -0
  61. package/src/ui/EditorCollectionAction.tsx +3 -3
  62. package/src/ui/EditorCollectionActionStart.tsx +1 -2
  63. package/src/ui/EditorEntityAction.tsx +3 -2
  64. package/src/ui/HomePageEditorCollectionAction.tsx +41 -13
  65. package/src/ui/KanbanSetupAction.tsx +38 -0
  66. package/src/ui/MissingReferenceWidget.tsx +1 -1
  67. package/src/ui/NewCollectionButton.tsx +4 -2
  68. package/src/ui/NewCollectionCard.tsx +7 -4
  69. package/src/ui/PropertyAddColumnComponent.tsx +4 -3
  70. package/src/ui/collection_editor/AICollectionGeneratorPopover.tsx +243 -0
  71. package/src/ui/collection_editor/AIModifiedPathsContext.tsx +88 -0
  72. package/src/ui/collection_editor/CollectionDetailsForm.tsx +222 -268
  73. package/src/ui/collection_editor/CollectionEditorDialog.tsx +270 -204
  74. package/src/ui/collection_editor/CollectionEditorWelcomeView.tsx +138 -71
  75. package/src/ui/collection_editor/CollectionJsonImportDialog.tsx +171 -0
  76. package/src/ui/collection_editor/CollectionPropertiesEditorForm.tsx +202 -101
  77. package/src/ui/collection_editor/DisplaySettingsForm.tsx +335 -0
  78. package/src/ui/collection_editor/EntityActionsEditTab.tsx +106 -97
  79. package/src/ui/collection_editor/EntityActionsSelectDialog.tsx +8 -10
  80. package/src/ui/collection_editor/EntityCustomViewsSelectDialog.tsx +5 -7
  81. package/src/ui/collection_editor/EnumForm.tsx +153 -102
  82. package/src/ui/collection_editor/ExtendSettingsForm.tsx +94 -0
  83. package/src/ui/collection_editor/GeneralSettingsForm.tsx +335 -0
  84. package/src/ui/collection_editor/GetCodeDialog.tsx +63 -41
  85. package/src/ui/collection_editor/KanbanConfigSection.tsx +209 -0
  86. package/src/ui/collection_editor/LayoutModeSwitch.tsx +27 -43
  87. package/src/ui/collection_editor/PropertyEditView.tsx +272 -199
  88. package/src/ui/collection_editor/PropertyFieldPreview.tsx +1 -1
  89. package/src/ui/collection_editor/PropertyTree.tsx +130 -58
  90. package/src/ui/collection_editor/SubcollectionsEditTab.tsx +169 -163
  91. package/src/ui/collection_editor/UnsavedChangesDialog.tsx +0 -2
  92. package/src/ui/collection_editor/ViewModeSwitch.tsx +43 -0
  93. package/src/ui/collection_editor/import/CollectionEditorImportDataPreview.tsx +6 -3
  94. package/src/ui/collection_editor/import/CollectionEditorImportMapping.tsx +5 -2
  95. package/src/ui/collection_editor/properties/BlockPropertyField.tsx +0 -2
  96. package/src/ui/collection_editor/properties/BooleanPropertyField.tsx +4 -1
  97. package/src/ui/collection_editor/properties/CommonPropertyFields.tsx +6 -4
  98. package/src/ui/collection_editor/properties/DateTimePropertyField.tsx +126 -42
  99. package/src/ui/collection_editor/properties/EnumPropertyField.tsx +32 -24
  100. package/src/ui/collection_editor/properties/MapPropertyField.tsx +8 -9
  101. package/src/ui/collection_editor/properties/MarkdownPropertyField.tsx +128 -53
  102. package/src/ui/collection_editor/properties/NumberPropertyField.tsx +3 -1
  103. package/src/ui/collection_editor/properties/ReferencePropertyField.tsx +6 -9
  104. package/src/ui/collection_editor/properties/StoragePropertyField.tsx +65 -49
  105. package/src/ui/collection_editor/properties/StringPropertyField.tsx +3 -1
  106. package/src/ui/collection_editor/properties/UrlPropertyField.tsx +12 -10
  107. package/src/ui/collection_editor/properties/advanced/AdvancedPropertyValidation.tsx +23 -4
  108. package/src/ui/collection_editor/properties/conditions/ConditionsEditor.tsx +866 -0
  109. package/src/ui/collection_editor/properties/conditions/ConditionsPanel.tsx +28 -0
  110. package/src/ui/collection_editor/properties/conditions/EnumConditionsEditor.tsx +599 -0
  111. package/src/ui/collection_editor/properties/conditions/index.ts +6 -0
  112. package/src/ui/collection_editor/properties/conditions/property_paths.ts +92 -0
  113. package/src/ui/collection_editor/properties/validation/ArrayPropertyValidation.tsx +5 -2
  114. package/src/ui/collection_editor/properties/validation/GeneralPropertyValidation.tsx +7 -5
  115. package/src/ui/collection_editor/properties/validation/NumberPropertyValidation.tsx +10 -7
  116. package/src/ui/collection_editor/properties/validation/StringPropertyValidation.tsx +11 -9
  117. package/src/ui/collection_editor/properties/validation/ValidationPanel.tsx +5 -2
  118. package/src/useCollectionEditorPlugin.tsx +53 -22
  119. package/src/utils/validateCollectionJson.ts +380 -0
@@ -0,0 +1,335 @@
1
+ import React, { useState } from "react";
2
+ import {
3
+ EntityCollection,
4
+ FieldCaption,
5
+ IconForView,
6
+ SearchIconsView,
7
+ singular,
8
+ toSnakeCase,
9
+ useAuthController,
10
+ useCustomizationController,
11
+ useTranslation
12
+ } from "@firecms/core";
13
+ import {
14
+ BooleanSwitchWithLabel,
15
+ Chip,
16
+ cls,
17
+ Container,
18
+ DebouncedTextField,
19
+ Dialog,
20
+ ExpandablePanel,
21
+ HistoryIcon,
22
+ IconButton,
23
+ SearchIcon,
24
+ Select,
25
+ SelectItem,
26
+ TextField,
27
+ Tooltip,
28
+ Typography
29
+ } from "@firecms/ui";
30
+
31
+ import { Field, getIn, useFormex } from "@firecms/formex";
32
+
33
+ export function GeneralSettingsForm({
34
+ isNewCollection,
35
+ existingPaths,
36
+ existingIds,
37
+ parentCollection
38
+ }: {
39
+ isNewCollection: boolean;
40
+ existingPaths?: string[];
41
+ existingIds?: string[];
42
+ parentCollection?: EntityCollection;
43
+ }) {
44
+
45
+ const {
46
+ values,
47
+ setFieldValue,
48
+ handleChange,
49
+ touched,
50
+ errors,
51
+ setFieldTouched,
52
+ submitCount
53
+ } = useFormex<EntityCollection>();
54
+
55
+ const [iconDialogOpen, setIconDialogOpen] = useState(false);
56
+
57
+ const authController = useAuthController();
58
+ const customizationController = useCustomizationController();
59
+ const { t } = useTranslation();
60
+
61
+ const updateDatabaseId = (databaseId: string) => {
62
+ setFieldValue("databaseId", databaseId ?? undefined);
63
+ }
64
+
65
+ const updateName = (name: string) => {
66
+ setFieldValue("name", name);
67
+
68
+ const pathTouched = getIn(touched, "path");
69
+ if (!pathTouched && isNewCollection && name) {
70
+ setFieldValue("path", toSnakeCase(name));
71
+ }
72
+
73
+ const idTouched = getIn(touched, "id");
74
+ if (!idTouched && isNewCollection && name) {
75
+ setFieldValue("id", toSnakeCase(name));
76
+ }
77
+
78
+ const singularNameTouched = getIn(touched, "singularName");
79
+ if (!singularNameTouched && isNewCollection && name) {
80
+ setFieldValue("singularName", singular(name));
81
+ }
82
+ };
83
+
84
+ const collectionIcon = <IconForView collectionOrView={values} />;
85
+ const isSubcollection = !!parentCollection;
86
+ const showErrors = submitCount > 0;
87
+
88
+ return (
89
+ <div className={"overflow-auto my-auto"}>
90
+ <Container maxWidth={"4xl"} className={"flex flex-col gap-4 p-8 m-auto"}>
91
+
92
+ <div>
93
+ <div className="flex flex-row gap-2 py-2 pt-3 items-center">
94
+ <Typography variant={!isNewCollection ? "h5" : "h4"} className={"flex-grow"}>
95
+ {isNewCollection ? t("new_collection") : t("collection_with_name", { name: values?.name })}
96
+ </Typography>
97
+ <DefaultDatabaseField databaseId={values.databaseId}
98
+ onDatabaseIdUpdate={updateDatabaseId} />
99
+
100
+ <Tooltip title={t("change_icon")}
101
+ asChild={true}>
102
+ <IconButton
103
+ shape={"square"}
104
+ onClick={() => setIconDialogOpen(true)}>
105
+ {collectionIcon}
106
+ </IconButton>
107
+ </Tooltip>
108
+ </div>
109
+
110
+ {parentCollection && <Chip colorScheme={"tealDarker"}>
111
+ <Typography variant={"caption"}>
112
+ {t("is_subcollection_of")} <b>{parentCollection.name}</b>
113
+ </Typography>
114
+ </Chip>}
115
+
116
+ </div>
117
+
118
+ <div className={"grid grid-cols-12 gap-4"}>
119
+
120
+ {/* Name */}
121
+ <div className={"col-span-12"}>
122
+ <TextField
123
+ value={values.name ?? ""}
124
+ onChange={(e: any) => updateName(e.target.value)}
125
+ label={t("name")}
126
+ autoFocus={true}
127
+ required
128
+ error={showErrors && Boolean(errors.name)} />
129
+ <FieldCaption error={touched.name && Boolean(errors.name)}>
130
+ {touched.name && Boolean(errors.name) ? errors.name : t("collection_name_description")}
131
+ </FieldCaption>
132
+ </div>
133
+
134
+ {/* Path */}
135
+ <div className={cls("col-span-12")}>
136
+ <Field name={"path"}
137
+ as={DebouncedTextField}
138
+ label={t("path")}
139
+ required
140
+ error={showErrors && Boolean(errors.path)} />
141
+
142
+ <FieldCaption error={touched.path && Boolean(errors.path)}>
143
+ {touched.path && Boolean(errors.path)
144
+ ? errors.path
145
+ : isSubcollection ? t("relative_path_to_parent") : t("path_in_database")}
146
+ </FieldCaption>
147
+ </div>
148
+
149
+ {/* Singular Name */}
150
+ <div className={"col-span-12"}>
151
+ <TextField
152
+ error={showErrors && Boolean(errors.singularName)}
153
+ name={"singularName"}
154
+ aria-describedby={"singularName-helper"}
155
+ onChange={(e) => {
156
+ setFieldTouched("singularName", true);
157
+ return handleChange(e);
158
+ }}
159
+ value={values.singularName ?? ""}
160
+ label={t("singular_name")} />
161
+ <FieldCaption error={showErrors && Boolean(errors.singularName)}>
162
+ {showErrors && Boolean(errors.singularName) ? errors.singularName : t("singular_name_description")}
163
+ </FieldCaption>
164
+ </div>
165
+
166
+ {/* Description */}
167
+ <div className={"col-span-12"}>
168
+ <TextField
169
+ error={showErrors && Boolean(errors.description)}
170
+ name="description"
171
+ value={values.description ?? ""}
172
+ onChange={handleChange}
173
+ multiline
174
+ minRows={2}
175
+ aria-describedby="description-helper-text"
176
+ label={t("description")}
177
+ />
178
+ <FieldCaption error={showErrors && Boolean(errors.description)}>
179
+ {showErrors && Boolean(errors.description) ? errors.description : t("description_of_collection")}
180
+ </FieldCaption>
181
+ </div>
182
+
183
+ {/* Collection ID */}
184
+ <div className={"col-span-12"}>
185
+ <Field name={"id"}
186
+ as={DebouncedTextField}
187
+ disabled={!isNewCollection}
188
+ label={t("collection_id")}
189
+ error={showErrors && Boolean(errors.id)} />
190
+ <FieldCaption error={touched.id && Boolean(errors.id)}>
191
+ {touched.id && Boolean(errors.id) ? errors.id : t("collection_id_description")}
192
+ </FieldCaption>
193
+ </div>
194
+
195
+ {/* Collection Group */}
196
+ <div className={"col-span-12"}>
197
+ <BooleanSwitchWithLabel
198
+ position={"start"}
199
+ size={"large"}
200
+ label={t("collection_group")}
201
+ onValueChange={(v) => setFieldValue("collectionGroup", v)}
202
+ value={values.collectionGroup ?? false}
203
+ />
204
+ <FieldCaption>
205
+ {t("collection_group_description")}
206
+ </FieldCaption>
207
+ </div>
208
+
209
+ </div>
210
+
211
+ {/* Advanced Settings */}
212
+ <ExpandablePanel
213
+ title={<Typography variant="subtitle2">{t("advanced_settings")}</Typography>}
214
+ initiallyExpanded={false}
215
+ className="mt-4"
216
+ innerClassName="p-4 flex flex-col gap-4"
217
+ >
218
+ {/* History revisions */}
219
+ <div>
220
+ <BooleanSwitchWithLabel
221
+ position={"start"}
222
+ size={"large"}
223
+ allowIndeterminate={true}
224
+ label={<span className="flex items-center gap-2"><HistoryIcon size={"smallest"} />{values.history === null || values.history === undefined ? t("doc_history_global") : (
225
+ values.history ? t("doc_history_enabled") : t("doc_history_not_enabled")
226
+ )}</span>}
227
+ onValueChange={(v) => setFieldValue("history", v)}
228
+ value={values.history === undefined ? null : values.history}
229
+ />
230
+ <FieldCaption>
231
+ {t("doc_history_description")}
232
+ </FieldCaption>
233
+ </div>
234
+
235
+ {/* Document ID generation */}
236
+ <div>
237
+ <Select
238
+ name="customId"
239
+ label={t("document_id_generation")}
240
+ position={"item-aligned"}
241
+ size={"large"}
242
+ fullWidth={true}
243
+ disabled={typeof values.customId === "object"}
244
+ onValueChange={(v) => {
245
+ if (v === "code_defined")
246
+ throw new Error("This should not happen");
247
+ if (v === "false") setFieldValue("customId", false);
248
+ else if (v === "true") setFieldValue("customId", true);
249
+ else if (v === "optional") setFieldValue("customId", "optional");
250
+ }}
251
+ value={
252
+ typeof values.customId === "object" ? "code_defined" :
253
+ values.customId === true ? "true" :
254
+ values.customId === "optional" ? "optional" : "false"
255
+ }
256
+ renderValue={(value: any) => {
257
+ if (value === "code_defined")
258
+ return t("code_defined");
259
+ else if (value === "true")
260
+ return t("users_must_define_id");
261
+ else if (value === "optional")
262
+ return t("users_can_define_id");
263
+ else
264
+ return t("doc_id_auto_generated");
265
+ }}
266
+ >
267
+ <SelectItem value={"false"}>
268
+ {t("doc_id_auto_generated")}
269
+ </SelectItem>
270
+ <SelectItem value={"true"}>
271
+ {t("users_must_define_id")}
272
+ </SelectItem>
273
+ <SelectItem value={"optional"}>
274
+ {t("users_can_define_id")}
275
+ </SelectItem>
276
+ </Select>
277
+ <FieldCaption>
278
+ {t("config_doc_id_generation")}
279
+ </FieldCaption>
280
+ </div>
281
+
282
+ {/* Text search */}
283
+ <div>
284
+ <BooleanSwitchWithLabel
285
+ position={"start"}
286
+ size={"large"}
287
+ label={<span className="flex items-center gap-2"><SearchIcon size={"smallest"} />{t("enable_text_search")}</span>}
288
+ onValueChange={(v) => setFieldValue("textSearchEnabled", v)}
289
+ value={values.textSearchEnabled ?? false}
290
+ />
291
+ <FieldCaption>
292
+ {t("text_search_description")}
293
+ </FieldCaption>
294
+ </div>
295
+ </ExpandablePanel>
296
+
297
+ <div style={{ height: "52px" }} />
298
+
299
+ <Dialog
300
+ open={iconDialogOpen}
301
+ onOpenChange={setIconDialogOpen}
302
+ maxWidth={"xl"}
303
+ fullWidth
304
+ >
305
+ <div className={"p-4 overflow-auto min-h-[200px]"}>
306
+ <SearchIconsView selectedIcon={typeof values.icon === "string" ? values.icon : undefined}
307
+ onIconSelected={(icon: string) => {
308
+ setIconDialogOpen(false);
309
+ setFieldValue("icon", icon);
310
+ }} />
311
+ </div>
312
+ </Dialog>
313
+
314
+ </Container>
315
+ </div>
316
+ );
317
+ }
318
+
319
+ function DefaultDatabaseField({
320
+ databaseId,
321
+ onDatabaseIdUpdate
322
+ }: { databaseId?: string, onDatabaseIdUpdate: (databaseId: string) => void }) {
323
+ const { t } = useTranslation();
324
+
325
+ return <Tooltip title={t("database_id")}
326
+ side={"top"}
327
+ align={"start"}>
328
+ <TextField size={"small"}
329
+ invisible={true}
330
+ inputClassName={"text-end"}
331
+ value={databaseId ?? ""}
332
+ onChange={(e: any) => onDatabaseIdUpdate(e.target.value)}
333
+ placeholder={t("default_text")}></TextField>
334
+ </Tooltip>
335
+ }
@@ -1,56 +1,77 @@
1
- import { EntityCollection, isEmptyObject, useSnackbarController } from "@firecms/core";
2
- import { Button, ContentCopyIcon, Dialog, DialogActions, DialogContent, DialogTitle, Typography } from "@firecms/ui";
3
- import React from "react";
1
+ import { EntityCollection, isEmptyObject, useSnackbarController, useTranslation } from "@firecms/core";
2
+ import { Button, ContentCopyIcon, Dialog, DialogActions, DialogContent, DialogTitle, Tab, Tabs, Typography } from "@firecms/ui";
3
+ import React, { useState } from "react";
4
4
  import JSON5 from "json5";
5
5
  import { Highlight, themes } from "prism-react-renderer"
6
6
  import { camelCase } from "./utils/strings";
7
7
  import { clone } from "@firecms/formex";
8
8
 
9
9
  export function GetCodeDialog({
10
- collection,
11
- onOpenChange,
12
- open
13
- }: { onOpenChange: (open: boolean) => void, collection: any, open: any }) {
10
+ collection,
11
+ onOpenChange,
12
+ open
13
+ }: { onOpenChange: (open: boolean) => void, collection: any, open: any }) {
14
14
 
15
15
  const snackbarController = useSnackbarController();
16
+ const { t } = useTranslation();
17
+ const [format, setFormat] = useState<"ts" | "json">("json");
18
+
19
+ const collectionData = collectionToCode({ ...collection });
20
+
21
+ const tsCode = collection
22
+ ? "import { EntityCollection } from \"@firecms/core\";\n\nconst " + (collection?.name ? camelCase(collection.name) : "my") + "Collection:EntityCollection = " + JSON5.stringify(collectionData, null, "\t")
23
+ : t("no_collection_selected");
24
+
25
+ const jsonCode = collection
26
+ ? JSON.stringify(collectionData, null, 2)
27
+ : t("no_collection_selected");
28
+
29
+ const code = format === "ts" ? tsCode : jsonCode;
16
30
 
17
- const code = collection
18
- ? "import { EntityCollection } from \"@firecms/core\";\n\nconst " + (collection?.name ? camelCase(collection.name) : "my") + "Collection:EntityCollection = " + JSON5.stringify(collectionToCode({ ...collection }), null, "\t")
19
- : "No collection selected";
20
31
  return <Dialog open={open}
21
- onOpenChange={onOpenChange}
22
- maxWidth={"4xl"}>
23
- <DialogTitle variant={"h6"}>Code for {collection.name}</DialogTitle>
32
+ onOpenChange={onOpenChange}
33
+ maxWidth={"4xl"}>
34
+ <div className="flex items-center justify-between pr-6">
35
+ <DialogTitle variant={"h6"}>{t("code_for_collection")} {collection.name}</DialogTitle>
36
+ <Tabs value={format} onValueChange={(v) => setFormat(v as "ts" | "json")}>
37
+ <Tab value="ts">TypeScript</Tab>
38
+ <Tab value="json">JSON</Tab>
39
+ </Tabs>
40
+ </div>
24
41
  <DialogContent>
25
42
 
26
- <Typography variant={"body2"} className={"my-4 mb-8"}>
27
- If you want to customise the collection in code, you can add this collection code to your CMS
28
- app configuration.
29
- More info in the <a
30
- rel="noopener noreferrer"
31
- href={"https://firecms.co/docs/cloud/quickstart"}>docs</a>.
43
+ <Typography variant={"body2"} className={"mb-4"}>
44
+ {format === "json"
45
+ ? t("use_config_define_json")
46
+ : <>
47
+ {t("customise_collection_code")}
48
+ <br/>
49
+ <a
50
+ rel="noopener noreferrer"
51
+ href={"https://firecms.co/docs/cloud/quickstart"}>{t("more_info")}</a>
52
+ </>}
32
53
  </Typography>
33
54
  <Highlight
34
55
  theme={themes.vsDark}
35
56
  code={code}
36
- language="typescript"
57
+ language={format === "ts" ? "typescript" : "json"}
37
58
  >
38
59
  {({
39
- className,
40
- style,
41
- tokens,
42
- getLineProps,
43
- getTokenProps
44
- }) => (
60
+ className,
61
+ style,
62
+ tokens,
63
+ getLineProps,
64
+ getTokenProps
65
+ }) => (
45
66
  <pre style={style} className={"p-4 rounded text-sm"}>
46
- {tokens.map((line, i) => (
47
- <div key={i} {...getLineProps({ line })}>
48
- {line.map((token, key) => (
49
- <span key={key} {...getTokenProps({ token })} />
50
- ))}
51
- </div>
52
- ))}
53
- </pre>
67
+ {tokens.map((line, i) => (
68
+ <div key={i} {...getLineProps({ line })}>
69
+ {line.map((token, key) => (
70
+ <span key={key} {...getTokenProps({ token })} />
71
+ ))}
72
+ </div>
73
+ ))}
74
+ </pre>
54
75
  )}
55
76
  </Highlight>
56
77
 
@@ -59,20 +80,19 @@ export function GetCodeDialog({
59
80
  <Button
60
81
  variant={"text"}
61
82
  size={"small"}
62
- color={"primary"}
63
83
  onClick={(e) => {
64
84
  e.stopPropagation();
65
85
  e.preventDefault();
66
86
  snackbarController.open({
67
87
  type: "success",
68
- message: "Copied"
88
+ message: t("copied")
69
89
  })
70
90
  return navigator.clipboard.writeText(code);
71
91
  }}>
72
- <ContentCopyIcon size={"small"}/>
73
- Copy to clipboard
92
+ <ContentCopyIcon size={"small"} />
93
+ {t("copy")}
74
94
  </Button>
75
- <Button onClick={() => onOpenChange(false)}>Close</Button>
95
+ <Button onClick={() => onOpenChange(false)}>{t("cancel")}</Button>
76
96
  </DialogActions>
77
97
  </Dialog>;
78
98
  }
@@ -134,8 +154,10 @@ function collectionToCode(collection: EntityCollection): object {
134
154
  .map(([key, value]) => ({
135
155
  [key]: propertyCleanup(value)
136
156
  }))
137
- .reduce((a, b) => ({ ...a,
138
- ...b }), {}),
157
+ .reduce((a, b) => ({
158
+ ...a,
159
+ ...b
160
+ }), {}),
139
161
  subcollections: (collection.subcollections ?? []).map(collectionToCode)
140
162
  }
141
163