jazz-tools 0.19.1 → 0.19.3
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/.turbo/turbo-build.log +63 -63
- package/CHANGELOG.md +21 -0
- package/dist/{chunk-NCNM6UDZ.js → chunk-JPWM4CS2.js} +4 -2
- package/dist/{chunk-NCNM6UDZ.js.map → chunk-JPWM4CS2.js.map} +1 -1
- package/dist/index.js +1 -1
- package/dist/inspector/{custom-element-QESCMFY7.js → custom-element-3JAYHXWQ.js} +1134 -464
- package/dist/inspector/custom-element-3JAYHXWQ.js.map +1 -0
- package/dist/inspector/index.js +1104 -434
- package/dist/inspector/index.js.map +1 -1
- package/dist/inspector/register-custom-element.js +1 -1
- package/dist/inspector/tests/utils/history.test.d.ts +2 -0
- package/dist/inspector/tests/utils/history.test.d.ts.map +1 -0
- package/dist/inspector/tests/viewer/co-value-editor.test.d.ts +2 -0
- package/dist/inspector/tests/viewer/co-value-editor.test.d.ts.map +1 -0
- package/dist/inspector/tests/viewer/comap-view.test.d.ts +2 -0
- package/dist/inspector/tests/viewer/comap-view.test.d.ts.map +1 -0
- package/dist/inspector/ui/icon.d.ts +6 -0
- package/dist/inspector/ui/icon.d.ts.map +1 -1
- package/dist/inspector/ui/icons/add-icon.d.ts +2 -0
- package/dist/inspector/ui/icons/add-icon.d.ts.map +1 -0
- package/dist/inspector/ui/icons/edit-icon.d.ts +2 -0
- package/dist/inspector/ui/icons/edit-icon.d.ts.map +1 -0
- package/dist/inspector/ui/icons/history.d.ts +2 -0
- package/dist/inspector/ui/icons/history.d.ts.map +1 -0
- package/dist/inspector/utils/history.d.ts +3 -0
- package/dist/inspector/utils/history.d.ts.map +1 -0
- package/dist/inspector/utils/permissions.d.ts +3 -0
- package/dist/inspector/utils/permissions.d.ts.map +1 -0
- package/dist/inspector/utils/transactions-changes.d.ts +38 -0
- package/dist/inspector/utils/transactions-changes.d.ts.map +1 -0
- package/dist/inspector/viewer/co-map-view.d.ts +9 -0
- package/dist/inspector/viewer/co-map-view.d.ts.map +1 -0
- package/dist/inspector/viewer/co-value-editor.d.ts +10 -0
- package/dist/inspector/viewer/co-value-editor.d.ts.map +1 -0
- package/dist/inspector/viewer/grid-view.d.ts +3 -2
- package/dist/inspector/viewer/grid-view.d.ts.map +1 -1
- package/dist/inspector/viewer/history-view.d.ts.map +1 -1
- package/dist/inspector/viewer/page.d.ts.map +1 -1
- package/dist/testing.js +1 -1
- package/dist/tools/coValues/CoFieldInit.d.ts +2 -1
- package/dist/tools/coValues/CoFieldInit.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/typeConverters/CoFieldSchemaInit.d.ts +3 -2
- package/dist/tools/implementation/zodSchema/typeConverters/CoFieldSchemaInit.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/unionUtils.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/inspector/tests/utils/history.test.ts +401 -0
- package/src/inspector/tests/viewer/co-value-editor.test.tsx +903 -0
- package/src/inspector/tests/viewer/comap-view.test.tsx +889 -0
- package/src/inspector/ui/icon.tsx +6 -0
- package/src/inspector/ui/icons/add-icon.tsx +21 -0
- package/src/inspector/ui/icons/edit-icon.tsx +17 -0
- package/src/inspector/ui/icons/history.tsx +28 -0
- package/src/inspector/ui/modal.tsx +3 -3
- package/src/inspector/utils/history.ts +49 -0
- package/src/inspector/utils/permissions.ts +10 -0
- package/src/inspector/utils/transactions-changes.ts +98 -0
- package/src/inspector/viewer/co-map-view.tsx +324 -0
- package/src/inspector/viewer/co-value-editor.tsx +164 -0
- package/src/inspector/viewer/grid-view.tsx +140 -10
- package/src/inspector/viewer/history-view.tsx +19 -119
- package/src/inspector/viewer/page.tsx +13 -0
- package/src/react-core/tests/usePassPhraseAuth.test.ts +1 -1
- package/src/tools/coValues/CoFieldInit.ts +6 -3
- package/src/tools/implementation/zodSchema/typeConverters/CoFieldSchemaInit.ts +12 -7
- package/src/tools/implementation/zodSchema/unionUtils.ts +3 -4
- package/src/tools/tests/coVector.test.ts +43 -0
- package/dist/inspector/custom-element-QESCMFY7.js.map +0 -1
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { LocalNode, RawCoValue } from "cojson";
|
|
2
|
+
import { JsonValue } from "cojson";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { styled } from "goober";
|
|
5
|
+
import { Button } from "../ui/button.js";
|
|
6
|
+
import { Select } from "../ui/select.js";
|
|
7
|
+
|
|
8
|
+
type ValueType =
|
|
9
|
+
| "number"
|
|
10
|
+
| "string"
|
|
11
|
+
| "true"
|
|
12
|
+
| "false"
|
|
13
|
+
| "object"
|
|
14
|
+
| "null"
|
|
15
|
+
| "undefined";
|
|
16
|
+
|
|
17
|
+
export function CoValueEditor({
|
|
18
|
+
node,
|
|
19
|
+
property,
|
|
20
|
+
value,
|
|
21
|
+
coValue,
|
|
22
|
+
onCancel,
|
|
23
|
+
}: {
|
|
24
|
+
node: LocalNode;
|
|
25
|
+
property: string;
|
|
26
|
+
value: JsonValue | undefined;
|
|
27
|
+
coValue: RawCoValue;
|
|
28
|
+
onCancel: () => void;
|
|
29
|
+
}) {
|
|
30
|
+
const getInitialType = (): ValueType => {
|
|
31
|
+
if (value === null) return "null";
|
|
32
|
+
if (value === undefined) return "undefined";
|
|
33
|
+
if (typeof value === "number") return "number";
|
|
34
|
+
if (typeof value === "string") return "string";
|
|
35
|
+
if (typeof value === "boolean") return value ? "true" : "false";
|
|
36
|
+
if (typeof value === "object") return "object";
|
|
37
|
+
return "undefined";
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const [selectedType, setSelectedType] = useState<ValueType>(getInitialType());
|
|
41
|
+
const [editValue, setEditValue] = useState(
|
|
42
|
+
value === undefined || value === null
|
|
43
|
+
? ""
|
|
44
|
+
: typeof value === "object"
|
|
45
|
+
? JSON.stringify(value, null, 2)
|
|
46
|
+
: String(value),
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
const handleSubmit = (e: React.FormEvent) => {
|
|
50
|
+
e.preventDefault();
|
|
51
|
+
e.stopPropagation();
|
|
52
|
+
|
|
53
|
+
let newValue;
|
|
54
|
+
switch (selectedType) {
|
|
55
|
+
case "null":
|
|
56
|
+
newValue = null;
|
|
57
|
+
break;
|
|
58
|
+
case "undefined":
|
|
59
|
+
newValue = undefined;
|
|
60
|
+
break;
|
|
61
|
+
case "true":
|
|
62
|
+
newValue = true;
|
|
63
|
+
break;
|
|
64
|
+
case "false":
|
|
65
|
+
newValue = false;
|
|
66
|
+
break;
|
|
67
|
+
case "number":
|
|
68
|
+
newValue = parseFloat(editValue);
|
|
69
|
+
break;
|
|
70
|
+
case "string":
|
|
71
|
+
newValue = editValue;
|
|
72
|
+
break;
|
|
73
|
+
case "object":
|
|
74
|
+
newValue = JSON.parse(editValue);
|
|
75
|
+
break;
|
|
76
|
+
default:
|
|
77
|
+
throw new Error(`Invalid type: ${selectedType}`);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
coValue.core.makeTransaction(
|
|
81
|
+
[
|
|
82
|
+
{
|
|
83
|
+
op: "set",
|
|
84
|
+
key: property,
|
|
85
|
+
value: newValue,
|
|
86
|
+
},
|
|
87
|
+
],
|
|
88
|
+
"private",
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
onCancel();
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const showTextarea =
|
|
95
|
+
selectedType === "number" ||
|
|
96
|
+
selectedType === "string" ||
|
|
97
|
+
selectedType === "object";
|
|
98
|
+
|
|
99
|
+
return (
|
|
100
|
+
<EditForm onSubmit={handleSubmit}>
|
|
101
|
+
<Select
|
|
102
|
+
label="Type"
|
|
103
|
+
value={selectedType}
|
|
104
|
+
onChange={(e) => {
|
|
105
|
+
setSelectedType(e.target.value as ValueType);
|
|
106
|
+
}}
|
|
107
|
+
onClick={(e) => e.stopPropagation()}
|
|
108
|
+
>
|
|
109
|
+
<option value="number">number</option>
|
|
110
|
+
<option value="string">string</option>
|
|
111
|
+
<option value="true">true</option>
|
|
112
|
+
<option value="false">false</option>
|
|
113
|
+
<option value="object">object</option>
|
|
114
|
+
<option value="null">null</option>
|
|
115
|
+
<option value="undefined">undefined</option>
|
|
116
|
+
</Select>
|
|
117
|
+
{showTextarea && (
|
|
118
|
+
<StyledTextarea
|
|
119
|
+
value={editValue}
|
|
120
|
+
onChange={(e) => setEditValue(e.target.value)}
|
|
121
|
+
onClick={(e) => e.stopPropagation()}
|
|
122
|
+
/>
|
|
123
|
+
)}
|
|
124
|
+
<FormActions>
|
|
125
|
+
<Button type="button" variant="secondary" onClick={onCancel}>
|
|
126
|
+
Cancel
|
|
127
|
+
</Button>
|
|
128
|
+
<Button type="submit" variant="primary">
|
|
129
|
+
Submit
|
|
130
|
+
</Button>
|
|
131
|
+
</FormActions>
|
|
132
|
+
</EditForm>
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const EditForm = styled("form")`
|
|
137
|
+
display: flex;
|
|
138
|
+
flex-direction: column;
|
|
139
|
+
gap: 0.75rem;
|
|
140
|
+
`;
|
|
141
|
+
|
|
142
|
+
const StyledTextarea = styled("textarea")`
|
|
143
|
+
width: 100%;
|
|
144
|
+
min-height: 120px;
|
|
145
|
+
border-radius: var(--j-radius-md);
|
|
146
|
+
border: 1px solid var(--j-border-color);
|
|
147
|
+
padding: 0.5rem 0.875rem;
|
|
148
|
+
box-shadow: var(--j-shadow-sm);
|
|
149
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
|
150
|
+
font-size: 0.875rem;
|
|
151
|
+
background-color: white;
|
|
152
|
+
color: var(--j-text-color-strong);
|
|
153
|
+
resize: vertical;
|
|
154
|
+
|
|
155
|
+
@media (prefers-color-scheme: dark) {
|
|
156
|
+
background-color: var(--j-foreground);
|
|
157
|
+
}
|
|
158
|
+
`;
|
|
159
|
+
|
|
160
|
+
const FormActions = styled("div")`
|
|
161
|
+
display: flex;
|
|
162
|
+
gap: 0.5rem;
|
|
163
|
+
justify-content: flex-end;
|
|
164
|
+
`;
|
|
@@ -1,27 +1,94 @@
|
|
|
1
1
|
import { CoID, LocalNode, RawCoValue } from "cojson";
|
|
2
2
|
import { JsonObject, JsonValue } from "cojson";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { styled } from "goober";
|
|
3
5
|
import { ResolveIcon } from "./type-icon.js";
|
|
4
6
|
import { PageInfo, isCoId } from "./types.js";
|
|
5
7
|
import { CoMapPreview, ValueRenderer } from "./value-renderer.js";
|
|
8
|
+
import { CoValueEditor } from "./co-value-editor.js";
|
|
6
9
|
|
|
7
10
|
import { Badge } from "../ui/badge.js";
|
|
8
11
|
import { Card, CardBody, CardHeader } from "../ui/card.js";
|
|
9
12
|
import { Grid } from "../ui/grid.js";
|
|
13
|
+
import { Icon } from "../ui/icon.js";
|
|
10
14
|
import { Text } from "../ui/text.js";
|
|
15
|
+
import { isWriter } from "../utils/permissions.js";
|
|
11
16
|
|
|
12
17
|
function GridItem({
|
|
13
18
|
entry,
|
|
14
19
|
onNavigate,
|
|
15
20
|
node,
|
|
21
|
+
coValue,
|
|
16
22
|
}: {
|
|
17
23
|
entry: [string, JsonValue | undefined];
|
|
18
24
|
onNavigate: (pages: PageInfo[]) => void;
|
|
19
25
|
node: LocalNode;
|
|
26
|
+
coValue?: RawCoValue;
|
|
20
27
|
}) {
|
|
21
28
|
const [key, value] = entry;
|
|
22
29
|
const isCoValue = isCoId(value);
|
|
30
|
+
const [isEditing, setIsEditing] = useState(false);
|
|
23
31
|
|
|
24
|
-
const
|
|
32
|
+
const handleEditClick = (e: React.MouseEvent) => {
|
|
33
|
+
e.stopPropagation();
|
|
34
|
+
setIsEditing(true);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const handleCancel = () => {
|
|
38
|
+
setIsEditing(false);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const handleDelete = (e: React.MouseEvent) => {
|
|
42
|
+
e.stopPropagation();
|
|
43
|
+
if (confirm(`Are you sure you want to delete the property "${key}"?`)) {
|
|
44
|
+
coValue?.core.makeTransaction(
|
|
45
|
+
[
|
|
46
|
+
{
|
|
47
|
+
op: "del",
|
|
48
|
+
key,
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
"private",
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
if (isEditing) {
|
|
57
|
+
return (
|
|
58
|
+
<Card
|
|
59
|
+
style={{
|
|
60
|
+
backgroundColor: "var(--j-foreground)",
|
|
61
|
+
borderColor: "var(--j-foreground)",
|
|
62
|
+
}}
|
|
63
|
+
>
|
|
64
|
+
<CardHeader>
|
|
65
|
+
<div style={{ display: "flex", alignItems: "center", gap: "0.5rem" }}>
|
|
66
|
+
{isCoValue ? (
|
|
67
|
+
<>
|
|
68
|
+
<Text strong>{key}</Text>
|
|
69
|
+
<Badge>
|
|
70
|
+
<ResolveIcon coId={value as CoID<RawCoValue>} node={node} />
|
|
71
|
+
</Badge>
|
|
72
|
+
</>
|
|
73
|
+
) : (
|
|
74
|
+
<Text strong>{key}</Text>
|
|
75
|
+
)}
|
|
76
|
+
</div>
|
|
77
|
+
</CardHeader>
|
|
78
|
+
<CardBody style={{ wordBreak: "break-word" }}>
|
|
79
|
+
<CoValueEditor
|
|
80
|
+
node={node}
|
|
81
|
+
property={key}
|
|
82
|
+
value={value}
|
|
83
|
+
coValue={coValue!}
|
|
84
|
+
onCancel={handleCancel}
|
|
85
|
+
/>
|
|
86
|
+
</CardBody>
|
|
87
|
+
</Card>
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const cardProps = isCoValue
|
|
25
92
|
? {
|
|
26
93
|
onClick: () =>
|
|
27
94
|
onNavigate([{ coId: value as CoID<RawCoValue>, name: key }]),
|
|
@@ -35,17 +102,37 @@ function GridItem({
|
|
|
35
102
|
};
|
|
36
103
|
|
|
37
104
|
return (
|
|
38
|
-
<Card {...
|
|
105
|
+
<Card {...cardProps}>
|
|
39
106
|
<CardHeader>
|
|
40
|
-
{
|
|
41
|
-
|
|
107
|
+
<div style={{ display: "flex", alignItems: "center", gap: "0.5rem" }}>
|
|
108
|
+
{isCoValue ? (
|
|
109
|
+
<>
|
|
110
|
+
<Text strong>{key}</Text>
|
|
111
|
+
<Badge>
|
|
112
|
+
<ResolveIcon coId={value as CoID<RawCoValue>} node={node} />
|
|
113
|
+
</Badge>
|
|
114
|
+
</>
|
|
115
|
+
) : (
|
|
42
116
|
<Text strong>{key}</Text>
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
117
|
+
)}
|
|
118
|
+
</div>
|
|
119
|
+
{coValue && isWriter(coValue.group.myRole()) && (
|
|
120
|
+
<ActionButtons>
|
|
121
|
+
<EditButton
|
|
122
|
+
onClick={handleEditClick}
|
|
123
|
+
type="button"
|
|
124
|
+
aria-label="Edit"
|
|
125
|
+
>
|
|
126
|
+
<Icon name="edit" size="sm" />
|
|
127
|
+
</EditButton>
|
|
128
|
+
<DeleteButton
|
|
129
|
+
onClick={handleDelete}
|
|
130
|
+
type="button"
|
|
131
|
+
aria-label="Delete"
|
|
132
|
+
>
|
|
133
|
+
<Icon name="delete" size="sm" />
|
|
134
|
+
</DeleteButton>
|
|
135
|
+
</ActionButtons>
|
|
49
136
|
)}
|
|
50
137
|
</CardHeader>
|
|
51
138
|
<CardBody style={{ wordBreak: "break-word" }}>
|
|
@@ -68,10 +155,12 @@ export function GridView({
|
|
|
68
155
|
data,
|
|
69
156
|
onNavigate,
|
|
70
157
|
node,
|
|
158
|
+
coValue,
|
|
71
159
|
}: {
|
|
72
160
|
data: JsonObject;
|
|
73
161
|
onNavigate: (pages: PageInfo[]) => void;
|
|
74
162
|
node: LocalNode;
|
|
163
|
+
coValue?: RawCoValue;
|
|
75
164
|
}) {
|
|
76
165
|
const entries = Object.entries(data);
|
|
77
166
|
|
|
@@ -82,9 +171,50 @@ export function GridView({
|
|
|
82
171
|
entry={entry}
|
|
83
172
|
onNavigate={onNavigate}
|
|
84
173
|
node={node}
|
|
174
|
+
coValue={coValue}
|
|
85
175
|
key={childIndex}
|
|
86
176
|
/>
|
|
87
177
|
))}
|
|
88
178
|
</Grid>
|
|
89
179
|
);
|
|
90
180
|
}
|
|
181
|
+
|
|
182
|
+
const EditButton = styled("button")`
|
|
183
|
+
display: inline-flex;
|
|
184
|
+
align-items: center;
|
|
185
|
+
justify-content: center;
|
|
186
|
+
padding: 0.25rem;
|
|
187
|
+
border: none;
|
|
188
|
+
background: transparent;
|
|
189
|
+
cursor: pointer;
|
|
190
|
+
color: var(--j-text-color);
|
|
191
|
+
border-radius: var(--j-radius-sm);
|
|
192
|
+
transition: background-color 0.2s;
|
|
193
|
+
|
|
194
|
+
&:hover {
|
|
195
|
+
background-color: var(--j-foreground);
|
|
196
|
+
}
|
|
197
|
+
`;
|
|
198
|
+
|
|
199
|
+
const DeleteButton = styled("button")`
|
|
200
|
+
display: inline-flex;
|
|
201
|
+
align-items: center;
|
|
202
|
+
justify-content: center;
|
|
203
|
+
padding: 0.25rem;
|
|
204
|
+
border: none;
|
|
205
|
+
background: transparent;
|
|
206
|
+
cursor: pointer;
|
|
207
|
+
color: var(--j-text-color);
|
|
208
|
+
border-radius: var(--j-radius-sm);
|
|
209
|
+
transition: background-color 0.2s;
|
|
210
|
+
|
|
211
|
+
&:hover {
|
|
212
|
+
background-color: var(--j-foreground);
|
|
213
|
+
}
|
|
214
|
+
`;
|
|
215
|
+
|
|
216
|
+
const ActionButtons = styled("div")`
|
|
217
|
+
display: flex;
|
|
218
|
+
align-items: center;
|
|
219
|
+
gap: 0.25rem;
|
|
220
|
+
`;
|
|
@@ -1,29 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
AccountRole,
|
|
3
|
-
BinaryStreamStart,
|
|
4
|
-
CoID,
|
|
5
|
-
JsonValue,
|
|
6
|
-
LocalNode,
|
|
7
|
-
OpID,
|
|
8
|
-
RawCoValue,
|
|
9
|
-
Role,
|
|
10
|
-
} from "cojson";
|
|
1
|
+
import { CoID, JsonValue, LocalNode, OpID, RawCoValue } from "cojson";
|
|
11
2
|
import { useMemo } from "react";
|
|
12
3
|
import { styled } from "goober";
|
|
13
|
-
import { isCoId } from "./types";
|
|
14
4
|
import { AccountOrGroupText } from "./account-or-group-text";
|
|
15
5
|
import { DataTable, ColumnDef } from "../ui/data-table";
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
DeletionOpPayload,
|
|
19
|
-
InsertionOpPayload,
|
|
20
|
-
} from "cojson/dist/coValues/coList.js";
|
|
21
|
-
import {
|
|
22
|
-
BinaryStreamChunk,
|
|
23
|
-
BinaryStreamEnd,
|
|
24
|
-
} from "cojson/dist/coValues/coStream.js";
|
|
25
|
-
import { VerifiedTransaction } from "cojson/dist/coValueCore/coValueCore.js";
|
|
6
|
+
import type { VerifiedTransaction } from "cojson/dist/coValueCore/coValueCore.js";
|
|
26
7
|
import { Icon, Accordion } from "../ui";
|
|
8
|
+
import * as TransactionChanges from "../utils/transactions-changes";
|
|
27
9
|
|
|
28
10
|
type HistoryEntry = {
|
|
29
11
|
id: string;
|
|
@@ -133,7 +115,9 @@ function getTransactionChanges(
|
|
|
133
115
|
if (tx.isValid === false && tx.tx.privacy === "private") {
|
|
134
116
|
const readKey = coValue.core.getReadKey(tx.tx.keyUsed);
|
|
135
117
|
if (!readKey) {
|
|
136
|
-
|
|
118
|
+
return [
|
|
119
|
+
`Unable to decrypt transaction: read key ${tx.tx.keyUsed} not found.`,
|
|
120
|
+
];
|
|
137
121
|
}
|
|
138
122
|
|
|
139
123
|
return (
|
|
@@ -168,7 +152,7 @@ function mapTransactionToAction(
|
|
|
168
152
|
coValue: RawCoValue,
|
|
169
153
|
): string {
|
|
170
154
|
// Group changes
|
|
171
|
-
if (isUserPromotion(change)) {
|
|
155
|
+
if (TransactionChanges.isUserPromotion(change)) {
|
|
172
156
|
if (change.value === "revoked") {
|
|
173
157
|
return `${change.key} has been revoked`;
|
|
174
158
|
}
|
|
@@ -176,28 +160,28 @@ function mapTransactionToAction(
|
|
|
176
160
|
return `${change.key} has been promoted to ${change.value}`;
|
|
177
161
|
}
|
|
178
162
|
|
|
179
|
-
if (isGroupExtension(change)) {
|
|
163
|
+
if (TransactionChanges.isGroupExtension(change)) {
|
|
180
164
|
const child = change.key.slice(6);
|
|
181
165
|
return `Group became a member of ${child}`;
|
|
182
166
|
}
|
|
183
167
|
|
|
184
|
-
if (isGroupExtendRevocation(change)) {
|
|
168
|
+
if (TransactionChanges.isGroupExtendRevocation(change)) {
|
|
185
169
|
const child = change.key.slice(6);
|
|
186
170
|
return `Group's membership of ${child} has been revoked.`;
|
|
187
171
|
}
|
|
188
172
|
|
|
189
|
-
if (isGroupPromotion(change)) {
|
|
173
|
+
if (TransactionChanges.isGroupPromotion(change)) {
|
|
190
174
|
const parent = change.key.slice(7);
|
|
191
175
|
return `Group ${parent} has been promoted to ${change.value}`;
|
|
192
176
|
}
|
|
193
177
|
|
|
194
|
-
if (isKeyRevelation(change)) {
|
|
178
|
+
if (TransactionChanges.isKeyRevelation(change)) {
|
|
195
179
|
const [key, target] = change.key.split("_for_");
|
|
196
180
|
return `Key "${key}" has been revealed to "${target}"`;
|
|
197
181
|
}
|
|
198
182
|
|
|
199
183
|
// coList changes
|
|
200
|
-
if (isItemAppend(change)) {
|
|
184
|
+
if (TransactionChanges.isItemAppend(change)) {
|
|
201
185
|
if (change.after === "start") {
|
|
202
186
|
return `"${change.value}" has been appended`;
|
|
203
187
|
}
|
|
@@ -211,7 +195,7 @@ function mapTransactionToAction(
|
|
|
211
195
|
return `"${change.value}" has been inserted after "${(after as any).value}"`;
|
|
212
196
|
}
|
|
213
197
|
|
|
214
|
-
if (isItemPrepend(change)) {
|
|
198
|
+
if (TransactionChanges.isItemPrepend(change)) {
|
|
215
199
|
if (change.before === "end") {
|
|
216
200
|
return `"${change.value}" has been prepended`;
|
|
217
201
|
}
|
|
@@ -225,7 +209,7 @@ function mapTransactionToAction(
|
|
|
225
209
|
return `"${change.value}" has been inserted before "${(before as any).value}"`;
|
|
226
210
|
}
|
|
227
211
|
|
|
228
|
-
if (isItemDeletion(change)) {
|
|
212
|
+
if (TransactionChanges.isItemDeletion(change)) {
|
|
229
213
|
const insertion = findListChange(change.insertion, coValue);
|
|
230
214
|
if (insertion === undefined) {
|
|
231
215
|
return `An undefined item has been deleted`;
|
|
@@ -235,24 +219,24 @@ function mapTransactionToAction(
|
|
|
235
219
|
}
|
|
236
220
|
|
|
237
221
|
// coStream changes
|
|
238
|
-
if (isStreamStart(change)) {
|
|
222
|
+
if (TransactionChanges.isStreamStart(change)) {
|
|
239
223
|
return `Stream started with mime type "${change.mimeType}" and file name "${change.fileName}"`;
|
|
240
224
|
}
|
|
241
225
|
|
|
242
|
-
if (isStreamChunk(change)) {
|
|
226
|
+
if (TransactionChanges.isStreamChunk(change)) {
|
|
243
227
|
return `Stream chunk added`;
|
|
244
228
|
}
|
|
245
229
|
|
|
246
|
-
if (isStreamEnd(change)) {
|
|
230
|
+
if (TransactionChanges.isStreamEnd(change)) {
|
|
247
231
|
return `Stream ended`;
|
|
248
232
|
}
|
|
249
233
|
|
|
250
234
|
// coMap changes
|
|
251
|
-
if (isPropertySet(change)) {
|
|
235
|
+
if (TransactionChanges.isPropertySet(change)) {
|
|
252
236
|
return `Property "${change.key}" has been set to ${JSON.stringify(change.value)}`;
|
|
253
237
|
}
|
|
254
238
|
|
|
255
|
-
if (isPropertyDeletion(change)) {
|
|
239
|
+
if (TransactionChanges.isPropertyDeletion(change)) {
|
|
256
240
|
return `Property "${change.key}" has been deleted`;
|
|
257
241
|
}
|
|
258
242
|
|
|
@@ -269,90 +253,6 @@ const findListChange = (
|
|
|
269
253
|
)?.changes?.[opId.changeIdx];
|
|
270
254
|
};
|
|
271
255
|
|
|
272
|
-
const isGroupExtension = (
|
|
273
|
-
change: any,
|
|
274
|
-
): change is Extract<
|
|
275
|
-
MapOpPayload<`child_${string}`, "extend">,
|
|
276
|
-
{ op: "set" }
|
|
277
|
-
> => {
|
|
278
|
-
return change?.op === "set" && change?.value === "extend";
|
|
279
|
-
};
|
|
280
|
-
|
|
281
|
-
const isGroupExtendRevocation = (
|
|
282
|
-
change: any,
|
|
283
|
-
): change is Extract<
|
|
284
|
-
MapOpPayload<`child_${string}`, "revoked">,
|
|
285
|
-
{ op: "set" }
|
|
286
|
-
> => {
|
|
287
|
-
return change?.op === "set" && change?.value === "revoked";
|
|
288
|
-
};
|
|
289
|
-
|
|
290
|
-
const isGroupPromotion = (
|
|
291
|
-
change: any,
|
|
292
|
-
): change is Extract<
|
|
293
|
-
MapOpPayload<`parent_co_${string}`, AccountRole>,
|
|
294
|
-
{ op: "set" }
|
|
295
|
-
> => {
|
|
296
|
-
return change?.op === "set" && change?.key.startsWith("parent_co_");
|
|
297
|
-
};
|
|
298
|
-
|
|
299
|
-
const isUserPromotion = (
|
|
300
|
-
change: any,
|
|
301
|
-
): change is Extract<MapOpPayload<CoID<RawCoValue>, Role>, { op: "set" }> => {
|
|
302
|
-
return (
|
|
303
|
-
change?.op === "set" && (isCoId(change?.key) || change?.key === "everyone")
|
|
304
|
-
);
|
|
305
|
-
};
|
|
306
|
-
|
|
307
|
-
const isKeyRevelation = (
|
|
308
|
-
change: any,
|
|
309
|
-
): change is Extract<
|
|
310
|
-
MapOpPayload<`${string}_for_${string}`, string>,
|
|
311
|
-
{ op: "set" }
|
|
312
|
-
> => {
|
|
313
|
-
return change?.op === "set" && change?.key.includes("_for_");
|
|
314
|
-
};
|
|
315
|
-
|
|
316
|
-
const isPropertySet = (
|
|
317
|
-
change: any,
|
|
318
|
-
): change is Extract<MapOpPayload<string, any>, { op: "set" }> => {
|
|
319
|
-
return change?.op === "set" && "key" in change && "value" in change;
|
|
320
|
-
};
|
|
321
|
-
const isPropertyDeletion = (
|
|
322
|
-
change: any,
|
|
323
|
-
): change is Extract<MapOpPayload<string, any>, { op: "del" }> => {
|
|
324
|
-
return change?.op === "del" && "key" in change;
|
|
325
|
-
};
|
|
326
|
-
|
|
327
|
-
const isItemAppend = (
|
|
328
|
-
change: any,
|
|
329
|
-
): change is Extract<InsertionOpPayload<any>, { op: "app" }> => {
|
|
330
|
-
return change?.op === "app" && "after" in change && "value" in change;
|
|
331
|
-
};
|
|
332
|
-
const isItemPrepend = (
|
|
333
|
-
change: any,
|
|
334
|
-
): change is Extract<InsertionOpPayload<any>, { op: "pre" }> => {
|
|
335
|
-
return change?.op === "pre" && "before" in change && "value" in change;
|
|
336
|
-
};
|
|
337
|
-
|
|
338
|
-
const isItemDeletion = (
|
|
339
|
-
change: any,
|
|
340
|
-
): change is Extract<DeletionOpPayload, { op: "del" }> => {
|
|
341
|
-
return change?.op === "del" && "insertion" in change;
|
|
342
|
-
};
|
|
343
|
-
|
|
344
|
-
const isStreamStart = (change: any): change is BinaryStreamStart => {
|
|
345
|
-
return change?.type === "start" && "mimeType" in change;
|
|
346
|
-
};
|
|
347
|
-
|
|
348
|
-
const isStreamChunk = (change: any): change is BinaryStreamChunk => {
|
|
349
|
-
return change?.type === "chunk" && "chunk" in change;
|
|
350
|
-
};
|
|
351
|
-
|
|
352
|
-
const isStreamEnd = (change: any): change is BinaryStreamEnd => {
|
|
353
|
-
return change?.type === "end";
|
|
354
|
-
};
|
|
355
|
-
|
|
356
256
|
const RedTooltip = styled("span")`
|
|
357
257
|
position:relative; /* making the .tooltip span a container for the tooltip text */
|
|
358
258
|
border-bottom:1px dashed #000; /* little indicater to indicate it's hoverable */
|
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
CoID,
|
|
3
3
|
LocalNode,
|
|
4
4
|
RawCoList,
|
|
5
|
+
RawCoMap,
|
|
5
6
|
RawCoStream,
|
|
6
7
|
RawCoValue,
|
|
7
8
|
RawGroup,
|
|
@@ -23,6 +24,7 @@ import { TypeIcon } from "./type-icon.js";
|
|
|
23
24
|
import { PageInfo } from "./types.js";
|
|
24
25
|
import { resolveCoValue, useResolvedCoValue } from "./use-resolve-covalue.js";
|
|
25
26
|
import { HistoryView } from "./history-view.js";
|
|
27
|
+
import { CoMapView } from "./co-map-view.js";
|
|
26
28
|
|
|
27
29
|
interface PageContainerProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
28
30
|
isTopLevel?: boolean;
|
|
@@ -165,6 +167,17 @@ function View(
|
|
|
165
167
|
return <TableView data={snapshot} node={node} onNavigate={onNavigate} />;
|
|
166
168
|
}
|
|
167
169
|
|
|
170
|
+
if (type === "comap") {
|
|
171
|
+
return (
|
|
172
|
+
<CoMapView
|
|
173
|
+
coValue={value as RawCoMap}
|
|
174
|
+
data={snapshot}
|
|
175
|
+
node={node}
|
|
176
|
+
onNavigate={onNavigate}
|
|
177
|
+
/>
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
|
|
168
181
|
return <GridView data={snapshot} onNavigate={onNavigate} node={node} />;
|
|
169
182
|
}
|
|
170
183
|
|
|
@@ -3,6 +3,7 @@ import { CoList } from "./coList.js";
|
|
|
3
3
|
import { CoMap, CoMapInit } from "./coMap.js";
|
|
4
4
|
import { CoPlainText } from "./coPlainText.js";
|
|
5
5
|
import { CoRichText } from "./coRichText.js";
|
|
6
|
+
import { CoVector } from "./coVector.js";
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Returns the type of values that can be used to initialize a field of the provided type.
|
|
@@ -15,6 +16,8 @@ export type CoFieldInit<V> = V extends CoMap
|
|
|
15
16
|
? V | CoMapInit<V>
|
|
16
17
|
: V extends CoList<infer T> | CoFeed<infer T>
|
|
17
18
|
? V | ReadonlyArray<CoFieldInit<T>>
|
|
18
|
-
: V extends
|
|
19
|
-
? V |
|
|
20
|
-
: V
|
|
19
|
+
: V extends CoVector | Readonly<CoVector>
|
|
20
|
+
? V | ReadonlyArray<number> | Float32Array
|
|
21
|
+
: V extends CoPlainText | CoRichText
|
|
22
|
+
? V | string
|
|
23
|
+
: V;
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
CoreCoListSchema,
|
|
6
6
|
CoreCoMapSchema,
|
|
7
7
|
CoreCoRecordSchema,
|
|
8
|
+
CoreCoVectorSchema,
|
|
8
9
|
CorePlainTextSchema,
|
|
9
10
|
Simplify,
|
|
10
11
|
} from "../../../internal.js";
|
|
@@ -33,13 +34,15 @@ export type CoFieldSchemaInit<S extends CoValueClass | AnyZodOrCoValueSchema> =
|
|
|
33
34
|
? CoListSchemaInit<T>
|
|
34
35
|
: S extends CoreCoFeedSchema<infer T>
|
|
35
36
|
? CoFeedSchemaInit<T>
|
|
36
|
-
: S extends
|
|
37
|
-
?
|
|
38
|
-
: S extends
|
|
39
|
-
?
|
|
40
|
-
: S extends
|
|
41
|
-
? CoFieldSchemaInit<
|
|
42
|
-
:
|
|
37
|
+
: S extends CoreCoVectorSchema
|
|
38
|
+
? CoVectorSchemaInit
|
|
39
|
+
: S extends CorePlainTextSchema | CoreRichTextSchema
|
|
40
|
+
? string
|
|
41
|
+
: S extends CoreCoOptionalSchema<infer T>
|
|
42
|
+
? CoFieldSchemaInit<T> | undefined
|
|
43
|
+
: S extends CoDiscriminatedUnionSchema<infer Members>
|
|
44
|
+
? CoFieldSchemaInit<Members[number]>
|
|
45
|
+
: never)
|
|
43
46
|
: S extends z.core.$ZodType
|
|
44
47
|
? TypeOfZodSchema<S>
|
|
45
48
|
: S extends CoValueClass
|
|
@@ -76,6 +79,8 @@ export type CoFeedSchemaInit<T extends AnyZodOrCoValueSchema> = Simplify<
|
|
|
76
79
|
ReadonlyArray<CoFieldSchemaInit<T>>
|
|
77
80
|
>;
|
|
78
81
|
|
|
82
|
+
export type CoVectorSchemaInit = ReadonlyArray<number> | Float32Array;
|
|
83
|
+
|
|
79
84
|
/**
|
|
80
85
|
* The convenience type for extracting the init type of a CoValue schema.
|
|
81
86
|
*/
|