Skip to content

Commit fb7a192

Browse files
committed
style(frontend): collapse short Field usages to single lines
1 parent 88a0cd5 commit fb7a192

4 files changed

Lines changed: 53 additions & 21 deletions

File tree

frontend/src/lib/dialogs/StatusCategoryModal.svelte

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,7 @@
8686
8787
{#if !isEditing}
8888
<div class="mb-6">
89-
<TextareaField
90-
label={t('common.description')}
91-
rows={2}
92-
bind:value={formData.description}
93-
/>
89+
<TextareaField label={t('common.description')} rows={2} bind:value={formData.description} />
9490
</div>
9591
{/if}
9692

frontend/src/lib/dialogs/TimeCustomerModal.svelte

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -117,11 +117,7 @@
117117
</div>
118118

119119
<div>
120-
<TextField
121-
label={t('organization.email')}
122-
type="email"
123-
bind:value={formData.email}
124-
/>
120+
<TextField label={t('organization.email')} type="email" bind:value={formData.email} />
125121
</div>
126122
</div>
127123

@@ -200,11 +196,7 @@
200196
</div>
201197

202198
<div class="mt-6">
203-
<TextareaField
204-
label={t('common.description')}
205-
rows={3}
206-
bind:value={formData.description}
207-
/>
199+
<TextareaField label={t('common.description')} rows={3} bind:value={formData.description} />
208200
</div>
209201

210202
<div class="mt-6">

frontend/src/lib/settings/LocalizedObjectFields.svelte

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -252,11 +252,7 @@
252252
{#if !objectId}
253253
<div class="space-y-4">
254254
<div>
255-
<TextField
256-
label={t('settings.localizedObjects.baseName')}
257-
required
258-
bind:value={canonicalName}
259-
/>
255+
<TextField label={t('settings.localizedObjects.baseName')} required bind:value={canonicalName} />
260256
</div>
261257
{#if includesDescription}
262258
<div>

frontend/src/lib/stores/itemDetailStore.svelte.js

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,10 @@ class ItemDetailStore {
111111
loading = $state(true);
112112
error = $state(null);
113113
saving = $state(false);
114+
// Latest requested save per field while another save is in flight; replayed
115+
// on completion so rapid edits are not dropped.
116+
#pendingSaves = new Map();
117+
#drainingPendingSaves = false;
114118
// The detail view closes when an SSE deletion or refresh 404 sets this.
115119
notFound = $state(false);
116120

@@ -852,7 +856,16 @@ class ItemDetailStore {
852856
}
853857

854858
async saveField(field, directValue = null, assigneeName = null, iterationName = null) {
855-
if (this.saving) return;
859+
if (this.saving) {
860+
// A save is in flight; remember the latest requested value per field
861+
// and replay it when that save finishes so rapid edits are not lost.
862+
this.#pendingSaves.set(field, {
863+
directValue: this.#resolveSaveValue(field, directValue),
864+
assigneeName,
865+
iterationName,
866+
});
867+
return;
868+
}
856869

857870
try {
858871
this.saving = true;
@@ -1041,10 +1054,43 @@ class ItemDetailStore {
10411054
throw err;
10421055
} finally {
10431056
this.saving = false;
1057+
await this.#drainPendingSaves();
10441058
this.#runPendingRefresh();
10451059
}
10461060
}
10471061

1062+
// Resolve an editing-state value into a direct value so a queued save keeps
1063+
// writing the same content after the editor closes.
1064+
#resolveSaveValue(field, directValue) {
1065+
if (directValue !== null || !field.startsWith('custom_field_')) {
1066+
return directValue;
1067+
}
1068+
const fieldId = field.replace('custom_field_', '');
1069+
const value = this.editing.customFields.values[fieldId];
1070+
return value !== undefined ? value : null;
1071+
}
1072+
1073+
// Replay queued saves sequentially; the nested saveField call re-enters
1074+
// this drain in its own finally, so guard against double processing.
1075+
async #drainPendingSaves() {
1076+
if (this.#drainingPendingSaves) return;
1077+
this.#drainingPendingSaves = true;
1078+
try {
1079+
while (this.#pendingSaves.size > 0) {
1080+
const [field, pending] = this.#pendingSaves.entries().next().value;
1081+
this.#pendingSaves.delete(field);
1082+
await this.saveField(
1083+
field,
1084+
pending.directValue,
1085+
pending.assigneeName,
1086+
pending.iterationName
1087+
);
1088+
}
1089+
} finally {
1090+
this.#drainingPendingSaves = false;
1091+
}
1092+
}
1093+
10481094
// === Auto-sync editing values when item loads/changes ===
10491095

10501096
#syncEditingFromItem() {
@@ -1255,6 +1301,8 @@ class ItemDetailStore {
12551301
this.#loadToken += 1;
12561302
this.#refreshToken += 1;
12571303
this.#refreshPending = false;
1304+
this.#pendingSaves.clear();
1305+
this.#drainingPendingSaves = false;
12581306
this.#loadController?.abort();
12591307
this.#refreshController?.abort();
12601308
this.#linksController?.abort();

0 commit comments

Comments
 (0)