fix: side peek des bases repasse en vanilla JS + largeur 1100px standard (v7.49.0)
- Panneau peek: les bindings Alpine (x-data absent du conteneur) rendaient loovverture et le redimensionnement inoperants -> cblage direct sur le document. - Helper unique window.fdWirePeekResize (app.js): pointer capture, 300px-90vw, clic=fermer, largeur persiste fd_peek_width partagee entre les 4 peeks. - database-table-container margin:0 (tableau colle a gauche, marge Library). - .lib-container remonte dans app.css (trash etait pleine largeur), .db-index 1100px. - ObsiGate verifie sans code: creation .xlsx OK (openpyxl, #186).
This commit is contained in:
+91
-40
@@ -238,6 +238,23 @@ const DB_CONFIG=(()=>{try{const el=document.getElementById('db-config');const v=
|
||||
return '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">'+(VIEW_ICONS[t]||VIEW_ICONS.table)+'</svg>';
|
||||
}
|
||||
|
||||
function taskDbButton(collection) {
|
||||
// Le libellé suit l'état réel de la base : convertie, à
|
||||
// configurer, ou pas encore convertie. Un simple ✓ était
|
||||
// introuvable pour l'utilisateur.
|
||||
var isTask = !!(collection && collection.is_task);
|
||||
var mapped = !!(collection && collection.task_assignee_prop &&
|
||||
collection.task_status_prop && collection.task_due_prop);
|
||||
var label = isTask ? (mapped ? '✓ Base de tâches' : '⚠ Configurer')
|
||||
: 'Convertir en base de tâches';
|
||||
var title = isTask
|
||||
? (mapped ? 'Cette base alimente My Tasks'
|
||||
: 'Base connectée mais mapping incomplet — reenregistrer')
|
||||
: 'Relier Assigné à / Statut / Échéance pour alimenter My Tasks';
|
||||
return '<button class="db-task-db-btn" data-task-db="' + collectionId +
|
||||
'" title="' + escHtml(title) + '">' + label + '</button>';
|
||||
}
|
||||
|
||||
function renderViewBar() {
|
||||
var h = '<div class="db-view-bar" style="padding:4px 0 8px"><div class="db-view-tabs">';
|
||||
if (!state.views.length) {
|
||||
@@ -251,7 +268,8 @@ const DB_CONFIG=(()=>{try{const el=document.getElementById('db-config');const v=
|
||||
});
|
||||
h += '<button class="db-view-add" data-view-add="1" title="Add a view">+</button>';
|
||||
h += '</div>';
|
||||
h += '<div class="db-view-actions"><button class="db-btn-new db-add-page-btn">+ New</button></div>';
|
||||
h += '<div class="db-view-actions">' + taskDbButton(state.collection) +
|
||||
'<button class="db-btn-new db-add-page-btn">+ New</button></div>';
|
||||
h += '</div>';
|
||||
return h;
|
||||
}
|
||||
@@ -1264,51 +1282,84 @@ const DB_CONFIG=(()=>{try{const el=document.getElementById('db-config');const v=
|
||||
}
|
||||
}
|
||||
|
||||
// ── Global Side Peek for Database Pages (auto-creates panel) ──
|
||||
function openPageInSidePeek(pageId) {
|
||||
var panel = document.getElementById('db-side-peek');
|
||||
if (!panel) {
|
||||
panel = document.createElement('div');
|
||||
panel.id = 'db-side-peek';
|
||||
panel.style.cssText = 'position:fixed;top:0;right:0;width:560px;height:100vh;background:var(--bg-primary);box-shadow:-4px 0 20px rgba(0,0,0,0.12);z-index:900;display:flex;flex-direction:column';
|
||||
panel.innerHTML = '<div id="db-side-peek-resize" style="position:absolute;top:0;left:0;width:6px;height:100%;cursor:col-resize;z-index:2"></div>'+
|
||||
'<div style="display:flex;align-items:center;justify-content:space-between;padding:8px 12px;border-bottom:1px solid var(--border);flex-shrink:0">'+
|
||||
'<button id="db-side-peek-close" style="display:flex;align-items:center;justify-content:center;width:28px;height:28px;border-radius:6px;border:none;background:transparent;cursor:pointer;font-size:18px;color:var(--text-dim)">×</button>'+
|
||||
'<button id="db-side-peek-full" style="display:flex;align-items:center;justify-content:center;width:28px;height:28px;border-radius:6px;border:none;background:transparent;cursor:pointer;font-size:18px;color:var(--text-dim)" title="Open full page">↗</button>'+
|
||||
'</div>'+
|
||||
'<iframe id="db-side-peek-iframe" src="" style="width:100%;height:100%;border:none;flex:1"></iframe>';
|
||||
document.body.appendChild(panel);
|
||||
document.getElementById('db-side-peek-close').onclick = function(){ panel.style.display='none'; document.getElementById('db-side-peek-iframe').src=''; };
|
||||
document.getElementById('db-side-peek-full').onclick = function(){
|
||||
var ifr = document.getElementById('db-side-peek-iframe');
|
||||
if (ifr && ifr.src) window.open(ifr.src.replace('?embed=1',''),'_blank');
|
||||
};
|
||||
var rh = document.getElementById('db-side-peek-resize');
|
||||
rh.onpointerdown = function(e) {
|
||||
e.preventDefault(); e.stopPropagation();
|
||||
var sx = e.clientX, sw = panel.offsetWidth;
|
||||
function mv(ev) { var w = Math.max(300, Math.min(window.innerWidth*0.9, sw-(ev.clientX-sx))); panel.style.width = w+'px'; }
|
||||
function up() { document.removeEventListener('pointermove',mv); document.removeEventListener('pointerup',up); document.body.style.cursor=''; }
|
||||
document.body.style.cursor='col-resize';
|
||||
document.addEventListener('pointermove',mv); document.addEventListener('pointerup',up);
|
||||
};
|
||||
// ── Side peek : panneau latéral des lignes de base (vanilla JS) ──
|
||||
// Le panneau vit dans _database_table.html (page de base ET bases
|
||||
// embarquées inline). Il doit être câblé SUR le document, jamais via
|
||||
// container.__x : le conteneur n'a pas de x-data (les bindings Alpine
|
||||
// du panneau restaient inertes — clic sur une ligne = rien).
|
||||
var peekEl = document.getElementById('db-side-peek');
|
||||
// Sans panneau (collections embarquées inline dans l'éditeur), le clic ne
|
||||
// doit pas lever de ReferenceError : repli discret, comme l'ancien code.
|
||||
if (!peekEl) window.openPageInSidePeek = function() {};
|
||||
if (peekEl) {
|
||||
var peekFrame = document.getElementById('db-side-peek-iframe');
|
||||
var peekTitle = document.getElementById('db-side-peek-title');
|
||||
var peekLoading = document.getElementById('db-side-peek-loading');
|
||||
function closeDbPeek() {
|
||||
peekEl.classList.remove('open');
|
||||
document.getElementById('db-side-peek-iframe').src='about:blank';
|
||||
if (peekTitle) { peekTitle.textContent = ''; }
|
||||
}
|
||||
var iframe = document.getElementById('db-side-peek-iframe');
|
||||
// v6.5.0: a database row id is NOT a pages id (raw /pages/{rowId}
|
||||
// opened an unrelated page with the same id) — resolve the row's
|
||||
// content page first (lazy-created), then load the real editor.
|
||||
resolveRowContentPage(pageId).then(function(pid){
|
||||
var fr = document.getElementById('db-side-peek-iframe');
|
||||
if (fr) { fr.src = '/pages/'+pid+'?embed=1'; panel.style.display = 'flex'; }
|
||||
window.openPageInSidePeek = function(pageId) {
|
||||
if (!pageId) return;
|
||||
peekEl.classList.add('open');
|
||||
if (peekLoading) peekLoading.style.display = '';
|
||||
var iframe = document.getElementById('db-side-peek-iframe');
|
||||
if (iframe) iframe.src='about:blank';
|
||||
if (peekTitle) peekTitle.textContent = '';
|
||||
resolveRowContentPage(pageId).then(function(pid){
|
||||
if (!peekEl.classList.contains('open')) return;
|
||||
if (peekTitle) peekTitle.textContent = '';
|
||||
if (peekLoading) peekLoading.style.display = 'none';
|
||||
if (iframe) iframe.src = '/pages/'+pid;
|
||||
})
|
||||
.catch(function(){
|
||||
// L'échec est rendu DANS le panneau (srcdoc) : sous le build
|
||||
// CSP d'Alpine les toasts ne s'affichent pas partout.
|
||||
if (iframe) {
|
||||
iframe.srcdoc = '<p style="font-family:sans-serif;color:#888;padding:40px;text-align:center">Impossible d’ouvrir le contenu de cette ligne</p>';
|
||||
}
|
||||
peekEl.classList.add('open');
|
||||
toast('Impossible d’ouvrir le contenu de cette ligne', 'error');
|
||||
});
|
||||
};
|
||||
var pc = document.getElementById('db-side-peek-close');
|
||||
if (pc) pc.addEventListener('click', closeDbPeek);
|
||||
var pf = document.getElementById('db-side-peek-full');
|
||||
if (pf) pf.addEventListener('click', function() {
|
||||
if (peekFrame && peekFrame.src && peekFrame.src !== 'about:blank') {
|
||||
window.location.href = peekFrame.src;
|
||||
}
|
||||
});
|
||||
if (iframe) panel.style.display = 'flex';
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Escape' && peekEl.classList.contains('open')) closeDbPeek();
|
||||
});
|
||||
document.addEventListener('pointerdown', function(e) {
|
||||
if (!peekEl.classList.contains('open')) return;
|
||||
if (peekEl.contains(e.target)) return;
|
||||
if (e.target.closest('#db-table-container, .database-table-container, [id^="inline-db-"]')) return;
|
||||
closeDbPeek();
|
||||
});
|
||||
function wireDbPeekResize() {
|
||||
if (window.fdWirePeekResize) {
|
||||
window.fdWirePeekResize(peekEl, peekEl.querySelector('.peek-resize-handle'), closeDbPeek);
|
||||
} else if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', wireDbPeekResize);
|
||||
}
|
||||
}
|
||||
wireDbPeekResize();
|
||||
}
|
||||
|
||||
function resolveRowContentPage(rowId){
|
||||
return fetch('/db/pages/'+rowId+'/open/api')
|
||||
.then(function(r){ return r.ok ? r.json() : null; })
|
||||
.then(function(d){ return (d && d.page_id) ? d.page_id : rowId; })
|
||||
.catch(function(){ return rowId; });
|
||||
.then(function(r){
|
||||
if (!r.ok) throw new Error('HTTP ' + r.status);
|
||||
return r.json();
|
||||
})
|
||||
.then(function(d){
|
||||
if (!d || !d.page_id) throw new Error('page de contenu introuvable');
|
||||
return d.page_id;
|
||||
});
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user