tangled
alpha
login
or
join now
slices.network
/
slices
137
fork
atom
Highly ambitious ATProtocol AppView service and sdks
137
fork
atom
overview
issues
10
pulls
3
pipelines
use checkboxes instead of inputs for sync modal
chadtmiller.com
5 months ago
a4cf9d0c
8aeb84c4
+77
-41
3 changed files
expand all
collapse all
unified
split
frontend
src
features
slices
sync
handlers.tsx
templates
fragments
SyncFormModal.tsx
shared
fragments
Checkbox.tsx
+2
-13
frontend/src/features/slices/sync/handlers.tsx
···
34
34
35
35
try {
36
36
const formData = await req.formData();
37
37
-
const collectionsText = (formData.get("collections") as string) || "";
38
38
-
const externalCollectionsText =
39
39
-
(formData.get("external_collections") as string) || "";
37
37
+
const collections = formData.getAll("collections") as string[];
38
38
+
const externalCollections = formData.getAll("external_collections") as string[];
40
39
const reposText = (formData.get("repos") as string) || "";
41
41
-
42
42
-
const collections = collectionsText
43
43
-
.split("\n")
44
44
-
.map((line) => line.trim())
45
45
-
.filter((line) => line.length > 0);
46
46
-
47
47
-
const externalCollections = externalCollectionsText
48
48
-
.split("\n")
49
49
-
.map((line) => line.trim())
50
50
-
.filter((line) => line.length > 0);
51
40
52
41
const repos = reposText
53
42
.split("\n")
+47
-28
frontend/src/features/slices/sync/templates/fragments/SyncFormModal.tsx
···
1
1
import { Button } from "../../../../../shared/fragments/Button.tsx";
2
2
import { Textarea } from "../../../../../shared/fragments/Textarea.tsx";
3
3
+
import { Checkbox } from "../../../../../shared/fragments/Checkbox.tsx";
3
4
import { Modal } from "../../../../../shared/fragments/Modal.tsx";
4
5
5
6
interface SyncFormModalProps {
···
24
25
hx-swap="innerHTML"
25
26
className="space-y-4"
26
27
>
27
27
-
<Textarea
28
28
-
id="collections"
29
29
-
name="collections"
30
30
-
label="Primary Collections"
31
31
-
rows={4}
32
32
-
placeholder={collections.length > 0
33
33
-
? "Primary collections (matching your slice domain) loaded below:"
34
34
-
: "Enter primary collections matching your slice domain, one per line:\n\nyour.domain.collection\nyour.domain.post"}
35
35
-
defaultValue={collections.length > 0 ? collections.join("\n") : ""}
36
36
-
/>
37
37
-
<p className="mt-1 text-xs text-zinc-500">
38
38
-
Primary collections are those that match your slice's domain.
39
39
-
</p>
28
28
+
<div className="space-y-2">
29
29
+
<label className="block text-sm font-medium text-zinc-700 dark:text-zinc-300">
30
30
+
Primary Collections
31
31
+
</label>
32
32
+
<p className="text-xs text-zinc-500">
33
33
+
Primary collections are those that match your slice's domain.
34
34
+
</p>
35
35
+
{collections.length > 0 ? (
36
36
+
<div className="space-y-2 border border-zinc-200 dark:border-zinc-700 rounded-md p-4 bg-white dark:bg-zinc-900">
37
37
+
{collections.map((collection) => (
38
38
+
<Checkbox
39
39
+
key={collection}
40
40
+
name="collections"
41
41
+
value={collection}
42
42
+
label={collection}
43
43
+
checked
44
44
+
/>
45
45
+
))}
46
46
+
</div>
47
47
+
) : (
48
48
+
<p className="text-sm text-zinc-500 italic">No primary collections available</p>
49
49
+
)}
50
50
+
</div>
40
51
41
41
-
<Textarea
42
42
-
id="external_collections"
43
43
-
name="external_collections"
44
44
-
label="External Collections"
45
45
-
rows={4}
46
46
-
placeholder={externalCollections.length > 0
47
47
-
? "External collections loaded below:"
48
48
-
: "Enter external collections (not matching your domain), one per line:\n\napp.bsky.feed.post\napp.bsky.actor.profile"}
49
49
-
defaultValue={externalCollections.length > 0
50
50
-
? externalCollections.join("\n")
51
51
-
: ""}
52
52
-
/>
53
53
-
<p className="mt-1 text-xs text-zinc-500">
54
54
-
External collections are those that don't match your slice's domain.
55
55
-
</p>
52
52
+
<div className="space-y-2">
53
53
+
<label className="block text-sm font-medium text-zinc-700 dark:text-zinc-300">
54
54
+
External Collections
55
55
+
</label>
56
56
+
<p className="text-xs text-zinc-500">
57
57
+
External collections are those that don't match your slice's domain.
58
58
+
</p>
59
59
+
{externalCollections.length > 0 ? (
60
60
+
<div className="space-y-2 border border-zinc-200 dark:border-zinc-700 rounded-md p-4 bg-white dark:bg-zinc-900">
61
61
+
{externalCollections.map((collection) => (
62
62
+
<Checkbox
63
63
+
key={collection}
64
64
+
name="external_collections"
65
65
+
value={collection}
66
66
+
label={collection}
67
67
+
checked
68
68
+
/>
69
69
+
))}
70
70
+
</div>
71
71
+
) : (
72
72
+
<p className="text-sm text-zinc-500 italic">No external collections available</p>
73
73
+
)}
74
74
+
</div>
56
75
57
76
<Textarea
58
77
id="repos"
+28
frontend/src/shared/fragments/Checkbox.tsx
···
1
1
+
import type { JSX } from "preact";
2
2
+
import { cn } from "../../utils/cn.ts";
3
3
+
4
4
+
export type CheckboxProps = JSX.IntrinsicElements["input"] & {
5
5
+
label?: string;
6
6
+
};
7
7
+
8
8
+
export function Checkbox(props: CheckboxProps): JSX.Element {
9
9
+
const { class: classProp, label, ...rest } = props;
10
10
+
11
11
+
const className = cn("accent-blue-600 dark:accent-white", classProp);
12
12
+
13
13
+
return (
14
14
+
<label className="flex items-center gap-2 cursor-pointer">
15
15
+
<input
16
16
+
type="checkbox"
17
17
+
class={className}
18
18
+
style="color-scheme: light dark;"
19
19
+
{...rest}
20
20
+
/>
21
21
+
{label && (
22
22
+
<span className="text-sm text-zinc-700 dark:text-zinc-300">
23
23
+
{label}
24
24
+
</span>
25
25
+
)}
26
26
+
</label>
27
27
+
);
28
28
+
}