tsondb 0.2.0 → 0.3.0
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/lib/ModelContainer.js +9 -7
- package/lib/client/api.d.ts +14 -1
- package/lib/client/api.js +119 -0
- package/lib/client/components/Git.d.ts +2 -0
- package/lib/client/components/Git.js +116 -0
- package/lib/client/components/Layout.js +2 -1
- package/lib/client/components/typeInputs/ArrayTypeInput.js +2 -1
- package/lib/client/components/typeInputs/EnumTypeInput.d.ts +13 -0
- package/lib/client/components/typeInputs/{utils/EnumDeclField.js → EnumTypeInput.js} +10 -10
- package/lib/client/components/typeInputs/IncludeIdentifierTypeInput.js +1 -10
- package/lib/client/components/typeInputs/TypeInput.js +3 -0
- package/lib/client/components/typeInputs/utils/Markdown.js +1 -32
- package/lib/client/hooks/useAPIResource.d.ts +1 -0
- package/lib/client/hooks/useAPIResource.js +2 -0
- package/lib/client/hooks/useMappedAPIResource.d.ts +1 -0
- package/lib/client/hooks/useMappedAPIResource.js +19 -0
- package/lib/client/routes/Entity.js +18 -24
- package/lib/client/routes/Home.js +3 -12
- package/lib/client/utils/typeSkeleton.js +10 -16
- package/lib/renderers/jsonschema/index.d.ts +1 -1
- package/lib/renderers/jsonschema/index.js +30 -7
- package/lib/renderers/jsonschema/render.d.ts +5 -1
- package/lib/renderers/jsonschema/render.js +35 -16
- package/lib/renderers/ts/index.d.ts +1 -1
- package/lib/renderers/ts/index.js +37 -6
- package/lib/renderers/ts/render.d.ts +2 -0
- package/lib/renderers/ts/render.js +55 -32
- package/lib/schema/Node.d.ts +1 -0
- package/lib/schema/Node.js +6 -1
- package/lib/schema/declarations/Declaration.d.ts +3 -1
- package/lib/schema/declarations/Declaration.js +4 -0
- package/lib/schema/declarations/EntityDecl.d.ts +3 -0
- package/lib/schema/declarations/EnumDecl.d.ts +4 -21
- package/lib/schema/declarations/EnumDecl.js +16 -79
- package/lib/schema/index.d.ts +1 -0
- package/lib/schema/index.js +1 -0
- package/lib/schema/types/Type.d.ts +8 -2
- package/lib/schema/types/Type.js +57 -11
- package/lib/schema/types/generic/ArrayType.d.ts +2 -1
- package/lib/schema/types/generic/ArrayType.js +2 -1
- package/lib/schema/types/generic/EnumType.d.ts +38 -0
- package/lib/schema/types/generic/EnumType.js +96 -0
- package/lib/schema/types/generic/ObjectType.d.ts +2 -1
- package/lib/schema/types/generic/ObjectType.js +4 -0
- package/lib/schema/types/primitives/BooleanType.d.ts +2 -1
- package/lib/schema/types/primitives/BooleanType.js +1 -0
- package/lib/schema/types/primitives/DateType.d.ts +2 -1
- package/lib/schema/types/primitives/DateType.js +1 -0
- package/lib/schema/types/primitives/FloatType.d.ts +2 -1
- package/lib/schema/types/primitives/FloatType.js +1 -0
- package/lib/schema/types/primitives/IntegerType.d.ts +2 -1
- package/lib/schema/types/primitives/IntegerType.js +1 -0
- package/lib/schema/types/primitives/StringType.d.ts +2 -1
- package/lib/schema/types/primitives/StringType.js +1 -0
- package/lib/schema/types/references/GenericArgumentIdentifierType.d.ts +2 -1
- package/lib/schema/types/references/GenericArgumentIdentifierType.js +1 -0
- package/lib/schema/types/references/IncludeIdentifierType.d.ts +5 -3
- package/lib/schema/types/references/IncludeIdentifierType.js +15 -2
- package/lib/schema/types/references/NestedEntityMapType.d.ts +2 -1
- package/lib/schema/types/references/NestedEntityMapType.js +5 -1
- package/lib/schema/types/references/ReferenceIdentifierType.d.ts +2 -1
- package/lib/schema/types/references/ReferenceIdentifierType.js +2 -1
- package/lib/server/api/declarations.d.ts +1 -0
- package/lib/server/api/declarations.js +154 -0
- package/lib/server/api/git.d.ts +1 -0
- package/lib/server/api/git.js +174 -0
- package/lib/server/api/index.d.ts +1 -0
- package/lib/server/api/index.js +8 -0
- package/lib/server/api/instanceOperations.d.ts +6 -0
- package/lib/server/api/instanceOperations.js +82 -0
- package/lib/server/api/instances.d.ts +1 -0
- package/lib/server/api/instances.js +23 -0
- package/lib/server/index.d.ts +22 -1
- package/lib/server/index.js +11 -165
- package/lib/server/init.d.ts +5 -0
- package/lib/server/init.js +56 -0
- package/lib/shared/api.d.ts +12 -1
- package/lib/shared/utils/array.d.ts +19 -0
- package/lib/shared/utils/array.js +27 -0
- package/lib/shared/utils/git.d.ts +12 -0
- package/lib/shared/utils/git.js +98 -0
- package/lib/shared/utils/instances.d.ts +10 -0
- package/lib/shared/utils/instances.js +8 -1
- package/lib/shared/utils/markdown.d.ts +14 -0
- package/lib/shared/utils/markdown.js +42 -0
- package/lib/shared/utils/object.d.ts +1 -0
- package/lib/shared/utils/object.js +4 -0
- package/lib/shared/utils/string.d.ts +1 -0
- package/lib/shared/utils/string.js +9 -0
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/utils/git.d.ts +3 -0
- package/lib/utils/git.js +12 -0
- package/lib/utils/instances.d.ts +3 -2
- package/lib/utils/instances.js +9 -2
- package/lib/utils/path.d.ts +1 -0
- package/lib/utils/path.js +2 -0
- package/lib/utils/references.d.ts +7 -0
- package/lib/utils/references.js +40 -0
- package/lib/utils/render.d.ts +6 -1
- package/lib/utils/render.js +27 -1
- package/package.json +8 -1
- package/public/css/styles.css +200 -1
- package/lib/client/components/typeInputs/utils/EnumDeclField.d.ts +0 -13
- package/lib/server/instanceOperations.d.ts +0 -7
- package/lib/server/instanceOperations.js +0 -67
package/lib/ModelContainer.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import Debug from "debug";
|
|
1
2
|
import { mkdir } from "fs/promises";
|
|
2
3
|
import { join } from "path";
|
|
3
4
|
import { getEntities } from "./Schema.js";
|
|
@@ -6,6 +7,7 @@ import { createServer } from "./server/index.js";
|
|
|
6
7
|
import { parallelizeErrors } from "./shared/utils/validation.js";
|
|
7
8
|
import { getErrorMessageForDisplay, wrapErrorsIfAny } from "./utils/error.js";
|
|
8
9
|
import { getInstancesByEntityName } from "./utils/instances.js";
|
|
10
|
+
const debug = Debug("tsondb:schema");
|
|
9
11
|
export const ModelContainer = (options) => ({
|
|
10
12
|
...options,
|
|
11
13
|
});
|
|
@@ -24,12 +26,12 @@ export const generateOutputs = async (modelContainer) => {
|
|
|
24
26
|
const _validate = async (entities, instancesByEntityName) => {
|
|
25
27
|
const errors = entities.flatMap(entity => parallelizeErrors(instancesByEntityName[entity.name].map(instance => wrapErrorsIfAny(`in file "${entity.name}/${instance.fileName}"`, validateEntityDecl(createValidators(instancesByEntityName), entity, instance.content)))));
|
|
26
28
|
if (errors.length === 0) {
|
|
27
|
-
|
|
29
|
+
debug("All entities are valid");
|
|
28
30
|
}
|
|
29
31
|
else {
|
|
30
|
-
|
|
32
|
+
debug("Errors:\n");
|
|
31
33
|
for (const error of errors) {
|
|
32
|
-
|
|
34
|
+
debug(getErrorMessageForDisplay(error) + "\n");
|
|
33
35
|
}
|
|
34
36
|
throw new Error("Validation failed");
|
|
35
37
|
}
|
|
@@ -37,27 +39,27 @@ const _validate = async (entities, instancesByEntityName) => {
|
|
|
37
39
|
export const validate = async (modelContainer) => {
|
|
38
40
|
const entities = getEntities(modelContainer.schema);
|
|
39
41
|
await prepareFolders(modelContainer, entities);
|
|
40
|
-
const instancesByEntityName = await getInstancesByEntityName(modelContainer, entities);
|
|
42
|
+
const instancesByEntityName = await getInstancesByEntityName(modelContainer.dataRootPath, entities);
|
|
41
43
|
return _validate(entities, instancesByEntityName);
|
|
42
44
|
};
|
|
43
45
|
export const generateAndValidate = async (modelContainer) => {
|
|
44
46
|
await generateOutputs(modelContainer);
|
|
45
47
|
const entities = getEntities(modelContainer.schema);
|
|
46
48
|
await prepareFolders(modelContainer, entities);
|
|
47
|
-
const instancesByEntityName = await getInstancesByEntityName(modelContainer, entities);
|
|
49
|
+
const instancesByEntityName = await getInstancesByEntityName(modelContainer.dataRootPath, entities);
|
|
48
50
|
await _validate(entities, instancesByEntityName);
|
|
49
51
|
};
|
|
50
52
|
export const serve = async (modelContainer) => {
|
|
51
53
|
const entities = getEntities(modelContainer.schema);
|
|
52
54
|
await prepareFolders(modelContainer, entities);
|
|
53
|
-
const instancesByEntityName = await getInstancesByEntityName(modelContainer, entities);
|
|
55
|
+
const instancesByEntityName = await getInstancesByEntityName(modelContainer.dataRootPath, entities);
|
|
54
56
|
createServer(modelContainer, instancesByEntityName);
|
|
55
57
|
};
|
|
56
58
|
export const generateValidateAndServe = async (modelContainer) => {
|
|
57
59
|
await generateOutputs(modelContainer);
|
|
58
60
|
const entities = getEntities(modelContainer.schema);
|
|
59
61
|
await prepareFolders(modelContainer, entities);
|
|
60
|
-
const instancesByEntityName = await getInstancesByEntityName(modelContainer, entities);
|
|
62
|
+
const instancesByEntityName = await getInstancesByEntityName(modelContainer.dataRootPath, entities);
|
|
61
63
|
await _validate(entities, instancesByEntityName);
|
|
62
64
|
createServer(modelContainer, instancesByEntityName);
|
|
63
65
|
};
|
package/lib/client/api.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SerializedEntityDecl } from "../schema/declarations/EntityDecl.js";
|
|
2
|
-
import { CreateInstanceOfEntityResponseBody, DeleteInstanceOfEntityResponseBody, GetAllDeclarationsResponseBody, GetAllInstancesOfEntityResponseBody, GetAllInstancesResponseBody, GetDeclarationResponseBody, GetInstanceOfEntityResponseBody, UpdateInstanceOfEntityResponseBody } from "../shared/api.js";
|
|
2
|
+
import { CreateInstanceOfEntityResponseBody, DeleteInstanceOfEntityResponseBody, GetAllDeclarationsResponseBody, GetAllGitBranchesResponseBody, GetAllInstancesOfEntityResponseBody, GetAllInstancesResponseBody, GetDeclarationResponseBody, GetInstanceOfEntityResponseBody, GitStatusResponseBody, UpdateInstanceOfEntityResponseBody } from "../shared/api.js";
|
|
3
3
|
export declare const getAllDeclarations: (kind?: "Entity" | "Enum" | "TypeAlias") => Promise<GetAllDeclarationsResponseBody>;
|
|
4
4
|
export declare const getAllEntities: () => Promise<GetAllDeclarationsResponseBody<SerializedEntityDecl>>;
|
|
5
5
|
export declare const getEntityByName: (name: string) => Promise<GetDeclarationResponseBody<SerializedEntityDecl>>;
|
|
@@ -9,3 +9,16 @@ export declare const getInstanceByEntityNameAndId: (name: string, id: string) =>
|
|
|
9
9
|
export declare const updateInstanceByEntityNameAndId: (name: string, id: string, content: unknown) => Promise<UpdateInstanceOfEntityResponseBody>;
|
|
10
10
|
export declare const deleteInstanceByEntityNameAndId: (name: string, id: string) => Promise<DeleteInstanceOfEntityResponseBody>;
|
|
11
11
|
export declare const getAllInstances: (locales: string[]) => Promise<GetAllInstancesResponseBody>;
|
|
12
|
+
export declare const getGitStatus: (locales: string[]) => Promise<GitStatusResponseBody>;
|
|
13
|
+
export declare const stageAllFiles: () => Promise<void>;
|
|
14
|
+
export declare const stageAllFilesOfEntity: (entityName: string) => Promise<void>;
|
|
15
|
+
export declare const stageFileOfEntity: (entityName: string, id: string) => Promise<void>;
|
|
16
|
+
export declare const unstageAllFiles: () => Promise<void>;
|
|
17
|
+
export declare const unstageAllFilesOfEntity: (entityName: string) => Promise<void>;
|
|
18
|
+
export declare const unstageFileOfEntity: (entityName: string, id: string) => Promise<void>;
|
|
19
|
+
export declare const commitStagedFiles: (message: string) => Promise<DeleteInstanceOfEntityResponseBody>;
|
|
20
|
+
export declare const pushCommits: () => Promise<DeleteInstanceOfEntityResponseBody>;
|
|
21
|
+
export declare const pullCommits: () => Promise<DeleteInstanceOfEntityResponseBody>;
|
|
22
|
+
export declare const getBranches: () => Promise<GetAllGitBranchesResponseBody>;
|
|
23
|
+
export declare const createBranch: (branchName: string) => Promise<void>;
|
|
24
|
+
export declare const switchBranch: (branchName: string) => Promise<void>;
|
package/lib/client/api.js
CHANGED
|
@@ -81,3 +81,122 @@ export const getAllInstances = async (locales) => {
|
|
|
81
81
|
}
|
|
82
82
|
return response.json();
|
|
83
83
|
};
|
|
84
|
+
export const getGitStatus = async (locales) => {
|
|
85
|
+
const url = new URL("/api/git/status", window.location.origin);
|
|
86
|
+
for (const locale of locales) {
|
|
87
|
+
url.searchParams.append("locales", locale);
|
|
88
|
+
}
|
|
89
|
+
const response = await fetch(url);
|
|
90
|
+
if (!response.ok) {
|
|
91
|
+
throw new Error(await response.text());
|
|
92
|
+
}
|
|
93
|
+
return response.json();
|
|
94
|
+
};
|
|
95
|
+
export const stageAllFiles = async () => {
|
|
96
|
+
const response = await fetch(`/api/git/stage`, {
|
|
97
|
+
method: "POST",
|
|
98
|
+
});
|
|
99
|
+
if (!response.ok) {
|
|
100
|
+
throw new Error(await response.text());
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
export const stageAllFilesOfEntity = async (entityName) => {
|
|
104
|
+
const response = await fetch(`/api/git/stage/${entityName}`, {
|
|
105
|
+
method: "POST",
|
|
106
|
+
});
|
|
107
|
+
if (!response.ok) {
|
|
108
|
+
throw new Error(await response.text());
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
export const stageFileOfEntity = async (entityName, id) => {
|
|
112
|
+
const response = await fetch(`/api/git/stage/${entityName}/${id}`, {
|
|
113
|
+
method: "POST",
|
|
114
|
+
});
|
|
115
|
+
if (!response.ok) {
|
|
116
|
+
throw new Error(await response.text());
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
export const unstageAllFiles = async () => {
|
|
120
|
+
const response = await fetch(`/api/git/unstage`, {
|
|
121
|
+
method: "POST",
|
|
122
|
+
});
|
|
123
|
+
if (!response.ok) {
|
|
124
|
+
throw new Error(await response.text());
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
export const unstageAllFilesOfEntity = async (entityName) => {
|
|
128
|
+
const response = await fetch(`/api/git/unstage/${entityName}`, {
|
|
129
|
+
method: "POST",
|
|
130
|
+
});
|
|
131
|
+
if (!response.ok) {
|
|
132
|
+
throw new Error(await response.text());
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
export const unstageFileOfEntity = async (entityName, id) => {
|
|
136
|
+
const response = await fetch(`/api/git/unstage/${entityName}/${id}`, {
|
|
137
|
+
method: "POST",
|
|
138
|
+
});
|
|
139
|
+
if (!response.ok) {
|
|
140
|
+
throw new Error(await response.text());
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
export const commitStagedFiles = async (message) => {
|
|
144
|
+
const response = await fetch(`/api/git/commit`, {
|
|
145
|
+
method: "POST",
|
|
146
|
+
body: JSON.stringify({ message }),
|
|
147
|
+
headers: {
|
|
148
|
+
"Content-Type": "application/json",
|
|
149
|
+
},
|
|
150
|
+
});
|
|
151
|
+
if (!response.ok) {
|
|
152
|
+
throw new Error(await response.text());
|
|
153
|
+
}
|
|
154
|
+
return response.json();
|
|
155
|
+
};
|
|
156
|
+
export const pushCommits = async () => {
|
|
157
|
+
const response = await fetch(`/api/git/push`, {
|
|
158
|
+
method: "POST",
|
|
159
|
+
});
|
|
160
|
+
if (!response.ok) {
|
|
161
|
+
throw new Error(await response.text());
|
|
162
|
+
}
|
|
163
|
+
return response.json();
|
|
164
|
+
};
|
|
165
|
+
export const pullCommits = async () => {
|
|
166
|
+
const response = await fetch(`/api/git/pull`, {
|
|
167
|
+
method: "POST",
|
|
168
|
+
});
|
|
169
|
+
if (!response.ok) {
|
|
170
|
+
throw new Error(await response.text());
|
|
171
|
+
}
|
|
172
|
+
return response.json();
|
|
173
|
+
};
|
|
174
|
+
export const getBranches = async () => {
|
|
175
|
+
const response = await fetch(`/api/git/branch`, {
|
|
176
|
+
method: "GET",
|
|
177
|
+
});
|
|
178
|
+
if (!response.ok) {
|
|
179
|
+
throw new Error(await response.text());
|
|
180
|
+
}
|
|
181
|
+
return response.json();
|
|
182
|
+
};
|
|
183
|
+
export const createBranch = async (branchName) => {
|
|
184
|
+
const response = await fetch(`/api/git/branch`, {
|
|
185
|
+
method: "POST",
|
|
186
|
+
body: JSON.stringify({ branchName }),
|
|
187
|
+
headers: {
|
|
188
|
+
"Content-Type": "application/json",
|
|
189
|
+
},
|
|
190
|
+
});
|
|
191
|
+
if (!response.ok) {
|
|
192
|
+
throw new Error(await response.text());
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
export const switchBranch = async (branchName) => {
|
|
196
|
+
const response = await fetch(`/api/git/branch/${branchName}`, {
|
|
197
|
+
method: "POST",
|
|
198
|
+
});
|
|
199
|
+
if (!response.ok) {
|
|
200
|
+
throw new Error(await response.text());
|
|
201
|
+
}
|
|
202
|
+
};
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
|
|
2
|
+
import { useEffect, useState } from "preact/hooks";
|
|
3
|
+
import { getGitStatusForDisplay, getLabelForGitStatus, isChangedInIndex, isChangedInWorkingDir, } from "../../shared/utils/git.js";
|
|
4
|
+
import { commitStagedFiles, createBranch, getAllEntities, getBranches, getGitStatus, pullCommits, pushCommits, stageAllFiles, stageFileOfEntity, switchBranch, unstageAllFiles, unstageFileOfEntity, } from "../api.js";
|
|
5
|
+
const filterFilesForDisplay = (predicate, entities, data) => Object.entries(data.instances)
|
|
6
|
+
.map(([entityName, instances]) => [
|
|
7
|
+
entityName,
|
|
8
|
+
entities.find(entity => entity.name === entityName)?.namePlural ?? entityName,
|
|
9
|
+
instances
|
|
10
|
+
.filter(instance => instance.gitStatus !== undefined && predicate(instance.gitStatus))
|
|
11
|
+
.sort((a, b) => a.displayName.localeCompare(b.displayName)),
|
|
12
|
+
])
|
|
13
|
+
.filter(([_1, _2, instances]) => instances.length > 0)
|
|
14
|
+
.sort((a, b) => a[1].localeCompare(b[1]));
|
|
15
|
+
const GitFileList = ({ filesByEntity, onFile, isIndex = false }) => filesByEntity.length === 0 ? (_jsx("p", { class: "no-changes", children: "No changes" })) : (_jsx("ul", { class: "git-entity-list", children: filesByEntity.map(([entityName, entityNamePlural, instances]) => (_jsxs("li", { class: "git-entity-list-item", children: [_jsx("span", { class: "title", children: entityNamePlural }), _jsx("ul", { class: "git-instance-list", children: instances.map(instance => {
|
|
16
|
+
const gitStatusForDisplay = getGitStatusForDisplay(instance.gitStatus);
|
|
17
|
+
return (_jsxs("li", { class: "git-instance-list-item", children: [_jsx("span", { class: "title", children: instance.displayName }), _jsx("span", { class: `git-status git-status--${gitStatusForDisplay}`, title: getLabelForGitStatus(gitStatusForDisplay), children: gitStatusForDisplay }), _jsx("button", { onClick: () => {
|
|
18
|
+
onFile(entityName, instance);
|
|
19
|
+
}, children: isIndex ? "Unstage" : "Stage" })] }, instance.fileName));
|
|
20
|
+
}) })] }, entityName))) }));
|
|
21
|
+
export const Git = () => {
|
|
22
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
23
|
+
const [commitsAhead, setCommitsAhead] = useState(0);
|
|
24
|
+
const [commitsBehind, setCommitsBehind] = useState(0);
|
|
25
|
+
const [commitMessage, setCommitMessage] = useState("");
|
|
26
|
+
const [indexFiles, setIndexFiles] = useState([]);
|
|
27
|
+
const [workingTreeFiles, setWorkingTreeFiles] = useState([]);
|
|
28
|
+
const [entities, setEntities] = useState([]);
|
|
29
|
+
const [allBranches, setAllBranches] = useState([]);
|
|
30
|
+
const [currentBranch, setCurrentBranch] = useState("");
|
|
31
|
+
const updateGitStatus = (localEntities) => Promise.all([getGitStatus(["de-DE"]), getBranches()]).then(([statusData, branchesData]) => {
|
|
32
|
+
setIndexFiles(filterFilesForDisplay(isChangedInIndex, localEntities, statusData));
|
|
33
|
+
setWorkingTreeFiles(filterFilesForDisplay(isChangedInWorkingDir, localEntities, statusData));
|
|
34
|
+
setCommitsAhead(statusData.commitsAhead);
|
|
35
|
+
setCommitsBehind(statusData.commitsBehind);
|
|
36
|
+
setAllBranches(branchesData.allBranches);
|
|
37
|
+
setCurrentBranch(branchesData.currentBranch);
|
|
38
|
+
});
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
getAllEntities().then(async (data) => {
|
|
41
|
+
const entitiesFromServer = data.declarations.map(decl => decl.declaration);
|
|
42
|
+
setEntities(entitiesFromServer);
|
|
43
|
+
return updateGitStatus(entitiesFromServer);
|
|
44
|
+
});
|
|
45
|
+
}, []);
|
|
46
|
+
const stage = (entityName, instance) => {
|
|
47
|
+
stageFileOfEntity(entityName, instance.id).then(() => updateGitStatus(entities));
|
|
48
|
+
};
|
|
49
|
+
const stageAll = () => {
|
|
50
|
+
stageAllFiles().then(() => updateGitStatus(entities));
|
|
51
|
+
};
|
|
52
|
+
const unstage = (entityName, instance) => {
|
|
53
|
+
unstageFileOfEntity(entityName, instance.id).then(() => updateGitStatus(entities));
|
|
54
|
+
};
|
|
55
|
+
const unstageAll = () => {
|
|
56
|
+
unstageAllFiles().then(() => updateGitStatus(entities));
|
|
57
|
+
};
|
|
58
|
+
const commit = () => {
|
|
59
|
+
if (commitMessage.length > 0 &&
|
|
60
|
+
indexFiles.length > 0 &&
|
|
61
|
+
confirm("Do you want to commit all staged files?")) {
|
|
62
|
+
commitStagedFiles(commitMessage).then(() => {
|
|
63
|
+
setCommitMessage("");
|
|
64
|
+
return updateGitStatus(entities);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
const push = () => {
|
|
69
|
+
pushCommits()
|
|
70
|
+
.then(() => {
|
|
71
|
+
alert("Pushed commits successfully");
|
|
72
|
+
return updateGitStatus(entities);
|
|
73
|
+
})
|
|
74
|
+
.catch(error => {
|
|
75
|
+
console.error("Error pushing commits:", error);
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
const pull = () => {
|
|
79
|
+
pullCommits()
|
|
80
|
+
.then(() => {
|
|
81
|
+
alert("Pulled commits successfully");
|
|
82
|
+
return updateGitStatus(entities);
|
|
83
|
+
})
|
|
84
|
+
.catch(error => {
|
|
85
|
+
console.error("Error pulling commits:", error);
|
|
86
|
+
});
|
|
87
|
+
};
|
|
88
|
+
const onCreateBranch = () => {
|
|
89
|
+
const newBranchName = prompt("Enter new branch name:");
|
|
90
|
+
if (!newBranchName) {
|
|
91
|
+
alert("Branch name cannot be empty");
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
if (allBranches.includes(newBranchName)) {
|
|
95
|
+
alert("Branch name already exists");
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
createBranch(newBranchName)
|
|
99
|
+
.then(() => {
|
|
100
|
+
return updateGitStatus(entities);
|
|
101
|
+
})
|
|
102
|
+
.catch(error => {
|
|
103
|
+
alert("Error switching branch: " + error);
|
|
104
|
+
});
|
|
105
|
+
};
|
|
106
|
+
const onSwitchBranch = (event) => {
|
|
107
|
+
switchBranch(event.currentTarget.value)
|
|
108
|
+
.then(() => {
|
|
109
|
+
return updateGitStatus(entities);
|
|
110
|
+
})
|
|
111
|
+
.catch(error => {
|
|
112
|
+
alert("Error switching branch: " + error);
|
|
113
|
+
});
|
|
114
|
+
};
|
|
115
|
+
return (_jsxs("aside", { class: "git", children: [_jsx("h2", { class: "h1-faded", children: "Version Control" }), _jsx("button", { onClick: () => setIsOpen(b => !b), children: "File changes" }), _jsxs("div", { className: `git-overlay ${isOpen ? "git-overlay--open" : ""}`, children: [_jsxs("div", { class: "sync", children: [_jsxs("button", { onClick: push, children: ["Push", commitsAhead > 0 ? ` (${commitsAhead})` : ""] }), _jsxs("button", { onClick: pull, children: ["Pull", commitsBehind > 0 ? ` (${commitsBehind})` : ""] })] }), _jsxs("div", { className: "branch", children: [_jsx("div", { className: "select-wrapper", children: _jsx("select", { value: currentBranch, onInput: onSwitchBranch, children: allBranches.map(branch => (_jsx("option", { value: branch, children: branch }, branch))) }) }), _jsx("button", { onClick: onCreateBranch, children: "New branch" })] }), _jsxs("div", { class: "commit", children: [_jsx("input", { type: "text", value: commitMessage, onInput: event => setCommitMessage(event.currentTarget.value), placeholder: "added X to instance Y, \u2026" }), _jsx("button", { onClick: commit, disabled: commitMessage.length === 0 || indexFiles.length === 0, children: "Commit" })] }), _jsxs("div", { className: "git-section-title", children: [_jsx("h3", { children: "Files to be committed" }), _jsx("button", { onClick: unstageAll, children: "Unstage all" })] }), _jsx(GitFileList, { filesByEntity: indexFiles, isIndex: true, onFile: unstage }), _jsxs("div", { className: "git-section-title", children: [_jsx("h3", { children: "Working tree changes" }), _jsx("button", { onClick: stageAll, children: "Stage all" })] }), _jsx(GitFileList, { filesByEntity: workingTreeFiles, onFile: stage })] })] }));
|
|
116
|
+
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "preact/jsx-runtime";
|
|
2
|
+
import { Git } from "./Git.js";
|
|
2
3
|
export const Layout = ({ breadcrumbs, children }) => {
|
|
3
|
-
return (_jsxs(_Fragment, { children: [_jsx("header", { children: _jsx("nav", { children: _jsx("ol", { children: breadcrumbs.map(({ url, label }) => (_jsx("li", { children: _jsx("a", { href: url, children: label }) }))) }) }) }), _jsx("main", { children: children })] }));
|
|
4
|
+
return (_jsxs(_Fragment, { children: [_jsx("header", { children: _jsx("nav", { children: _jsx("ol", { children: breadcrumbs.map(({ url, label }) => (_jsx("li", { children: _jsx("a", { href: url, children: label }) }))) }) }) }), _jsx(Git, {}), _jsx("main", { children: children })] }));
|
|
4
5
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsxs as _jsxs, jsx as _jsx } from "preact/jsx-runtime";
|
|
2
|
+
import { removeAt } from "../../../shared/utils/array.js";
|
|
2
3
|
import { validateArrayConstraints } from "../../../shared/validation/array.js";
|
|
3
4
|
import { createTypeSkeleton } from "../../utils/typeSkeleton.js";
|
|
4
5
|
import { TypeInput } from "./TypeInput.js";
|
|
@@ -6,5 +7,5 @@ import { ValidationErrors } from "./utils/ValidationErrors.js";
|
|
|
6
7
|
export const ArrayTypeInput = ({ type, value, instanceNamesByEntity, getDeclFromDeclName, onChange, }) => {
|
|
7
8
|
const errors = validateArrayConstraints(type, value);
|
|
8
9
|
const isTuple = typeof type.minItems === "number" && type.minItems === type.maxItems;
|
|
9
|
-
return (_jsxs("div", { class: "field field--container field--array", children: [value.length > 0 && (_jsx("ol", { children: value.map((item, i) => (_jsxs("li", { class: "container-item array-item", children: [isTuple ? null : (_jsxs("div", { className: "container-item-header", children: [_jsxs("div", { className: "container-item-title", children: [i + 1, "."] }), _jsx("button", { class: "destructive", onClick: () => onChange(
|
|
10
|
+
return (_jsxs("div", { class: "field field--container field--array", children: [value.length > 0 && (_jsx("ol", { children: value.map((item, i) => (_jsxs("li", { class: "container-item array-item", children: [isTuple ? null : (_jsxs("div", { className: "container-item-header", children: [_jsxs("div", { className: "container-item-title", children: [i + 1, "."] }), _jsx("button", { class: "destructive", onClick: () => onChange(removeAt(value, i)), disabled: type.minItems !== undefined && value.length <= type.minItems, children: "Delete Item" })] })), _jsx(TypeInput, { type: type.items, value: item, instanceNamesByEntity: instanceNamesByEntity, getDeclFromDeclName: getDeclFromDeclName, onChange: newItem => onChange(value.with(i, newItem)) })] }, i))) })), isTuple ? null : (_jsx("div", { class: "add-item-container", children: _jsx("button", { onClick: () => onChange([...value, createTypeSkeleton(getDeclFromDeclName, type.items)]), disabled: type.maxItems !== undefined && value.length >= type.maxItems, children: "Add Item" }) })), _jsx(ValidationErrors, { errors: errors })] }));
|
|
10
11
|
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { FunctionComponent } from "preact";
|
|
2
|
+
import { SerializedEnumType } from "../../../schema/types/generic/EnumType.js";
|
|
3
|
+
import { InstanceNamesByEntity } from "../../hooks/useInstanceNamesByEntity.js";
|
|
4
|
+
import { GetDeclFromDeclName } from "../../hooks/useSecondaryDeclarations.js";
|
|
5
|
+
type Props = {
|
|
6
|
+
type: SerializedEnumType;
|
|
7
|
+
value: unknown;
|
|
8
|
+
instanceNamesByEntity: InstanceNamesByEntity;
|
|
9
|
+
getDeclFromDeclName: GetDeclFromDeclName;
|
|
10
|
+
onChange: (value: unknown) => void;
|
|
11
|
+
};
|
|
12
|
+
export declare const EnumTypeInput: FunctionComponent<Props>;
|
|
13
|
+
export {};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
|
|
2
|
-
import { discriminatorKey } from "
|
|
3
|
-
import { toTitleCase } from "
|
|
4
|
-
import { createTypeSkeleton } from "
|
|
5
|
-
import { Select } from "
|
|
6
|
-
import { TypeInput } from "
|
|
7
|
-
import { MismatchingTypeError } from "./MismatchingTypeError.js";
|
|
8
|
-
export const
|
|
2
|
+
import { discriminatorKey } from "../../../shared/enum.js";
|
|
3
|
+
import { toTitleCase } from "../../../shared/utils/string.js";
|
|
4
|
+
import { createTypeSkeleton } from "../../utils/typeSkeleton.js";
|
|
5
|
+
import { Select } from "../Select.js";
|
|
6
|
+
import { TypeInput } from "./TypeInput.js";
|
|
7
|
+
import { MismatchingTypeError } from "./utils/MismatchingTypeError.js";
|
|
8
|
+
export const EnumTypeInput = ({ type, value, instanceNamesByEntity, getDeclFromDeclName, onChange, }) => {
|
|
9
9
|
if (typeof value !== "object" ||
|
|
10
10
|
value === null ||
|
|
11
11
|
Array.isArray(value) ||
|
|
@@ -13,11 +13,11 @@ export const EnumDeclField = ({ decl, value, instanceNamesByEntity, getDeclFromD
|
|
|
13
13
|
typeof value[discriminatorKey] !== "string") {
|
|
14
14
|
return _jsx(MismatchingTypeError, { expected: "enumeration value", actual: value });
|
|
15
15
|
}
|
|
16
|
-
const enumValues = Object.keys(
|
|
16
|
+
const enumValues = Object.keys(type.values);
|
|
17
17
|
const activeEnumCase = value[discriminatorKey];
|
|
18
|
-
const caseMember =
|
|
18
|
+
const caseMember = type.values[activeEnumCase];
|
|
19
19
|
return (_jsxs("div", { class: "field field--enum", children: [_jsx(Select, { value: activeEnumCase, onInput: event => {
|
|
20
|
-
const caseMember =
|
|
20
|
+
const caseMember = type.values[event.currentTarget.value];
|
|
21
21
|
if (caseMember?.type == null) {
|
|
22
22
|
onChange({
|
|
23
23
|
[discriminatorKey]: event.currentTarget.value,
|
|
@@ -1,18 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
|
|
2
|
-
import { assertExhaustive } from "../../../shared/utils/typeSafety.js";
|
|
3
2
|
import { TypeInput } from "./TypeInput.js";
|
|
4
|
-
import { EnumDeclField } from "./utils/EnumDeclField.js";
|
|
5
3
|
export const IncludeIdentifierTypeInput = ({ type, value, instanceNamesByEntity, getDeclFromDeclName, onChange, }) => {
|
|
6
4
|
const decl = getDeclFromDeclName(type.reference);
|
|
7
5
|
if (decl === undefined) {
|
|
8
6
|
return (_jsxs("div", { role: "alert", children: ["Unresolved declaration identifier ", _jsx("code", { children: type.reference })] }));
|
|
9
7
|
}
|
|
10
|
-
|
|
11
|
-
case "EnumDecl":
|
|
12
|
-
return (_jsx(EnumDeclField, { decl: decl, value: value, instanceNamesByEntity: instanceNamesByEntity, getDeclFromDeclName: getDeclFromDeclName, onChange: onChange }));
|
|
13
|
-
case "TypeAliasDecl":
|
|
14
|
-
return (_jsx(TypeInput, { type: decl.type, value: value, instanceNamesByEntity: instanceNamesByEntity, getDeclFromDeclName: getDeclFromDeclName, onChange: onChange }));
|
|
15
|
-
default:
|
|
16
|
-
return assertExhaustive(decl);
|
|
17
|
-
}
|
|
8
|
+
return (_jsx(TypeInput, { type: decl.type, value: value, instanceNamesByEntity: instanceNamesByEntity, getDeclFromDeclName: getDeclFromDeclName, onChange: onChange }));
|
|
18
9
|
};
|
|
@@ -3,6 +3,7 @@ import { assertExhaustive } from "../../../shared/utils/typeSafety.js";
|
|
|
3
3
|
import { ArrayTypeInput } from "./ArrayTypeInput.js";
|
|
4
4
|
import { BooleanTypeInput } from "./BooleanTypeInput.js";
|
|
5
5
|
import { DateTypeInput } from "./DateTypeInput.js";
|
|
6
|
+
import { EnumTypeInput } from "./EnumTypeInput.js";
|
|
6
7
|
import { FloatTypeInput } from "./FloatTypeInput.js";
|
|
7
8
|
import { GenericArgumentIdentifierTypeInput } from "./GenericTypeArgumentIdentifierTypeInput.js";
|
|
8
9
|
import { IncludeIdentifierTypeInput } from "./IncludeIdentifierTypeInput.js";
|
|
@@ -81,6 +82,8 @@ export const TypeInput = ({ type, value, instanceNamesByEntity, getDeclFromDeclN
|
|
|
81
82
|
else {
|
|
82
83
|
return _jsx(MismatchingTypeError, { expected: "entity map", actual: value });
|
|
83
84
|
}
|
|
85
|
+
case "EnumType":
|
|
86
|
+
return (_jsx(EnumTypeInput, { type: type, value: value, instanceNamesByEntity: instanceNamesByEntity, getDeclFromDeclName: getDeclFromDeclName, onChange: onChange }));
|
|
84
87
|
default:
|
|
85
88
|
return assertExhaustive(type);
|
|
86
89
|
}
|
|
@@ -1,34 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx } from "preact/jsx-runtime";
|
|
2
|
-
|
|
3
|
-
const italic = /\*(.+?)\*/;
|
|
4
|
-
const boldItalic = /\*\*\*(.+?)\*\*\*/;
|
|
5
|
-
const parseBlockMarkdown = (text) => text.split(/\n{2,}/).map(par => ({ kind: "paragraph", content: parseInlineMarkdown(par) }));
|
|
6
|
-
const parseForPattern = (pattern, kind, text, nextPatterns = []) => {
|
|
7
|
-
const res = pattern.exec(text);
|
|
8
|
-
if (res) {
|
|
9
|
-
const { index } = res;
|
|
10
|
-
const before = text.slice(0, index);
|
|
11
|
-
const after = text.slice(index + res[0].length);
|
|
12
|
-
const inner = res[1];
|
|
13
|
-
const innerNode = nextPatterns.length > 0
|
|
14
|
-
? parseForPattern(nextPatterns[0][1], nextPatterns[0][0], inner, nextPatterns.slice(1))
|
|
15
|
-
: [{ kind, content: [{ kind: "text", content: inner }] }];
|
|
16
|
-
return [
|
|
17
|
-
...(before.length > 0 ? [{ kind: "text", content: before }] : []),
|
|
18
|
-
{ kind, content: innerNode },
|
|
19
|
-
...(after.length > 0 ? parseForPattern(pattern, kind, after) : []),
|
|
20
|
-
];
|
|
21
|
-
}
|
|
22
|
-
else {
|
|
23
|
-
return nextPatterns.length > 0
|
|
24
|
-
? parseForPattern(nextPatterns[0][1], nextPatterns[0][0], text, nextPatterns.slice(1))
|
|
25
|
-
: [{ kind: "text", content: text }];
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
const parseInlineMarkdown = (text) => parseForPattern(boldItalic, "boldItalic", text, [
|
|
29
|
-
["bold", bold],
|
|
30
|
-
["italic", italic],
|
|
31
|
-
]);
|
|
2
|
+
import { parseBlockMarkdown, } from "../../../../shared/utils/markdown.js";
|
|
32
3
|
export const Markdown = ({ string }) => {
|
|
33
4
|
const blocks = parseBlockMarkdown(string);
|
|
34
5
|
return blocks.map((block, i) => _jsx(BlockMarkdown, { node: block }, `md-block-${i}`));
|
|
@@ -49,8 +20,6 @@ const InlineMarkdown = ({ node }) => {
|
|
|
49
20
|
return (_jsx("strong", { children: node.content.map((inline, i) => (_jsx(InlineMarkdown, { node: inline }, i))) }));
|
|
50
21
|
case "italic":
|
|
51
22
|
return (_jsx("em", { children: node.content.map((inline, i) => (_jsx(InlineMarkdown, { node: inline }, i))) }));
|
|
52
|
-
case "boldItalic":
|
|
53
|
-
return (_jsx("strong", { children: _jsx("em", { children: node.content.map((inline, i) => (_jsx(InlineMarkdown, { node: inline }, i))) }) }));
|
|
54
23
|
case "text":
|
|
55
24
|
return node.content;
|
|
56
25
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const useAPIResource: <T, A extends any[]>(apiFn: (...args: A) => Promise<T>, ...args: A) => [T | undefined, () => Promise<void>];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const useMappedAPIResource: <T, A extends any[], U>(apiFn: (...args: A) => Promise<T>, mapFn: (data: T) => U, ...args: A) => [U | undefined, () => Promise<void>];
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { useCallback, useEffect, useState } from "preact/hooks";
|
|
2
|
+
export const useMappedAPIResource = (apiFn, mapFn, ...args) => {
|
|
3
|
+
const [data, setData] = useState();
|
|
4
|
+
const fetchData = () => apiFn(...args)
|
|
5
|
+
.then(result => {
|
|
6
|
+
setData(mapFn(result));
|
|
7
|
+
})
|
|
8
|
+
.catch(err => {
|
|
9
|
+
console.log(err);
|
|
10
|
+
});
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
fetchData();
|
|
13
|
+
}, []);
|
|
14
|
+
const reload = useCallback(() => {
|
|
15
|
+
setData(undefined);
|
|
16
|
+
return fetchData();
|
|
17
|
+
}, [apiFn, ...args]);
|
|
18
|
+
return [data, reload];
|
|
19
|
+
};
|
|
@@ -1,25 +1,18 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
|
|
2
2
|
import { useRoute } from "preact-iso";
|
|
3
|
-
import { useEffect
|
|
3
|
+
import { useEffect } from "preact/hooks";
|
|
4
4
|
import { getDisplayNameFromEntityInstance } from "../../shared/utils/displayName.js";
|
|
5
|
+
import { getGitStatusForDisplay, getLabelForGitStatus } from "../../shared/utils/git.js";
|
|
5
6
|
import { deleteInstanceByEntityNameAndId, getEntityByName, getInstancesByEntityName, } from "../api.js";
|
|
6
7
|
import { Layout } from "../components/Layout.js";
|
|
8
|
+
import { useAPIResource } from "../hooks/useAPIResource.js";
|
|
9
|
+
import { useMappedAPIResource } from "../hooks/useMappedAPIResource.js";
|
|
7
10
|
import { NotFound } from "./NotFound.js";
|
|
8
11
|
export const Entity = () => {
|
|
9
12
|
const { params: { name }, query: { created }, } = useRoute();
|
|
10
|
-
const [entity
|
|
11
|
-
const [instances,
|
|
13
|
+
const [entity] = useAPIResource(getEntityByName, name ?? "");
|
|
14
|
+
const [instances, reloadInstances] = useMappedAPIResource(getInstancesByEntityName, data => data.instances, name ?? "");
|
|
12
15
|
useEffect(() => {
|
|
13
|
-
if (name) {
|
|
14
|
-
Promise.all([getEntityByName(name), getInstancesByEntityName(name)])
|
|
15
|
-
.then(([entityData, instancesData]) => {
|
|
16
|
-
setEntity(entityData);
|
|
17
|
-
setInstances(instancesData.instances);
|
|
18
|
-
})
|
|
19
|
-
.catch(error => {
|
|
20
|
-
console.error("Error fetching entities:", error);
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
16
|
if (created) {
|
|
24
17
|
const instanceElement = document.getElementById(`instance-${created}`);
|
|
25
18
|
if (instanceElement) {
|
|
@@ -33,15 +26,16 @@ export const Entity = () => {
|
|
|
33
26
|
if (!entity || !instances) {
|
|
34
27
|
return (_jsxs("div", { children: [_jsx("h1", { children: name }), _jsx("p", { className: "loading", children: "Loading \u2026" })] }));
|
|
35
28
|
}
|
|
36
|
-
return (_jsxs(Layout, { breadcrumbs: [{ url: "/", label: "Home" }], children: [_jsxs("div", { class: "header-with-btns", children: [_jsx("h1", { children: name }), _jsx("a", { class: "btn btn--primary", href: `/entities/${entity.declaration.name}/instances/create`, children: "Add" })] }), entity.declaration.comment && _jsx("p", { className: "description", children: entity.declaration.comment }), _jsxs("p", { children: [instances.length, " instance", instances.length === 1 ? "" : "s"] }), _jsx("ul", { class: "instances", children: instances.map(instance =>
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
29
|
+
return (_jsxs(Layout, { breadcrumbs: [{ url: "/", label: "Home" }], children: [_jsxs("div", { class: "header-with-btns", children: [_jsx("h1", { children: name }), _jsx("a", { class: "btn btn--primary", href: `/entities/${entity.declaration.name}/instances/create`, children: "Add" })] }), entity.declaration.comment && _jsx("p", { className: "description", children: entity.declaration.comment }), _jsxs("p", { children: [instances.length, " instance", instances.length === 1 ? "" : "s"] }), _jsx("ul", { class: "instances", children: instances.map(instance => {
|
|
30
|
+
const gitStatusForDisplay = getGitStatusForDisplay(instance.gitStatus);
|
|
31
|
+
return (_jsxs("li", { id: `instance-${instance.id}`, class: `instance-item ${created === instance.id ? "instance-item--created" : ""} ${gitStatusForDisplay === undefined ? "" : `git-status--${gitStatusForDisplay}`}`, children: [_jsx("h2", { children: getDisplayNameFromEntityInstance(entity.declaration, instance.content, instance.id) }), _jsx("p", { "aria-hidden": true, class: "id", children: instance.id }), gitStatusForDisplay !== undefined && (_jsx("p", { class: `git-status git-status--${gitStatusForDisplay}`, title: getLabelForGitStatus(gitStatusForDisplay), children: gitStatusForDisplay })), _jsxs("div", { className: "btns", children: [_jsx("a", { href: `/entities/${entity.declaration.name}/instances/${instance.id}`, class: "btn", children: "Edit" }), _jsx("button", { class: "destructive", onClick: () => {
|
|
32
|
+
if (confirm("Are you sure you want to delete this instance?")) {
|
|
33
|
+
deleteInstanceByEntityNameAndId(entity.declaration.name, instance.id)
|
|
34
|
+
.then(() => reloadInstances())
|
|
35
|
+
.catch(error => {
|
|
36
|
+
alert("Error deleting instance:\n\n" + error);
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}, children: "Delete" })] })] }, instance.id));
|
|
40
|
+
}) })] }));
|
|
47
41
|
};
|
|
@@ -1,18 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
|
|
2
|
-
import { useEffect, useState } from "preact/hooks";
|
|
3
2
|
import { toTitleCase } from "../../shared/utils/string.js";
|
|
4
3
|
import { getAllEntities } from "../api.js";
|
|
5
4
|
import { Layout } from "../components/Layout.js";
|
|
5
|
+
import { useMappedAPIResource } from "../hooks/useMappedAPIResource.js";
|
|
6
6
|
export const Home = () => {
|
|
7
|
-
const [entities
|
|
8
|
-
|
|
9
|
-
getAllEntities()
|
|
10
|
-
.then(data => {
|
|
11
|
-
setEntities(data.declarations.sort((a, b) => a.declaration.name.localeCompare(b.declaration.name)));
|
|
12
|
-
})
|
|
13
|
-
.catch(error => {
|
|
14
|
-
console.error("Error fetching entities:", error);
|
|
15
|
-
});
|
|
16
|
-
}, []);
|
|
17
|
-
return (_jsxs(Layout, { breadcrumbs: [{ url: "/", label: "Home" }], children: [_jsx("h1", { children: "Entities" }), _jsx("ul", { class: "entities", children: entities.map(entity => (_jsxs("li", { class: "entity-item", children: [_jsxs("div", { className: "title", children: [_jsx("h2", { children: toTitleCase(entity.declaration.name) }), entity.declaration.comment && _jsx("p", { children: entity.declaration.comment })] }), _jsxs("p", { class: "meta", children: [entity.instanceCount, " instance", entity.instanceCount === 1 ? "" : "s"] }), _jsx("div", { className: "btns", children: _jsx("a", { href: `/entities/${entity.declaration.name}`, class: "btn", children: "View" }) })] }, entity.declaration.name))) })] }));
|
|
7
|
+
const [entities] = useMappedAPIResource(getAllEntities, data => data.declarations.sort((a, b) => a.declaration.name.localeCompare(b.declaration.name)));
|
|
8
|
+
return (_jsxs(Layout, { breadcrumbs: [{ url: "/", label: "Home" }], children: [_jsx("h1", { children: "Entities" }), _jsx("ul", { class: "entities", children: (entities ?? []).map(entity => (_jsxs("li", { class: "entity-item", children: [_jsxs("div", { className: "title", children: [_jsx("h2", { children: toTitleCase(entity.declaration.name) }), entity.declaration.comment && _jsx("p", { children: entity.declaration.comment })] }), _jsxs("p", { class: "meta", children: [entity.instanceCount, " instance", entity.instanceCount === 1 ? "" : "s"] }), _jsx("div", { className: "btns", children: _jsx("a", { href: `/entities/${entity.declaration.name}`, class: "btn", children: "View" }) })] }, entity.declaration.name))) })] }));
|
|
18
9
|
};
|