diff --git a/app/templates/_database_table_scripts.html b/app/templates/_database_table_scripts.html index a5b282b..a852af5 100644 --- a/app/templates/_database_table_scripts.html +++ b/app/templates/_database_table_scripts.html @@ -232,31 +232,72 @@ } catch(e) { console.error('[DB] addNewPage error:', e); } } - // ── Property modal (uses global modal from page) ── + // ── Property modal (inline, self-contained) ── function showPropModal() { - const modal = document.getElementById('db-prop-modal'); - if (!modal) return; - modal._dbInstance = this; - modal.style.display = 'flex'; - document.getElementById('db-prop-name-input').value = ''; - document.getElementById('db-prop-name-input').focus(); - // Store ref to this instance for the create handler - modal._collectionId = collectionId; - modal._onPropCreated = function(newProp) { state.properties.push(newProp); render(); }; + // Remove any existing inline modal + var old = containerEl.querySelector('.db-prop-modal-inline'); + if (old) old.remove(); + + var modal = document.createElement('div'); + modal.className = 'db-prop-modal-inline'; + modal.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.3);z-index:1000;display:flex;align-items:center;justify-content:center'; + modal.innerHTML = '
'; + document.body.appendChild(modal); + + var nameInput = modal.querySelector('.db-prop-name-inline'); + nameInput.focus(); + + modal.querySelector('.db-prop-modal-close-btn').onclick = function(){ modal.remove(); }; + modal.querySelector('.db-prop-cancel-inline').onclick = function(){ modal.remove(); }; + modal.onclick = function(e){ if(e.target===modal) modal.remove(); }; + + modal.querySelector('.db-prop-create-inline').onclick = async function(){ + var name = nameInput.value.trim(); + if(!name) return; + var type = modal.querySelector('.db-prop-type-inline').value; + try { + var r = await fetch('/db/'+collectionId+'/properties/api',{ + method:'POST',headers:{'Content-Type':'application/json','X-CSRF-Token':getCsrf()}, + body:JSON.stringify({name:name,prop_type:type}) + }); + var d = await r.json(); + if(d.id){ state.properties.push(d); render(); modal.remove(); } + } catch(e){ console.error('[DB] createProperty error:',e); } + }; + nameInput.onkeydown = function(e){ if(e.key==='Enter') modal.querySelector('.db-prop-create-inline').click(); }; } - // ── Column context menu ── + // ── Column context menu (inline) ── function showColMenu(propId, propType, propName, anchor) { - const menu = document.getElementById('db-col-menu'); - if (!menu) return; - state.colMenuPropId = propId; - document.getElementById('db-col-menu-icon').innerHTML = propTypeSvg(propType); - const nameEl = document.getElementById('db-col-menu-name'); - nameEl.textContent = propName; - const rect = anchor.getBoundingClientRect(); - menu.style.top = (rect.bottom+4)+'px'; menu.style.left = rect.left+'px'; menu.style.display = 'block'; + // Remove any existing + var old = document.querySelector('.db-col-menu-inline'); + if (old) old.remove(); + + var menu = document.createElement('div'); + menu.className = 'db-col-menu-inline'; + menu.style.cssText = 'position:fixed;min-width:240px;max-width:320px;background:var(--bg-modal);border:1px solid var(--border);border-radius:8px;box-shadow:0 8px 24px rgba(0,0,0,0.14);z-index:800;padding:4px 0;font-size:13px;color:var(--text-primary)'; + var rect = anchor.getBoundingClientRect(); + menu.style.top = (rect.bottom+4)+'px'; menu.style.left = rect.left+'px'; + + menu.innerHTML = '