Skip to content

Commit 44ac941

Browse files
committed
refactor: remove settings panels and inline all form fields
- Delete ArticleSettings, MemberSettings, ProjectSettings components - Move slug, cover image, category, URLs inline into editors - Move author/visibility to header dropdown menus - Add delete option to "..." menu in headers - Remove competitive view counts from dashboard (Top Articles/Projects/Members) - Fix nested scrolling by using native browser scroll - leadMemberId dropdown always visible (not conditional on isNew)
1 parent 803d242 commit 44ac941

File tree

22 files changed

+567
-1039
lines changed

22 files changed

+567
-1039
lines changed

src/lib/components/ArticleForm.svelte

Lines changed: 17 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import { triggerSubmit } from "$lib/utils/form";
66
import { onSaveShortcut } from "$lib/utils/keyboard";
77
import { snapshot } from "$lib/utils/snapshot.svelte";
8-
import { ArticleEditor, ArticleFormHeader, ArticleSettings } from "./article-form";
8+
import { ArticleEditor, ArticleFormHeader } from "./article-form";
99
import { confirm } from "$lib/components/confirm-modal.svelte";
1010
1111
let {
@@ -23,7 +23,6 @@
2323
submitLabel = "Save",
2424
isSubmitting = $bindable(false),
2525
articleId = null,
26-
viewCount = 0,
2726
}: {
2827
initialData?: ArticleData;
2928
authors?: Author[];
@@ -32,12 +31,10 @@
3231
submitLabel?: string;
3332
isSubmitting?: boolean;
3433
articleId?: string | null;
35-
viewCount?: number;
3634
} = $props();
3735
3836
let formData = $state(snapshot(() => initialData));
3937
let errors = $state<Record<string, string>>({});
40-
let showSettings = $state(false);
4138
let saveSuccess = $state(false);
4239
let createRedirect = $state(false);
4340
@@ -64,8 +61,6 @@
6461
errors = validator.getErrors();
6562
6663
if (validator.hasErrors()) {
67-
// Show settings panel if there are errors in settings fields
68-
if (errors.slug) showSettings = true;
6964
return;
7065
}
7166
@@ -95,46 +90,33 @@
9590
window.open(`/admin/articles/${articleId}/preview`, "_blank");
9691
}
9792
}
98-
9993
</script>
10094

10195
<svelte:window onkeydown={onSaveShortcut(() => triggerSubmit(handleSubmit, isSubmitting))} />
10296

103-
<form onsubmit={handleSubmit} class="flex h-full flex-col">
97+
<form onsubmit={handleSubmit} class="flex min-h-screen flex-col">
10498
<ArticleFormHeader
10599
bind:published={formData.published}
106-
bind:showSettings
100+
bind:authorId={formData.authorId}
107101
bind:saveSuccess
102+
{authors}
108103
{isSubmitting}
109104
{submitLabel}
110105
{articleId}
106+
{onDelete}
111107
onPreview={openPreviewPage}
112108
/>
113109

114-
<div class="flex flex-1 overflow-hidden">
115-
<ArticleEditor
116-
bind:title={formData.title}
117-
bind:content={formData.content}
118-
slug={formData.slug}
119-
coverUrl={formData.coverUrl}
120-
titleError={errors["title"]}
121-
contentError={errors["content"]}
122-
onTitleChange={handleTitleChange}
123-
onOpenSettings={() => (showSettings = true)}
124-
/>
125-
126-
<ArticleSettings
127-
bind:show={showSettings}
128-
bind:published={formData.published}
129-
bind:slug={formData.slug}
130-
bind:authorId={formData.authorId}
131-
bind:coverUrl={formData.coverUrl}
132-
bind:createRedirect
133-
initialSlug={initialData.slug}
134-
{authors}
135-
slugError={errors["slug"]}
136-
{onDelete}
137-
{viewCount}
138-
/>
139-
</div>
110+
<ArticleEditor
111+
bind:title={formData.title}
112+
bind:content={formData.content}
113+
bind:slug={formData.slug}
114+
bind:coverUrl={formData.coverUrl}
115+
bind:createRedirect
116+
initialSlug={initialData.slug}
117+
titleError={errors["title"]}
118+
contentError={errors["content"]}
119+
slugError={errors["slug"]}
120+
onTitleChange={handleTitleChange}
121+
/>
140122
</form>

