What happened?
@JonnyTran found some issues that i thought should be reported here
PR #171 (a793b1e1e) rewrote BaseSimpleTable to wrap RenderTable. The wrapper is a lot narrower than what its callers still expect, so a few things broke quietly.
Affected: ImportAnalysisTable.vue, ImportHistoryList.vue, ImportHistoryDataPreview.vue, ImportSummary.vue.
I Found this mostly by reading the code, will confirm it by running the app. Bugs 3 and 4 are structural and I'm confident about them. Bugs 1, 2 and 6 are worth confirming
1. Table never renders if data arrives late
RenderTable.vue:812 returns early before building Tabulator:
mounted() {
if (!this.tableJSON?.data?.length || !this.tableJSON?.schema) return;
Nothing retries after that. The old BaseSimpleTable built the table unconditionally and had a data watcher calling setData(). That watcher wasn't ported. So any table that mounts with data: [] stays blank forever, and even the placeholder text is missing because Tabulator was never created.
ImportHistoryList and ImportHistoryDataPreview sit behind v-if loading guards so they get lucky. ImportSummary and ImportAnalysisTable don't.
2. Changing data after mount does nothing
Same missing watcher. BaseSimpleTable.vue:73 builds a fresh TableData when data changes, but the only tableJSON watcher in RenderTable.vue:133-146 starts with if (!this.editable) return; and just emits change-text. It never touches Tabulator.
To reproduce, open import history, then type in the search box or change the status filter. The counts in the header update, the rows don't.
Same thing hits goToPage() in ImportHistoryList whenever it doesn't toggle isLoading and force a remount.
3. Column config is thrown away except field
BaseSimpleTable.vue:74-77:
const fields = this.columns.map((col: any) => ({
name: col.field,
type: col.type || "string",
}));
TableColumn still declares title, width, formatter, cellClick, headerFilter, frozen and the rest, and all four callers still pass them. Nothing complains because the interface was never narrowed, the values just vanish at runtime.
Two things this breaks:
The status toggle on the Import Analysis screen is now unreachable. ImportAnalysisTable.vue:249-256 sets cellClick: this.handleStatusClick on the status column, which is how you flip a document between add, update and skip. That's the main thing you do on that step. The statusFormatter badge is gone too, so the cell is plain text, and the header filter is gone.
Headers now show raw field names. generateColumnConfig sets field but never title, so Tabulator falls back to the field name. "Source File" shows as filename, "Uploaded By" as username, "Date & Time" as created_at.
Also col.type on line 76 doesn't exist on TableColumn, so every field ends up typed "string".
4. Read-only import tables fire a schema fetch that can't succeed
BaseSimpleTable.vue:79-84 hardcodes "simple-table" as the schema name. RenderTable.created() then calls fetchValidation() unconditionally, and the only way out is a falsy schema name (useSchemaTableViewModel.ts:44-47).
"simple-table" is truthy, so every import table either hangs on waitForAsyncValue(() => dataset.workspaceName) (import pages aren't dataset pages) or calls getSchema.fetch(workspaceName, "simple-table", undefined), which 404s and pops an error toast from the catch in created().
That guard should be an explicit opt-out, not a truthiness check on a placeholder name.
5. None of the BaseSimpleTable styling applies
BaseSimpleTable.vue:146 opens <style lang="scss"> with no scoped, then uses :deep() three times. vue-loader only compiles :deep() inside scoped blocks. Unscoped it passes straight through and the browser drops the rule as invalid.
Every other :deep() in the repo (111 of them across 56 files, including all four sibling import components) is inside a scoped block. So the header colors, row striping, and the .tabulator-container--editable rule that hides __table-buttons on read-only tables all do nothing.
Commit f6ba7499e added the missing Tabulator CSS import but didn't catch this.
6. validateTable() throws instead of returning true
BaseSimpleTable.vue:129-134 checks that this.$refs.renderTable?.validateTable exists, which it always does, then calls into RenderTable.vue:441 where this.tabulator.validate() is unguarded. Combined with bug 1, calling this on an empty table is a TypeError, not the true the wrapper implies.
7. validators prop isn't wired up
The prop is declared at BaseSimpleTable.vue:57 and never read. It isn't passed to RenderTable and isn't merged into computedTableJSON, so the documented usage does nothing.
Smaller stuff
options and loading are declared at BaseSimpleTable.vue:41-48 and passed by all four callers, but never read. That loses per-table height, layout: "fitColumns", pagination and custom placeholder text.
- Emitted events went from 13 down to 4. Gone:
data-loaded, data-changed, row-dblclick, row-selected, row-deselected, column-moved, column-resized, header-click, header-dblclick, error.
RenderTable.vue:903 builds persistenceID from the schema name and reference, which is tabulator-simple-table-null for every BaseSimpleTable. Harmless now since persistence is off when not editable, but any editable simple table would share one localStorage key with all the others.
- Read-only tables now inherit
movableRows: true, a drag row handle, and the annotation row context menu ("LLM fill-in", "Add row below", "Duplicate row(s)") greyed out.
BaseSimpleTable.vue:87 passes [...this.data] into a Tabulator configured with reactiveData: true. That's a fresh copy Vue isn't observing.
Once confirmed live then i can start fixing them maybe
Screenshots
No response
Steps to reproduce
Start the frontend against a workspace that has at least one completed import.
Bug 2, the easiest one to see:
- Go to the workspace and open Import History.
- Click any past import to open its data preview.
- Type anything into the search box above the table.
- The record count in the header drops, but the rows in the table stay exactly the same. Same if you change the status filter instead.
Bug 3a:
- Start a new import and upload a bibliography plus a few PDFs.
- Continue to the Import Analysis step.
- Look at the Import Status column. The values are plain text instead of badges, and there is no filter dropdown on the header.
- Click a status cell to switch a document between add, update and skip. Nothing happens.
Bug 3b:
- On the same Import History list from above, read the column headers.
- They say
filename, username, created_at instead of "Source File", "Uploaded By", "Date & Time".
Bug 4:
- Open any import screen with the browser devtools network tab open.
- There is a request for a schema named
simple-table that comes back 404, and an error toast appears. On some routes the request never resolves at all because it is waiting on a workspace name the import pages never set.
Bugs 1 and 6 need a table that mounts with no rows yet, so they are easiest to trigger on the Import Summary or Import Analysis screens when the data loads after the component mounts. The table area stays empty with no placeholder text.
Bug 5 shows up anywhere a BaseSimpleTable renders. Inspect the table and none of the .tabulator-container--simple rules are applied.
Operating System
Windows
Browsers
Chrome
Extralit Version
latest
ElasticSearch Version
No response
Docker Image (optional)
No response
Additional context
No response
What happened?
@JonnyTran found some issues that i thought should be reported here
PR #171 (
a793b1e1e) rewroteBaseSimpleTableto wrapRenderTable. The wrapper is a lot narrower than what its callers still expect, so a few things broke quietly.Affected:
ImportAnalysisTable.vue,ImportHistoryList.vue,ImportHistoryDataPreview.vue,ImportSummary.vue.I Found this mostly by reading the code, will confirm it by running the app. Bugs 3 and 4 are structural and I'm confident about them. Bugs 1, 2 and 6 are worth confirming
1. Table never renders if data arrives late
RenderTable.vue:812returns early before building Tabulator:Nothing retries after that. The old
BaseSimpleTablebuilt the table unconditionally and had adatawatcher callingsetData(). That watcher wasn't ported. So any table that mounts withdata: []stays blank forever, and even the placeholder text is missing because Tabulator was never created.ImportHistoryListandImportHistoryDataPreviewsit behindv-ifloading guards so they get lucky.ImportSummaryandImportAnalysisTabledon't.2. Changing
dataafter mount does nothingSame missing watcher.
BaseSimpleTable.vue:73builds a freshTableDatawhendatachanges, but the onlytableJSONwatcher inRenderTable.vue:133-146starts withif (!this.editable) return;and just emitschange-text. It never touches Tabulator.To reproduce, open import history, then type in the search box or change the status filter. The counts in the header update, the rows don't.
Same thing hits
goToPage()inImportHistoryListwhenever it doesn't toggleisLoadingand force a remount.3. Column config is thrown away except
fieldBaseSimpleTable.vue:74-77:TableColumnstill declarestitle,width,formatter,cellClick,headerFilter,frozenand the rest, and all four callers still pass them. Nothing complains because the interface was never narrowed, the values just vanish at runtime.Two things this breaks:
The status toggle on the Import Analysis screen is now unreachable.
ImportAnalysisTable.vue:249-256setscellClick: this.handleStatusClickon the status column, which is how you flip a document between add, update and skip. That's the main thing you do on that step. ThestatusFormatterbadge is gone too, so the cell is plain text, and the header filter is gone.Headers now show raw field names.
generateColumnConfigsetsfieldbut nevertitle, so Tabulator falls back to the field name. "Source File" shows asfilename, "Uploaded By" asusername, "Date & Time" ascreated_at.Also
col.typeon line 76 doesn't exist onTableColumn, so every field ends up typed"string".4. Read-only import tables fire a schema fetch that can't succeed
BaseSimpleTable.vue:79-84hardcodes"simple-table"as the schema name.RenderTable.created()then callsfetchValidation()unconditionally, and the only way out is a falsy schema name (useSchemaTableViewModel.ts:44-47)."simple-table"is truthy, so every import table either hangs onwaitForAsyncValue(() => dataset.workspaceName)(import pages aren't dataset pages) or callsgetSchema.fetch(workspaceName, "simple-table", undefined), which 404s and pops an error toast from thecatchincreated().That guard should be an explicit opt-out, not a truthiness check on a placeholder name.
5. None of the BaseSimpleTable styling applies
BaseSimpleTable.vue:146opens<style lang="scss">with noscoped, then uses:deep()three times. vue-loader only compiles:deep()inside scoped blocks. Unscoped it passes straight through and the browser drops the rule as invalid.Every other
:deep()in the repo (111 of them across 56 files, including all four sibling import components) is inside a scoped block. So the header colors, row striping, and the.tabulator-container--editablerule that hides__table-buttonson read-only tables all do nothing.Commit
f6ba7499eadded the missing Tabulator CSS import but didn't catch this.6.
validateTable()throws instead of returningtrueBaseSimpleTable.vue:129-134checks thatthis.$refs.renderTable?.validateTableexists, which it always does, then calls intoRenderTable.vue:441wherethis.tabulator.validate()is unguarded. Combined with bug 1, calling this on an empty table is aTypeError, not thetruethe wrapper implies.7.
validatorsprop isn't wired upThe prop is declared at
BaseSimpleTable.vue:57and never read. It isn't passed toRenderTableand isn't merged intocomputedTableJSON, so the documented usage does nothing.Smaller stuff
optionsandloadingare declared atBaseSimpleTable.vue:41-48and passed by all four callers, but never read. That loses per-tableheight,layout: "fitColumns",paginationand custom placeholder text.data-loaded,data-changed,row-dblclick,row-selected,row-deselected,column-moved,column-resized,header-click,header-dblclick,error.RenderTable.vue:903buildspersistenceIDfrom the schema name and reference, which istabulator-simple-table-nullfor everyBaseSimpleTable. Harmless now sincepersistenceis off when not editable, but any editable simple table would share one localStorage key with all the others.movableRows: true, a drag row handle, and the annotation row context menu ("LLM fill-in", "Add row below", "Duplicate row(s)") greyed out.BaseSimpleTable.vue:87passes[...this.data]into a Tabulator configured withreactiveData: true. That's a fresh copy Vue isn't observing.Once confirmed live then i can start fixing them maybe
Screenshots
No response
Steps to reproduce
Start the frontend against a workspace that has at least one completed import.
Bug 2, the easiest one to see:
Bug 3a:
Bug 3b:
filename,username,created_atinstead of "Source File", "Uploaded By", "Date & Time".Bug 4:
simple-tablethat comes back 404, and an error toast appears. On some routes the request never resolves at all because it is waiting on a workspace name the import pages never set.Bugs 1 and 6 need a table that mounts with no rows yet, so they are easiest to trigger on the Import Summary or Import Analysis screens when the data loads after the component mounts. The table area stays empty with no placeholder text.
Bug 5 shows up anywhere a
BaseSimpleTablerenders. Inspect the table and none of the.tabulator-container--simplerules are applied.Operating System
Windows
Browsers
Chrome
Extralit Version
latest
ElasticSearch Version
No response
Docker Image (optional)
No response
Additional context
No response