feat(generator): post data to parent preset form

This commit is contained in:
2026-07-31 06:43:01 +07:00
parent bc36e40967
commit 437980ea9f
4 changed files with 44 additions and 14 deletions
+24
View File
@@ -5488,6 +5488,30 @@ const AIPresetModal = ({ isOpen, onClose }) => {
.finally(function() { setSyncing(false); }); .finally(function() { setSyncing(false); });
}, []); }, []);
// Listen for GENERATOR_PRESET_DATA from the iframe generator modal
React.useEffect(() => {
const handleMessage = (event) => {
if (event.data && event.data.type === 'GENERATOR_PRESET_DATA') {
const d = event.data;
setFormName(d.name || '');
setFormCategory(d.category || 'Orchestral / Film Score');
setSelectedCategory(d.category || 'Orchestral / Film Score');
setFormKeywords(d.keywords || '');
setFormBars(parseInt(d.default_bars) || 8);
setFormBpm(parseInt(d.default_bpm) || 120);
setFormScale(d.default_scale || 'C Minor');
setFormTemplate(d.template || '');
setEditingPreset('new');
setShowGeneratorModal(false);
setIsAddingCategory(false);
setNewCategoryValue('');
refreshPresets();
}
};
window.addEventListener('message', handleMessage);
return () => window.removeEventListener('message', handleMessage);
}, []);
const savePresets = (newPresets) => { const savePresets = (newPresets) => {
setPresets(newPresets); setPresets(newPresets);
mgr.presets = newPresets; mgr.presets = newPresets;
File diff suppressed because one or more lines are too long
+12 -13
View File
@@ -654,14 +654,13 @@
}, 2500); }, 2500);
} }
// Open Save Preset Modal Event Handler — auto-populate per spec // Open Save Preset Modal Event Handler — post data to parent React app
btnSavePresetModal.addEventListener('click', () => { btnSavePresetModal.addEventListener('click', () => {
const timeData = computeTimeMetrics(); const timeData = computeTimeMetrics();
const currentPromptText = promptOutputText.innerText.trim(); const currentPromptText = promptOutputText.innerText.trim();
const sectionType = inputSectionType.value.trim() || "Building Section"; const sectionType = inputSectionType.value.trim() || "Building Section";
const role = inputRole.value.trim() || "Composer"; const role = inputRole.value.trim() || "Composer";
const actionDesc = inputActionDesc.value.trim();
// Auto-infer Category based on Role // Auto-infer Category based on Role
let category = "Orchestral / Film Score"; let category = "Orchestral / Film Score";
@@ -679,17 +678,17 @@
]; ];
const keywordsStr = keywordList.filter(Boolean).join(', '); const keywordsStr = keywordList.filter(Boolean).join(', ');
// Populate Form Fields // Post data to parent window (React AI PROMPT PRESET MANAGER)
presetNameInput.value = `${sectionType} (${timeData.barCount} Bars)`; window.parent.postMessage({
presetCategorySelect.value = category; type: 'GENERATOR_PRESET_DATA',
presetKeywordsInput.value = keywordsStr; name: `${sectionType} (${timeData.barCount} Bars)`,
presetBarsInput.value = timeData.barCount; category: category,
presetBpmInput.value = 120; keywords: keywordsStr,
presetScaleInput.value = "C Minor"; default_bars: timeData.barCount,
presetTemplateTextarea.value = currentPromptText; default_bpm: 120,
default_scale: "C Minor",
// Display Modal template: currentPromptText
presetManagerModal.classList.remove('hidden'); }, '*');
}); });
// Close Modal Event Handlers // Close Modal Event Handlers
+6
View File
@@ -919,3 +919,9 @@
- **Tóm tắt thay đổi:** Áp dụng spec từ md/50_APPLY_GENERATOR.md vào md/49_AI_PROMPT_GENERATOR.md: (1) Category input chuyển thành `<select id="presetCategorySelect">`; (2) Thêm nút "Tạo preset có cấu trúc" (xanh lá) bên trái action bar; (3) autoFillPresetModal cập nhật logic infer category từ role/keywords; (4) Thêm handler `btnCreateStructuredPreset` thay static number bằng template variable; (5) Save handler dùng `presetCategorySelect.value`, dispatch `AI_PRESET_SAVED` CustomEvent. - **Tóm tắt thay đổi:** Áp dụng spec từ md/50_APPLY_GENERATOR.md vào md/49_AI_PROMPT_GENERATOR.md: (1) Category input chuyển thành `<select id="presetCategorySelect">`; (2) Thêm nút "Tạo preset có cấu trúc" (xanh lá) bên trái action bar; (3) autoFillPresetModal cập nhật logic infer category từ role/keywords; (4) Thêm handler `btnCreateStructuredPreset` thay static number bằng template variable; (5) Save handler dùng `presetCategorySelect.value`, dispatch `AI_PRESET_SAVED` CustomEvent.
- **Các file ảnh hưởng:** `md/49_AI_PROMPT_GENERATOR.md` - **Các file ảnh hưởng:** `md/49_AI_PROMPT_GENERATOR.md`
- **Ghi chú/Test (nếu có):** Refresh generator → Lưu thành Preset → Category tự chọn dropdown → Tạo preset có cấu trúc → số bars/beats biến thành {{bars}}/{{total_beats}}. - **Ghi chú/Test (nếu có):** Refresh generator → Lưu thành Preset → Category tự chọn dropdown → Tạo preset có cấu trúc → số bars/beats biến thành {{bars}}/{{total_beats}}.
---
### [2026-07-31 06:42] Task: Transfer generator data to parent AI PRESET MANAGER form
- **Tóm tắt thay đổi:** Thay vì mở modal standalone trong iframe generator, "Lưu thành Preset" giờ postMessage `GENERATOR_PRESET_DATA` lên parent window. React AIPresetModal thêm `message` listener nhận data, auto-populate form (name, category, keywords, bars, bpm, scale, template), set editingPreset='new' và đóng generator modal. Nút "Tạo preset có cấu trúc" trong React form vẫn hoạt động độc lập.
- **Các file ảnh hưởng:** `md/49_AI_PROMPT_GENERATOR.md`, `app/static/js/app.jsx`, `app/static/js/app.precompiled.js`
- **Ghi chú/Test (nếu có):** `npm run build` pass. Flow: generator iframe → Lưu thành Preset → form React tự điền → generator modal đóng.