tsondb 0.5.19 → 0.6.1
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/src/bin/tsondb.js +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/node/config.d.ts +20 -0
- package/dist/src/node/config.js +5 -0
- package/dist/src/node/index.d.ts +3 -2
- package/dist/src/node/index.js +13 -8
- package/dist/src/node/renderers/jsonschema/render.d.ts +1 -1
- package/dist/src/node/renderers/jsonschema/render.js +12 -7
- package/dist/src/node/renderers/ts/render.d.ts +1 -1
- package/dist/src/node/renderers/ts/render.js +12 -6
- package/dist/src/node/schema/Node.d.ts +100 -29
- package/dist/src/node/schema/Node.js +268 -61
- package/dist/src/node/schema/Schema.js +96 -1
- package/dist/src/node/schema/TypeParameter.d.ts +7 -9
- package/dist/src/node/schema/TypeParameter.js +7 -5
- package/dist/src/node/schema/declarations/Declaration.d.ts +10 -28
- package/dist/src/node/schema/declarations/Declaration.js +8 -110
- package/dist/src/node/schema/declarations/EntityDecl.d.ts +48 -48
- package/dist/src/node/schema/declarations/EntityDecl.js +15 -12
- package/dist/src/node/schema/declarations/EnumDecl.d.ts +14 -17
- package/dist/src/node/schema/declarations/EnumDecl.js +12 -12
- package/dist/src/node/schema/declarations/TypeAliasDecl.d.ts +8 -14
- package/dist/src/node/schema/declarations/TypeAliasDecl.js +10 -11
- package/dist/src/node/schema/index.d.ts +0 -2
- package/dist/src/node/schema/index.js +0 -1
- package/dist/src/node/schema/types/Type.d.ts +19 -42
- package/dist/src/node/schema/types/Type.js +29 -167
- package/dist/src/node/schema/types/generic/ArrayType.d.ts +5 -14
- package/dist/src/node/schema/types/generic/ArrayType.js +15 -20
- package/dist/src/node/schema/types/generic/EnumType.d.ts +5 -17
- package/dist/src/node/schema/types/generic/EnumType.js +12 -20
- package/dist/src/node/schema/types/generic/ObjectType.d.ts +5 -19
- package/dist/src/node/schema/types/generic/ObjectType.js +11 -15
- package/dist/src/node/schema/types/primitives/BooleanType.d.ts +7 -8
- package/dist/src/node/schema/types/primitives/BooleanType.js +5 -4
- package/dist/src/node/schema/types/primitives/DateType.d.ts +6 -8
- package/dist/src/node/schema/types/primitives/DateType.js +5 -4
- package/dist/src/node/schema/types/primitives/FloatType.d.ts +9 -21
- package/dist/src/node/schema/types/primitives/FloatType.js +5 -4
- package/dist/src/node/schema/types/primitives/IntegerType.d.ts +9 -21
- package/dist/src/node/schema/types/primitives/IntegerType.js +5 -4
- package/dist/src/node/schema/types/primitives/StringType.d.ts +6 -10
- package/dist/src/node/schema/types/primitives/StringType.js +5 -4
- package/dist/src/node/schema/types/references/ChildEntitiesType.d.ts +18 -0
- package/dist/src/node/schema/types/references/ChildEntitiesType.js +18 -0
- package/dist/src/node/schema/types/references/IncludeIdentifierType.d.ts +7 -13
- package/dist/src/node/schema/types/references/IncludeIdentifierType.js +12 -12
- package/dist/src/node/schema/types/references/NestedEntityMapType.d.ts +7 -17
- package/dist/src/node/schema/types/references/NestedEntityMapType.js +11 -13
- package/dist/src/node/schema/types/references/ReferenceIdentifierType.d.ts +4 -10
- package/dist/src/node/schema/types/references/ReferenceIdentifierType.js +3 -5
- package/dist/src/node/schema/types/references/TypeArgumentType.d.ts +5 -10
- package/dist/src/node/schema/types/references/TypeArgumentType.js +10 -5
- package/dist/src/node/server/api/declarations.js +24 -6
- package/dist/src/node/server/api/index.js +11 -0
- package/dist/src/node/server/api/instances.js +9 -6
- package/dist/src/node/server/index.d.ts +6 -1
- package/dist/src/node/server/index.js +7 -3
- package/dist/src/node/server/init.d.ts +2 -1
- package/dist/src/node/server/init.js +11 -11
- package/dist/src/node/server/utils/childInstances.d.ts +4 -0
- package/dist/src/node/server/utils/childInstances.js +41 -0
- package/dist/src/node/server/utils/instanceOperations.d.ts +8 -0
- package/dist/src/node/server/utils/instanceOperations.js +107 -0
- package/dist/src/node/server/utils/locales.d.ts +2 -0
- package/dist/src/node/server/utils/locales.js +8 -0
- package/dist/src/node/utils/childInstances.d.ts +32 -0
- package/dist/src/node/utils/childInstances.js +164 -0
- package/dist/src/node/utils/displayName.d.ts +2 -1
- package/dist/src/node/utils/displayName.js +5 -4
- package/dist/src/node/utils/files.d.ts +5 -0
- package/dist/src/node/utils/files.js +9 -0
- package/dist/src/node/utils/instanceOperations.d.ts +14 -0
- package/dist/src/node/utils/instanceOperations.js +88 -0
- package/dist/src/node/utils/instances.d.ts +1 -1
- package/dist/src/node/utils/instances.js +12 -6
- package/dist/src/node/utils/references.d.ts +3 -1
- package/dist/src/node/utils/references.js +43 -18
- package/dist/src/node/utils/referencesWorker.d.ts +5 -0
- package/dist/src/node/utils/referencesWorker.js +22 -0
- package/dist/src/node/utils/workers.d.ts +15 -0
- package/dist/src/node/utils/workers.js +90 -0
- package/dist/src/shared/api.d.ts +14 -1
- package/dist/src/shared/schema/Node.d.ts +63 -0
- package/dist/src/shared/schema/Node.js +128 -0
- package/dist/src/shared/schema/TypeParameter.d.ts +9 -0
- package/dist/src/shared/schema/TypeParameter.js +2 -0
- package/dist/src/shared/schema/declarations/Declaration.d.ts +21 -0
- package/dist/src/shared/schema/declarations/Declaration.js +4 -0
- package/dist/src/shared/schema/declarations/EntityDecl.d.ts +32 -0
- package/dist/src/shared/schema/declarations/EntityDecl.js +8 -0
- package/dist/src/shared/schema/declarations/EnumDecl.d.ts +11 -0
- package/dist/src/shared/schema/declarations/EnumDecl.js +9 -0
- package/dist/src/shared/schema/declarations/TypeAliasDecl.d.ts +11 -0
- package/dist/src/shared/schema/declarations/TypeAliasDecl.js +7 -0
- package/dist/src/shared/schema/types/ArrayType.d.ts +11 -0
- package/dist/src/shared/schema/types/ArrayType.js +8 -0
- package/dist/src/shared/schema/types/BooleanType.d.ts +7 -0
- package/dist/src/shared/schema/types/BooleanType.js +2 -0
- package/dist/src/shared/schema/types/ChildEntitiesType.d.ts +8 -0
- package/dist/src/shared/schema/types/ChildEntitiesType.js +2 -0
- package/dist/src/shared/schema/types/DateType.d.ts +8 -0
- package/dist/src/shared/schema/types/DateType.js +2 -0
- package/dist/src/shared/schema/types/EnumType.d.ts +14 -0
- package/dist/src/shared/schema/types/EnumType.js +28 -0
- package/dist/src/shared/schema/types/FloatType.d.ts +11 -0
- package/dist/src/shared/schema/types/FloatType.js +2 -0
- package/dist/src/shared/schema/types/IncludeIdentifierType.d.ts +11 -0
- package/dist/src/shared/schema/types/IncludeIdentifierType.js +13 -0
- package/dist/src/shared/schema/types/IntegerType.d.ts +11 -0
- package/dist/src/shared/schema/types/IntegerType.js +2 -0
- package/dist/src/shared/schema/types/NestedEntityMapType.d.ts +17 -0
- package/dist/src/shared/schema/types/NestedEntityMapType.js +14 -0
- package/dist/src/shared/schema/types/ObjectType.d.ts +19 -0
- package/dist/src/shared/schema/types/ObjectType.js +14 -0
- package/dist/src/shared/schema/types/ReferenceIdentifierType.d.ts +8 -0
- package/dist/src/shared/schema/types/ReferenceIdentifierType.js +2 -0
- package/dist/src/shared/schema/types/StringType.d.ts +10 -0
- package/dist/src/shared/schema/types/StringType.js +2 -0
- package/dist/src/shared/schema/types/Type.d.ts +20 -0
- package/dist/src/shared/schema/types/TypeArgumentType.d.ts +12 -0
- package/dist/src/shared/schema/types/TypeArgumentType.js +7 -0
- package/dist/src/shared/utils/array.d.ts +4 -0
- package/dist/src/shared/utils/array.js +30 -0
- package/dist/src/shared/utils/async.d.ts +8 -0
- package/dist/src/shared/utils/async.js +35 -0
- package/dist/src/shared/utils/compare.js +3 -3
- package/dist/src/shared/utils/displayName.d.ts +6 -2
- package/dist/src/shared/utils/displayName.js +21 -8
- package/dist/src/shared/utils/instances.d.ts +2 -3
- package/dist/src/shared/utils/instances.js +3 -1
- package/dist/src/shared/utils/markdown.d.ts +4 -0
- package/dist/src/shared/utils/markdown.js +91 -4
- package/dist/src/shared/utils/object.d.ts +2 -0
- package/dist/src/shared/utils/object.js +2 -0
- package/dist/src/shared/utils/result.d.ts +8 -2
- package/dist/src/shared/utils/result.js +1 -1
- package/dist/src/web/api/declarations.d.ts +26 -0
- package/dist/src/web/api/declarations.js +51 -0
- package/dist/src/web/api/git.d.ts +14 -0
- package/dist/src/web/api/git.js +20 -0
- package/dist/src/web/api/index.d.ts +1 -0
- package/dist/src/web/api/index.js +2 -0
- package/dist/src/web/api/instances.d.ts +2 -0
- package/dist/src/web/api/instances.js +2 -0
- package/dist/src/web/components/Git.js +19 -16
- package/dist/src/web/components/InstanceRouteSkeleton.d.ts +42 -0
- package/dist/src/web/components/InstanceRouteSkeleton.js +114 -0
- package/dist/src/web/components/Layout.js +3 -2
- package/dist/src/web/components/ModalDialog.d.ts +2 -0
- package/dist/src/web/components/ModalDialog.js +16 -0
- package/dist/src/web/components/Select.d.ts +1 -2
- package/dist/src/web/components/Settings.d.ts +2 -0
- package/dist/src/web/components/Settings.js +47 -0
- package/dist/src/web/components/typeInputs/ArrayTypeInput.d.ts +3 -11
- package/dist/src/web/components/typeInputs/ArrayTypeInput.js +5 -4
- package/dist/src/web/components/typeInputs/BooleanTypeInput.d.ts +3 -6
- package/dist/src/web/components/typeInputs/BooleanTypeInput.js +2 -2
- package/dist/src/web/components/typeInputs/ChildEntitiesTypeInput.d.ts +6 -0
- package/dist/src/web/components/typeInputs/ChildEntitiesTypeInput.js +27 -0
- package/dist/src/web/components/typeInputs/DateTypeInput.d.ts +3 -6
- package/dist/src/web/components/typeInputs/DateTypeInput.js +2 -2
- package/dist/src/web/components/typeInputs/EnumTypeInput.d.ts +3 -11
- package/dist/src/web/components/typeInputs/EnumTypeInput.js +55 -22
- package/dist/src/web/components/typeInputs/FloatTypeInput.d.ts +3 -6
- package/dist/src/web/components/typeInputs/FloatTypeInput.js +2 -2
- package/dist/src/web/components/typeInputs/GenericTypeArgumentIdentifierTypeInput.d.ts +3 -4
- package/dist/src/web/components/typeInputs/IncludeIdentifierTypeInput.d.ts +3 -11
- package/dist/src/web/components/typeInputs/IncludeIdentifierTypeInput.js +3 -2
- package/dist/src/web/components/typeInputs/IntegerTypeInput.d.ts +3 -6
- package/dist/src/web/components/typeInputs/IntegerTypeInput.js +2 -2
- package/dist/src/web/components/typeInputs/NestedEntityMapTypeInput.d.ts +3 -11
- package/dist/src/web/components/typeInputs/NestedEntityMapTypeInput.js +5 -4
- package/dist/src/web/components/typeInputs/ObjectTypeInput.d.ts +3 -11
- package/dist/src/web/components/typeInputs/ObjectTypeInput.js +8 -5
- package/dist/src/web/components/typeInputs/ReferenceIdentifierTypeInput.d.ts +3 -8
- package/dist/src/web/components/typeInputs/ReferenceIdentifierTypeInput.js +2 -2
- package/dist/src/web/components/typeInputs/StringTypeInput.d.ts +3 -6
- package/dist/src/web/components/typeInputs/StringTypeInput.js +3 -3
- package/dist/src/web/components/typeInputs/TypeInput.d.ts +12 -4
- package/dist/src/web/components/typeInputs/TypeInput.js +22 -17
- package/dist/src/web/components/typeInputs/utils/ValidationErrors.d.ts +1 -0
- package/dist/src/web/components/typeInputs/utils/ValidationErrors.js +1 -3
- package/dist/src/web/context/config.d.ts +11 -0
- package/dist/src/web/context/config.js +6 -0
- package/dist/src/web/context/entities.d.ts +8 -5
- package/dist/src/web/context/entities.js +1 -1
- package/dist/src/web/context/settings.d.ts +8 -0
- package/dist/src/web/context/settings.js +10 -0
- package/dist/src/web/hooks/useEntityFromRoute.d.ts +1 -1
- package/dist/src/web/hooks/useEntityFromRoute.js +2 -2
- package/dist/src/web/hooks/useInstanceNamesByEntity.d.ts +1 -1
- package/dist/src/web/hooks/useInstanceNamesByEntity.js +4 -2
- package/dist/src/web/hooks/useMappedAPIResource.js +2 -4
- package/dist/src/web/hooks/useSecondaryDeclarations.d.ts +1 -1
- package/dist/src/web/hooks/useSecondaryDeclarations.js +8 -4
- package/dist/src/web/hooks/useSettings.d.ts +10 -0
- package/dist/src/web/hooks/useSettings.js +51 -0
- package/dist/src/web/index.js +11 -5
- package/dist/src/web/routes/CreateInstance.js +40 -79
- package/dist/src/web/routes/Entity.js +42 -19
- package/dist/src/web/routes/Home.js +24 -5
- package/dist/src/web/routes/Instance.js +34 -85
- package/dist/src/web/utils/InlineMarkdown.d.ts +1 -1
- package/dist/src/web/utils/InlineMarkdown.js +13 -1
- package/dist/src/web/utils/api.d.ts +25 -0
- package/dist/src/web/utils/api.js +34 -0
- package/dist/src/web/utils/typeSkeleton.d.ts +1 -1
- package/dist/src/web/utils/typeSkeleton.js +2 -0
- package/package.json +14 -13
- package/public/css/styles.css +171 -12
- package/dist/src/node/schema/types/primitives/NumericType.d.ts +0 -6
- package/dist/src/node/schema/types/primitives/NumericType.js +0 -2
- package/dist/src/node/schema/types/primitives/PrimitiveType.d.ts +0 -6
- package/dist/src/node/schema/validation/type.d.ts +0 -4
- package/dist/src/node/schema/validation/type.js +0 -1
- package/dist/src/node/server/api/instanceOperations.d.ts +0 -6
- package/dist/src/node/server/api/instanceOperations.js +0 -93
- package/dist/src/shared/config.d.ts +0 -11
- package/dist/src/shared/config.js +0 -1
- package/dist/src/web/api.d.ts +0 -24
- package/dist/src/web/api.js +0 -201
- /package/dist/src/{node/schema/types/primitives/PrimitiveType.js → shared/schema/types/Type.js} +0 -0
|
@@ -9,11 +9,9 @@ export const useMappedAPIResource = (apiFn, mapFn, ...args) => {
|
|
|
9
9
|
useEffect(() => {
|
|
10
10
|
fetchData().catch((err) => {
|
|
11
11
|
console.log(err);
|
|
12
|
+
alert(err);
|
|
12
13
|
});
|
|
13
14
|
}, [fetchData]);
|
|
14
|
-
const reload = useCallback(
|
|
15
|
-
setData(undefined);
|
|
16
|
-
return fetchData();
|
|
17
|
-
}, [fetchData]);
|
|
15
|
+
const reload = useCallback(fetchData, [fetchData]);
|
|
18
16
|
return [data, reload];
|
|
19
17
|
};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type { SerializedSecondaryDecl } from "../../
|
|
1
|
+
import type { SerializedSecondaryDecl } from "../../shared/schema/declarations/Declaration.ts";
|
|
2
2
|
export type GetDeclFromDeclName = (name: string) => SerializedSecondaryDecl | undefined;
|
|
3
3
|
export declare const useGetDeclFromDeclName: () => [GetDeclFromDeclName, loaded: boolean];
|
|
@@ -1,20 +1,24 @@
|
|
|
1
1
|
import { useCallback, useEffect, useState } from "preact/hooks";
|
|
2
|
-
import { getAllDeclarations } from "../api.js";
|
|
2
|
+
import { getAllDeclarations } from "../api/declarations.js";
|
|
3
|
+
import { useSetting } from "./useSettings.js";
|
|
3
4
|
export const useGetDeclFromDeclName = () => {
|
|
5
|
+
const [locales] = useSetting("displayedLocales");
|
|
4
6
|
const [secondaryDeclarations, setSecondaryDeclarations] = useState();
|
|
5
7
|
useEffect(() => {
|
|
6
|
-
getAllDeclarations()
|
|
8
|
+
getAllDeclarations(locales)
|
|
7
9
|
.then(data => {
|
|
8
10
|
setSecondaryDeclarations(data.declarations
|
|
9
11
|
.map(decl => decl.declaration)
|
|
10
|
-
.filter((decl) => decl.kind === "EnumDecl" ||
|
|
12
|
+
.filter((decl) => decl.kind === "EnumDecl" ||
|
|
13
|
+
decl.kind === "TypeAliasDecl" ||
|
|
14
|
+
decl.parentReferenceKey !== undefined));
|
|
11
15
|
})
|
|
12
16
|
.catch((error) => {
|
|
13
17
|
if (error instanceof Error) {
|
|
14
18
|
console.error("Error fetching data:", error.toString());
|
|
15
19
|
}
|
|
16
20
|
});
|
|
17
|
-
}, []);
|
|
21
|
+
}, [locales]);
|
|
18
22
|
const getDeclFromDeclName = useCallback((name) => secondaryDeclarations?.find(decl => decl.name === name), [secondaryDeclarations]);
|
|
19
23
|
return [getDeclFromDeclName, secondaryDeclarations !== undefined];
|
|
20
24
|
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { SetStateAction } from "preact/compat";
|
|
2
|
+
import { type Dispatch } from "preact/hooks";
|
|
3
|
+
import type { WebConfig } from "../context/config.ts";
|
|
4
|
+
import { SettingsContext } from "../context/settings.ts";
|
|
5
|
+
export type UserSettings = {
|
|
6
|
+
displayedLocales: string[];
|
|
7
|
+
enumDisplay: "select" | "radio";
|
|
8
|
+
};
|
|
9
|
+
export declare const useSettings: (config: WebConfig) => SettingsContext;
|
|
10
|
+
export declare const useSetting: <K extends keyof UserSettings>(key: K) => [UserSettings[K], Dispatch<SetStateAction<UserSettings[K]>>];
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { useCallback, useContext, useState } from "preact/hooks";
|
|
2
|
+
import { defaultSettings, SettingsContext } from "../context/settings.js";
|
|
3
|
+
const settingsGuards = {
|
|
4
|
+
displayedLocales: (v) => Array.isArray(v) && v.every(e => typeof e === "string") && v.length > 0,
|
|
5
|
+
enumDisplay: (v) => typeof v === "string" && ["select", "radio"].includes(v),
|
|
6
|
+
};
|
|
7
|
+
const defaultSettingsFromConfig = (config) => ({
|
|
8
|
+
...defaultSettings,
|
|
9
|
+
displayedLocales: config.defaultLocales.length > 0 ? config.defaultLocales : defaultSettings.displayedLocales,
|
|
10
|
+
});
|
|
11
|
+
export const useSettings = (config) => {
|
|
12
|
+
console.log("useSettings");
|
|
13
|
+
const [settings, setSettings] = useState(() => Object.fromEntries(Object.entries(defaultSettingsFromConfig(config)).map(([key, initialValue]) => {
|
|
14
|
+
const item = localStorage.getItem(key);
|
|
15
|
+
if (item) {
|
|
16
|
+
try {
|
|
17
|
+
const parsed = JSON.parse(item);
|
|
18
|
+
return [
|
|
19
|
+
key,
|
|
20
|
+
settingsGuards[key](parsed) ? parsed : initialValue,
|
|
21
|
+
];
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return [key, initialValue];
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return [key, initialValue];
|
|
28
|
+
})));
|
|
29
|
+
return {
|
|
30
|
+
settings,
|
|
31
|
+
setSetting: useCallback((key, value) => {
|
|
32
|
+
setSettings(prev => {
|
|
33
|
+
const newSettings = {
|
|
34
|
+
...prev,
|
|
35
|
+
[key]: typeof value === "function" ? value(prev[key]) : value,
|
|
36
|
+
};
|
|
37
|
+
localStorage.setItem(key, JSON.stringify(newSettings[key]));
|
|
38
|
+
return newSettings;
|
|
39
|
+
});
|
|
40
|
+
}, []),
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
export const useSetting = (key) => {
|
|
44
|
+
const { settings, setSetting } = useContext(SettingsContext);
|
|
45
|
+
return [
|
|
46
|
+
settings[key],
|
|
47
|
+
useCallback((value) => {
|
|
48
|
+
setSetting(key, value);
|
|
49
|
+
}, [key, setSetting]),
|
|
50
|
+
];
|
|
51
|
+
};
|
package/dist/src/web/index.js
CHANGED
|
@@ -2,10 +2,14 @@ import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
|
|
|
2
2
|
import { render } from "preact";
|
|
3
3
|
import { LocationProvider, Route, Router, useLocation } from "preact-iso";
|
|
4
4
|
import { useEffect } from "preact/hooks";
|
|
5
|
-
import { getAllEntities } from "./api.js";
|
|
5
|
+
import { getAllEntities } from "./api/declarations.js";
|
|
6
|
+
import { getWebConfig } from "./api/index.js";
|
|
6
7
|
import { Git } from "./components/Git.js";
|
|
8
|
+
import { ConfigContext } from "./context/config.js";
|
|
7
9
|
import { EntitiesContext } from "./context/entities.js";
|
|
10
|
+
import { SettingsContext } from "./context/settings.js";
|
|
8
11
|
import { useMappedAPIResource } from "./hooks/useMappedAPIResource.js";
|
|
12
|
+
import { useSettings } from "./hooks/useSettings.js";
|
|
9
13
|
import { CreateInstance } from "./routes/CreateInstance.js";
|
|
10
14
|
import { Entity } from "./routes/Entity.js";
|
|
11
15
|
import { Home } from "./routes/Home.js";
|
|
@@ -14,15 +18,17 @@ import { NotFound } from "./routes/NotFound.js";
|
|
|
14
18
|
const mapEntities = (data) => data.declarations
|
|
15
19
|
.map(decl => ({ ...decl, isLocaleEntity: decl.declaration.name === data.localeEntity }))
|
|
16
20
|
.sort((a, b) => a.declaration.name.localeCompare(b.declaration.name));
|
|
17
|
-
const App = () => {
|
|
18
|
-
const
|
|
21
|
+
const App = ({ config }) => {
|
|
22
|
+
const settingsContext = useSettings(config);
|
|
23
|
+
const [entities, reloadEntities] = useMappedAPIResource(getAllEntities, mapEntities, settingsContext.settings.displayedLocales);
|
|
19
24
|
const location = useLocation();
|
|
20
25
|
useEffect(() => {
|
|
21
26
|
reloadEntities().catch((error) => {
|
|
22
27
|
alert("Error reloading entities: " + String(error));
|
|
23
28
|
});
|
|
24
29
|
}, [location.path, reloadEntities]);
|
|
25
|
-
return (_jsx(LocationProvider, { children: _jsxs(EntitiesContext.Provider, { value: entities ?? [], children: [_jsxs(Router, { children: [_jsx(Route, { path: "/", component: Home }), _jsx(Route, { path: "/entities/:name", component: Entity }), _jsx(Route, { path: "/entities/:name/instances/create", component: CreateInstance }), _jsx(Route, { path: "/entities/:name/instances/:id", component: Instance }), _jsx(Route, { default: true, component: NotFound })] }), _jsx(Git, {})] }) }));
|
|
30
|
+
return (_jsx(ConfigContext.Provider, { value: config, children: _jsx(SettingsContext.Provider, { value: settingsContext, children: _jsx(LocationProvider, { children: _jsxs(EntitiesContext.Provider, { value: { entities: entities ?? [], reloadEntities }, children: [_jsxs(Router, { children: [_jsx(Route, { path: "/", component: Home }), _jsx(Route, { path: "/entities/:name", component: Entity }), _jsx(Route, { path: "/entities/:name/instances/create", component: CreateInstance }), _jsx(Route, { path: "/entities/:name/instances/:id", component: Instance }), _jsx(Route, { default: true, component: NotFound })] }), _jsx(Git, {})] }) }) }) }));
|
|
26
31
|
};
|
|
32
|
+
const config = await getWebConfig();
|
|
27
33
|
const root = document.getElementById("app");
|
|
28
|
-
render(_jsx(App, {}), root);
|
|
34
|
+
render(_jsx(App, { config: config }), root);
|
|
@@ -1,85 +1,46 @@
|
|
|
1
|
-
import { jsx as _jsx
|
|
2
|
-
import { useLocation, useRoute } from "preact-iso";
|
|
3
|
-
import { useEffect, useState } from "preact/hooks";
|
|
4
|
-
import { getSerializedDisplayNameFromEntityInstance } from "../../shared/utils/displayName.js";
|
|
1
|
+
import { jsx as _jsx } from "preact/jsx-runtime";
|
|
5
2
|
import { toTitleCase } from "../../shared/utils/string.js";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { Layout } from "../components/Layout.js";
|
|
9
|
-
import { TypeInput } from "../components/typeInputs/TypeInput.js";
|
|
10
|
-
import { ValidationErrors } from "../components/typeInputs/utils/ValidationErrors.js";
|
|
11
|
-
import { useEntityFromRoute } from "../hooks/useEntityFromRoute.js";
|
|
12
|
-
import { useInstanceNamesByEntity } from "../hooks/useInstanceNamesByEntity.js";
|
|
13
|
-
import { useGetDeclFromDeclName } from "../hooks/useSecondaryDeclarations.js";
|
|
3
|
+
import { createInstanceByEntityNameAndId } from "../api/declarations.js";
|
|
4
|
+
import { InstanceRouteSkeleton, } from "../components/InstanceRouteSkeleton.js";
|
|
14
5
|
import { createTypeSkeleton } from "../utils/typeSkeleton.js";
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
6
|
+
const init = ({ entity, setInstanceContent, getDeclFromDeclName, }) => {
|
|
7
|
+
setInstanceContent(createTypeSkeleton(getDeclFromDeclName, entity.type));
|
|
8
|
+
return Promise.resolve();
|
|
9
|
+
};
|
|
10
|
+
const titleBuilder = ({ entity }) => {
|
|
11
|
+
const entityName = entity.name;
|
|
12
|
+
return "New " + toTitleCase(entityName) + " — TSONDB";
|
|
13
|
+
};
|
|
14
|
+
const onSubmit = async ({ locales, entity, buttonName, instanceContent, isLocaleEntity, customId, childInstances, setInstanceContent, setCustomId, route, getDeclFromDeclName, }) => {
|
|
15
|
+
try {
|
|
16
|
+
const createdInstance = await createInstanceByEntityNameAndId(locales, entity.name, {
|
|
17
|
+
childInstances,
|
|
18
|
+
entityName: entity.name,
|
|
19
|
+
content: instanceContent,
|
|
20
|
+
id: undefined,
|
|
21
|
+
}, isLocaleEntity ? customId : undefined);
|
|
22
|
+
switch (buttonName) {
|
|
23
|
+
case "saveandcontinue": {
|
|
24
|
+
route(`/entities/${entity.name}/instances/${createdInstance.instance.id}`);
|
|
25
|
+
break;
|
|
26
|
+
}
|
|
27
|
+
case "saveandaddanother": {
|
|
28
|
+
setInstanceContent(createTypeSkeleton(getDeclFromDeclName, entity.type));
|
|
29
|
+
setCustomId("");
|
|
30
|
+
alert(`Instance of entity ${entity.name} created successfully with identifier ${createdInstance.instance.id}. You can add another instance now.`);
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
case "save":
|
|
34
|
+
default: {
|
|
35
|
+
route(`/entities/${entity.name}?created=${encodeURIComponent(createdInstance.instance.id)}`);
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
27
38
|
}
|
|
28
|
-
}, [getDeclFromDeclName, entityFromRoute]);
|
|
29
|
-
const { route } = useLocation();
|
|
30
|
-
useEffect(() => {
|
|
31
|
-
const entityName = entityFromRoute?.declaration.name ?? name;
|
|
32
|
-
document.title =
|
|
33
|
-
entityName === undefined ? "Not found" : "New " + toTitleCase(entityName) + " — TSONDB";
|
|
34
|
-
}, [entityFromRoute?.declaration.name, name]);
|
|
35
|
-
if (!name) {
|
|
36
|
-
return _jsx(NotFound, {});
|
|
37
39
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const { declaration: entity, isLocaleEntity } = entityFromRoute;
|
|
42
|
-
const handleSubmit = (event) => {
|
|
43
|
-
event.preventDefault();
|
|
44
|
-
const name = event.submitter?.getAttribute("name");
|
|
45
|
-
if (name) {
|
|
46
|
-
createInstanceByEntityNameAndId(entity.name, instance, isLocaleEntity ? customId : undefined)
|
|
47
|
-
.then(createdInstance => {
|
|
48
|
-
switch (name) {
|
|
49
|
-
case "saveandcontinue": {
|
|
50
|
-
route(`/entities/${entity.name}/instances/${createdInstance.instance.id}`);
|
|
51
|
-
break;
|
|
52
|
-
}
|
|
53
|
-
case "saveandaddanother": {
|
|
54
|
-
setInstance(createTypeSkeleton(getDeclFromDeclName, entity.type));
|
|
55
|
-
setCustomId("");
|
|
56
|
-
alert(`Instance of entity ${entity.name} created successfully with identifier ${createdInstance.instance.id}. You can add another instance now.`);
|
|
57
|
-
break;
|
|
58
|
-
}
|
|
59
|
-
case "save":
|
|
60
|
-
default: {
|
|
61
|
-
route(`/entities/${entity.name}?created=${encodeURIComponent(createdInstance.instance.id)}`);
|
|
62
|
-
break;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
})
|
|
66
|
-
.catch((error) => {
|
|
67
|
-
if (error instanceof Error) {
|
|
68
|
-
alert(`Error creating instance:\n\n${error.toString()}`);
|
|
69
|
-
}
|
|
70
|
-
});
|
|
40
|
+
catch (error) {
|
|
41
|
+
if (error instanceof Error) {
|
|
42
|
+
alert(`Error creating instance:\n\n${error.toString()}`);
|
|
71
43
|
}
|
|
72
|
-
}
|
|
73
|
-
const defaultName = customId || `New ${toTitleCase(entity.name)}`;
|
|
74
|
-
const instanceName = getSerializedDisplayNameFromEntityInstance(entity, instance, defaultName);
|
|
75
|
-
const idErrors = isLocaleEntity ? validateLocaleIdentifier(customId) : [];
|
|
76
|
-
return (_jsxs(Layout, { breadcrumbs: [
|
|
77
|
-
{ url: "/", label: homeTitle },
|
|
78
|
-
{ url: `/entities/${entity.name}`, label: toTitleCase(entity.namePlural) },
|
|
79
|
-
], children: [_jsx("div", { class: "header-with-btns", children: _jsx("h1", { class: instanceName.length === 0 ? "empty-name" : undefined, children: instanceName || defaultName }) }), isLocaleEntity && (_jsxs("div", { class: "field field--id", children: [_jsx("label", { htmlFor: "id", children: "ID" }), _jsx("p", { className: "comment", children: "The instance\u2019s identifier. An IETF language tag (BCP47)." }), _jsx("input", { type: "text", id: "id", value: customId, required: true, pattern: "[a-z]{2,3}(-[A-Z]{2,3})?", placeholder: "en-US, de-DE, \u2026", onInput: event => {
|
|
80
|
-
setCustomId(event.currentTarget.value);
|
|
81
|
-
}, "aria-invalid": idErrors.length > 0 }), _jsx(ValidationErrors, { errors: idErrors })] })), _jsxs("form", { onSubmit: handleSubmit, children: [_jsx(TypeInput, { type: entity.type, path: undefined, value: instance, instanceNamesByEntity: instanceNamesByEntity, getDeclFromDeclName: getDeclFromDeclName, onChange: value => {
|
|
82
|
-
console.log("onChange", value);
|
|
83
|
-
setInstance(value);
|
|
84
|
-
} }), _jsxs("div", { class: "form-footer btns", children: [_jsx("button", { type: "submit", class: "primary", name: "save", children: "Save" }), _jsx("button", { type: "submit", class: "primary", name: "saveandcontinue", children: "Save and Continue" }), _jsx("button", { type: "submit", class: "primary", name: "saveandaddanother", children: "Save and Add Another" })] })] })] }));
|
|
44
|
+
}
|
|
85
45
|
};
|
|
46
|
+
export const CreateInstance = () => (_jsx(InstanceRouteSkeleton, { mode: "create", init: init, titleBuilder: titleBuilder, onSubmit: onSubmit }));
|
|
@@ -1,22 +1,30 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
|
|
2
2
|
import { useRoute } from "preact-iso";
|
|
3
|
-
import { useEffect, useState } from "preact/hooks";
|
|
3
|
+
import { useContext, useEffect, useState } from "preact/hooks";
|
|
4
4
|
import { getGitStatusForDisplay, getLabelForGitStatus } from "../../shared/utils/git.js";
|
|
5
5
|
import { toTitleCase } from "../../shared/utils/string.js";
|
|
6
|
-
import { deleteInstanceByEntityNameAndId, getInstancesByEntityName } from "../api.js";
|
|
6
|
+
import { deleteInstanceByEntityNameAndId, getInstancesByEntityName, getLocaleInstances, } from "../api/declarations.js";
|
|
7
7
|
import { Layout } from "../components/Layout.js";
|
|
8
|
+
import { ConfigContext } from "../context/config.js";
|
|
9
|
+
import { EntitiesContext } from "../context/entities.js";
|
|
8
10
|
import { useEntityFromRoute } from "../hooks/useEntityFromRoute.js";
|
|
9
11
|
import { useMappedAPIResource } from "../hooks/useMappedAPIResource.js";
|
|
12
|
+
import { useSetting } from "../hooks/useSettings.js";
|
|
10
13
|
import { Markdown } from "../utils/Markdown.js";
|
|
11
14
|
import { homeTitle } from "./Home.js";
|
|
12
15
|
import { NotFound } from "./NotFound.js";
|
|
16
|
+
const localeMapper = (result) => result.instances;
|
|
13
17
|
const mapInstances = (data) => data.instances;
|
|
14
18
|
export const Entity = () => {
|
|
15
19
|
const { params: { name }, query: { created }, } = useRoute();
|
|
20
|
+
const [locales] = useSetting("displayedLocales");
|
|
16
21
|
const [searchText, setSearchText] = useState("");
|
|
17
22
|
const entityFromRoute = useEntityFromRoute();
|
|
18
|
-
const
|
|
19
|
-
const
|
|
23
|
+
const config = useContext(ConfigContext);
|
|
24
|
+
const { reloadEntities } = useContext(EntitiesContext);
|
|
25
|
+
const { declaration: entity, isLocaleEntity } = entityFromRoute ?? {};
|
|
26
|
+
const [instances, reloadInstances] = useMappedAPIResource(getInstancesByEntityName, mapInstances, locales, name ?? "");
|
|
27
|
+
const [localeInstances] = useMappedAPIResource(getLocaleInstances, localeMapper, locales, config.localeEntityName);
|
|
20
28
|
useEffect(() => {
|
|
21
29
|
document.title = toTitleCase(entity?.namePlural ?? name ?? "") + " — TSONDB";
|
|
22
30
|
}, [entity?.namePlural, name]);
|
|
@@ -32,29 +40,44 @@ export const Entity = () => {
|
|
|
32
40
|
return _jsx(NotFound, {});
|
|
33
41
|
}
|
|
34
42
|
if (!entity || !instances) {
|
|
35
|
-
return (_jsxs("div", { children: [_jsx("h1", { children: toTitleCase(entity?.namePlural ?? name) }), _jsx("p", {
|
|
43
|
+
return (_jsxs(Layout, { breadcrumbs: [{ url: "/", label: homeTitle }], children: [_jsxs("div", { class: "header-with-btns", children: [_jsx("h1", { children: toTitleCase(entity?.namePlural ?? name) }), _jsx("a", { class: "btn btn--primary", "aria-disabled": true, children: "Add" })] }), _jsx("p", { class: "loading", children: "Loading \u2026" })] }));
|
|
36
44
|
}
|
|
37
45
|
const lowerSearchText = searchText.toLowerCase();
|
|
38
46
|
const filteredInstances = searchText.length === 0
|
|
39
47
|
? instances
|
|
40
48
|
: instances.filter(instance => instance.id.includes(searchText) ||
|
|
41
49
|
instance.displayName.toLowerCase().includes(lowerSearchText));
|
|
50
|
+
const instancesByLocale = Object.groupBy(filteredInstances, instance => instance.displayNameLocaleId ?? "undefined");
|
|
51
|
+
const groupedInstances = [...locales, "undefined"]
|
|
52
|
+
.map(key => ({
|
|
53
|
+
id: key,
|
|
54
|
+
name: key === "undefined"
|
|
55
|
+
? "No matching locale"
|
|
56
|
+
: (localeInstances?.find(instance => instance.id === key)?.displayName ?? key),
|
|
57
|
+
instances: instancesByLocale[key] ?? [],
|
|
58
|
+
}))
|
|
59
|
+
.filter(group => group.instances.length > 0);
|
|
60
|
+
const instanceMapper = (instance) => {
|
|
61
|
+
const gitStatusForDisplay = getGitStatusForDisplay(instance.gitStatus);
|
|
62
|
+
return (_jsxs("li", { id: `instance-${instance.id}`, class: `entries-item ${created === instance.id ? "entries-item--created" : ""} ${gitStatusForDisplay === undefined ? "" : `git-status--${gitStatusForDisplay}`}`, children: [_jsx("h2", { class: "entries-item__title", children: instance.displayName }), _jsx("p", { "aria-hidden": true, class: "entries-item__subtitle entries-item__subtitle--id", children: instance.id }), _jsxs("div", { class: "entries-item__side", children: [gitStatusForDisplay !== undefined && (_jsx("p", { class: `git-status git-status--${gitStatusForDisplay}`, title: getLabelForGitStatus(gitStatusForDisplay), children: gitStatusForDisplay })), _jsxs("div", { class: "btns", children: [_jsx("a", { href: `/entities/${entity.name}/instances/${instance.id}`, class: "btn", children: "Edit" }), _jsx("button", { class: "destructive", onClick: () => {
|
|
63
|
+
if (confirm("Are you sure you want to delete this instance?")) {
|
|
64
|
+
deleteInstanceByEntityNameAndId(locales, entity.name, instance.id)
|
|
65
|
+
.then(() => reloadInstances())
|
|
66
|
+
.then(() => reloadEntities())
|
|
67
|
+
.catch((error) => {
|
|
68
|
+
if (error instanceof Error) {
|
|
69
|
+
alert("Error deleting instance:\n\n" + error.toString());
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}, children: "Delete" })] })] })] }, instance.id));
|
|
74
|
+
};
|
|
42
75
|
return (_jsxs(Layout, { breadcrumbs: [{ url: "/", label: homeTitle }], children: [_jsxs("div", { class: "header-with-btns", children: [_jsx("h1", { children: toTitleCase(entity.namePlural) }), _jsx("a", { class: "btn btn--primary", href: `/entities/${entity.name}/instances/create`, children: "Add" })] }), entity.comment && _jsx(Markdown, { class: "description", string: entity.comment }), _jsxs("div", { className: "list-header", children: [_jsxs("p", { class: "instance-count", children: [searchText === "" ? "" : `${filteredInstances.length.toString()} of `, instances.length, " instance", instances.length === 1 ? "" : "s"] }), _jsxs("form", { action: "", rel: "search", onSubmit: e => {
|
|
43
76
|
e.preventDefault();
|
|
44
77
|
}, children: [_jsx("label", { htmlFor: "instance-search", class: "visually-hidden", children: "Search" }), _jsx("input", { type: "text", id: "instance-search", value: searchText, onInput: event => {
|
|
45
78
|
setSearchText(event.currentTarget.value);
|
|
46
|
-
} })] })] }),
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
deleteInstanceByEntityNameAndId(entity.name, instance.id)
|
|
51
|
-
.then(() => reloadInstances())
|
|
52
|
-
.catch((error) => {
|
|
53
|
-
if (error instanceof Error) {
|
|
54
|
-
alert("Error deleting instance:\n\n" + error.toString());
|
|
55
|
-
}
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
}, children: "Delete" })] })] })] }, instance.id));
|
|
59
|
-
}) })] }));
|
|
79
|
+
} })] })] }), isLocaleEntity ||
|
|
80
|
+
(groupedInstances.length === 1 &&
|
|
81
|
+
groupedInstances[0]?.id !== "undefined" &&
|
|
82
|
+
locales[0] === groupedInstances[0]?.id) ? (_jsx("ul", { class: "entries entries--instances", children: filteredInstances.map(instanceMapper) })) : (_jsx("ul", { class: "entry-groups", children: groupedInstances.map(group => (_jsxs("li", { class: "entry-groups-item", children: [_jsx("h2", { class: "entry-groups-item__title", children: group.name }), group.id === "undefined" ? (_jsxs("p", { children: [group.instances.length, " other instance", group.instances.length === 1 ? "" : "s"] })) : (_jsx("ul", { class: "entries entries--instances", children: group.instances.map(instanceMapper) }))] }, `group-${group.id}`))) }))] }));
|
|
60
83
|
};
|
|
@@ -2,23 +2,42 @@ import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
|
|
|
2
2
|
import { useContext, useEffect, useState } from "preact/hooks";
|
|
3
3
|
import { toTitleCase } from "../../shared/utils/string.js";
|
|
4
4
|
import { Layout } from "../components/Layout.js";
|
|
5
|
+
import { ConfigContext } from "../context/config.js";
|
|
5
6
|
import { EntitiesContext } from "../context/entities.js";
|
|
6
7
|
import { Markdown } from "../utils/Markdown.js";
|
|
7
8
|
export const homeTitle = "Entities";
|
|
9
|
+
const isEntityInAnyHomeLayoutSection = (entityName, homeLayoutSections) => homeLayoutSections.some(section => section.entities.includes(entityName));
|
|
8
10
|
export const Home = () => {
|
|
9
|
-
const
|
|
11
|
+
const { homeLayoutSections } = useContext(ConfigContext);
|
|
12
|
+
const { entities } = useContext(EntitiesContext);
|
|
10
13
|
useEffect(() => {
|
|
11
14
|
document.title = homeTitle + " — TSONDB";
|
|
12
15
|
}, []);
|
|
13
16
|
const [searchText, setSearchText] = useState("");
|
|
14
17
|
const lowerSearchText = searchText.toLowerCase().replaceAll(" ", "");
|
|
15
18
|
const filteredEntities = searchText.length === 0
|
|
16
|
-
? entities
|
|
17
|
-
: entities.filter(entity => entity.declaration.
|
|
18
|
-
entity.declaration.
|
|
19
|
+
? entities.filter(entity => entity.declaration.parentReferenceKey === undefined)
|
|
20
|
+
: entities.filter(entity => entity.declaration.parentReferenceKey === undefined &&
|
|
21
|
+
(entity.declaration.name.toLowerCase().includes(lowerSearchText) ||
|
|
22
|
+
entity.declaration.namePlural.toLowerCase().includes(lowerSearchText)));
|
|
23
|
+
const filteredEntitiesBySection = homeLayoutSections
|
|
24
|
+
? [
|
|
25
|
+
...homeLayoutSections.map(section => ({
|
|
26
|
+
...section,
|
|
27
|
+
entities: section.entities
|
|
28
|
+
.map(entityName => filteredEntities.find(entity => entity.declaration.name === entityName))
|
|
29
|
+
.filter(entity => entity !== undefined),
|
|
30
|
+
})),
|
|
31
|
+
{
|
|
32
|
+
title: "Other",
|
|
33
|
+
entities: filteredEntities.filter(entity => !isEntityInAnyHomeLayoutSection(entity.declaration.name, homeLayoutSections)),
|
|
34
|
+
},
|
|
35
|
+
].filter(section => section.entities.length > 0)
|
|
36
|
+
: undefined;
|
|
37
|
+
const mapEntity = (entity) => (_jsxs("li", { class: "entries-item", children: [_jsxs("div", { class: "entries-item__title", children: [_jsx("h2", { children: toTitleCase(entity.declaration.namePlural) }), entity.declaration.comment && (_jsx(Markdown, { class: "description", string: entity.declaration.comment }))] }), _jsxs("p", { class: "entries-item__subtitle", children: [entity.instanceCount, " instance", entity.instanceCount === 1 ? "" : "s"] }), _jsx("div", { class: "entries-item__side", children: _jsx("div", { class: "btns", children: _jsx("a", { href: `/entities/${entity.declaration.name}`, class: "btn", children: "View" }) }) })] }, entity.declaration.name));
|
|
19
38
|
return (_jsxs(Layout, { breadcrumbs: [], children: [_jsx("h1", { children: homeTitle }), _jsxs("div", { className: "list-header", children: [_jsxs("p", { class: "instance-count", children: [searchText === "" ? "" : `${filteredEntities.length.toString()} of `, entities.length, " entit", entities.length === 1 ? "y" : "ies"] }), _jsxs("form", { action: "", rel: "search", onSubmit: e => {
|
|
20
39
|
e.preventDefault();
|
|
21
40
|
}, children: [_jsx("label", { htmlFor: "entity-search", class: "visually-hidden", children: "Search" }), _jsx("input", { type: "text", id: "entity-search", value: searchText, onInput: event => {
|
|
22
41
|
setSearchText(event.currentTarget.value);
|
|
23
|
-
} })] })] }), _jsx("ul", { class: "
|
|
42
|
+
} })] })] }), filteredEntitiesBySection ? (_jsx("ul", { class: "entry-groups", children: filteredEntitiesBySection.map((section, si) => (_jsxs("li", { class: "entry-groups-item", children: [_jsx("h2", { class: "entry-groups-item__title", children: section.title }), section.comment && _jsx(Markdown, { class: "description", string: section.comment }), _jsx("ul", { class: "entries entries--entities", children: section.entities.map(mapEntity) })] }, si))) })) : (_jsx("ul", { class: "entries entries--entities", children: filteredEntities.map(mapEntity) }))] }));
|
|
24
43
|
};
|
|
@@ -1,94 +1,43 @@
|
|
|
1
|
-
import { jsx as _jsx
|
|
2
|
-
import { useLocation, useRoute } from "preact-iso";
|
|
3
|
-
import { useCallback, useEffect, useState } from "preact/hooks";
|
|
1
|
+
import { jsx as _jsx } from "preact/jsx-runtime";
|
|
4
2
|
import { getSerializedDisplayNameFromEntityInstance } from "../../shared/utils/displayName.js";
|
|
5
3
|
import { toTitleCase } from "../../shared/utils/string.js";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
import { NotFound } from "./NotFound.js";
|
|
14
|
-
export const Instance = () => {
|
|
15
|
-
const { params: { name, id }, } = useRoute();
|
|
16
|
-
const [getDeclFromDeclName, declsLoaded] = useGetDeclFromDeclName();
|
|
17
|
-
const entityFromRoute = useEntityFromRoute();
|
|
18
|
-
const { declaration: entity } = entityFromRoute ?? {};
|
|
19
|
-
const [instanceNamesByEntity] = useInstanceNamesByEntity();
|
|
20
|
-
const [instance, setInstance] = useState();
|
|
21
|
-
const [originalInstance, setOriginalInstance] = useState();
|
|
22
|
-
const { route } = useLocation();
|
|
23
|
-
useEffect(() => {
|
|
24
|
-
if (entity && instance?.content && id) {
|
|
25
|
-
const defaultName = id;
|
|
26
|
-
const instanceName = getSerializedDisplayNameFromEntityInstance(entity, instance.content, defaultName);
|
|
27
|
-
const entityName = entity.name;
|
|
28
|
-
document.title = instanceName + " — " + toTitleCase(entityName) + " — TSONDB";
|
|
4
|
+
import { getInstanceByEntityNameAndId, updateInstanceByEntityNameAndId, } from "../api/declarations.js";
|
|
5
|
+
import { InstanceRouteSkeleton, } from "../components/InstanceRouteSkeleton.js";
|
|
6
|
+
const init = async ({ locales, entity, instanceId, setInstanceContent, }) => {
|
|
7
|
+
if (instanceId) {
|
|
8
|
+
try {
|
|
9
|
+
const instanceData = await getInstanceByEntityNameAndId(locales, entity.name, instanceId);
|
|
10
|
+
setInstanceContent(instanceData.instance.content);
|
|
29
11
|
}
|
|
30
|
-
|
|
31
|
-
|
|
12
|
+
catch (error) {
|
|
13
|
+
console.error("Error fetching entities:", error);
|
|
32
14
|
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
const titleBuilder = ({ locales, entity, instanceId, instanceContent, }) => {
|
|
18
|
+
if (instanceContent && instanceId) {
|
|
19
|
+
const instanceName = getSerializedDisplayNameFromEntityInstance(entity, instanceContent, instanceId, locales).name;
|
|
20
|
+
return instanceName + " — " + toTitleCase(entity.name) + " — TSONDB";
|
|
21
|
+
}
|
|
22
|
+
return undefined;
|
|
23
|
+
};
|
|
24
|
+
const onSubmit = async ({ locales, entity, instanceId, instanceContent, buttonName, childInstances, }) => {
|
|
25
|
+
if (instanceId && buttonName === "save") {
|
|
26
|
+
try {
|
|
27
|
+
await updateInstanceByEntityNameAndId(locales, entity.name, instanceId, {
|
|
28
|
+
childInstances,
|
|
29
|
+
entityName: entity.name,
|
|
30
|
+
content: instanceContent,
|
|
31
|
+
id: instanceId,
|
|
43
32
|
});
|
|
44
33
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
updateInstanceByEntityNameAndId(name, id, instance.content)
|
|
50
|
-
.then(updatedInstance => {
|
|
51
|
-
setInstance(updatedInstance.instance);
|
|
52
|
-
setOriginalInstance(updatedInstance.instance);
|
|
53
|
-
})
|
|
54
|
-
.catch((error) => {
|
|
55
|
-
if (error instanceof Error) {
|
|
56
|
-
alert(`Error updating instance:\n\n${error}`);
|
|
57
|
-
}
|
|
58
|
-
});
|
|
34
|
+
catch (error) {
|
|
35
|
+
if (error instanceof Error) {
|
|
36
|
+
alert(`Error updating instance:\n\n${error}`);
|
|
37
|
+
}
|
|
59
38
|
}
|
|
60
|
-
};
|
|
61
|
-
const handleOnChange = useCallback((value) => {
|
|
62
|
-
setInstance(container => container && { ...container, content: value });
|
|
63
|
-
}, []);
|
|
64
|
-
if (!name || !id) {
|
|
65
|
-
return _jsx(NotFound, {});
|
|
66
|
-
}
|
|
67
|
-
if (!entity || !instance || !originalInstance || !instanceNamesByEntity || !declsLoaded) {
|
|
68
|
-
return (_jsxs(Layout, { breadcrumbs: [
|
|
69
|
-
{ url: "/", label: homeTitle },
|
|
70
|
-
{
|
|
71
|
-
url: `/entities/${name}`,
|
|
72
|
-
label: entity ? toTitleCase(entity.namePlural) : name,
|
|
73
|
-
},
|
|
74
|
-
], children: [_jsx("h1", { children: id }), _jsx("p", { className: "loading", children: "Loading \u2026" })] }));
|
|
75
39
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
return (
|
|
79
|
-
{ url: "/", label: homeTitle },
|
|
80
|
-
{ url: `/entities/${name}`, label: toTitleCase(entity.namePlural) },
|
|
81
|
-
], children: [_jsxs("div", { class: "header-with-btns", children: [_jsxs("h1", { class: instanceName.length === 0 ? "empty-name" : undefined, children: [_jsx("span", { children: instanceName || defaultName }), " ", _jsx("span", { className: "id", "aria-hidden": true, children: instance.id })] }), _jsx("button", { class: "destructive", onClick: () => {
|
|
82
|
-
if (confirm("Are you sure you want to delete this instance?")) {
|
|
83
|
-
deleteInstanceByEntityNameAndId(entity.name, instance.id)
|
|
84
|
-
.then(() => {
|
|
85
|
-
route(`/entities/${name}`);
|
|
86
|
-
})
|
|
87
|
-
.catch((error) => {
|
|
88
|
-
if (error instanceof Error) {
|
|
89
|
-
alert("Error deleting instance:\n\n" + error.toString());
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
}, children: "Delete" })] }), _jsxs("form", { onSubmit: handleSubmit, children: [_jsx(TypeInput, { type: entity.type, value: instance.content, path: undefined, instanceNamesByEntity: instanceNamesByEntity, getDeclFromDeclName: getDeclFromDeclName, onChange: handleOnChange }), _jsx("div", { class: "form-footer btns", children: _jsx("button", { type: "submit", name: "save", class: "primary", children: "Save" }) })] })] }));
|
|
40
|
+
};
|
|
41
|
+
export const Instance = () => {
|
|
42
|
+
return (_jsx(InstanceRouteSkeleton, { mode: "edit", init: init, titleBuilder: titleBuilder, onSubmit: onSubmit }));
|
|
94
43
|
};
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { jsx as _jsx } from "preact/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
|
|
2
|
+
import { Fragment } from "preact";
|
|
3
|
+
const emptyNode = { kind: "text", content: "" };
|
|
2
4
|
export const InlineMarkdown = ({ node }) => {
|
|
3
5
|
switch (node.kind) {
|
|
4
6
|
case "code":
|
|
@@ -9,6 +11,16 @@ export const InlineMarkdown = ({ node }) => {
|
|
|
9
11
|
return (_jsx("em", { children: node.content.map((inline, i) => (_jsx(InlineMarkdown, { node: inline }, i))) }));
|
|
10
12
|
case "link":
|
|
11
13
|
return (_jsx("a", { href: node.href, children: node.content.map((inline, i) => (_jsx(InlineMarkdown, { node: inline }, i))) }));
|
|
14
|
+
case "attributed": {
|
|
15
|
+
const separatorIndex = node.content.findIndex(attr => attr.kind === "text" && attr.content === "](");
|
|
16
|
+
const count = Object.keys(node.attributes).length;
|
|
17
|
+
const attributesStart = separatorIndex + 1;
|
|
18
|
+
const attributesEnd = attributesStart + (count === 0 ? 0 : count * 4 - 1);
|
|
19
|
+
const leadingNodes = node.content.slice(0, attributesStart);
|
|
20
|
+
const attributes = node.content.slice(attributesStart, attributesEnd);
|
|
21
|
+
const trailingNodes = node.content.slice(attributesEnd);
|
|
22
|
+
return (_jsxs("span", { class: "attributed", ...Object.fromEntries(Object.entries(node.attributes).map(([k, v]) => [`data-${k}`, v.toString()])), children: [leadingNodes.map((inline, i) => (_jsx(InlineMarkdown, { node: inline }, i))), Array.from({ length: count }, (_, i) => (_jsxs(Fragment, { children: [_jsx("span", { class: "attributed__name", children: _jsx(InlineMarkdown, { node: attributes[i * 4] ?? emptyNode }) }), _jsx("span", { class: "attributed__separator", children: _jsx(InlineMarkdown, { node: attributes[i * 4 + 1] ?? emptyNode }) }), _jsx("span", { class: "attributed__value", children: _jsx(InlineMarkdown, { node: attributes[i * 4 + 2] ?? emptyNode }) }), i < count - 1 && (_jsx("span", { class: "attributed__separator", children: _jsx(InlineMarkdown, { node: attributes[i * 4 + 3] ?? emptyNode }) }))] }, `attr-${(i + 1).toString()}`))), trailingNodes.map((inline, i) => (_jsx(InlineMarkdown, { node: inline }, i)))] }));
|
|
23
|
+
}
|
|
12
24
|
case "text":
|
|
13
25
|
return node.content;
|
|
14
26
|
}
|