Added Draft Melodies. Further improvements to the UI

This commit is contained in:
2026-02-18 19:33:59 +02:00
parent a6e0b1d46e
commit aad8942d65
12 changed files with 1080 additions and 518 deletions

View File

@@ -58,6 +58,7 @@ export default function MelodyForm() {
const [url, setUrl] = useState("");
const [uid, setUid] = useState("");
const [pid, setPid] = useState("");
const [melodyStatus, setMelodyStatus] = useState("draft");
const [binaryFile, setBinaryFile] = useState(null);
const [previewFile, setPreviewFile] = useState(null);
@@ -116,6 +117,7 @@ export default function MelodyForm() {
setUrl(melody.url || "");
setUid(melody.uid || "");
setPid(melody.pid || "");
setMelodyStatus(melody.status || "published");
setExistingFiles(files);
} catch (err) {
setError(err.message);
@@ -150,33 +152,39 @@ export default function MelodyForm() {
updateInfo(fieldKey, serializeLocalizedString(dict));
};
const handleSubmit = async (e) => {
e.preventDefault();
const buildBody = () => {
const { notes, ...infoWithoutNotes } = information;
return {
information: infoWithoutNotes,
default_settings: settings,
type, url, uid, pid,
};
};
const uploadFiles = async (melodyId) => {
if (binaryFile || previewFile) {
setUploading(true);
if (binaryFile) await api.upload(`/melodies/${melodyId}/upload/binary`, binaryFile);
if (previewFile) await api.upload(`/melodies/${melodyId}/upload/preview`, previewFile);
setUploading(false);
}
};
const handleSave = async (publish) => {
setSaving(true);
setError("");
try {
const { notes, ...infoWithoutNotes } = information;
const body = {
information: infoWithoutNotes,
default_settings: settings,
type, url, uid, pid,
};
const body = buildBody();
let melodyId = id;
if (isEdit) {
await api.put(`/melodies/${id}`, body);
} else {
const created = await api.post("/melodies", body);
const created = await api.post(`/melodies?publish=${publish}`, body);
melodyId = created.id;
}
if (binaryFile || previewFile) {
setUploading(true);
if (binaryFile) await api.upload(`/melodies/${melodyId}/upload/binary`, binaryFile);
if (previewFile) await api.upload(`/melodies/${melodyId}/upload/preview`, previewFile);
setUploading(false);
}
await uploadFiles(melodyId);
navigate(`/melodies/${melodyId}`);
} catch (err) {
setError(err.message);
@@ -186,6 +194,46 @@ export default function MelodyForm() {
}
};
const handlePublishAction = async () => {
setSaving(true);
setError("");
try {
const body = buildBody();
await api.put(`/melodies/${id}`, body);
await uploadFiles(id);
await api.post(`/melodies/${id}/publish`);
navigate(`/melodies/${id}`);
} catch (err) {
setError(err.message);
setUploading(false);
} finally {
setSaving(false);
}
};
const handleUnpublishAction = async () => {
setSaving(true);
setError("");
try {
await api.post(`/melodies/${id}/unpublish`);
navigate(`/melodies/${id}`);
} catch (err) {
setError(err.message);
} finally {
setSaving(false);
}
};
const handleSubmit = async (e) => {
e.preventDefault();
// Default form submit: save as draft for new, update for existing
if (isEdit) {
await handleSave(false);
} else {
await handleSave(false);
}
};
if (loading) {
return <div className="text-center py-8" style={mutedStyle}>Loading...</div>;
}
@@ -214,15 +262,70 @@ export default function MelodyForm() {
>
Cancel
</button>
<button
type="submit"
form="melody-form"
disabled={saving || uploading}
className="px-4 py-2 text-sm rounded-md disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
style={{ backgroundColor: "var(--btn-primary)", color: "var(--text-white)" }}
>
{uploading ? "Uploading files..." : saving ? "Saving..." : isEdit ? "Update Melody" : "Create Melody"}
</button>
{!isEdit ? (
<>
<button
type="submit"
form="melody-form"
disabled={saving || uploading}
className="px-4 py-2 text-sm rounded-md disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
style={{ backgroundColor: "var(--bg-card-hover)", color: "var(--text-primary)", border: "1px solid var(--border-primary)" }}
>
{saving ? "Saving..." : "Save as Draft"}
</button>
<button
type="button"
disabled={saving || uploading}
onClick={() => handleSave(true)}
className="px-4 py-2 text-sm rounded-md disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
style={{ backgroundColor: "var(--btn-primary)", color: "var(--text-white)" }}
>
{uploading ? "Uploading files..." : "Publish Melody"}
</button>
</>
) : melodyStatus === "draft" ? (
<>
<button
type="submit"
form="melody-form"
disabled={saving || uploading}
className="px-4 py-2 text-sm rounded-md disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
style={{ backgroundColor: "var(--bg-card-hover)", color: "var(--text-primary)", border: "1px solid var(--border-primary)" }}
>
{saving ? "Saving..." : "Update Draft"}
</button>
<button
type="button"
disabled={saving || uploading}
onClick={handlePublishAction}
className="px-4 py-2 text-sm rounded-md disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
style={{ backgroundColor: "#16a34a", color: "#fff" }}
>
{uploading ? "Uploading files..." : "Publish"}
</button>
</>
) : (
<>
<button
type="submit"
form="melody-form"
disabled={saving || uploading}
className="px-4 py-2 text-sm rounded-md disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
style={{ backgroundColor: "var(--btn-primary)", color: "var(--text-white)" }}
>
{uploading ? "Uploading files..." : saving ? "Saving..." : "Update Melody"}
</button>
<button
type="button"
disabled={saving || uploading}
onClick={handleUnpublishAction}
className="px-4 py-2 text-sm rounded-md disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
style={{ backgroundColor: "#ea580c", color: "#fff" }}
>
Unpublish
</button>
</>
)}
</div>
</div>