feat: A20 phase 3 LOT 1 — shell + library migres, harnais csp_preview vert (v7.38.0)
Ajout : - e2e/csp_preview.spec.js — apercu CSP strict SANS deployer : le build officiel @alpinejs/csp (e2e/fixtures/alpine.csp.js, 0 eval) est servi a la place de alpine.min.js par interception Playwright ; toute expression que le parseur maison ne digere pas = pageerror (filet). Premiere surface VERTE : library (composant lie, icones SVG via Alpine.effect, recherche ouverte + focalisee, 0 erreur). Changed : - 16 composants x-data="fn()" enregistres via Alpine.data (registre = seule resolution du build CSP, probe « Undefined variable » ; scripts classiques executes pendant le parsing => alpine:init toujours joint) : appState, libraryPage, workspacesPage, editorState, board x4, settings/import/table_view/team_load/trash/workspace/welcome/accounts/ card_detail. - base.html (shell) migre : x-effect document.* -> syncSidebarClass(), $nextTick(arrow) -> initSidebarSort(), window.FlowDeck.* -> fdCreatePage/fdCreateFolder/fdGwRefresh, Object.keys/Math.min/ window.innerWidth dans x-for et :style -> sidebarSections()/ sectionMenuPos() — tout = simple appel de methode. - x-html restants du shell -> x-init + Alpine.effect : icone agent, carte projet, library x3 ; recherche library -> toggleSearch() (Alpine.nextTick) ; openMoveSelected() pour Object.keys en expression. - eslint : 70 warnings -> 0/0 (globals getCsrf depuis A38 ph1, /* exported openCardDetail */ + /* global owner, repo */, 3 ;; residuels). suite **1093/1093** · ruff OK · eslint 0/0 · E2E 3/3 (csp_preview + smoke x2) · docs a jour (ROADMAP ph3 LOT 1, CHANGELOG, WORKLOAD, VERSION)
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
// FlowDeck Notion UI — Client-side logic
|
||||
// Alpine.js + SortableJS + HTMX + Mobile support
|
||||
/* exported openCardDetail */ /* global owner, repo */
|
||||
|
||||
// ── Frontend Error Capture ──────────────────────────────────
|
||||
// Intercepte TOUTES les erreurs JS et les envoie au backend.
|
||||
|
||||
+22
-2
@@ -18,6 +18,11 @@ const BD=(()=>{try{const el=document.getElementById('bd-config');return el?JSON.
|
||||
el.classList.add('active');
|
||||
}
|
||||
|
||||
// A20 phase 3 : registre Alpine.data (le build CSP ne résout pas les
|
||||
|
||||
// globales window — probe « Undefined variable: kanbanBoard »).
|
||||
|
||||
document.addEventListener('alpine:init', function () { Alpine.data('kanbanBoard', kanbanBoard); });
|
||||
function kanbanBoard() {
|
||||
return {
|
||||
collapsedGroups: [],
|
||||
@@ -33,6 +38,11 @@ const BD=(()=>{try{const el=document.getElementById('bd-config');return el?JSON.
|
||||
};
|
||||
}
|
||||
|
||||
// A20 phase 3 : registre Alpine.data (le build CSP ne résout pas les
|
||||
|
||||
// globales window — probe « Undefined variable: filterSystem »).
|
||||
|
||||
document.addEventListener('alpine:init', function () { Alpine.data('filterSystem', filterSystem); });
|
||||
function filterSystem() {
|
||||
return {
|
||||
activeFilters: [],
|
||||
@@ -67,6 +77,11 @@ const BD=(()=>{try{const el=document.getElementById('bd-config');return el?JSON.
|
||||
};
|
||||
}
|
||||
|
||||
// A20 phase 3 : registre Alpine.data (le build CSP ne résout pas les
|
||||
|
||||
// globales window — probe « Undefined variable: sortSystem »).
|
||||
|
||||
document.addEventListener('alpine:init', function () { Alpine.data('sortSystem', sortSystem); });
|
||||
function sortSystem() {
|
||||
return {
|
||||
sorts: [],
|
||||
@@ -89,12 +104,17 @@ const BD=(()=>{try{const el=document.getElementById('bd-config');return el?JSON.
|
||||
};
|
||||
}
|
||||
|
||||
// A20 phase 3 : registre Alpine.data (le build CSP ne résout pas les
|
||||
|
||||
// globales window — probe « Undefined variable: newIssueForm »).
|
||||
|
||||
document.addEventListener('alpine:init', function () { Alpine.data('newIssueForm', newIssueForm); });
|
||||
function newIssueForm() {
|
||||
return {
|
||||
title: '', status: 'todo',
|
||||
create() {
|
||||
if (!this.title.trim()) return;
|
||||
const csrf = getCsrf();;
|
||||
const csrf = getCsrf();
|
||||
fetch(`/api/issues/${owner}/${repo}?title=${encodeURIComponent(this.title)}&labels=${this.status}`, {
|
||||
method: 'POST',
|
||||
headers: { 'X-CSRF-Token': csrf }
|
||||
@@ -131,7 +151,7 @@ const BD=(()=>{try{const el=document.getElementById('bd-config');return el?JSON.
|
||||
onEnd: function(evt) {
|
||||
const cardId = evt.item.dataset.cardId;
|
||||
const toStatus = evt.to.dataset.status;
|
||||
const csrf = getCsrf();;
|
||||
const csrf = getCsrf();
|
||||
fetch(`/api/move?owner=${owner}&repo=${repo}&issue_id=${cardId}&column=${toStatus}`, {
|
||||
method: 'POST',
|
||||
headers: { 'X-CSRF-Token': csrf }
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
/* exported importWizard -- appeles depuis les attributs HTML des templates */
|
||||
|
||||
// A20 phase 3 : registre Alpine.data (le build CSP ne résout pas les
|
||||
|
||||
// globales window — probe « Undefined variable: importWizard »).
|
||||
|
||||
document.addEventListener('alpine:init', function () { Alpine.data('importWizard', importWizard); });
|
||||
function importWizard() {
|
||||
return {
|
||||
sources: [],
|
||||
|
||||
+28
-2
@@ -1,5 +1,11 @@
|
||||
/* exported libraryPage -- appeles depuis les attributs HTML des templates */
|
||||
|
||||
// A20 phase 3 : enregistrement Alpine.data — le build CSP ne résout que le
|
||||
// registre (probe : globale window → « Undefined variable: libraryPage »).
|
||||
document.addEventListener('alpine:init', function () {
|
||||
Alpine.data('libraryPage', libraryPage);
|
||||
});
|
||||
|
||||
function libraryPage() {
|
||||
return {
|
||||
tab: 'recents',
|
||||
@@ -160,7 +166,27 @@ function libraryPage() {
|
||||
|
||||
_escHtml(s) { var d=document.createElement('div'); d.textContent = s||''; return d.innerHTML; },
|
||||
_escAttr(s) { return String(s||'').replace(/&/g,'&').replace(/"/g,'"').replace(/</g,'<').replace(/>/g,'>'); },
|
||||
_renderIcon(item) {
|
||||
openMoveSelected() {
|
||||
this.openMovePicker(Object.keys(this.selected).map(Number));
|
||||
},
|
||||
// ── A20 phase 3 (surface library) : formes compatibles build CSP ──
|
||||
// $nextTick / x-html ne passent pas par l'évaluateur maison du build CSP
|
||||
// (arrow inline = parse error ; x-html = interdit) → méthodes JS réelles,
|
||||
// réactivité via Alpine.effect — valable sous les deux builds.
|
||||
toggleSearch() {
|
||||
this.searchOpen = !this.searchOpen;
|
||||
if (this.searchOpen) Alpine.nextTick(() => {
|
||||
var el = document.getElementById('lib-search-input');
|
||||
if (el) el.focus();
|
||||
});
|
||||
},
|
||||
bindHtmlIcon(el) {
|
||||
Alpine.effect(() => { el.innerHTML = getSvgIcon(this.emptyIcon, 48); });
|
||||
},
|
||||
bindHtmlItem(el, item) {
|
||||
Alpine.effect(() => { el.innerHTML = this._renderIcon(item); });
|
||||
},
|
||||
_renderIcon(item) {
|
||||
if (!item) return getSvgIcon('file', 14);
|
||||
// Custom emoji (image URL), icon name, or unicode emoji
|
||||
if (item.page_icon) return '<span style="font-size:14px;line-height:1;display:inline-flex;align-items:center;">' + (window.fdIconHtml ? window.fdIconHtml(item.page_icon, 14) : this._escHtml(item.page_icon)) + '</span>';
|
||||
@@ -363,7 +389,7 @@ function libraryPage() {
|
||||
},
|
||||
|
||||
_getCsrf() {
|
||||
var m = getCsrf();;
|
||||
var m = getCsrf();
|
||||
return m;
|
||||
},
|
||||
|
||||
|
||||
@@ -2512,5 +2512,10 @@ applyAIBlocks(text){
|
||||
default: return c;
|
||||
}
|
||||
}
|
||||
// A20 phase 3 : registre Alpine.data (le build CSP ne résout pas les
|
||||
|
||||
// globales window — probe « Undefined variable: editorState »).
|
||||
|
||||
document.addEventListener('alpine:init', function () { Alpine.data('editorState', editorState); });
|
||||
window.editorState = editorState;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
/* exported settingsInit -- appeles depuis les attributs HTML des templates */
|
||||
const ST=(()=>{try{const el=document.getElementById('st-config');return el?JSON.parse(el.textContent):{}}catch{return {}}})();
|
||||
|
||||
// A20 phase 3 : registre Alpine.data (le build CSP ne résout pas les
|
||||
|
||||
// globales window — probe « Undefined variable: settingsInit »).
|
||||
|
||||
document.addEventListener('alpine:init', function () { Alpine.data('settingsInit', settingsInit); });
|
||||
function settingsInit() {
|
||||
return {
|
||||
activeSection: 'account',
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
/* exported workspacesPage -- appeles depuis les attributs HTML des templates */
|
||||
|
||||
// A20 phase 3 : registre Alpine.data (le build CSP ne résout pas les
|
||||
|
||||
// globales window — probe « Undefined variable: workspacesPage »).
|
||||
|
||||
document.addEventListener('alpine:init', function () { Alpine.data('workspacesPage', workspacesPage); });
|
||||
function workspacesPage() {
|
||||
return {
|
||||
workspaces: [],
|
||||
|
||||
Reference in New Issue
Block a user