diff --git a/.github/workflows/auto-merge-claude.yml b/.github/workflows/auto-merge-claude.yml index 1d8ae057..0f3ceea9 100644 --- a/.github/workflows/auto-merge-claude.yml +++ b/.github/workflows/auto-merge-claude.yml @@ -62,6 +62,8 @@ jobs: - run: npm ci - run: npm run build:cdn + env: + NODE_OPTIONS: --max-old-space-size=6144 - name: Prepare site files run: | diff --git a/.github/workflows/build-cdn.yml b/.github/workflows/build-cdn.yml index 93165d5b..c2fe202c 100644 --- a/.github/workflows/build-cdn.yml +++ b/.github/workflows/build-cdn.yml @@ -8,6 +8,7 @@ jobs: runs-on: ubuntu-latest permissions: contents: write + actions: write steps: - uses: actions/checkout@v4 @@ -32,3 +33,8 @@ jobs: git add dist-cdn/ git diff --cached --quiet || git commit -m "chore: rebuild dist-cdn [skip ci]" git push origin main + + - name: Trigger deploy + run: gh workflow run deploy.yml --ref main + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/src/app/components/SqlDataTable.tsx b/src/app/components/SqlDataTable.tsx index f3cafa7f..c3646416 100644 --- a/src/app/components/SqlDataTable.tsx +++ b/src/app/components/SqlDataTable.tsx @@ -1,14 +1,10 @@ -/** - * SqlDataTable — remplace SimpleDatatables pour les cellules sql/table. - * Utilise DataTablePaginated de @sqlrooms/data-table avec tri et pagination - * client-side. Gère les colonnes spéciales PERCENT et TREND. - */ import { useMemo, useState } from 'react' -import DataTablePaginated from '@sqlrooms/data-table/dist/DataTablePaginated' +import { DataTablePaginated, QueryDataTableActionsMenu } from '@sqlrooms/data-table' +import { sanitizeQuery } from '@sqlrooms/duckdb' import { rawTableDataStore as _rawTableDataStore } from '../../lib/tableDataStore' import { parseColumnRoles, getTableColumnDisplayNames } from '../../lib/EChartSqlParser' +import { ConfigManager } from '../../lib/ConfigManager' -// Types Arrow numériques tels que retournés par String(field.type) de duckdb-wasm const NUMERIC_ARROW_RE = /^(Int|Uint|Float|Decimal)/i function colMeta(schemaTypes: Record, key: string) { @@ -23,6 +19,7 @@ export function SqlDataTable({ cell, searchable = false }: { cell: any; searchab const rawResults = _rawTableDataStore.get(cell._id) || cell._results || [] const schemaTypes: Record = cell._schemaTypes || {} + const cellQuery = sanitizeQuery(ConfigManager.getCellQuery(cell, 'main') || '') const { columns, allColKeys } = useMemo(() => { if (!rawResults?.length) return { columns: [], allColKeys: [] } @@ -130,6 +127,7 @@ export function SqlDataTable({ cell, searchable = false }: { cell: any; searchab onPaginationChange={setPagination} onSortingChange={setSorting} fontSize="text-xs" + footerActions={cellQuery ? : null} /> ) diff --git a/src/app/room.tsx b/src/app/room.tsx index ebfd45b3..89e5386e 100644 --- a/src/app/room.tsx +++ b/src/app/room.tsx @@ -1,15 +1,16 @@ /** * Room — Composant racine utilisant RoomShell de @sqlrooms/room-shell. * - * - RoomShell.Sidebar : sidebar (boutons panels auto-inclus) + boutons custom + * - Sidebar custom : boutons groupés (datasources en haut du groupe bas) * - RoomShell.LayoutComposer : mosaic layout (NotebookPanel + DataSourcesPanel) * - RoomShell.LoadingProgress : barre de progression DuckDB * - RoomShell.CommandPalette : palette de commandes (Ctrl+K) * - Modals globaux (portals → document.body, indépendants du layout) */ -import { RoomShell } from '@sqlrooms/room-shell' +import { RoomShell, useBaseRoomShellStore } from '@sqlrooms/room-shell' import { useDisclosure, ThemeSwitch } from '@sqlrooms/ui' import { useShallow } from 'zustand/react/shallow' +import { useMemo } from 'react' import { roomStore, useNotebookStore } from './store/notebookStore' import { SqlEditorModal } from '@sqlrooms/sql-editor' import { BookHeartIcon, MessageSquareCodeIcon, PaintbrushIcon, Settings2Icon, TerminalIcon } from 'lucide-react' @@ -23,6 +24,33 @@ import { ExportModal, GistTokenModal, GistResultModal, JsonPassphraseModal } fro import { CellConfigModal } from './components/modals/CellConfigModal' import { LoopConfigModal, GroupSettingsModal, ChildGroupModal } from './components/modals/GroupModals' +function getMosaicLeaves(node: any): string[] { + if (!node) return [] + if (typeof node === 'string') return [node] + return [...getMosaicLeaves(node.first), ...getMosaicLeaves(node.second)] +} + +function DataPanelSidebarButton() { + const togglePanel = useBaseRoomShellStore(s => s.layout.togglePanel) + const layoutConfig = useBaseRoomShellStore(s => s.layout.config) + const panels = useBaseRoomShellStore(s => s.layout.panels) + const initialized = useBaseRoomShellStore(s => s.room.initialized) + + const panel = panels?.['data'] + const isSelected = useMemo(() => getMosaicLeaves(layoutConfig?.nodes).includes('data'), [layoutConfig]) + + if (!panel) return null + return ( + togglePanel('data')} + /> + ) +} + function DbEngineIcon({ className }: { className?: string }) { const dbEngine = useNotebookStore(s => s.dbEngine) return {dbEngine === 'ducklings' ? '🐤' : '🦆'} @@ -84,6 +112,9 @@ function SidebarControls() { {/* Ancrés en bas via spacer */}
+ {/* Sources de données — en haut du groupe ancré */} + + {/* Documentation (gist) */} s.showLayout) + return ( <> - +
- +
+
{/* Modals globaux — portals vers document.body, indépendants du layout */} @@ -135,7 +168,6 @@ export function Room() { -