@arpproject/recrate 0.1.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.
Files changed (286) hide show
  1. package/.eslintrc.json +37 -0
  2. package/.storybook/main.ts +40 -0
  3. package/.storybook/preview.tsx +46 -0
  4. package/LICENCE +18 -0
  5. package/README.md +83 -0
  6. package/babel.config.json +5 -0
  7. package/dist/app/App.d.ts +2 -0
  8. package/dist/app/EmbeddedComponent.d.ts +3 -0
  9. package/dist/app/index.d.ts +0 -0
  10. package/dist/app/lookup.d.ts +82 -0
  11. package/dist/crate-builder/CrateManager/contexts.d.ts +6 -0
  12. package/dist/crate-builder/CrateManager/crate-manager-benchmarking.spec.d.ts +1 -0
  13. package/dist/crate-builder/CrateManager/crate-manager-loading-exporting.spec.d.ts +1 -0
  14. package/dist/crate-builder/CrateManager/crate-manager-operations.spec.d.ts +0 -0
  15. package/dist/crate-builder/CrateManager/crate-manager.d.ts +641 -0
  16. package/dist/crate-builder/CrateManager/crate-manager.spec.d.ts +1 -0
  17. package/dist/crate-builder/CrateManager/lib.d.ts +26 -0
  18. package/dist/crate-builder/CrateManager/lib.spec.d.ts +1 -0
  19. package/dist/crate-builder/CrateManager/profile-manager.d.ts +143 -0
  20. package/dist/crate-builder/CrateManager/profile-manager.spec.d.ts +1 -0
  21. package/dist/crate-builder/CrateManager/schema-type-definitions.json.d.ts +35125 -0
  22. package/dist/crate-builder/CrateManager/validate-identifier.d.ts +10 -0
  23. package/dist/crate-builder/CrateManager/validate-identifier.spec.d.ts +1 -0
  24. package/dist/crate-builder/RenderEntity/Add.d.ts +26 -0
  25. package/dist/crate-builder/RenderEntity/AddControl.d.ts +14 -0
  26. package/dist/crate-builder/RenderEntity/AddControl.stories.d.ts +29 -0
  27. package/dist/crate-builder/RenderEntity/AutoComplete.d.ts +12 -0
  28. package/dist/crate-builder/RenderEntity/BulkAdd.d.ts +10 -0
  29. package/dist/crate-builder/RenderEntity/DeleteProperty.d.ts +8 -0
  30. package/dist/crate-builder/RenderEntity/DialogAddProperty.d.ts +9 -0
  31. package/dist/crate-builder/RenderEntity/DialogBrowseEntities.d.ts +8 -0
  32. package/dist/crate-builder/RenderEntity/DialogEditContext.d.ts +8 -0
  33. package/dist/crate-builder/RenderEntity/DialogPreviewCrate.d.ts +7 -0
  34. package/dist/crate-builder/RenderEntity/DialogSaveCrateAsTemplate.d.ts +13 -0
  35. package/dist/crate-builder/RenderEntity/DialogSaveEntityTemplate.d.ts +14 -0
  36. package/dist/crate-builder/RenderEntity/DisplayPropertyName.d.ts +8 -0
  37. package/dist/crate-builder/RenderEntity/DisplayPropertyName.stories.d.ts +6 -0
  38. package/dist/crate-builder/RenderEntity/EntityId.d.ts +13 -0
  39. package/dist/crate-builder/RenderEntity/EntityName.d.ts +13 -0
  40. package/dist/crate-builder/RenderEntity/EntityProperty.d.ts +19 -0
  41. package/dist/crate-builder/RenderEntity/EntityPropertyInstance.d.ts +25 -0
  42. package/dist/crate-builder/RenderEntity/EntityType.d.ts +12 -0
  43. package/dist/crate-builder/RenderEntity/ItemLink.d.ts +14 -0
  44. package/dist/crate-builder/RenderEntity/PaginateLinkedEntities.d.ts +23 -0
  45. package/dist/crate-builder/RenderEntity/PaginateLinkedEntities.stories.d.ts +7 -0
  46. package/dist/crate-builder/RenderEntity/PropertyHelp.d.ts +6 -0
  47. package/dist/crate-builder/RenderEntity/RenderControls.d.ts +22 -0
  48. package/dist/crate-builder/RenderEntity/RenderLinkedItem.d.ts +20 -0
  49. package/dist/crate-builder/RenderEntity/RenderPropertyHelp.d.ts +6 -0
  50. package/dist/crate-builder/RenderEntity/RenderReverseConnections.d.ts +16 -0
  51. package/dist/crate-builder/RenderEntity/RenderTypes.d.ts +6 -0
  52. package/dist/crate-builder/RenderEntity/Shell2.d.ts +14 -0
  53. package/dist/crate-builder/RenderEntity/UnlinkEntity.d.ts +14 -0
  54. package/dist/crate-builder/RenderEntity/auto-complete.lib.d.ts +25 -0
  55. package/dist/crate-builder/RenderEntity/keys.d.ts +4 -0
  56. package/dist/crate-builder/RenderEntity/layout.d.ts +14 -0
  57. package/dist/crate-builder/RenderEntity/layout.spec.d.ts +1 -0
  58. package/dist/crate-builder/Shell.d.ts +40 -0
  59. package/dist/crate-builder/editor-state.d.ts +72 -0
  60. package/dist/crate-builder/helpers.d.ts +9 -0
  61. package/dist/crate-builder/i18n.d.ts +2 -0
  62. package/dist/crate-builder/lib/validate-iri.d.ts +6 -0
  63. package/dist/crate-builder/locales/en.d.ts +79 -0
  64. package/dist/crate-builder/locales/hu.d.ts +79 -0
  65. package/dist/crate-builder/primitives/Boolean.d.ts +11 -0
  66. package/dist/crate-builder/primitives/Boolean.stories.d.ts +7 -0
  67. package/dist/crate-builder/primitives/Date.d.ts +11 -0
  68. package/dist/crate-builder/primitives/Date.stories.d.ts +5 -0
  69. package/dist/crate-builder/primitives/DateTime.d.ts +11 -0
  70. package/dist/crate-builder/primitives/DateTime.stories.d.ts +5 -0
  71. package/dist/crate-builder/primitives/Geo.d.ts +12 -0
  72. package/dist/crate-builder/primitives/Geo.stories.d.ts +26 -0
  73. package/dist/crate-builder/primitives/Map.SelectArea.d.ts +9 -0
  74. package/dist/crate-builder/primitives/Map.d.ts +15 -0
  75. package/dist/crate-builder/primitives/Map.stories.d.ts +6 -0
  76. package/dist/crate-builder/primitives/Number.d.ts +16 -0
  77. package/dist/crate-builder/primitives/Number.stories.d.ts +10 -0
  78. package/dist/crate-builder/primitives/Select.d.ts +15 -0
  79. package/dist/crate-builder/primitives/Select.stories.d.ts +9 -0
  80. package/dist/crate-builder/primitives/SelectObject.d.ts +13 -0
  81. package/dist/crate-builder/primitives/SelectObject.stories.d.ts +5 -0
  82. package/dist/crate-builder/primitives/SelectUrl.d.ts +14 -0
  83. package/dist/crate-builder/primitives/SelectUrl.stories.d.ts +7 -0
  84. package/dist/crate-builder/primitives/Text.d.ts +19 -0
  85. package/dist/crate-builder/primitives/Text.stories.d.ts +13 -0
  86. package/dist/crate-builder/primitives/Time.d.ts +11 -0
  87. package/dist/crate-builder/primitives/Time.stories.d.ts +7 -0
  88. package/dist/crate-builder/primitives/Url.d.ts +11 -0
  89. package/dist/crate-builder/primitives/Url.stories.d.ts +7 -0
  90. package/dist/crate-builder/primitives/Value.d.ts +7 -0
  91. package/dist/crate-builder/primitives/Value.stories.d.ts +7 -0
  92. package/dist/crate-builder/primitives/date-libs.d.ts +1 -0
  93. package/dist/crate-builder/property-definitions.d.ts +78 -0
  94. package/dist/crate-builder/store.d.ts +8 -0
  95. package/dist/favicon.ico +0 -0
  96. package/dist/index.d.ts +3 -0
  97. package/dist/index.html +43 -0
  98. package/dist/logo192.png +0 -0
  99. package/dist/logo512.png +0 -0
  100. package/dist/manifest.json +25 -0
  101. package/dist/marker-icon.png +0 -0
  102. package/dist/marker-shadow.png +0 -0
  103. package/dist/recrate.es.js +158699 -0
  104. package/dist/recrate.umd.js +158717 -0
  105. package/dist/robots.txt +3 -0
  106. package/dist/style.css +1721 -0
  107. package/dist/types.d.ts +42 -0
  108. package/docker-compose.yml +30 -0
  109. package/docs/.nojekyll +1 -0
  110. package/docs/assets/highlight.css +99 -0
  111. package/docs/assets/icons.js +18 -0
  112. package/docs/assets/icons.svg +1 -0
  113. package/docs/assets/main.js +60 -0
  114. package/docs/assets/navigation.js +1 -0
  115. package/docs/assets/search.js +1 -0
  116. package/docs/assets/style.css +1448 -0
  117. package/docs/classes/src_crate_builder_CrateManager_crate_manager.CrateManager.html +240 -0
  118. package/docs/classes/src_crate_builder_CrateManager_profile_manager.ProfileManager.html +42 -0
  119. package/docs/classes/src_crate_builder_editor_state.EditorState.html +28 -0
  120. package/docs/classes/src_crate_builder_types.CrateManagerType.html +57 -0
  121. package/docs/classes/src_crate_builder_types.ProfileManagerType.html +13 -0
  122. package/docs/functions/src_crate_builder_CrateManager_lib.isURL.html +2 -0
  123. package/docs/functions/src_crate_builder_CrateManager_lib.mintNewCrate.html +3 -0
  124. package/docs/functions/src_crate_builder_CrateManager_lib.normalise.html +5 -0
  125. package/docs/functions/src_crate_builder_CrateManager_lib.normaliseEntityType.html +1 -0
  126. package/docs/index.html +58 -0
  127. package/docs/interfaces/src_crate_builder_types.NormalisedCrate.html +3 -0
  128. package/docs/interfaces/src_crate_builder_types.NormalisedEntityDefinition.html +4 -0
  129. package/docs/interfaces/src_crate_builder_types.NormalisedProfile.html +9 -0
  130. package/docs/interfaces/src_crate_builder_types.ProfileLayout.html +2 -0
  131. package/docs/interfaces/src_crate_builder_types.ProfileLayoutGroup.html +9 -0
  132. package/docs/interfaces/src_crate_builder_types.UnverifiedCrate.html +3 -0
  133. package/docs/interfaces/src_crate_builder_types.UnverifiedEntityDefinition.html +4 -0
  134. package/docs/modules/src_crate_builder_CrateManager_crate_manager.html +2 -0
  135. package/docs/modules/src_crate_builder_CrateManager_lib.html +6 -0
  136. package/docs/modules/src_crate_builder_CrateManager_profile_manager.html +2 -0
  137. package/docs/modules/src_crate_builder_editor_state.html +2 -0
  138. package/docs/modules/src_crate_builder_types.html +16 -0
  139. package/docs/types/src_crate_builder_types.EntityReference.html +1 -0
  140. package/docs/types/src_crate_builder_types.NormalisedContext.html +1 -0
  141. package/docs/types/src_crate_builder_types.PrimitiveType.html +1 -0
  142. package/docs/types/src_crate_builder_types.ProfileAssociation.html +1 -0
  143. package/docs/types/src_crate_builder_types.ProfileInput.html +1 -0
  144. package/docs/types/src_crate_builder_types.UnverifiedContext.html +1 -0
  145. package/docs/variables/src_crate_builder_CrateManager_lib.urlProtocols.html +1 -0
  146. package/index.html +13 -0
  147. package/load-data-packs.cjs +38 -0
  148. package/package.json +135 -0
  149. package/postcss.config.cjs +6 -0
  150. package/public/favicon.ico +0 -0
  151. package/public/index.html +43 -0
  152. package/public/logo192.png +0 -0
  153. package/public/logo512.png +0 -0
  154. package/public/manifest.json +25 -0
  155. package/public/marker-icon.png +0 -0
  156. package/public/marker-shadow.png +0 -0
  157. package/public/robots.txt +3 -0
  158. package/react-app-env.d.ts +1 -0
  159. package/rollup.config.js +26 -0
  160. package/src/app/App.tsx +13 -0
  161. package/src/app/EmbeddedComponent.tsx +432 -0
  162. package/src/app/index.html +20 -0
  163. package/src/app/index.tsx +19 -0
  164. package/src/app/lookup.ts +141 -0
  165. package/src/app/override-styles.css +96 -0
  166. package/src/crate-builder/CrateManager/contexts/1.1-context.jsonld +2660 -0
  167. package/src/crate-builder/CrateManager/contexts/1.2-DRAFT-context.jsonld +2918 -0
  168. package/src/crate-builder/CrateManager/contexts.ts +42 -0
  169. package/src/crate-builder/CrateManager/crate-manager-benchmarking.spec.ts +31 -0
  170. package/src/crate-builder/CrateManager/crate-manager-loading-exporting.spec.ts +431 -0
  171. package/src/crate-builder/CrateManager/crate-manager-operations.spec.ts +298 -0
  172. package/src/crate-builder/CrateManager/crate-manager.spec.ts +2336 -0
  173. package/src/crate-builder/CrateManager/crate-manager.ts +2111 -0
  174. package/src/crate-builder/CrateManager/lib.spec.ts +133 -0
  175. package/src/crate-builder/CrateManager/lib.ts +170 -0
  176. package/src/crate-builder/CrateManager/profile-manager.spec.ts +593 -0
  177. package/src/crate-builder/CrateManager/profile-manager.ts +367 -0
  178. package/src/crate-builder/CrateManager/schema-type-definitions.json +35122 -0
  179. package/src/crate-builder/CrateManager/validate-identifier.spec.ts +82 -0
  180. package/src/crate-builder/CrateManager/validate-identifier.ts +65 -0
  181. package/src/crate-builder/RenderEntity/Add.tsx +249 -0
  182. package/src/crate-builder/RenderEntity/AddControl.stories.tsx +126 -0
  183. package/src/crate-builder/RenderEntity/AddControl.tsx +84 -0
  184. package/src/crate-builder/RenderEntity/AutoComplete.tsx +215 -0
  185. package/src/crate-builder/RenderEntity/BulkAdd.tsx +136 -0
  186. package/src/crate-builder/RenderEntity/DeleteProperty.tsx +33 -0
  187. package/src/crate-builder/RenderEntity/DialogAddProperty.tsx +83 -0
  188. package/src/crate-builder/RenderEntity/DialogBrowseEntities.tsx +136 -0
  189. package/src/crate-builder/RenderEntity/DialogEditContext.tsx +107 -0
  190. package/src/crate-builder/RenderEntity/DialogPreviewCrate.tsx +54 -0
  191. package/src/crate-builder/RenderEntity/DialogSaveCrateAsTemplate.tsx +65 -0
  192. package/src/crate-builder/RenderEntity/DialogSaveEntityTemplate.tsx +87 -0
  193. package/src/crate-builder/RenderEntity/DisplayPropertyName.stories.tsx +30 -0
  194. package/src/crate-builder/RenderEntity/DisplayPropertyName.tsx +21 -0
  195. package/src/crate-builder/RenderEntity/EntityId.tsx +75 -0
  196. package/src/crate-builder/RenderEntity/EntityName.tsx +49 -0
  197. package/src/crate-builder/RenderEntity/EntityProperty.tsx +188 -0
  198. package/src/crate-builder/RenderEntity/EntityPropertyInstance.tsx +255 -0
  199. package/src/crate-builder/RenderEntity/EntityType.tsx +95 -0
  200. package/src/crate-builder/RenderEntity/ItemLink.tsx +37 -0
  201. package/src/crate-builder/RenderEntity/PaginateLinkedEntities.stories.tsx +43 -0
  202. package/src/crate-builder/RenderEntity/PaginateLinkedEntities.tsx +141 -0
  203. package/src/crate-builder/RenderEntity/PropertyHelp.tsx +39 -0
  204. package/src/crate-builder/RenderEntity/RenderControls.tsx +278 -0
  205. package/src/crate-builder/RenderEntity/RenderLinkedItem.tsx +139 -0
  206. package/src/crate-builder/RenderEntity/RenderPropertyHelp.tsx +41 -0
  207. package/src/crate-builder/RenderEntity/RenderReverseConnections.tsx +150 -0
  208. package/src/crate-builder/RenderEntity/RenderTypes.tsx +102 -0
  209. package/src/crate-builder/RenderEntity/Shell2.tsx +576 -0
  210. package/src/crate-builder/RenderEntity/UnlinkEntity.tsx +30 -0
  211. package/src/crate-builder/RenderEntity/auto-complete.lib.ts +184 -0
  212. package/src/crate-builder/RenderEntity/keys.ts +4 -0
  213. package/src/crate-builder/RenderEntity/layout.spec.js +593 -0
  214. package/src/crate-builder/RenderEntity/layout.ts +220 -0
  215. package/src/crate-builder/Shell.tsx +323 -0
  216. package/src/crate-builder/component.css +65 -0
  217. package/src/crate-builder/editor-state.ts +114 -0
  218. package/src/crate-builder/helpers.ts +16 -0
  219. package/src/crate-builder/i18n.ts +22 -0
  220. package/src/crate-builder/lib/validate-iri.js +69 -0
  221. package/src/crate-builder/lib/validate-iri.ts +57 -0
  222. package/src/crate-builder/locales/en.js +149 -0
  223. package/src/crate-builder/locales/hu.js +147 -0
  224. package/src/crate-builder/primitives/Boolean.stories.tsx +33 -0
  225. package/src/crate-builder/primitives/Boolean.tsx +67 -0
  226. package/src/crate-builder/primitives/Date.stories.tsx +32 -0
  227. package/src/crate-builder/primitives/Date.tsx +58 -0
  228. package/src/crate-builder/primitives/DateTime.stories.tsx +32 -0
  229. package/src/crate-builder/primitives/DateTime.tsx +64 -0
  230. package/src/crate-builder/primitives/Geo.stories.tsx +57 -0
  231. package/src/crate-builder/primitives/Geo.tsx +225 -0
  232. package/src/crate-builder/primitives/Map.SelectArea.js +359 -0
  233. package/src/crate-builder/primitives/Map.stories.tsx +61 -0
  234. package/src/crate-builder/primitives/Map.tsx +124 -0
  235. package/src/crate-builder/primitives/Number.stories.tsx +74 -0
  236. package/src/crate-builder/primitives/Number.tsx +166 -0
  237. package/src/crate-builder/primitives/Select.stories.tsx +66 -0
  238. package/src/crate-builder/primitives/Select.tsx +122 -0
  239. package/src/crate-builder/primitives/SelectObject.stories.tsx +29 -0
  240. package/src/crate-builder/primitives/SelectObject.tsx +105 -0
  241. package/src/crate-builder/primitives/SelectUrl.stories.tsx +42 -0
  242. package/src/crate-builder/primitives/SelectUrl.tsx +110 -0
  243. package/src/crate-builder/primitives/Text.stories.tsx +106 -0
  244. package/src/crate-builder/primitives/Text.tsx +197 -0
  245. package/src/crate-builder/primitives/Time.stories.tsx +38 -0
  246. package/src/crate-builder/primitives/Time.tsx +71 -0
  247. package/src/crate-builder/primitives/Url.stories.tsx +43 -0
  248. package/src/crate-builder/primitives/Url.tsx +75 -0
  249. package/src/crate-builder/primitives/Value.stories.tsx +37 -0
  250. package/src/crate-builder/primitives/Value.tsx +30 -0
  251. package/src/crate-builder/primitives/date-libs.ts +12 -0
  252. package/src/crate-builder/profile-schema.json +145 -0
  253. package/src/crate-builder/property-definitions.ts +78 -0
  254. package/src/crate-builder/store.ts +14 -0
  255. package/src/crate-builder/tailwind.css +7 -0
  256. package/src/crate-builder/types.d.ts +318 -0
  257. package/src/examples/collection/collections-entity-example.json +131 -0
  258. package/src/examples/collection/crate-builder-entity-example.json +33 -0
  259. package/src/examples/item/complex-collection/ro-crate-metadata.json +174 -0
  260. package/src/examples/item/complex-item/ro-crate-metadata.json +769 -0
  261. package/src/examples/item/crate-with-language.json +38 -0
  262. package/src/examples/item/empty/ro-crate-metadata.json +20 -0
  263. package/src/examples/item/item-with-relationship-and-action/ro-crate-metadata.json +66 -0
  264. package/src/examples/item/large-crate/ro-crate-metadata.json +5762 -0
  265. package/src/examples/item/multiple-types/ro-crate-metadata.json +20 -0
  266. package/src/examples/item/ridiculously-big-collection/ro-crate-metadata.json +162977 -0
  267. package/src/examples/profile/aroma.complex.profile.json +11098 -0
  268. package/src/examples/profile/aroma.profile.json +9158 -0
  269. package/src/examples/profile/nyingarn-item-profile.json +426 -0
  270. package/src/examples/profile/profile-to-test-inverse-associations.json +73 -0
  271. package/src/examples/profile/profile-to-test-multiple-types.json +31 -0
  272. package/src/examples/profile/profile-with-all-primitives-and-groups.json +207 -0
  273. package/src/examples/profile/profile-with-all-primitives.json +244 -0
  274. package/src/examples/profile/profile-with-constraints.json +446 -0
  275. package/src/examples/profile/profile-with-resolve.json +57 -0
  276. package/src/examples/profile/vocabulary-creation-profile.json +231 -0
  277. package/src/images.d.ts +5 -0
  278. package/src/index.ts +10 -0
  279. package/src/types.ts +104 -0
  280. package/tailwind.config.js +20 -0
  281. package/tsconfig.app.json +31 -0
  282. package/tsconfig.json +26 -0
  283. package/typedoc.json +11 -0
  284. package/update-deps.sh +4 -0
  285. package/vite-env.d.ts +1 -0
  286. package/vite.config.ts +41 -0