src/lib/components/MemberForm.svelte

Lines changed: 13 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,24 @@
55
import { triggerSubmit } from "$lib/utils/form";
66
import { onSaveShortcut } from "$lib/utils/keyboard";
77
import { snapshot } from "$lib/utils/snapshot.svelte";
8-
import { MemberEditor, MemberFormHeader, MemberSettings } from "./member-form";
8+
import { MemberEditor, MemberFormHeader } from "./member-form";
99
1010
let {
1111
initialData = { slug: "", name: "", bio: "", imageUrl: "", pageContent: "" },
1212
onSubmit,
1313
onDelete = null,
1414
submitLabel = "Save",
1515
isSubmitting = $bindable(false),
16-
viewCount = 0,
1716
}: {
1817
initialData?: MemberData;
1918
onSubmit: (data: MemberData) => Promise<void>;
2019
onDelete?: (() => Promise<void>) | null;
2120
submitLabel?: string;
2221
isSubmitting?: boolean;
23-
viewCount?: number;
2422
} = $props();
2523
2624
let formData = $state(snapshot(() => initialData));
2725
let errors = $state<Record<string, string>>({});
28-
let showSettings = $state(false);
2926
3027
function handleNameChange() {
3128
if (!formData.slug || formData.slug === generateSlug(initialData.name)) {
@@ -47,7 +44,6 @@
4744
errors = validator.getErrors();
4845
4946
if (validator.hasErrors()) {
50-
if (errors.slug) showSettings = true;
5147
return;
5248
}
5349
@@ -62,32 +58,17 @@
6258

6359
<svelte:window onkeydown={onSaveShortcut(() => triggerSubmit(handleSubmit, isSubmitting))} />
6460

65-
<form onsubmit={handleSubmit} class="flex h-full flex-col">
66-
<MemberFormHeader
67-
bind:showSettings
68-
{isSubmitting}
69-
{submitLabel}
70-
/>
71-
72-
<div class="flex flex-1 overflow-hidden">
73-
<MemberEditor
74-
bind:name={formData.name}
75-
bind:bio={formData.bio}
76-
bind:pageContent={formData.pageContent}
77-
slug={formData.slug}
78-
imageUrl={formData.imageUrl}
79-
nameError={errors["name"]}
80-
onNameChange={handleNameChange}
81-
onOpenSettings={() => (showSettings = true)}
82-
/>
61+
<form onsubmit={handleSubmit} class="flex min-h-screen flex-col">
62+
<MemberFormHeader {isSubmitting} {submitLabel} {onDelete} />
8363

84-
<MemberSettings
85-
bind:show={showSettings}
86-
bind:slug={formData.slug}
87-
bind:imageUrl={formData.imageUrl}
88-
slugError={errors["slug"]}
89-
{viewCount}
90-
{onDelete}
91-
/>
92-
</div>
64+
<MemberEditor
65+
bind:name={formData.name}
66+
bind:slug={formData.slug}
67+
bind:bio={formData.bio}
68+
bind:imageUrl={formData.imageUrl}
69+
bind:pageContent={formData.pageContent}
70+
nameError={errors["name"]}
71+
slugError={errors["slug"]}
72+
onNameChange={handleNameChange}
73+
/>
9374
</form>

src/lib/components/ProjectForm.svelte

Lines changed: 20 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import { snapshot } from "$lib/utils/snapshot.svelte";
88
import ProjectEditor from "./project-form/ProjectEditor.svelte";
99
import ProjectFormHeader from "./project-form/ProjectFormHeader.svelte";
10-
import ProjectSettings from "./project-form/ProjectSettings.svelte";
1110
1211
let {
1312
initialData = {
@@ -27,7 +26,6 @@
2726
submitLabel = "Save",
2827
isSubmitting = $bindable(false),
2928
isNew = false,
30-
viewCount = 0,
3129
}: {
3230
initialData?: ProjectData;
3331
members?: Member[];
@@ -36,12 +34,11 @@
3634
submitLabel?: string;
3735
isSubmitting?: boolean;
3836
isNew?: boolean;
39-
viewCount?: number;
4037
} = $props();
4138
4239
let formData = $state(snapshot(() => initialData));
4340
let errors = $state<Record<string, string>>({});
44-
let showSettings = $state(false);
41+
let saveSuccess = $state(false);
4542
4643
function handleNameChange() {
4744
if (!formData.slug || formData.slug === generateSlug(initialData.name)) {
@@ -62,19 +59,19 @@
6259
6360
if (isNew && !formData.leadMemberId) {
6461
validator.validate("leadMemberId", "", () => "Lead member is required");
65-
showSettings = true;
6662
}
6763
6864
errors = validator.getErrors();
6965
7066
if (validator.hasErrors()) {
71-
if (errors.slug || errors.leadMemberId) showSettings = true;
7267
return;
7368
}
7469
7570
isSubmitting = true;
71+
saveSuccess = false;
7672
try {
7773
await onSubmit(formData);
74+
saveSuccess = true;
7875
} finally {
7976
isSubmitting = false;
8077
}
@@ -83,41 +80,26 @@
8380

8481
<svelte:window onkeydown={onSaveShortcut(() => triggerSubmit(handleSubmit, isSubmitting))} />
8582

86-
<form onsubmit={handleSubmit} class="flex h-full flex-col">
83+
<form onsubmit={handleSubmit} class="flex min-h-screen flex-col">
8784
<ProjectFormHeader
88-
category={formData.category}
89-
bind:showSettings
85+
bind:leadMemberId={formData.leadMemberId}
86+
bind:saveSuccess
87+
{members}
9088
{isSubmitting}
9189
{submitLabel}
92-
onToggleSettings={() => (showSettings = !showSettings)}
90+
{onDelete}
9391
/>
9492

95-
<div class="flex flex-1 overflow-hidden">
96-
<ProjectEditor
97-
bind:name={formData.name}
98-
bind:description={formData.description}
99-
bind:content={formData.content}
100-
slug={formData.slug}
101-
coverUrl={formData.coverUrl}
102-
{errors}
103-
onNameChange={handleNameChange}
104-
onOpenSettings={() => (showSettings = true)}
105-
/>
106-
107-
<ProjectSettings
108-
show={showSettings}
109-
bind:category={formData.category}
110-
bind:slug={formData.slug}
111-
bind:leadMemberId={formData.leadMemberId}
112-
bind:coverUrl={formData.coverUrl}
113-
bind:repoUrl={formData.repoUrl}
114-
bind:demoUrl={formData.demoUrl}
115-
{members}
116-
{errors}
117-
{isNew}
118-
{viewCount}
119-
onClose={() => (showSettings = false)}
120-
{onDelete}
121-
/>
122-
</div>
93+
<ProjectEditor
94+
bind:name={formData.name}
95+
bind:description={formData.description}
96+
bind:content={formData.content}
97+
bind:slug={formData.slug}
98+
bind:coverUrl={formData.coverUrl}
99+
bind:category={formData.category}
100+
bind:repoUrl={formData.repoUrl}
101+
bind:demoUrl={formData.demoUrl}
102+
{errors}
103+
onNameChange={handleNameChange}
104+
/>
123105
</form>

0 commit comments

Comments
 (0)