fix(database): rewrite table view in vanilla JS (Alpine 3.14.9 compat)
Alpine 3.14.9 evaluates x-data expressions before Alpine.data() registration, causing 'pages is not defined', 'emptyRows is not defined', etc. Solution: pure vanilla JS DOM rendering (same pattern as Library fix). - _database_table.html: static DOM with IDs only, no Alpine directives - _database_table_scripts.html: vanilla JS state, render, cell editing, modals - Removes all x-data, x-for, x-show, x-model from database table
This commit is contained in:
@@ -1,145 +1,53 @@
|
||||
<!-- ═══════════ Database Table View (Notion-style) ═══════════ -->
|
||||
<div x-data="databaseTable()" x-init="init($el)" class="database-table-container">
|
||||
<!-- ═══════════ Database Table View (Notion-style) — Vanilla JS ═══════════ -->
|
||||
<div id="db-table-container" class="database-table-container">
|
||||
<!-- View Selector Bar -->
|
||||
<div class="db-view-bar">
|
||||
<div id="db-view-bar" class="db-view-bar">
|
||||
<div class="db-view-tabs">
|
||||
<button class="db-view-tab active"
|
||||
@click="switchView('table')">
|
||||
{{ fd_icon("table",14) }} Table
|
||||
<button id="db-view-tab-table" class="db-view-tab active">
|
||||
{{ fd_icon("grid",14) }} Table
|
||||
</button>
|
||||
<button class="db-view-add" @click="addViewMenuOpen=!addViewMenuOpen"
|
||||
title="Add a view">
|
||||
<button id="db-view-add-btn" class="db-view-add" title="Add a view">
|
||||
{{ fd_icon("plus",14) }}
|
||||
</button>
|
||||
<!-- View type dropdown -->
|
||||
<div x-show="addViewMenuOpen" @click.outside="addViewMenuOpen=false"
|
||||
class="db-dropdown" x-transition>
|
||||
<div id="db-add-view-dropdown" class="db-dropdown" style="display:none">
|
||||
<div class="db-dropdown-header">Add a new view</div>
|
||||
<div class="db-dropdown-item" @click="addViewMenuOpen=false">{{ fd_icon("table",14) }} Table</div>
|
||||
<div class="db-dropdown-item" @click="addViewMenuOpen=false">{{ fd_icon("columns",14) }} Board</div>
|
||||
<div class="db-dropdown-item" @click="addViewMenuOpen=false">{{ fd_icon("list",14) }} List</div>
|
||||
<div class="db-dropdown-item" @click="addViewMenuOpen=false">{{ fd_icon("calendar",14) }} Calendar</div>
|
||||
<div class="db-dropdown-item">{{ fd_icon("grid",14) }} Table</div>
|
||||
<div class="db-dropdown-item">{{ fd_icon("grid",14) }} Board</div>
|
||||
<div class="db-dropdown-item">{{ fd_icon("list",14) }} List</div>
|
||||
<div class="db-dropdown-item">{{ fd_icon("calendar",14) }} Calendar</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="db-view-actions">
|
||||
<button class="db-btn-icon" title="Filter">{{ fd_icon("filter",14) }}</button>
|
||||
<button class="db-btn-new" @click="addNewPage()">
|
||||
<button id="db-filter-btn" class="db-btn-icon" title="Filter">{{ fd_icon("search",14) }}</button>
|
||||
<button id="db-new-btn" class="db-btn-new">
|
||||
<span class="db-new-icon">{{ fd_icon("plus",12) }}</span> New
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Database Table -->
|
||||
<div class="db-table-wrapper">
|
||||
<table class="db-table">
|
||||
<thead>
|
||||
<tr class="db-header-row">
|
||||
<!-- Drag handle column -->
|
||||
<th class="db-th db-th-handle" style="width:32px"></th>
|
||||
<!-- Property columns -->
|
||||
<template x-for="prop in properties" :key="prop.id">
|
||||
<th class="db-th db-th-property">
|
||||
<div class="db-th-content">
|
||||
<span class="db-prop-type-icon" x-text="propTypeIcon(prop.prop_type)"></span>
|
||||
<span class="db-prop-name" x-text="prop.name"></span>
|
||||
</div>
|
||||
</th>
|
||||
</template>
|
||||
<!-- Add Property column -->
|
||||
<th class="db-th db-th-add-prop">
|
||||
<button class="db-add-prop-btn" @click="addProperty()"
|
||||
title="Add a property">
|
||||
{{ fd_icon("plus",14) }} Add property
|
||||
</button>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- New Page row (always first) -->
|
||||
<tr class="db-row db-row-new">
|
||||
<td class="db-td db-td-handle">
|
||||
<span class="db-plus-icon">{{ fd_icon("plus",14) }}</span>
|
||||
</td>
|
||||
<td class="db-td db-td-name" colspan="99">
|
||||
<button class="db-new-page-btn" @click="addNewPage()">
|
||||
New page
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- Data rows -->
|
||||
<template x-for="(cpage, idx) in pages" :key="cpage.id">
|
||||
<tr class="db-row"
|
||||
@mouseenter="cpage._hover=true"
|
||||
@mouseleave="cpage._hover=false"
|
||||
:class="{ 'db-row-selected': cpage._selected }">
|
||||
<!-- Drag handle / hover actions -->
|
||||
<td class="db-td db-td-handle">
|
||||
<span class="db-drag-handle" x-show="cpage._hover"
|
||||
@mousedown.prevent="startDrag(idx, $event)">
|
||||
{{ fd_icon("grip-vertical",14) }}
|
||||
</span>
|
||||
</td>
|
||||
<!-- Property cells -->
|
||||
<template x-for="prop in properties" :key="prop.id">
|
||||
<td class="db-td db-td-cell">
|
||||
<div class="db-cell-content"
|
||||
:class="{'db-cell-editing': editingCell && editingCell.pageId === cpage.id && editingCell.propId === prop.id}"
|
||||
@click="startEditCell(cpage.id, prop.id, $event)"
|
||||
@dblclick="openPage(cpage.id)">
|
||||
<!-- Render property value -->
|
||||
<span x-show="!(editingCell && editingCell.pageId === cpage.id && editingCell.propId === prop.id)"
|
||||
x-text="cellValue(cpage, prop) || '—'"
|
||||
class="db-cell-value"></span>
|
||||
<!-- Edit mode -->
|
||||
<input x-show="editingCell && editingCell.pageId === cpage.id && editingCell.propId === prop.id"
|
||||
x-ref="cellInput"
|
||||
:value="cellValue(cpage, prop)"
|
||||
@keydown.enter="commitEditCell(cpage, prop)"
|
||||
@keydown.escape="cancelEditCell()"
|
||||
@blur="commitEditCell(cpage, prop)"
|
||||
class="db-cell-input" />
|
||||
</div>
|
||||
</td>
|
||||
</template>
|
||||
<!-- Open button on hover -->
|
||||
<td class="db-td db-td-open" x-show="cpage._hover">
|
||||
<button class="db-open-btn" @click="openPage(cpage.id)"
|
||||
title="Open">
|
||||
{{ fd_icon("external-link",14) }}
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
<!-- Empty rows (fill to 5 total if less than 4 data rows) -->
|
||||
<template x-for="i in emptyRows()" :key="'e'+i">
|
||||
<tr class="db-row db-row-empty">
|
||||
<td class="db-td db-td-handle"></td>
|
||||
<template x-for="prop in properties" :key="prop.id">
|
||||
<td class="db-td db-td-cell"><div class="db-cell-content"></div></td>
|
||||
</template>
|
||||
<td class="db-td db-td-open"></td>
|
||||
</tr>
|
||||
</template>
|
||||
</tbody>
|
||||
<div id="db-table-wrapper" class="db-table-wrapper">
|
||||
<table id="db-table" class="db-table">
|
||||
<thead id="db-thead"></thead>
|
||||
<tbody id="db-tbody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Add Property Modal -->
|
||||
<div x-show="propModalOpen" class="db-modal-overlay" @click.self="propModalOpen=false">
|
||||
<div class="db-modal" x-transition>
|
||||
<div id="db-prop-modal" class="db-modal-overlay" style="display:none">
|
||||
<div class="db-modal">
|
||||
<div class="db-modal-header">
|
||||
<h3>Add a property</h3>
|
||||
<button @click="propModalOpen=false">{{ fd_icon("x",14) }}</button>
|
||||
<button id="db-prop-modal-close">{{ fd_icon("x",14) }}</button>
|
||||
</div>
|
||||
<div class="db-modal-body">
|
||||
<div class="db-modal-field">
|
||||
<label>Name</label>
|
||||
<input x-model="newPropName" type="text" placeholder="Property name"
|
||||
@keydown.enter="createProperty()" />
|
||||
<input id="db-prop-name-input" type="text" placeholder="Property name" />
|
||||
</div>
|
||||
<div class="db-modal-field">
|
||||
<label>Type</label>
|
||||
<select x-model="newPropType">
|
||||
<select id="db-prop-type-select">
|
||||
<option value="text">Text</option>
|
||||
<option value="number">Number</option>
|
||||
<option value="select">Select</option>
|
||||
@@ -152,28 +60,8 @@
|
||||
</select>
|
||||
</div>
|
||||
<div class="db-modal-actions">
|
||||
<button class="db-btn-cancel" @click="propModalOpen=false">Cancel</button>
|
||||
<button class="db-btn-create" @click="createProperty()">Create</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Page title rename (inline) -->
|
||||
<div x-show="renameOpen" class="db-modal-overlay" @click.self="renameOpen=false" style="z-index:600">
|
||||
<div class="db-modal" x-transition style="max-width:400px">
|
||||
<div class="db-modal-header">
|
||||
<h3>Rename page</h3>
|
||||
<button @click="renameOpen=false">{{ fd_icon("x",14) }}</button>
|
||||
</div>
|
||||
<div class="db-modal-body">
|
||||
<div class="db-modal-field">
|
||||
<input x-model="renameTitle" type="text" placeholder="Page title"
|
||||
@keydown.enter="commitRename()" x-ref="renameInput" />
|
||||
</div>
|
||||
<div class="db-modal-actions">
|
||||
<button class="db-btn-cancel" @click="renameOpen=false">Cancel</button>
|
||||
<button class="db-btn-create" @click="commitRename()">Save</button>
|
||||
<button id="db-prop-cancel" class="db-btn-cancel">Cancel</button>
|
||||
<button id="db-prop-create" class="db-btn-create">Create</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user