@@ -0,0 +1,107 @@
1
+ import React, { useRef, useEffect, useState, useContext } from 'react';
2
+ import {
3
+ Drawer,
4
+ Button,
5
+ Flex,
6
+ Typography,
7
+ Divider,
8
+ } from 'antd';
9
+ import { CloseOutlined, SaveOutlined } from '@ant-design/icons';
10
+ import { useTranslation } from 'react-i18next';
11
+ import { EditorView, basicSetup } from 'codemirror';
12
+ import { EditorState } from '@codemirror/state';
13
+ import { javascript } from '@codemirror/lang-javascript';
14
+ import { oneDark } from '@codemirror/theme-one-dark';
15
+ import { CrateManagerContext } from '../Shell';
16
+
17
+ interface DialogEditContextProps {
18
+ onClose: () => void;
19
+ onUpdateContext: (context: any) => void;
20
+ open: boolean;
21
+ }
22
+
23
+ const DialogEditContext: React.FC<DialogEditContextProps> = ({
24
+ onClose,
25
+ onUpdateContext,
26
+ open,
27
+ }) => {
28
+ const { t } = useTranslation();
29
+ const crateManager = useContext(CrateManagerContext);
30
+ const [error, setError] = useState(false);
31
+ const editorRef = useRef<EditorView | undefined>(undefined);
32
+ const containerRef = useRef<HTMLDivElement>(null);
33
+
34
+ useEffect(() => {
35
+ if (open) {
36
+ const timeout = setTimeout(() => {
37
+ if (containerRef.current) {
38
+ const context = crateManager.getContext();
39
+ const initialState = EditorState.create({
40
+ doc: JSON.stringify(context, null, 2),
41
+ extensions: [basicSetup, oneDark, javascript()],
42
+ });
43
+
44
+ if (editorRef.current) {
45
+ editorRef.current.destroy();
46
+ }
47
+
48
+ editorRef.current = new EditorView({
49
+ state: initialState,
50
+ parent: containerRef.current,
51
+ });
52
+ }
53
+ }, 50); // Delay just enough for the drawer to render
54
+
55
+ return () => {
56
+ clearTimeout(timeout);
57
+ editorRef.current?.destroy();
58
+ };
59
+ }
60
+ }, [open, crateManager]);
61
+
62
+ const handleSave = () => {
63
+ try {
64
+ const context = JSON.parse(editorRef.current?.state.doc.toString() || '');
65
+ onUpdateContext(context);
66
+ setError(false);
67
+ onClose();
68
+ } catch (error) {
69
+ console.error(error);
70
+ setError(true);
71
+ }
72
+ };
73
+
74
+ return (
75
+ <Drawer
76
+ title={<Typography.Title className='m-2' level={4}>{t('edit_context')}</Typography.Title>}
77
+ placement="left"
78
+ onClose={onClose}
79
+ open={open}
80
+ width={600} // Equivalent to minWidth: '600px'
81
+ >
82
+ <Divider style={{ margin: '16px 0' }} />
83
+
84
+ <div
85
+ ref={containerRef}
86
+ className="cm-editor"
87
+ ></div>
88
+
89
+ {error && (
90
+ <Typography.Text type="danger">
91
+ The context is not a valid JSON data structure.
92
+ </Typography.Text>
93
+ )}
94
+
95
+ <Button
96
+ onClick={handleSave}
97
+ type="primary"
98
+ icon={<SaveOutlined />}
99
+ style={{ marginTop: '16px' }}
100
+ >
101
+ {t('save_label')}
102
+ </Button>
103
+ </Drawer>
104
+ );
105
+ };
106
+
107
+ export default DialogEditContext;
@@ -0,0 +1,54 @@
1
+ import React, { useState, useEffect, useContext } from 'react';
2
+ import { Flex, Typography, Drawer, Button } from 'antd';
3
+ import { useTranslation } from 'react-i18next';
4
+ import { CrateManagerContext } from '../Shell';
5
+ import { CloseOutlined } from '@ant-design/icons';
6
+
7
+ interface DialogPreviewCrateProps {
8
+ onClose: () => void;
9
+ open: boolean;
10
+ }
11
+
12
+ const DialogPreviewCrate: React.FC<DialogPreviewCrateProps> = ({ onClose, open }) => {
13
+ const { t } = useTranslation();
14
+ const crateManager = useContext(CrateManagerContext);
15
+ const [crate, setCrate] = useState<any>({});
16
+ const [loading, setLoading] = useState(false);
17
+
18
+ useEffect(() => {
19
+ if (open) { // Only load when drawer is open
20
+ const loadCrate = async () => {
21
+ setLoading(true);
22
+ await new Promise(resolve => setTimeout(resolve, 400));
23
+ setCrate(crateManager.exportCrate());
24
+ setLoading(false);
25
+ };
26
+ loadCrate();
27
+ }
28
+ return () => {
29
+ setCrate({});
30
+ };
31
+ }, [crateManager, open]); // Removed 'key' from dependencies
32
+
33
+ return (
34
+ <Drawer
35
+ title={<Typography.Title className='m-2' level={4}>{t('preview_crate') || 'Preview Crate'}</Typography.Title>}
36
+ placement="left"
37
+ onClose={onClose}
38
+ open={open}
39
+ width={600} // Equivalent to minWidth: '600px'
40
+ >
41
+ <Flex vertical className="h-full">
42
+ <div className="text-sm overflow-auto flex-grow">
43
+ {crate['@graph'] ? (
44
+ <pre className="whitespace-pre-wrap">{JSON.stringify(crate, null, 2)}</pre>
45
+ ) : (
46
+ <Typography.Text>{t('preview_loading')}</Typography.Text>
47
+ )}
48
+ </div>
49
+ </Flex>
50
+ </Drawer>
51
+ );
52
+ };
53
+
54
+ export default DialogPreviewCrate;
@@ -0,0 +1,65 @@
1
+ import React, { useState } from 'react';
2
+ import { Flex, Input, Button, Drawer, Typography } from 'antd';
3
+ import { SaveOutlined, CloseOutlined } from '@ant-design/icons';
4
+ import { useTranslation } from 'react-i18next';
5
+
6
+ interface DialogSaveCrateAsTemplateProps {
7
+ entity: {
8
+ [key: string]: any;
9
+ };
10
+ onClose: () => void;
11
+ open: boolean;
12
+ onSaveCrateTemplate: (data: { name: string }) => void;
13
+ }
14
+
15
+ const DialogSaveCrateAsTemplate: React.FC<DialogSaveCrateAsTemplateProps> = ({
16
+ entity,
17
+ onClose,
18
+ open,
19
+ onSaveCrateTemplate
20
+ }) => {
21
+ const { t } = useTranslation();
22
+ const [crateName, setCrateName] = useState<string>('');
23
+
24
+ const handleSave = () => {
25
+ onSaveCrateTemplate({ name: crateName });
26
+ setCrateName('');
27
+ onClose();
28
+ };
29
+
30
+ return (
31
+ <Drawer
32
+ title={<Typography.Title className='m-2' level={4} style={{ margin: 0 }}>{t('save_template') || 'Save as Template'}</Typography.Title>}
33
+ placement="right"
34
+ onClose={onClose}
35
+ open={open}
36
+ width={600} // Equivalent to minWidth: '600px'
37
+ >
38
+ <Flex vertical className="h-full">
39
+ <Flex vertical gap={16}>
40
+ <Typography.Text className="text-sm">
41
+ {t('save_template_prompt')}
42
+ </Typography.Text>
43
+ <Input
44
+ value={crateName}
45
+ onChange={(e) => setCrateName(e.target.value)}
46
+ placeholder={t('provide_name_for_template') || 'Enter template name'}
47
+ size="middle"
48
+ />
49
+ <Flex justify="flex-end">
50
+ <Button
51
+ onClick={handleSave}
52
+ disabled={!crateName}
53
+ type="primary"
54
+ icon={<SaveOutlined />}
55
+ >
56
+ {t('save_label')}
57
+ </Button>
58
+ </Flex>
59
+ </Flex>
60
+ </Flex>
61
+ </Drawer>
62
+ );
63
+ };
64
+
65
+ export default DialogSaveCrateAsTemplate;
@@ -0,0 +1,87 @@
1
+ import React, { useState, useContext, useEffect } from 'react';
2
+ import { Flex, Radio, Button, Drawer, Typography } from 'antd';
3
+ import { useTranslation } from 'react-i18next';
4
+ import { CrateManagerContext } from '../Shell';
5
+ import { CloseOutlined, SaveOutlined } from '@ant-design/icons';
6
+
7
+ interface DialogSaveEntityTemplateProps {
8
+ entity: {
9
+ '@id': string;
10
+ [key: string]: any;
11
+ };
12
+ onClose: () => void;
13
+ open: boolean;
14
+ onSaveEntityTemplate: (data: { resolveDepth: number }) => void;
15
+ }
16
+
17
+ const DialogSaveEntityTemplate: React.FC<DialogSaveEntityTemplateProps> = ({
18
+ entity,
19
+ onClose,
20
+ open,
21
+ onSaveEntityTemplate
22
+ }) => {
23
+ const { t } = useTranslation();
24
+ const crateManager = useContext(CrateManagerContext);
25
+ const [resolveDepth, setResolveDepth] = useState<string>('0');
26
+
27
+ const [exportedEntity, setExportedEntity] = useState<any>(null);
28
+
29
+ useEffect(() => {
30
+ if (crateManager && entity?.['@id']) {
31
+ try {
32
+ const exported = crateManager.exportEntityTemplate({
33
+ id: entity['@id'],
34
+ resolveDepth: parseInt(resolveDepth)
35
+ });
36
+ setExportedEntity(exported);
37
+ } catch (error) {
38
+ console.error('Error exporting entity template:', error);
39
+ }
40
+ }
41
+ }, [crateManager, entity, resolveDepth]);
42
+
43
+ return (
44
+ <Drawer
45
+ title={<Typography.Title level={4} style={{ margin: 0 }}>{'Save Entity Template'}</Typography.Title>}
46
+ placement="right"
47
+ onClose={onClose}
48
+ open={open}
49
+ width={600} // Equivalent to minWidth: '600px'
50
+ >
51
+ <Flex vertical className="h-full">
52
+ <Flex vertical gap={16}>
53
+ <Flex gap={16} align="center">
54
+ <Radio.Group
55
+ onChange={(e) => setResolveDepth(e.target.value as string)}
56
+ value={resolveDepth}
57
+ >
58
+ <Radio value="0">Depth: 0</Radio>
59
+ <Radio value="1">Depth: 1</Radio>
60
+ </Radio.Group>
61
+ <Button
62
+ type="primary"
63
+ icon={<SaveOutlined />}
64
+ onClick={() => {
65
+ onSaveEntityTemplate({ resolveDepth: parseInt(resolveDepth) });
66
+ onClose();
67
+ }}
68
+ >
69
+ {'Save Template'}
70
+ </Button>
71
+ </Flex>
72
+
73
+ <Flex vertical className="flex-grow overflow-auto">
74
+ <Typography.Text strong className="mb-2">
75
+ {'Template Preview'}
76
+ </Typography.Text>
77
+ <div className="p-4 border rounded bg-gray-50 font-mono text-sm overflow-auto">
78
+ <pre className="whitespace-pre-wrap">{JSON.stringify(exportedEntity, null, 2)}</pre>
79
+ </div>
80
+ </Flex>
81
+ </Flex>
82
+ </Flex>
83
+ </Drawer>
84
+ );
85
+ };
86
+
87
+ export default DialogSaveEntityTemplate;
@@ -0,0 +1,30 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import DisplayPropertyName from './DisplayPropertyName';
3
+
4
+ const meta: Meta<typeof DisplayPropertyName> = {
5
+ component: DisplayPropertyName,
6
+ argTypes: {
7
+ label: {
8
+ options: [
9
+ 'name',
10
+ 'nameOfThing',
11
+ 'NameOfThing',
12
+ 'name-of-thing',
13
+ 'foaf:name',
14
+ 'dcterms:nameOfThing',
15
+ 'dcterms:name-of-thing',
16
+ ],
17
+ control: { type: 'select' },
18
+ },
19
+ },
20
+ };
21
+
22
+ export default meta;
23
+ type Story = StoryObj<typeof DisplayPropertyName>;
24
+
25
+ export const Default: Story = {
26
+ args: {
27
+ property: 'something',
28
+ label: 'name',
29
+ },
30
+ };
@@ -0,0 +1,21 @@
1
+ import React from 'react';
2
+
3
+ interface DisplayPropertyNameProps {
4
+ property: string;
5
+ label?: string;
6
+ className?: string; // Add this prop
7
+ }
8
+
9
+ const DisplayPropertyName: React.FC<DisplayPropertyNameProps> = ({
10
+ property,
11
+ label,
12
+ className = '' // Default to empty string
13
+ }) => {
14
+ return (
15
+ <div className={`describo-property-name ${className}`}>
16
+ {label || property}
17
+ </div>
18
+ );
19
+ };
20
+
21
+ export default DisplayPropertyName;
@@ -0,0 +1,75 @@
1
+ import React from 'react';
2
+ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
3
+ import { ExportOutlined } from '@ant-design/icons';
4
+ import { Button, Typography } from 'antd';
5
+ import TextComponent from '../primitives/Text';
6
+ import { isURL } from '../CrateManager/lib';
7
+ import { useStateStore } from '../store';
8
+
9
+ interface EntityIdProps {
10
+ entity: {
11
+ '@id': string;
12
+ '@type': string | string[];
13
+ };
14
+ onUpdate: (data: { property: string; value: string }) => void;
15
+ }
16
+
17
+ export const EntityId: React.FC<EntityIdProps> = ({ entity, onUpdate }) => {
18
+ const state = useStateStore();
19
+
20
+ const handleSave = async (data: { property: string; value: string }) => {
21
+ onUpdate(data);
22
+ };
23
+
24
+ const openInNewTab = (url: string) => {
25
+ window.open(url, '_blank');
26
+ };
27
+
28
+ const isDatasetOrFile = () => {
29
+ const types = Array.isArray(entity['@type']) ? entity['@type'] : [entity['@type']];
30
+ return entity['@id'] === './' || types.some(type => ['Dataset', 'File'].includes(type));
31
+ };
32
+
33
+ return (
34
+ <div className="flex flex-row">
35
+ <div className="min-w-32 w-1/3 xl:w-1/5 flex flex-col describo-property-name">@id</div>
36
+
37
+ {!state.configuration?.readonly ? (
38
+ <div className="w-2/3 xl:w-4/5 flex flex-row describo-property-value">
39
+ {isURL(entity['@id']) && (
40
+ <Button
41
+ type="link"
42
+ icon={<ExportOutlined />}
43
+ onClick={() => openInNewTab(entity['@id'])}
44
+ title="Open in new tab"
45
+ />
46
+ )}
47
+ {isDatasetOrFile() ? (
48
+ <div>{entity['@id']}</div>
49
+ ) : (
50
+ <div className="flex-grow">
51
+ <TextComponent
52
+ property="@id"
53
+ value={entity['@id']}
54
+ onSaveProperty={handleSave}
55
+ />
56
+ </div>
57
+ )}
58
+ </div>
59
+ ) : (
60
+ <div className="w-2/3 xl:w-4/5 flex flex-row describo-property-value">
61
+ {isURL(entity['@id']) ? (
62
+ <Typography.Link className='text-large' style={{ fontSize: '1em' }} href={entity['@id']} target="_blank" rel="noopener noreferrer">
63
+ {entity['@id']}
64
+ &nbsp;<ExportOutlined />
65
+ </Typography.Link>
66
+ ) : (
67
+ <div>{entity['@id']}</div>
68
+ )}
69
+ </div>
70
+ )}
71
+ </div>
72
+ );
73
+ };
74
+
75
+ export default EntityId;
@@ -0,0 +1,49 @@
1
+ import React from 'react';
2
+ import TextComponent from '../primitives/Text';
3
+ import { useTranslation } from 'react-i18next';
4
+ import { useStateStore } from '../store';
5
+
6
+ interface EntityNameProps {
7
+ entity: {
8
+ name: string;
9
+ value?: string;
10
+ };
11
+ onUpdate: (data: { property: string; value: string }) => void;
12
+ }
13
+
14
+ export const EntityName: React.FC<EntityNameProps> = ({ entity, onUpdate }) => {
15
+ const [t, i18n] = useTranslation();
16
+ const state = useStateStore();
17
+
18
+ const handleSave = async (data: { property: string; value: string }) => {
19
+ onUpdate(data);
20
+ };
21
+
22
+ return (
23
+ <div className="flex flex-row">
24
+ <div className="min-w-32 w-1/3 xl:w-1/5 flex flex-col">
25
+ <div className="describo-property-name">{t('name_field_label')}</div>
26
+ <div className="text-gray-600 font-light text-xs pr-1 describo-property-help">
27
+ {t('name_field_help')}
28
+ </div>
29
+ </div>
30
+ {!state.configuration?.readonly ? (
31
+ <div className="w-2/3 xl:w-4/5 flex flex-col">
32
+ <div className="flex-grow">
33
+ <TextComponent
34
+ property="name"
35
+ value={entity.name}
36
+ onSaveProperty={handleSave}
37
+ />
38
+ </div>
39
+ </div>
40
+ ) : (
41
+ <div className="w-2/3 xl:w-4/5 flex flex-row">
42
+ {entity.name}
43
+ </div>
44
+ )}
45
+ </div>
46
+ );
47
+ };
48
+
49
+ export default EntityName;
@@ -0,0 +1,188 @@
1
+ import React, { useState, useEffect, useContext } from 'react';
2
+ import { Badge } from 'antd';
3
+ import { useTranslation } from 'react-i18next';
4
+ import { isPlainObject, orderBy } from 'lodash';
5
+ import { ProfileManagerContext, CrateManagerContext } from '../Shell';
6
+ import { useStateStore } from '../store';
7
+ import PropertyHelp from './PropertyHelp';
8
+ import EntityPropertyInstance from './EntityPropertyInstance';
9
+ import PaginateLinkedEntities from './PaginateLinkedEntities';
10
+ import DeleteProperty from './DeleteProperty';
11
+ import Add from './Add';
12
+ import DisplayPropertyName from './DisplayPropertyName';
13
+
14
+ interface EntityPropertyProps {
15
+ entity: any;
16
+ property: string;
17
+ values: any[];
18
+ highlightRequired?: boolean;
19
+ savedProperty?: boolean;
20
+ onLoadEntity: (data: { id: string }) => void;
21
+ onCreateProperty: (data: any) => void;
22
+ onCreateEntity: (data: any) => void;
23
+ onLinkEntity: (data: any) => void;
24
+ onSaveProperty: (data: any) => void;
25
+ onDeleteProperty: (data: any) => void;
26
+ onUnlinkEntity: (data: any) => void;
27
+ }
28
+
29
+ export const EntityProperty: React.FC<EntityPropertyProps> = ({
30
+ entity,
31
+ property,
32
+ values,
33
+ highlightRequired = false,
34
+ savedProperty = false,
35
+ onLoadEntity,
36
+ onCreateProperty,
37
+ onCreateEntity,
38
+ onLinkEntity,
39
+ onSaveProperty,
40
+ onDeleteProperty,
41
+ onUnlinkEntity
42
+ }) => {
43
+ const { t } = useTranslation();
44
+ const profileManager = useContext(ProfileManagerContext);
45
+ const crateManager = useContext(CrateManagerContext);
46
+ const state = useStateStore();
47
+ const [linkInstances, setLinkInstances] = useState<any[]>([]);
48
+ const [simpleInstances, setSimpleInstances] = useState<any[]>([]);
49
+
50
+ const propertyDefinition = profileManager?.getPropertyDefinition({
51
+ property,
52
+ entity
53
+ })?.propertyDefinition;
54
+
55
+ const isValid = values.length > 0;
56
+ const isRequired = propertyDefinition?.required;
57
+ const isNotValue = propertyDefinition?.type !== 'Value';
58
+ const profileWarnMissingProperty = profileManager?.profile.warnMissingProperty;
59
+ const showAddControl = !propertyDefinition?.readonly &&
60
+ (propertyDefinition?.multiple || !values?.length);
61
+
62
+ // Fix: Use a JSON string representation of values to prevent infinite loops
63
+ const valuesString = JSON.stringify(values);
64
+
65
+ useEffect(() => {
66
+ // Only sort instances when values or propertyDefinition changes
67
+ let simpleInsts;
68
+ if (propertyDefinition?.handlesMultipleValues === true) {
69
+ simpleInsts = values.length === 0 ? values : [values];
70
+ } else {
71
+ simpleInsts = values;
72
+ }
73
+
74
+ setSimpleInstances(
75
+ simpleInsts
76
+ .map((v: any, i: number) => {
77
+ // Special handling for boolean values and non-objects
78
+ if (!isPlainObject(v) || typeof v === 'boolean') {
79
+ return { idx: i, value: v };
80
+ }
81
+ return null;
82
+ })
83
+ .filter(Boolean)
84
+ );
85
+
86
+ setLinkInstances(
87
+ orderBy(
88
+ values
89
+ .map((v: any, i: number) => {
90
+ if (isPlainObject(v) && typeof v !== 'boolean') return { idx: i, value: v };
91
+ return null;
92
+ })
93
+ .filter(Boolean),
94
+ '@id'
95
+ )
96
+ );
97
+ }, [valuesString, propertyDefinition?.handlesMultipleValues]);
98
+
99
+ // Remove the separate sortInstances function since we've moved its logic directly into the useEffect
100
+ return (
101
+ <div
102
+ className={`flex flex-row flex-grow p-2 describo-property-background ${
103
+ highlightRequired && isRequired && !isValid ? 'bg-red-200' : ''
104
+ } ${savedProperty ? 'bg-green-100 transition-colors duration-1000' : ''} describo-property describo-property-name-${property}`}
105
+ >
106
+ <div className="min-w-32 w-1/3 xl:w-1/5 flex flex-col describo-property-heading">
107
+ <div className="flex flex-row items-center">
108
+ <DisplayPropertyName
109
+ property={property}
110
+ label={propertyDefinition?.label}
111
+ className={`inline-block ${isRequired && !isValid ? 'text-red-600' : ''}`}
112
+ />
113
+ {isRequired && !isValid && (
114
+ <Badge status="error" dot className="animate-pulse ml-2" />
115
+ )}
116
+ </div>
117
+ <PropertyHelp help={propertyDefinition?.help} />
118
+ {!propertyDefinition && profileWarnMissingProperty && (
119
+ <div className="text-red-600 text-xs">
120
+ ({t('not_defined_in_profile')})
121
+ </div>
122
+ )}
123
+ </div>
124
+
125
+ <div className="w-2/3 xl:w-4/5 flex flex-col flex-grow describo-property-value">
126
+ <div className="flex flex-col space-y-1">
127
+ {simpleInstances.map((instance) => (
128
+ <div key={instance.idx}>
129
+ {propertyDefinition?.readonly ? (
130
+ <div className="describo-property-value-readonly">
131
+ {instance.value}
132
+ </div>
133
+ ) : (
134
+ <div className="flex flex-row space-x-2">
135
+ <EntityPropertyInstance
136
+ className="flex-grow"
137
+ property={property}
138
+ value={instance.value}
139
+ idx={instance.idx}
140
+ definition={propertyDefinition}
141
+ onSaveProperty={onSaveProperty}
142
+ onCreateEntity={onCreateEntity}
143
+ />
144
+ {isNotValue &&
145
+ !state.configuration?.readonly &&
146
+ (instance.value || instance.value === false) &&
147
+ !instance.value?.['@id'] && (
148
+ <DeleteProperty
149
+ type="delete"
150
+ property={property}
151
+ onDeleteProperty={() => onDeleteProperty({ property, idx: instance.idx })}
152
+ />
153
+ )}
154
+ </div>
155
+ )}
156
+ </div>
157
+ ))}
158
+ </div>
159
+
160
+ {linkInstances.length > 0 && (
161
+ <PaginateLinkedEntities
162
+ className={simpleInstances.length && linkInstances.length ? 'mt-2' : ''}
163
+ entities={linkInstances}
164
+ property={property}
165
+ readonly={propertyDefinition?.readonly}
166
+ onLoadEntity={onLoadEntity}
167
+ onUnlinkEntity={onUnlinkEntity}
168
+ />
169
+ )}
170
+
171
+ {showAddControl && !state.configuration?.readonly && (
172
+ <Add
173
+ property={property}
174
+ definition={propertyDefinition}
175
+ embedded={false}
176
+ placeholder={propertyDefinition?.placeholder}
177
+ onCreateProperty={onCreateProperty}
178
+ onCreateEntity={onCreateEntity}
179
+ onLinkEntity={onLinkEntity}
180
+ crateManager={crateManager}
181
+ />
182
+ )}
183
+ </div>
184
+ </div>
185
+ );
186
+ };
187
+
188
+ export default EntityProperty;