@commonpub/layer 0.59.0 → 0.60.0
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@commonpub/layer",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.60.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./nuxt.config.ts",
|
|
6
6
|
"files": [
|
|
@@ -55,13 +55,13 @@
|
|
|
55
55
|
"zod": "^4.3.6",
|
|
56
56
|
"@commonpub/auth": "0.8.0",
|
|
57
57
|
"@commonpub/config": "0.18.0",
|
|
58
|
-
"@commonpub/docs": "0.6.3",
|
|
59
58
|
"@commonpub/editor": "0.7.11",
|
|
60
|
-
"@commonpub/
|
|
61
|
-
"@commonpub/
|
|
59
|
+
"@commonpub/docs": "0.6.3",
|
|
60
|
+
"@commonpub/protocol": "0.13.0",
|
|
62
61
|
"@commonpub/server": "2.80.0",
|
|
63
62
|
"@commonpub/ui": "0.9.2",
|
|
64
|
-
"@commonpub/
|
|
63
|
+
"@commonpub/explainer": "0.7.15",
|
|
64
|
+
"@commonpub/schema": "0.33.0",
|
|
65
65
|
"@commonpub/learning": "0.5.2"
|
|
66
66
|
},
|
|
67
67
|
"devDependencies": {
|
|
@@ -65,9 +65,17 @@ const currentStageIdRef = ref<string | null>(null);
|
|
|
65
65
|
const advancing = ref<string | null>(null);
|
|
66
66
|
const advanceN = ref<Record<string, number>>({});
|
|
67
67
|
|
|
68
|
+
// Dirty tracking: any edit after the contest loads flips this so the save bar
|
|
69
|
+
// shows "unsaved changes" — feedback that a change (e.g. checking an eligible
|
|
70
|
+
// type) registered. `hydratingForm` suppresses the watcher while the loader
|
|
71
|
+
// populates the fields from the fetched contest.
|
|
72
|
+
const formDirty = ref(false);
|
|
73
|
+
let hydratingForm = false;
|
|
74
|
+
|
|
68
75
|
// Load current data
|
|
69
76
|
watch(contest, (c) => {
|
|
70
77
|
if (!c) return;
|
|
78
|
+
hydratingForm = true;
|
|
71
79
|
title.value = c.title ?? '';
|
|
72
80
|
slugInput.value = c.slug ?? '';
|
|
73
81
|
subheading.value = c.subheading ?? '';
|
|
@@ -104,8 +112,20 @@ watch(contest, (c) => {
|
|
|
104
112
|
weight: cr.weight ?? null,
|
|
105
113
|
description: cr.description ?? '',
|
|
106
114
|
}));
|
|
115
|
+
// Let the field watchers settle from this hydration, then re-arm dirty tracking.
|
|
116
|
+
void nextTick(() => { hydratingForm = false; });
|
|
107
117
|
}, { immediate: true });
|
|
108
118
|
|
|
119
|
+
// Mark the form dirty on any post-hydration edit (gives the save bar its
|
|
120
|
+
// "unsaved changes" cue). Worst case (timing) is a harmless early "dirty".
|
|
121
|
+
watch(
|
|
122
|
+
[title, slugInput, subheading, description, rules, bannerUrl, coverImageUrl, startDate, endDate, judgingEndDate,
|
|
123
|
+
communityVotingEnabled, judgingVisibility, eligibleContentTypes, maxEntriesPerUser, visibility, visibleToRoles,
|
|
124
|
+
showPrizes, stages, currentStageIdRef, prizesDescription, prizes, criteria],
|
|
125
|
+
() => { if (!hydratingForm) formDirty.value = true; },
|
|
126
|
+
{ deep: true },
|
|
127
|
+
);
|
|
128
|
+
|
|
109
129
|
function addPrize(): void {
|
|
110
130
|
prizes.value.push({ place: null, category: '', title: '', description: '', value: '' });
|
|
111
131
|
}
|
|
@@ -190,6 +210,7 @@ async function handleSave(): Promise<void> {
|
|
|
190
210
|
},
|
|
191
211
|
});
|
|
192
212
|
toast.success('Contest updated');
|
|
213
|
+
formDirty.value = false;
|
|
193
214
|
// Slug changed → the old URL no longer resolves. Navigate to the renamed
|
|
194
215
|
// contest's page — a different route component, so it loads fresh. (Navigating
|
|
195
216
|
// to the new /edit URL would reuse THIS component with its stale fetch key.)
|
|
@@ -594,11 +615,12 @@ async function transitionStatus(newStatus: string): Promise<void> {
|
|
|
594
615
|
<div class="cpub-edit-actionbar">
|
|
595
616
|
<span class="cpub-edit-actionbar-status">
|
|
596
617
|
Status <span class="cpub-status-badge" :class="`cpub-status-${contest.status}`">{{ contest.status }}</span>
|
|
618
|
+
<span v-if="formDirty" class="cpub-edit-dirty"><i class="fa-solid fa-circle"></i> Unsaved changes</span>
|
|
597
619
|
</span>
|
|
598
620
|
<div class="cpub-edit-actionbar-btns">
|
|
599
621
|
<NuxtLink :to="`/contests/${slug}`" class="cpub-btn cpub-edit-cancel">Cancel</NuxtLink>
|
|
600
|
-
<button type="submit" class="cpub-btn cpub-btn-primary" :disabled="saving || !title.trim() || !!dateError">
|
|
601
|
-
<i class="fa-solid fa-floppy-disk"></i> {{ saving ? 'Saving…' : 'Save Changes' }}
|
|
622
|
+
<button type="submit" class="cpub-btn cpub-btn-primary" :disabled="saving || !title.trim() || !!dateError || !formDirty">
|
|
623
|
+
<i class="fa-solid fa-floppy-disk"></i> {{ saving ? 'Saving…' : formDirty ? 'Save Changes' : 'Saved' }}
|
|
602
624
|
</button>
|
|
603
625
|
</div>
|
|
604
626
|
</div>
|
|
@@ -703,7 +725,9 @@ async function transitionStatus(newStatus: string): Promise<void> {
|
|
|
703
725
|
.cpub-advance-pick-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
704
726
|
.cpub-advance-pick-score { font-family: var(--font-mono); font-size: 11px; color: var(--accent); flex-shrink: 0; }
|
|
705
727
|
.cpub-advance-manual .cpub-btn { align-self: flex-start; margin-top: 6px; }
|
|
706
|
-
.cpub-edit-actionbar-status { font-size: 11px; font-family: var(--font-mono); text-transform: uppercase; letter-spacing: .06em; color: var(--text-faint); display: flex; align-items: center; gap: 8px; }
|
|
728
|
+
.cpub-edit-actionbar-status { font-size: 11px; font-family: var(--font-mono); text-transform: uppercase; letter-spacing: .06em; color: var(--text-faint); display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
|
|
729
|
+
.cpub-edit-dirty { color: var(--accent); display: inline-flex; align-items: center; gap: 5px; }
|
|
730
|
+
.cpub-edit-dirty i { font-size: 6px; }
|
|
707
731
|
.cpub-edit-actionbar-btns { display: flex; align-items: center; gap: 8px; }
|
|
708
732
|
|
|
709
733
|
/* Collapse the meta rail under the main column on narrower viewports. */
|