fix: peek des bases hydrate FlowDeckDB + Open de ligne, tableau pleine largeur (v7.50.1)
FlowDeck CI / test (push) Failing after 14m37s
FlowDeck CI / lint (push) Successful in 2m11s
FlowDeck CI / docker (push) Skipped

- page_editor_embed.html incluait seulement _page_editor_scripts.html :
  window.FlowDeckDB etait undefined dans l'iframe -> une base ouverte en side
  peek restait a « Loading database... ». Include _database_table_scripts.html
  ajoute (meme traitement que page_editor.html).
- Le panneau #db-side-peek n'existait que dans _database_table.html : hors page
  dediee, openPageInSidePeek etait un no-op. Desormais cree a la demande par
  ensureDbPeek (database_table.js) ; markup unique retire du partial.
- .database-table-container : plafond 1100px retire (regle heritee de Library)
  + max-width 100% pour .db-first et database-page-title : le tableau prend la
  largeur du document, plus de barre de scroll parasite sous le tableau.
- Tests: test_embed_editor_can_render_inline_databases. Suite 1265/0 (-n auto)
  + ruff 0. Bump VERSION/main.py 7.50.1, CHANGELOG, WORKLOAD, OpenAPI.
This commit is contained in:
2026-10-06 15:15:01 -04:00
parent 3706689eca
commit f53205bc45
10 changed files with 137 additions and 92 deletions
+7 -6
View File
@@ -2246,13 +2246,15 @@ button.breadcrumb-current { max-width: 260px; }
/* Page de base (premier bloc = embed collection) : le titre et le tableau
s'alignent sur la marge gauche de la topbar (16px) au lieu d'être centrés
dans la colonne 900px — le tableau démarre au ras du sidebar. */
dans la colonne 900px — le tableau démarre au ras du sidebar et prend la
LARGEUR DU DOCUMENT (les colonnes dictent le scroll horizontal). */
.page-editor-wrapper.db-first .page-cover-area,
.page-editor-wrapper.db-first .page-title-block,
.page-editor-wrapper.db-first .blocks-container {
max-width: 1100px;
max-width: 100%;
margin: 0;
padding-left: var(--space-lg);
padding-right: var(--space-lg);
}
/* Une base embarquée ne doit jamais déborder de sa colonne de blocs :
@@ -2262,7 +2264,7 @@ button.breadcrumb-current { max-width: 260px; }
/* Titre des pages de base dédiées (page_editor_collection.html) — même
liseré gauche que .database-table-container. */
.database-page-title {
max-width: 1100px;
max-width: 100%;
margin: 0;
padding: 28px var(--space-lg) 0;
font-size: 30px;
@@ -3899,11 +3901,10 @@ button.breadcrumb-current { max-width: 260px; }
═══════════════════════════════════════════════════════════ */
/* Base = viewport du contenu ; les vues tabulaires larges (bases de
données) s'alignent à gauche, au ras de la marge, à la même largeur
que Library (1100px). */
données) prennent la LARGEUR DU DOCUMENT (les colonnes dictent le scroll
horizontal), alignées à gauche au ras de la marge. */
.database-table-container {
width: 100%;
max-width: 1100px;
margin: 0;
/* var(--space-lg) = padding de .topbar : le bord gauche du tableau
s'aligne sur le titre du fil d'ariane, au ras de la marge. */
+75 -65
View File
@@ -1283,76 +1283,86 @@ const DB_CONFIG=(()=>{try{const el=document.getElementById('db-config');const v=
}
// ── 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) {
// Le panneau vit dans _database_table.html (page de base). Une base
// EMBARQUÉE dans un document n'a pas ce markup : on le crée à la demande
// (comme mt-peek de My Tasks), sinon l'icône Open de fin de ligne était
// un no-op silencieux. Il doit être câblé SUR le document, jamais via
// container.__x : le conteneur n'a pas de x-data.
var PEEK_HTML =
'<div class="peek-resize-handle" title="Glisser pour redimensionner — cliquer pour fermer"></div>' +
'<div class="db-side-peek-header">' +
'<button id="db-side-peek-close" title="Close"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg></button>' +
'<div class="db-side-peek-title" id="db-side-peek-title"></div>' +
'<button id="db-side-peek-full" title="Open full page"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 13v6a2 2 0 01-2 2H5a2 2 0 01-2-2V8a2 2 0 012-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg></button>' +
'</div>' +
'<div class="db-side-peek-body">' +
'<div class="db-side-peek-loading" id="db-side-peek-loading">Chargement…</div>' +
'<iframe id="db-side-peek-iframe" src="about:blank" title="Document" style="width:100%;height:100%;border:none;flex:1;min-height:0;"></iframe>' +
'</div>';
function ensureDbPeek() {
var p = document.getElementById('db-side-peek');
if (p) return p;
p = document.createElement('div');
p.id = 'db-side-peek';
p.className = 'db-side-peek';
p.innerHTML = PEEK_HTML;
document.body.appendChild(p);
document.getElementById('db-side-peek-close').addEventListener('click', closeDbPeek);
document.getElementById('db-side-peek-full').addEventListener('click', function () {
var f = document.getElementById('db-side-peek-iframe');
// `dataset.page` et non `iframe.src` : le src porte `?embed=1`,
// la pleine page doit garder sa sidebar et sa barre.
if (f && f.dataset.page) window.location.href = '/pages/' + f.dataset.page;
});
if (window.fdWirePeekResize) window.fdWirePeekResize(p, p.querySelector('.peek-resize-handle'), closeDbPeek);
return p;
}
function closeDbPeek() {
var p = document.getElementById('db-side-peek');
if (!p) return;
p.classList.remove('open');
document.getElementById('db-side-peek-iframe').src='about:blank';
var t = document.getElementById('db-side-peek-title');
if (t) t.textContent = '';
}
window.openPageInSidePeek = function(pageId) {
if (!pageId) return;
var peekEl = ensureDbPeek();
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 = ''; }
}
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';
// `?embed=1` : uniquement le document edite, pas l'habillage
// (sidebar + barre) — la pleine page reste via le bouton « full ».
if (iframe) { iframe.dataset.page = pid; iframe.src = '/pages/'+pid+'?embed=1'; }
})
.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() {
// `dataset.page` et non `iframe.src` : le src porte `?embed=1`,
// la pleine page doit garder sa sidebar et sa barre.
if (peekFrame && peekFrame.dataset.page) {
window.location.href = '/pages/' + peekFrame.dataset.page;
}
});
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape' && peekEl.classList.contains('open')) closeDbPeek();
});
document.addEventListener('pointerdown', function(e) {
peekEl.classList.add('open');
if (peekLoading) peekLoading.style.display = '';
if (peekFrame) peekFrame.src = 'about:blank';
if (peekTitle) peekTitle.textContent = '';
resolveRowContentPage(pageId).then(function(pid){
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);
if (peekLoading) peekLoading.style.display = 'none';
// `?embed=1` : uniquement le document edite, pas l'habillage
// (sidebar + barre) — la pleine page reste via le bouton « full ».
if (peekFrame) { peekFrame.dataset.page = pid; peekFrame.src = '/pages/'+pid+'?embed=1'; }
})
.catch(function(){
// L'échec est rendu DANS le panneau (srcdoc) : sous le build
// CSP d'Alpine les toasts ne s'affichent pas partout.
if (peekFrame) {
peekFrame.srcdoc = '<p style="font-family:sans-serif;color:#888;padding:40px;text-align:center">Impossible d’ouvrir le contenu de cette ligne</p>';
}
}
wireDbPeekResize();
}
peekEl.classList.add('open');
toast('Impossible d’ouvrir le contenu de cette ligne', 'error');
});
};
document.addEventListener('keydown', function(e) {
var p = document.getElementById('db-side-peek');
if (e.key === 'Escape' && p && p.classList.contains('open')) closeDbPeek();
});
document.addEventListener('pointerdown', function(e) {
var p = document.getElementById('db-side-peek');
if (!p || !p.classList.contains('open')) return;
if (p.contains(e.target)) return;
if (e.target.closest('#db-table-container, .database-table-container, [id^="inline-db-"]')) return;
closeDbPeek();
});
function resolveRowContentPage(rowId){
return fetch('/db/pages/'+rowId+'/open/api')