@cytario/web 2.2.6 → 2.2.7
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/app/components/GlobalSearch/SearchBar.tsx +1 -0
- package/app/routes/admin/bulkInvite/bulkInvite.form.tsx +27 -9
- package/app/routes/admin/createGroup/createGroup.form.tsx +16 -20
- package/app/routes/admin/inviteUser/inviteUser.form.tsx +50 -53
- package/app/routes/admin/updateUser/updateUser.form.tsx +45 -49
- package/app/routes/connections/connection.form.tsx +119 -145
- package/package.json +4 -4
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Button, Checkbox,
|
|
1
|
+
import { Button, Checkbox, Icon, IconButton, Input, Select } from "@cytario/design";
|
|
2
2
|
import { Plus, X } from "lucide-react";
|
|
3
3
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
4
4
|
import { useSubmit } from "react-router";
|
|
@@ -150,9 +150,10 @@ export function BulkInviteForm({
|
|
|
150
150
|
renderItem={(item) => <ScopePill scope={item.id} />}
|
|
151
151
|
/>
|
|
152
152
|
) : (
|
|
153
|
-
<
|
|
153
|
+
<div className="flex flex-col gap-1">
|
|
154
|
+
<p className="text-sm font-medium text-(--color-text-primary)">Group Membership</p>
|
|
154
155
|
<p className="text-sm text-slate-400">No groups available in this scope.</p>
|
|
155
|
-
</
|
|
156
|
+
</div>
|
|
156
157
|
)}
|
|
157
158
|
<div className="flex items-center gap-2">
|
|
158
159
|
<Checkbox isSelected={enabled} onChange={setEnabled}>
|
|
@@ -164,16 +165,30 @@ export function BulkInviteForm({
|
|
|
164
165
|
</div>
|
|
165
166
|
</div>
|
|
166
167
|
|
|
167
|
-
{formError &&
|
|
168
|
+
{formError && (
|
|
169
|
+
<p role="alert" className="text-sm text-rose-600 mb-4">
|
|
170
|
+
{formError}
|
|
171
|
+
</p>
|
|
172
|
+
)}
|
|
168
173
|
|
|
169
174
|
<table ref={tableRef} className="w-full border-collapse">
|
|
170
175
|
<thead>
|
|
171
176
|
<tr className="text-left text-sm text-slate-500">
|
|
172
|
-
<th className="w-10 pr-2 py-2 font-medium"
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
<th className="px-1 py-2 font-medium">
|
|
176
|
-
|
|
177
|
+
<th scope="col" className="w-10 pr-2 py-2 font-medium">
|
|
178
|
+
#
|
|
179
|
+
</th>
|
|
180
|
+
<th scope="col" className="px-1 py-2 font-medium">
|
|
181
|
+
Email
|
|
182
|
+
</th>
|
|
183
|
+
<th scope="col" className="px-1 py-2 font-medium">
|
|
184
|
+
First Name
|
|
185
|
+
</th>
|
|
186
|
+
<th scope="col" className="px-1 py-2 font-medium">
|
|
187
|
+
Last Name
|
|
188
|
+
</th>
|
|
189
|
+
<th scope="col" className="w-8">
|
|
190
|
+
<span className="sr-only">Remove</span>
|
|
191
|
+
</th>
|
|
177
192
|
</tr>
|
|
178
193
|
</thead>
|
|
179
194
|
<tbody>
|
|
@@ -185,6 +200,7 @@ export function BulkInviteForm({
|
|
|
185
200
|
</td>
|
|
186
201
|
<td className="px-1 py-1">
|
|
187
202
|
<Input
|
|
203
|
+
aria-label={`Email, row ${i + 1}`}
|
|
188
204
|
value={row.email}
|
|
189
205
|
onChange={(value) => updateRow(i, "email", value)}
|
|
190
206
|
placeholder="email@example.com"
|
|
@@ -194,6 +210,7 @@ export function BulkInviteForm({
|
|
|
194
210
|
</td>
|
|
195
211
|
<td className="px-1 py-1">
|
|
196
212
|
<Input
|
|
213
|
+
aria-label={`First name, row ${i + 1}`}
|
|
197
214
|
value={row.firstName}
|
|
198
215
|
onChange={(value) => updateRow(i, "firstName", value)}
|
|
199
216
|
placeholder="First"
|
|
@@ -203,6 +220,7 @@ export function BulkInviteForm({
|
|
|
203
220
|
</td>
|
|
204
221
|
<td className="px-1 py-1">
|
|
205
222
|
<Input
|
|
223
|
+
aria-label={`Last name, row ${i + 1}`}
|
|
206
224
|
value={row.lastName}
|
|
207
225
|
onChange={(value) => updateRow(i, "lastName", value)}
|
|
208
226
|
placeholder="Last"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Fieldset, Input } from "@cytario/design";
|
|
2
2
|
import { zodResolver } from "@hookform/resolvers/zod";
|
|
3
3
|
import { Controller, useForm, useWatch } from "react-hook-form";
|
|
4
4
|
import { useSubmit } from "react-router";
|
|
@@ -13,11 +13,7 @@ interface CreateGroupFormProps {
|
|
|
13
13
|
export function CreateGroupForm({ scope }: CreateGroupFormProps) {
|
|
14
14
|
const submit = useSubmit();
|
|
15
15
|
|
|
16
|
-
const {
|
|
17
|
-
control,
|
|
18
|
-
handleSubmit,
|
|
19
|
-
formState: { errors },
|
|
20
|
-
} = useForm<CreateGroupFormData>({
|
|
16
|
+
const { control, handleSubmit } = useForm<CreateGroupFormData>({
|
|
21
17
|
resolver: zodResolver(createGroupSchema),
|
|
22
18
|
defaultValues: { name: "" },
|
|
23
19
|
mode: "onBlur",
|
|
@@ -34,20 +30,20 @@ export function CreateGroupForm({ scope }: CreateGroupFormProps) {
|
|
|
34
30
|
return (
|
|
35
31
|
<form id="create-group-form" onSubmit={handleSubmit(onSubmit)} className="space-y-4">
|
|
36
32
|
<Fieldset>
|
|
37
|
-
<
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
33
|
+
<Controller
|
|
34
|
+
control={control}
|
|
35
|
+
name="name"
|
|
36
|
+
render={({ field, fieldState }) => (
|
|
37
|
+
<Input
|
|
38
|
+
label="Group name"
|
|
39
|
+
size="lg"
|
|
40
|
+
value={field.value}
|
|
41
|
+
onChange={field.onChange}
|
|
42
|
+
onBlur={field.onBlur}
|
|
43
|
+
errorMessage={fieldState.error?.message}
|
|
44
|
+
/>
|
|
45
|
+
)}
|
|
46
|
+
/>
|
|
51
47
|
</Fieldset>
|
|
52
48
|
|
|
53
49
|
{nameValue.trim() && (
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Checkbox,
|
|
1
|
+
import { Checkbox, Fieldset, Input, Select } from "@cytario/design";
|
|
2
2
|
import { zodResolver } from "@hookform/resolvers/zod";
|
|
3
3
|
import { useEffect } from "react";
|
|
4
4
|
import { Controller, useForm } from "react-hook-form";
|
|
@@ -22,12 +22,7 @@ export function InviteUserForm({
|
|
|
22
22
|
}: InviteUserFormProps) {
|
|
23
23
|
const submit = useSubmit();
|
|
24
24
|
|
|
25
|
-
const {
|
|
26
|
-
control,
|
|
27
|
-
handleSubmit,
|
|
28
|
-
reset,
|
|
29
|
-
formState: { errors },
|
|
30
|
-
} = useForm<InviteUserFormData>({
|
|
25
|
+
const { control, handleSubmit, reset } = useForm<InviteUserFormData>({
|
|
31
26
|
resolver: zodResolver(inviteUserSchema),
|
|
32
27
|
defaultValues: {
|
|
33
28
|
email: "",
|
|
@@ -65,67 +60,69 @@ export function InviteUserForm({
|
|
|
65
60
|
return (
|
|
66
61
|
<form id="invite-form" onSubmit={handleSubmit(onSubmit)} className="space-y-4">
|
|
67
62
|
<Fieldset>
|
|
68
|
-
<
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
<
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
<
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
63
|
+
<Controller
|
|
64
|
+
control={control}
|
|
65
|
+
name="email"
|
|
66
|
+
render={({ field, fieldState }) => (
|
|
67
|
+
<Input
|
|
68
|
+
label="Email"
|
|
69
|
+
type="email"
|
|
70
|
+
size="lg"
|
|
71
|
+
value={field.value}
|
|
72
|
+
onChange={field.onChange}
|
|
73
|
+
onBlur={field.onBlur}
|
|
74
|
+
errorMessage={fieldState.error?.message}
|
|
75
|
+
/>
|
|
76
|
+
)}
|
|
77
|
+
/>
|
|
78
|
+
<Controller
|
|
79
|
+
control={control}
|
|
80
|
+
name="firstName"
|
|
81
|
+
render={({ field, fieldState }) => (
|
|
82
|
+
<Input
|
|
83
|
+
label="First name"
|
|
84
|
+
size="lg"
|
|
85
|
+
value={field.value}
|
|
86
|
+
onChange={field.onChange}
|
|
87
|
+
onBlur={field.onBlur}
|
|
88
|
+
errorMessage={fieldState.error?.message}
|
|
89
|
+
/>
|
|
90
|
+
)}
|
|
91
|
+
/>
|
|
92
|
+
<Controller
|
|
93
|
+
control={control}
|
|
94
|
+
name="lastName"
|
|
95
|
+
render={({ field, fieldState }) => (
|
|
96
|
+
<Input
|
|
97
|
+
label="Last name"
|
|
98
|
+
size="lg"
|
|
99
|
+
value={field.value}
|
|
100
|
+
onChange={field.onChange}
|
|
101
|
+
onBlur={field.onBlur}
|
|
102
|
+
errorMessage={fieldState.error?.message}
|
|
103
|
+
/>
|
|
104
|
+
)}
|
|
105
|
+
/>
|
|
111
106
|
{groupOptions.length > 0 ? (
|
|
112
107
|
<Controller
|
|
113
108
|
control={control}
|
|
114
109
|
name="groupPath"
|
|
115
|
-
render={({ field }) => (
|
|
110
|
+
render={({ field, fieldState }) => (
|
|
116
111
|
<Select
|
|
117
112
|
label="Group Membership"
|
|
118
113
|
items={groupOptions.map((p) => ({ id: p, name: p }))}
|
|
119
114
|
selectedKey={field.value}
|
|
120
115
|
onSelectionChange={(key) => field.onChange(key as string)}
|
|
121
116
|
renderItem={(item) => <ScopePill scope={item.id} />}
|
|
117
|
+
errorMessage={fieldState.error?.message}
|
|
122
118
|
/>
|
|
123
119
|
)}
|
|
124
120
|
/>
|
|
125
121
|
) : (
|
|
126
|
-
<
|
|
122
|
+
<div className="flex flex-col gap-1">
|
|
123
|
+
<p className="text-sm font-medium text-(--color-text-primary)">Group Membership</p>
|
|
127
124
|
<p className="text-sm text-slate-400">No groups available in this scope.</p>
|
|
128
|
-
</
|
|
125
|
+
</div>
|
|
129
126
|
)}
|
|
130
127
|
<div className="flex items-center gap-2">
|
|
131
128
|
<Controller
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Checkbox,
|
|
1
|
+
import { Checkbox, Fieldset, H3, Input } from "@cytario/design";
|
|
2
2
|
import { zodResolver } from "@hookform/resolvers/zod";
|
|
3
3
|
import { useState } from "react";
|
|
4
4
|
import { Controller, useForm } from "react-hook-form";
|
|
@@ -30,11 +30,7 @@ export const UpdateUserForm = ({ user, groups, groupPaths }: UpdateUserFormProps
|
|
|
30
30
|
return ids;
|
|
31
31
|
});
|
|
32
32
|
|
|
33
|
-
const {
|
|
34
|
-
control,
|
|
35
|
-
handleSubmit,
|
|
36
|
-
formState: { errors },
|
|
37
|
-
} = useForm<UpdateUserFormData>({
|
|
33
|
+
const { control, handleSubmit } = useForm<UpdateUserFormData>({
|
|
38
34
|
resolver: zodResolver(updateUserSchema),
|
|
39
35
|
defaultValues: {
|
|
40
36
|
email: user.email,
|
|
@@ -136,49 +132,49 @@ export const UpdateUserForm = ({ user, groups, groupPaths }: UpdateUserFormProps
|
|
|
136
132
|
<>
|
|
137
133
|
<form id="update-form" onSubmit={handleSubmit(onSubmit)} className="">
|
|
138
134
|
<Fieldset>
|
|
139
|
-
<
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
<
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
<
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
135
|
+
<Controller
|
|
136
|
+
control={control}
|
|
137
|
+
name="email"
|
|
138
|
+
render={({ field, fieldState }) => (
|
|
139
|
+
<Input
|
|
140
|
+
label="Email"
|
|
141
|
+
type="email"
|
|
142
|
+
size="lg"
|
|
143
|
+
value={field.value}
|
|
144
|
+
onChange={field.onChange}
|
|
145
|
+
onBlur={field.onBlur}
|
|
146
|
+
errorMessage={fieldState.error?.message}
|
|
147
|
+
/>
|
|
148
|
+
)}
|
|
149
|
+
/>
|
|
150
|
+
<Controller
|
|
151
|
+
control={control}
|
|
152
|
+
name="firstName"
|
|
153
|
+
render={({ field, fieldState }) => (
|
|
154
|
+
<Input
|
|
155
|
+
label="First name"
|
|
156
|
+
size="lg"
|
|
157
|
+
value={field.value}
|
|
158
|
+
onChange={field.onChange}
|
|
159
|
+
onBlur={field.onBlur}
|
|
160
|
+
errorMessage={fieldState.error?.message}
|
|
161
|
+
/>
|
|
162
|
+
)}
|
|
163
|
+
/>
|
|
164
|
+
<Controller
|
|
165
|
+
control={control}
|
|
166
|
+
name="lastName"
|
|
167
|
+
render={({ field, fieldState }) => (
|
|
168
|
+
<Input
|
|
169
|
+
label="Last name"
|
|
170
|
+
size="lg"
|
|
171
|
+
value={field.value}
|
|
172
|
+
onChange={field.onChange}
|
|
173
|
+
onBlur={field.onBlur}
|
|
174
|
+
errorMessage={fieldState.error?.message}
|
|
175
|
+
/>
|
|
176
|
+
)}
|
|
177
|
+
/>
|
|
182
178
|
<div className="flex items-center gap-2">
|
|
183
179
|
<Controller
|
|
184
180
|
control={control}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Banner,
|
|
3
|
-
Field,
|
|
4
3
|
Fieldset,
|
|
5
4
|
FormWizard,
|
|
6
5
|
FormWizardNav,
|
|
@@ -97,14 +96,7 @@ export const ConnectionForm = ({
|
|
|
97
96
|
|
|
98
97
|
const [currentStep, setCurrentStep] = useState(initialStep);
|
|
99
98
|
|
|
100
|
-
const {
|
|
101
|
-
control,
|
|
102
|
-
handleSubmit,
|
|
103
|
-
setError,
|
|
104
|
-
setValue,
|
|
105
|
-
trigger,
|
|
106
|
-
formState: { errors },
|
|
107
|
-
} = useForm<ConnectBucketFormData>({
|
|
99
|
+
const { control, handleSubmit, setError, setValue, trigger } = useForm<ConnectBucketFormData>({
|
|
108
100
|
resolver: zodResolver(connectionSchema),
|
|
109
101
|
defaultValues: initialData
|
|
110
102
|
? {
|
|
@@ -212,165 +204,147 @@ export const ConnectionForm = ({
|
|
|
212
204
|
>
|
|
213
205
|
{currentStep === 0 && (
|
|
214
206
|
<Fieldset>
|
|
215
|
-
<
|
|
207
|
+
<Controller
|
|
208
|
+
name="providerType"
|
|
209
|
+
control={control}
|
|
210
|
+
render={({ field, fieldState }) => (
|
|
211
|
+
<Select
|
|
212
|
+
label="Provider"
|
|
213
|
+
items={providerItems}
|
|
214
|
+
renderItem={(item) => <ProviderPill provider={item.id} />}
|
|
215
|
+
selectedKey={field.value}
|
|
216
|
+
onSelectionChange={(key) => field.onChange(key)}
|
|
217
|
+
errorMessage={fieldState.error?.message}
|
|
218
|
+
/>
|
|
219
|
+
)}
|
|
220
|
+
/>
|
|
221
|
+
|
|
222
|
+
<Controller
|
|
223
|
+
name="s3Uri"
|
|
224
|
+
control={control}
|
|
225
|
+
render={({ field, fieldState }) => (
|
|
226
|
+
<Input
|
|
227
|
+
label="S3 URI"
|
|
228
|
+
description="Bucket name and optional path prefix."
|
|
229
|
+
value={field.value}
|
|
230
|
+
onChange={(val) => {
|
|
231
|
+
const trimmed = val.replace(/^s3:\/\//, "");
|
|
232
|
+
field.onChange(trimmed);
|
|
233
|
+
}}
|
|
234
|
+
onBlur={field.onBlur}
|
|
235
|
+
name={field.name}
|
|
236
|
+
placeholder="my-bucket/path/prefix"
|
|
237
|
+
prefix="s3://"
|
|
238
|
+
size="lg"
|
|
239
|
+
errorMessage={fieldState.error?.message}
|
|
240
|
+
/>
|
|
241
|
+
)}
|
|
242
|
+
/>
|
|
243
|
+
|
|
244
|
+
<Controller
|
|
245
|
+
name="name"
|
|
246
|
+
control={control}
|
|
247
|
+
render={({ field, fieldState }) => (
|
|
248
|
+
<Input
|
|
249
|
+
label="Name"
|
|
250
|
+
description="A friendly name, auto-suggested from the S3 URI."
|
|
251
|
+
value={field.value}
|
|
252
|
+
onChange={(val) => {
|
|
253
|
+
if (!isAutoUpdatingName.current) {
|
|
254
|
+
userEditedName.current = true;
|
|
255
|
+
}
|
|
256
|
+
field.onChange(val);
|
|
257
|
+
}}
|
|
258
|
+
onBlur={field.onBlur}
|
|
259
|
+
name={field.name}
|
|
260
|
+
placeholder="my-connection"
|
|
261
|
+
size="lg"
|
|
262
|
+
errorMessage={fieldState.error?.message}
|
|
263
|
+
/>
|
|
264
|
+
)}
|
|
265
|
+
/>
|
|
266
|
+
</Fieldset>
|
|
267
|
+
)}
|
|
268
|
+
|
|
269
|
+
{currentStep === 1 && (
|
|
270
|
+
<Fieldset>
|
|
271
|
+
{adminScopes.length > 0 && (
|
|
216
272
|
<Controller
|
|
217
|
-
name="
|
|
273
|
+
name="ownerScope"
|
|
218
274
|
control={control}
|
|
219
|
-
render={({ field }) => (
|
|
275
|
+
render={({ field, fieldState }) => (
|
|
220
276
|
<Select
|
|
221
|
-
|
|
222
|
-
|
|
277
|
+
label="Visibility"
|
|
278
|
+
description="Who can access this connection."
|
|
279
|
+
items={[
|
|
280
|
+
{ id: userId, name: "Personal" },
|
|
281
|
+
...adminScopes.map((str) => ({
|
|
282
|
+
id: str,
|
|
283
|
+
name: str,
|
|
284
|
+
})),
|
|
285
|
+
]}
|
|
223
286
|
selectedKey={field.value}
|
|
224
287
|
onSelectionChange={(key) => field.onChange(key)}
|
|
288
|
+
renderItem={(item) => <ScopePill scope={item.id} />}
|
|
289
|
+
errorMessage={fieldState.error?.message}
|
|
225
290
|
/>
|
|
226
291
|
)}
|
|
227
292
|
/>
|
|
228
|
-
</Field>
|
|
229
|
-
|
|
230
|
-
<Field
|
|
231
|
-
label="S3 URI"
|
|
232
|
-
description="Bucket name and optional path prefix."
|
|
233
|
-
error={errors.s3Uri}
|
|
234
|
-
>
|
|
235
|
-
<Controller
|
|
236
|
-
name="s3Uri"
|
|
237
|
-
control={control}
|
|
238
|
-
render={({ field }) => (
|
|
239
|
-
<Input
|
|
240
|
-
value={field.value}
|
|
241
|
-
onChange={(val) => {
|
|
242
|
-
const trimmed = val.replace(/^s3:\/\//, "");
|
|
243
|
-
field.onChange(trimmed);
|
|
244
|
-
}}
|
|
245
|
-
onBlur={field.onBlur}
|
|
246
|
-
name={field.name}
|
|
247
|
-
placeholder="my-bucket/path/prefix"
|
|
248
|
-
prefix="s3://"
|
|
249
|
-
size="lg"
|
|
250
|
-
/>
|
|
251
|
-
)}
|
|
252
|
-
/>
|
|
253
|
-
</Field>
|
|
254
|
-
|
|
255
|
-
<Field
|
|
256
|
-
label="Name"
|
|
257
|
-
description="A friendly name, auto-suggested from the S3 URI."
|
|
258
|
-
error={errors.name}
|
|
259
|
-
>
|
|
260
|
-
<Controller
|
|
261
|
-
name="name"
|
|
262
|
-
control={control}
|
|
263
|
-
render={({ field }) => (
|
|
264
|
-
<Input
|
|
265
|
-
value={field.value}
|
|
266
|
-
onChange={(val) => {
|
|
267
|
-
if (!isAutoUpdatingName.current) {
|
|
268
|
-
userEditedName.current = true;
|
|
269
|
-
}
|
|
270
|
-
field.onChange(val);
|
|
271
|
-
}}
|
|
272
|
-
onBlur={field.onBlur}
|
|
273
|
-
name={field.name}
|
|
274
|
-
placeholder="my-connection"
|
|
275
|
-
size="lg"
|
|
276
|
-
/>
|
|
277
|
-
)}
|
|
278
|
-
/>
|
|
279
|
-
</Field>
|
|
280
|
-
</Fieldset>
|
|
281
|
-
)}
|
|
282
|
-
|
|
283
|
-
{currentStep === 1 && (
|
|
284
|
-
<Fieldset>
|
|
285
|
-
{adminScopes.length > 0 && (
|
|
286
|
-
<Field
|
|
287
|
-
label="Visibility"
|
|
288
|
-
description="Who can access this connection."
|
|
289
|
-
error={errors.ownerScope}
|
|
290
|
-
>
|
|
291
|
-
<Controller
|
|
292
|
-
name="ownerScope"
|
|
293
|
-
control={control}
|
|
294
|
-
render={({ field }) => (
|
|
295
|
-
<Select
|
|
296
|
-
items={[
|
|
297
|
-
{ id: userId, name: "Personal" },
|
|
298
|
-
...adminScopes.map((str) => ({
|
|
299
|
-
id: str,
|
|
300
|
-
name: str,
|
|
301
|
-
})),
|
|
302
|
-
]}
|
|
303
|
-
selectedKey={field.value}
|
|
304
|
-
onSelectionChange={(key) => field.onChange(key)}
|
|
305
|
-
renderItem={(item) => <ScopePill scope={item.id} />}
|
|
306
|
-
/>
|
|
307
|
-
)}
|
|
308
|
-
/>
|
|
309
|
-
</Field>
|
|
310
293
|
)}
|
|
311
294
|
|
|
312
295
|
{isAWS ? (
|
|
313
296
|
<>
|
|
314
|
-
<Field
|
|
315
|
-
label="Role ARN"
|
|
316
|
-
description="IAM role Cytario assumes to access your S3 data."
|
|
317
|
-
error={errors.roleArn}
|
|
318
|
-
>
|
|
319
|
-
<Controller
|
|
320
|
-
name="roleArn"
|
|
321
|
-
control={control}
|
|
322
|
-
render={({ field }) => (
|
|
323
|
-
<Input
|
|
324
|
-
value={field.value}
|
|
325
|
-
onChange={field.onChange}
|
|
326
|
-
onBlur={field.onBlur}
|
|
327
|
-
name={field.name}
|
|
328
|
-
placeholder="arn:aws:iam::123456789012:role/MyRole"
|
|
329
|
-
size="lg"
|
|
330
|
-
/>
|
|
331
|
-
)}
|
|
332
|
-
/>
|
|
333
|
-
</Field>
|
|
334
|
-
|
|
335
|
-
<Field
|
|
336
|
-
label="Region"
|
|
337
|
-
description="AWS region where this bucket is located."
|
|
338
|
-
error={errors.bucketRegion}
|
|
339
|
-
>
|
|
340
|
-
<Controller
|
|
341
|
-
name="bucketRegion"
|
|
342
|
-
control={control}
|
|
343
|
-
render={({ field }) => (
|
|
344
|
-
<Select
|
|
345
|
-
items={regionItems}
|
|
346
|
-
selectedKey={field.value}
|
|
347
|
-
onSelectionChange={(key) => field.onChange(key)}
|
|
348
|
-
/>
|
|
349
|
-
)}
|
|
350
|
-
/>
|
|
351
|
-
</Field>
|
|
352
|
-
</>
|
|
353
|
-
) : (
|
|
354
|
-
<Field
|
|
355
|
-
label="Endpoint"
|
|
356
|
-
description="Endpoint URL of your S3-compatible storage."
|
|
357
|
-
error={errors.bucketEndpoint}
|
|
358
|
-
>
|
|
359
297
|
<Controller
|
|
360
|
-
name="
|
|
298
|
+
name="roleArn"
|
|
361
299
|
control={control}
|
|
362
|
-
render={({ field }) => (
|
|
300
|
+
render={({ field, fieldState }) => (
|
|
363
301
|
<Input
|
|
302
|
+
label="Role ARN"
|
|
303
|
+
description="IAM role Cytario assumes to access your S3 data."
|
|
364
304
|
value={field.value}
|
|
365
305
|
onChange={field.onChange}
|
|
366
306
|
onBlur={field.onBlur}
|
|
367
307
|
name={field.name}
|
|
368
|
-
placeholder="
|
|
308
|
+
placeholder="arn:aws:iam::123456789012:role/MyRole"
|
|
369
309
|
size="lg"
|
|
310
|
+
errorMessage={fieldState.error?.message}
|
|
311
|
+
/>
|
|
312
|
+
)}
|
|
313
|
+
/>
|
|
314
|
+
|
|
315
|
+
<Controller
|
|
316
|
+
name="bucketRegion"
|
|
317
|
+
control={control}
|
|
318
|
+
render={({ field, fieldState }) => (
|
|
319
|
+
<Select
|
|
320
|
+
label="Region"
|
|
321
|
+
description="AWS region where this bucket is located."
|
|
322
|
+
items={regionItems}
|
|
323
|
+
selectedKey={field.value}
|
|
324
|
+
onSelectionChange={(key) => field.onChange(key)}
|
|
325
|
+
errorMessage={fieldState.error?.message}
|
|
370
326
|
/>
|
|
371
327
|
)}
|
|
372
328
|
/>
|
|
373
|
-
|
|
329
|
+
</>
|
|
330
|
+
) : (
|
|
331
|
+
<Controller
|
|
332
|
+
name="bucketEndpoint"
|
|
333
|
+
control={control}
|
|
334
|
+
render={({ field, fieldState }) => (
|
|
335
|
+
<Input
|
|
336
|
+
label="Endpoint"
|
|
337
|
+
description="Endpoint URL of your S3-compatible storage."
|
|
338
|
+
value={field.value}
|
|
339
|
+
onChange={field.onChange}
|
|
340
|
+
onBlur={field.onBlur}
|
|
341
|
+
name={field.name}
|
|
342
|
+
placeholder="https://s3.cytario.com"
|
|
343
|
+
size="lg"
|
|
344
|
+
errorMessage={fieldState.error?.message}
|
|
345
|
+
/>
|
|
346
|
+
)}
|
|
347
|
+
/>
|
|
374
348
|
)}
|
|
375
349
|
</Fieldset>
|
|
376
350
|
)}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cytario/web",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.7",
|
|
4
4
|
"description": "Cytario Web — scientific imaging data browser and viewer for OME-TIFF, OME-Zarr, Parquet and GeoTIFF on S3-compatible storage.",
|
|
5
5
|
"license": "AGPL-3.0",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -55,8 +55,8 @@
|
|
|
55
55
|
"codegen:check": "tsx scripts/codegen-check.ts",
|
|
56
56
|
"dev": "node bin/cytario-web.mjs dev",
|
|
57
57
|
"predev": "node scripts/prebuild.mjs && if [ -L node_modules/@cytario/design ]; then npm unlink @cytario/design --no-save 2>/dev/null && npm install @cytario/design --quiet; fi",
|
|
58
|
-
"predev:design": "cd ../cytario-design && npm link --quiet && cd - > /dev/null && npm link @cytario/design --quiet && for p in react react-dom react-aria-components; do rm -rf ../cytario-design/node_modules/$p && ln -s \"$(pwd)/node_modules/$p\" ../cytario-design/node_modules/$p; done",
|
|
59
|
-
"dev:design": "concurrently -n tsup,storybook,web -c blue,magenta,green \"cd ../cytario-design && npx tsup --watch\" \"cd ../cytario-design && npm run dev\" \"node bin/cytario-web.mjs dev\"",
|
|
58
|
+
"predev:design": "cd ../cytario-design && npm link --quiet && cd - > /dev/null && npm link @cytario/design --quiet && for p in react react-dom react-aria-components lucide-react; do rm -rf ../cytario-design/node_modules/$p && ln -s \"$(pwd)/node_modules/$p\" ../cytario-design/node_modules/$p; done && cd ../cytario-design && npm run build:css",
|
|
59
|
+
"dev:design": "concurrently -n tsup,css,storybook,web -c blue,yellow,magenta,green \"cd ../cytario-design && npx tsup --watch\" \"cd ../cytario-design && npx @tailwindcss/cli -i src/styles/tailwind.css -o dist/index.css --watch\" \"cd ../cytario-design && npm run dev\" \"node bin/cytario-web.mjs dev\"",
|
|
60
60
|
"lint": "eslint --cache --cache-location ./node_modules/.cache/eslint .",
|
|
61
61
|
"prestart": "npm run build:server",
|
|
62
62
|
"start": "node bin/cytario-web.mjs start",
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
"@aws-sdk/client-sts": "^3.687.0",
|
|
73
73
|
"@aws-sdk/s3-request-presigner": "^3.693.0",
|
|
74
74
|
"@cornerstonejs/codec-openjpeg": "^1.3.0",
|
|
75
|
-
"@cytario/design": "^
|
|
75
|
+
"@cytario/design": "^4.0.0",
|
|
76
76
|
"@deck.gl/core": "~9.1.15",
|
|
77
77
|
"@deck.gl/extensions": "~9.1.15",
|
|
78
78
|
"@deck.gl/geo-layers": "~9.1.15",
|