From 2653f90dc25955bda981b032a287e569d849c1e9 Mon Sep 17 00:00:00 2001 From: Anastasiia Sliusar Date: Mon, 5 Jan 2026 14:00:12 +0100 Subject: [PATCH 1/8] feat(client): Add column and row numbers --- src/model.ts | 7 +++++++ src/toolbar.ts | 29 +++++++++++++++++++++++++---- src/widget.ts | 8 ++++++++ 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/src/model.ts b/src/model.ts index 8f02ba2..45a5b19 100644 --- a/src/model.ts +++ b/src/model.ts @@ -127,6 +127,13 @@ export class ArrowModel extends DataModel { } } + getColsAndRows(): {cols: number, rows:number} { + return { + cols: this._numCols, + rows:this._numRows + } + } + private dataBody(row: number, col: number): string { const chunkIdx = this._chunks.getChunkIdx({ rowIdx: row, colIdx: col }); diff --git a/src/toolbar.ts b/src/toolbar.ts index c3470f3..5b27dd4 100644 --- a/src/toolbar.ts +++ b/src/toolbar.ts @@ -21,11 +21,14 @@ import type { ArrowGridViewer } from "./widget"; * Maintain a value synchronized with the UI and falls back to the previous value on error. */ abstract class DropdownToolbar extends Widget { - constructor(labelName: string, options: Array<[string, string]>, selected: string) { + constructor(labelName: string, options: Array<[string, string]>, selected: string, cols: number, rows: number ) { const node = DropdownToolbar.createDropdownNode(labelName, options, selected); super({ node }); this._currentValue = selected; this._labelName = labelName; + + let metadataContent = DropdownToolbar.addColsRows(cols,rows); + this.node.appendChild(metadataContent); this.addClass("arrow-viewer-toolbar"); } @@ -58,6 +61,20 @@ abstract class DropdownToolbar extends Widget { return div; } + protected static addColsRows(cols: number, rows: number) { + const span = document.createElement("span"); + const labelCols = document.createElement("span"); + const labelRows = document.createElement("span"); + + labelCols.textContent = ` Column numbers: ${cols};`; + labelRows.textContent = ` Row numbers: ${rows}`; + labelCols.className = "toolbar-label-cols"; + labelRows.className = "toolbar-label-rows"; + span.appendChild(labelCols); + span.appendChild(labelRows); + return span; + } + /** * Called when the dropdown value changes. Implement this to handle the change. * If this method throws an error, the dropdown will revert to the previous value. @@ -144,8 +161,9 @@ export class CsvToolbar extends DropdownToolbar { const translator = options.translator || nullTranslator; const trans = translator.load("jupyterlab"); const delimiterOptions: [string, string][] = fileInfo.delimiters.map((delim) => [delim, delim]); - super(trans.__("Delimiter"), delimiterOptions, fileOptions.delimiter); - this._gridViewer = options.gridViewer; + const colsRows = options.gridViewer.getNumColsAndRows(); + super(trans.__("Delimiter"), delimiterOptions, fileOptions.delimiter, colsRows.cols, colsRows.rows); + this._gridViewer = options.gridViewer; } get fileOptions(): CsvReadOptions { @@ -178,7 +196,8 @@ export class SqliteToolbar extends DropdownToolbar { const translator = options.translator || nullTranslator; const trans = translator.load("jupyterlab"); const tableOptions: [string, string][] = fileInfo.table_names.map((name) => [name, name]); - super(trans.__("Table"), tableOptions, fileOptions.table_name); + const colsRows = options.gridViewer.getNumColsAndRows(); + super(trans.__("Table"), tableOptions, fileOptions.table_name, colsRows.cols, colsRows.rows); this._gridViewer = options.gridViewer; } @@ -214,6 +233,8 @@ export function createToolbar( fileOptions: FileReadOptionsFor, fileInfo: FileInfoFor, ): Widget | null { + console.log('ToolbarOptions', options); + console.log('fileOptions', fileOptions); switch (fileType) { case FileType.Csv: return new CsvToolbar(options, fileOptions as CsvReadOptions, fileInfo as CsvFileInfo); diff --git a/src/widget.ts b/src/widget.ts index 503483e..d2ab498 100644 --- a/src/widget.ts +++ b/src/widget.ts @@ -89,6 +89,14 @@ export class ArrowGridViewer extends Panel { }; } + getNumColsAndRows() { + const data = this.dataModel.getColsAndRows(); + return { + cols:data.cols, + rows: data.rows + }; + } + /** * The style used by the data grid. */ From a18ad8863fd9da81c3e63326eee9b47495acb62a Mon Sep 17 00:00:00 2001 From: Anastasiia Sliusar Date: Mon, 5 Jan 2026 15:58:38 +0100 Subject: [PATCH 2/8] refactoring --- src/toolbar.ts | 68 +++++++++++++++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 28 deletions(-) diff --git a/src/toolbar.ts b/src/toolbar.ts index 5b27dd4..0dafe65 100644 --- a/src/toolbar.ts +++ b/src/toolbar.ts @@ -21,14 +21,11 @@ import type { ArrowGridViewer } from "./widget"; * Maintain a value synchronized with the UI and falls back to the previous value on error. */ abstract class DropdownToolbar extends Widget { - constructor(labelName: string, options: Array<[string, string]>, selected: string, cols: number, rows: number ) { + constructor(labelName: string, options: Array<[string, string]>, selected: string) { const node = DropdownToolbar.createDropdownNode(labelName, options, selected); super({ node }); this._currentValue = selected; this._labelName = labelName; - - let metadataContent = DropdownToolbar.addColsRows(cols,rows); - this.node.appendChild(metadataContent); this.addClass("arrow-viewer-toolbar"); } @@ -61,20 +58,6 @@ abstract class DropdownToolbar extends Widget { return div; } - protected static addColsRows(cols: number, rows: number) { - const span = document.createElement("span"); - const labelCols = document.createElement("span"); - const labelRows = document.createElement("span"); - - labelCols.textContent = ` Column numbers: ${cols};`; - labelRows.textContent = ` Row numbers: ${rows}`; - labelCols.className = "toolbar-label-cols"; - labelRows.className = "toolbar-label-rows"; - span.appendChild(labelCols); - span.appendChild(labelRows); - return span; - } - /** * Called when the dropdown value changes. Implement this to handle the change. * If this method throws an error, the dropdown will revert to the previous value. @@ -149,6 +132,7 @@ abstract class DropdownToolbar extends Widget { private _labelName: string; } + export namespace CsvToolbar { export interface Options { gridViewer: ArrowGridViewer; @@ -160,10 +144,9 @@ export class CsvToolbar extends DropdownToolbar { constructor(options: CsvToolbar.Options, fileOptions: CsvReadOptions, fileInfo: CsvFileInfo) { const translator = options.translator || nullTranslator; const trans = translator.load("jupyterlab"); - const delimiterOptions: [string, string][] = fileInfo.delimiters.map((delim) => [delim, delim]); - const colsRows = options.gridViewer.getNumColsAndRows(); - super(trans.__("Delimiter"), delimiterOptions, fileOptions.delimiter, colsRows.cols, colsRows.rows); - this._gridViewer = options.gridViewer; + const delimiterOptions: [string, string][] = fileInfo.delimiters.map((delim) => [delim, delim]); + super(trans.__("Delimiter"), delimiterOptions, fileOptions.delimiter); + this._gridViewer = options.gridViewer; } get fileOptions(): CsvReadOptions { @@ -196,9 +179,10 @@ export class SqliteToolbar extends DropdownToolbar { const translator = options.translator || nullTranslator; const trans = translator.load("jupyterlab"); const tableOptions: [string, string][] = fileInfo.table_names.map((name) => [name, name]); - const colsRows = options.gridViewer.getNumColsAndRows(); - super(trans.__("Table"), tableOptions, fileOptions.table_name, colsRows.cols, colsRows.rows); + super(trans.__("Table"), tableOptions, fileOptions.table_name); this._gridViewer = options.gridViewer; + + } get fileOptions(): SqliteReadOptions { @@ -235,16 +219,44 @@ export function createToolbar( ): Widget | null { console.log('ToolbarOptions', options); console.log('fileOptions', fileOptions); + const colsRows = options.gridViewer.getNumColsAndRows(); + let widget = null; switch (fileType) { case FileType.Csv: - return new CsvToolbar(options, fileOptions as CsvReadOptions, fileInfo as CsvFileInfo); + widget = new CsvToolbar(options, fileOptions as CsvReadOptions, fileInfo as CsvFileInfo); + break; case FileType.Sqlite: - return new SqliteToolbar( + widget = new SqliteToolbar( options, fileOptions as SqliteReadOptions, fileInfo as SqliteFileInfo, ); + break; default: - return null; - } + widget = new Widget(); + widget.addClass("arrow-viewer-toolbar"); + break; + } + widget.node.appendChild(addColsRows(colsRows.cols, colsRows.rows, options.translator)); + + return widget; } + + function addColsRows(cols: number, rows: number, translator?: ITranslator) { + translator = translator || nullTranslator; + const trans = translator.load("jupyterlab"); + + const div = document.createElement("div"); + const labelCols = document.createElement("span"); + const labelRows = document.createElement("span"); + + labelCols.textContent = trans.__(`Number Columns: ${cols}`); + labelRows.textContent = trans.__(`Number Rows: ${rows}`); + labelCols.classList.add('jp-toolbal-number-label'); + labelRows.classList.add('jp-toolbal-number-label'); + labelCols.classList.add('toolbar-label'); + labelRows.classList.add('toolbar-label'); + div.appendChild(labelCols); + div.appendChild(labelRows); + return div; + } From a4bec639122bdc0927999c0453fe0ab6161d3c34 Mon Sep 17 00:00:00 2001 From: Anastasiia Sliusar Date: Mon, 5 Jan 2026 16:36:38 +0100 Subject: [PATCH 3/8] refactoring --- src/model.ts | 6 +++--- src/toolbar.ts | 50 +++++++++++++++++++++++--------------------------- src/widget.ts | 9 +++++---- 3 files changed, 31 insertions(+), 34 deletions(-) diff --git a/src/model.ts b/src/model.ts index 45a5b19..2357fd9 100644 --- a/src/model.ts +++ b/src/model.ts @@ -127,11 +127,11 @@ export class ArrowModel extends DataModel { } } - getColsAndRows(): {cols: number, rows:number} { + get numColsAndRows(): { cols: number; rows: number } { return { cols: this._numCols, - rows:this._numRows - } + rows: this._numRows, + }; } private dataBody(row: number, col: number): string { diff --git a/src/toolbar.ts b/src/toolbar.ts index 0dafe65..50a2676 100644 --- a/src/toolbar.ts +++ b/src/toolbar.ts @@ -132,7 +132,6 @@ abstract class DropdownToolbar extends Widget { private _labelName: string; } - export namespace CsvToolbar { export interface Options { gridViewer: ArrowGridViewer; @@ -144,7 +143,7 @@ export class CsvToolbar extends DropdownToolbar { constructor(options: CsvToolbar.Options, fileOptions: CsvReadOptions, fileInfo: CsvFileInfo) { const translator = options.translator || nullTranslator; const trans = translator.load("jupyterlab"); - const delimiterOptions: [string, string][] = fileInfo.delimiters.map((delim) => [delim, delim]); + const delimiterOptions: [string, string][] = fileInfo.delimiters.map((delim) => [delim, delim]); super(trans.__("Delimiter"), delimiterOptions, fileOptions.delimiter); this._gridViewer = options.gridViewer; } @@ -181,8 +180,6 @@ export class SqliteToolbar extends DropdownToolbar { const tableOptions: [string, string][] = fileInfo.table_names.map((name) => [name, name]); super(trans.__("Table"), tableOptions, fileOptions.table_name); this._gridViewer = options.gridViewer; - - } get fileOptions(): SqliteReadOptions { @@ -217,13 +214,12 @@ export function createToolbar( fileOptions: FileReadOptionsFor, fileInfo: FileInfoFor, ): Widget | null { - console.log('ToolbarOptions', options); - console.log('fileOptions', fileOptions); - const colsRows = options.gridViewer.getNumColsAndRows(); + const colsRows = options.gridViewer.numColsAndRows; + console.log("colsRows", colsRows); let widget = null; switch (fileType) { case FileType.Csv: - widget = new CsvToolbar(options, fileOptions as CsvReadOptions, fileInfo as CsvFileInfo); + widget = new CsvToolbar(options, fileOptions as CsvReadOptions, fileInfo as CsvFileInfo); break; case FileType.Sqlite: widget = new SqliteToolbar( @@ -236,27 +232,27 @@ export function createToolbar( widget = new Widget(); widget.addClass("arrow-viewer-toolbar"); break; - } - widget.node.appendChild(addColsRows(colsRows.cols, colsRows.rows, options.translator)); + } + widget.node.appendChild(addColsRows(colsRows.cols, colsRows.rows, options.translator)); return widget; } - function addColsRows(cols: number, rows: number, translator?: ITranslator) { - translator = translator || nullTranslator; - const trans = translator.load("jupyterlab"); +function addColsRows(cols: number, rows: number, translator?: ITranslator) { + translator = translator || nullTranslator; + const trans = translator.load("jupyterlab"); - const div = document.createElement("div"); - const labelCols = document.createElement("span"); - const labelRows = document.createElement("span"); - - labelCols.textContent = trans.__(`Number Columns: ${cols}`); - labelRows.textContent = trans.__(`Number Rows: ${rows}`); - labelCols.classList.add('jp-toolbal-number-label'); - labelRows.classList.add('jp-toolbal-number-label'); - labelCols.classList.add('toolbar-label'); - labelRows.classList.add('toolbar-label'); - div.appendChild(labelCols); - div.appendChild(labelRows); - return div; - } + const div = document.createElement("div"); + const labelCols = document.createElement("span"); + const labelRows = document.createElement("span"); + + labelCols.textContent = trans.__(`Number Columns: ${cols}`); + labelRows.textContent = trans.__(`Number Rows: ${rows}`); + labelCols.classList.add("jp-toolbal-number-label"); + labelRows.classList.add("jp-toolbal-number-label"); + labelCols.classList.add("toolbar-label"); + labelRows.classList.add("toolbar-label"); + div.appendChild(labelCols); + div.appendChild(labelRows); + return div; +} diff --git a/src/widget.ts b/src/widget.ts index d2ab498..7ae27a5 100644 --- a/src/widget.ts +++ b/src/widget.ts @@ -89,11 +89,12 @@ export class ArrowGridViewer extends Panel { }; } - getNumColsAndRows() { - const data = this.dataModel.getColsAndRows(); + get numColsAndRows() { + const data = this.dataModel.numColsAndRows; + console.log('data', data); return { - cols:data.cols, - rows: data.rows + cols: data.cols, + rows: data.rows, }; } From 53e41e70cb1538ce248a3a18e6bfb2bb4ae8388b Mon Sep 17 00:00:00 2001 From: Anastasiia Sliusar Date: Tue, 6 Jan 2026 11:59:18 +0100 Subject: [PATCH 4/8] update toolbar when there are new changes --- src/model.ts | 11 ++++++----- src/toolbar.ts | 39 ++++++++++++++++++++++++++++++++------- src/widget.ts | 15 ++++++++------- 3 files changed, 46 insertions(+), 19 deletions(-) diff --git a/src/model.ts b/src/model.ts index 2357fd9..0ba928b 100644 --- a/src/model.ts +++ b/src/model.ts @@ -127,11 +127,12 @@ export class ArrowModel extends DataModel { } } - get numColsAndRows(): { cols: number; rows: number } { - return { - cols: this._numCols, - rows: this._numRows, - }; + get cols() { + return this._numCols; + } + + get rows() { + return this._numRows; } private dataBody(row: number, col: number): string { diff --git a/src/toolbar.ts b/src/toolbar.ts index 50a2676..5529418 100644 --- a/src/toolbar.ts +++ b/src/toolbar.ts @@ -146,6 +146,7 @@ export class CsvToolbar extends DropdownToolbar { const delimiterOptions: [string, string][] = fileInfo.delimiters.map((delim) => [delim, delim]); super(trans.__("Delimiter"), delimiterOptions, fileOptions.delimiter); this._gridViewer = options.gridViewer; + this._translator = options.translator; } get fileOptions(): CsvReadOptions { @@ -157,9 +158,20 @@ export class CsvToolbar extends DropdownToolbar { protected async onChange(newValue: string): Promise { this._gridViewer.updateFileReadOptions({ delimiter: newValue }); await this._gridViewer.ready; + + const cols = this._gridViewer.cols; + const rows = this._gridViewer.rows; + + this.updateToolbar(cols, rows, this._translator); + } + protected updateToolbar(cols: number, rows: number, translator?: ITranslator) { + const colsAndRows = this.node.getElementsByClassName("toolbar-group-cols-rows")[0]; + this.node.removeChild(colsAndRows); + this.node.appendChild(addColsRows(cols, rows, translator)); } private _gridViewer: ArrowGridViewer; + private _translator?: ITranslator; } export namespace SqliteToolbar { @@ -180,6 +192,7 @@ export class SqliteToolbar extends DropdownToolbar { const tableOptions: [string, string][] = fileInfo.table_names.map((name) => [name, name]); super(trans.__("Table"), tableOptions, fileOptions.table_name); this._gridViewer = options.gridViewer; + this._translator = options.translator; } get fileOptions(): SqliteReadOptions { @@ -191,9 +204,19 @@ export class SqliteToolbar extends DropdownToolbar { protected async onChange(newValue: string): Promise { this._gridViewer.updateFileReadOptions({ table_name: newValue }); await this._gridViewer.ready; + const cols = this._gridViewer.cols; + const rows = this._gridViewer.rows; + this.updateToolbar(cols, rows, this._translator); + } + + protected updateToolbar(cols: number, rows: number, translator?: ITranslator) { + const colsAndRows = this.node.getElementsByClassName("toolbar-group-cols-rows")[0]; + this.node.removeChild(colsAndRows); + this.node.appendChild(addColsRows(cols, rows, translator)); } private _gridViewer: ArrowGridViewer; + private _translator?: ITranslator; } /** @@ -214,8 +237,10 @@ export function createToolbar( fileOptions: FileReadOptionsFor, fileInfo: FileInfoFor, ): Widget | null { - const colsRows = options.gridViewer.numColsAndRows; - console.log("colsRows", colsRows); + const cols = options.gridViewer.cols; + const rows = options.gridViewer.rows; + console.log("cols", cols); + console.log("rows", rows); let widget = null; switch (fileType) { case FileType.Csv: @@ -233,7 +258,7 @@ export function createToolbar( widget.addClass("arrow-viewer-toolbar"); break; } - widget.node.appendChild(addColsRows(colsRows.cols, colsRows.rows, options.translator)); + widget.node.appendChild(addColsRows(cols, rows, options.translator)); return widget; } @@ -243,15 +268,15 @@ function addColsRows(cols: number, rows: number, translator?: ITranslator) { const trans = translator.load("jupyterlab"); const div = document.createElement("div"); + div.className = "toolbar-group-cols-rows"; const labelCols = document.createElement("span"); const labelRows = document.createElement("span"); labelCols.textContent = trans.__(`Number Columns: ${cols}`); labelRows.textContent = trans.__(`Number Rows: ${rows}`); - labelCols.classList.add("jp-toolbal-number-label"); - labelRows.classList.add("jp-toolbal-number-label"); - labelCols.classList.add("toolbar-label"); - labelRows.classList.add("toolbar-label"); + + labelCols.className = "toolbar-label"; + labelRows.className = "toolbar-label"; div.appendChild(labelCols); div.appendChild(labelRows); return div; diff --git a/src/widget.ts b/src/widget.ts index 7ae27a5..471d8b6 100644 --- a/src/widget.ts +++ b/src/widget.ts @@ -83,19 +83,20 @@ export class ArrowGridViewer extends Panel { } updateFileReadOptions(fileOptionsUpdate: Partial) { + console.log("fileReadOptions", this.fileReadOptions); + console.log("fileOptionsUpdate", fileOptionsUpdate); this.fileReadOptions = { ...this.fileReadOptions, ...fileOptionsUpdate, }; } - get numColsAndRows() { - const data = this.dataModel.numColsAndRows; - console.log('data', data); - return { - cols: data.cols, - rows: data.rows, - }; + get cols() { + return this.dataModel.cols; + } + + get rows() { + return this.dataModel.rows; } /** From ccb0ecae88442902690c6b295858853d1f326379 Mon Sep 17 00:00:00 2001 From: Anastasiia Sliusar Date: Tue, 6 Jan 2026 14:24:31 +0100 Subject: [PATCH 5/8] fix css --- src/toolbar.ts | 18 ++++++++++-------- src/widget.ts | 2 -- style/base.css | 16 ++++++++++++++++ 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/toolbar.ts b/src/toolbar.ts index 5529418..598d5e2 100644 --- a/src/toolbar.ts +++ b/src/toolbar.ts @@ -38,6 +38,8 @@ abstract class DropdownToolbar extends Widget { selected: string, ): HTMLElement { const div = document.createElement("div"); + const selectDiv = document.createElement("div"); + selectDiv.className = 'toolbar-select'; const label = document.createElement("span"); const select = document.createElement("select"); label.textContent = `${labelName}: `; @@ -51,10 +53,12 @@ abstract class DropdownToolbar extends Widget { } select.appendChild(option); } - div.appendChild(label); + selectDiv.appendChild(label); + const node = Styling.wrapSelect(select); node.classList.add("toolbar-dropdown"); - div.appendChild(node); + selectDiv.appendChild(node); + div.appendChild(selectDiv); return div; } @@ -239,8 +243,6 @@ export function createToolbar( ): Widget | null { const cols = options.gridViewer.cols; const rows = options.gridViewer.rows; - console.log("cols", cols); - console.log("rows", rows); let widget = null; switch (fileType) { case FileType.Csv: @@ -272,12 +274,12 @@ function addColsRows(cols: number, rows: number, translator?: ITranslator) { const labelCols = document.createElement("span"); const labelRows = document.createElement("span"); - labelCols.textContent = trans.__(`Number Columns: ${cols}`); - labelRows.textContent = trans.__(`Number Rows: ${rows}`); + labelCols.textContent = trans.__(`${cols} column${cols >1 ? 's':''}`); + labelRows.textContent = trans.__(`${rows} row${rows > 1 ? 's': ''};`); - labelCols.className = "toolbar-label"; + labelCols.classList.add("toolbar-label", "cols"); labelRows.className = "toolbar-label"; - div.appendChild(labelCols); div.appendChild(labelRows); + div.appendChild(labelCols); return div; } diff --git a/src/widget.ts b/src/widget.ts index 471d8b6..11a621b 100644 --- a/src/widget.ts +++ b/src/widget.ts @@ -83,8 +83,6 @@ export class ArrowGridViewer extends Panel { } updateFileReadOptions(fileOptionsUpdate: Partial) { - console.log("fileReadOptions", this.fileReadOptions); - console.log("fileOptionsUpdate", fileOptionsUpdate); this.fileReadOptions = { ...this.fileReadOptions, ...fileOptionsUpdate, diff --git a/style/base.css b/style/base.css index 83823bb..c5be4e9 100644 --- a/style/base.css +++ b/style/base.css @@ -13,6 +13,7 @@ } .arrow-viewer-toolbar { + width: 99%; display: flex; flex: 0 0 auto; flex-direction: row; @@ -21,11 +22,22 @@ background: var(--jp-toolbar-background); z-index: 1; + .toolbar-select { + display: flex; + flex-direction: row; + flex: 1; + align-items: center; + } + .toolbar-label { color: var(--jp-ui-font-color1); font-size: var(--jp-ui-font-size1); padding-left: 8px; padding-right: 8px; + + .cols { + padding-right:0px; + } } .toolbar-dropdown { @@ -45,5 +57,9 @@ padding-right: 20px; } } + + .toolbar-group-cols-rows { + margin-left: auto; + } } } From dd498300d6933b2b58ce65c66fd69a35d0c4d71d Mon Sep 17 00:00:00 2001 From: Anastasiia Sliusar Date: Tue, 6 Jan 2026 14:25:08 +0100 Subject: [PATCH 6/8] fix by formatiing --- src/toolbar.ts | 8 ++++---- style/base.css | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/toolbar.ts b/src/toolbar.ts index 598d5e2..62979d4 100644 --- a/src/toolbar.ts +++ b/src/toolbar.ts @@ -39,7 +39,7 @@ abstract class DropdownToolbar extends Widget { ): HTMLElement { const div = document.createElement("div"); const selectDiv = document.createElement("div"); - selectDiv.className = 'toolbar-select'; + selectDiv.className = "toolbar-select"; const label = document.createElement("span"); const select = document.createElement("select"); label.textContent = `${labelName}: `; @@ -54,7 +54,7 @@ abstract class DropdownToolbar extends Widget { select.appendChild(option); } selectDiv.appendChild(label); - + const node = Styling.wrapSelect(select); node.classList.add("toolbar-dropdown"); selectDiv.appendChild(node); @@ -274,8 +274,8 @@ function addColsRows(cols: number, rows: number, translator?: ITranslator) { const labelCols = document.createElement("span"); const labelRows = document.createElement("span"); - labelCols.textContent = trans.__(`${cols} column${cols >1 ? 's':''}`); - labelRows.textContent = trans.__(`${rows} row${rows > 1 ? 's': ''};`); + labelCols.textContent = trans.__(`${cols} column${cols > 1 ? "s" : ""}`); + labelRows.textContent = trans.__(`${rows} row${rows > 1 ? "s" : ""};`); labelCols.classList.add("toolbar-label", "cols"); labelRows.className = "toolbar-label"; diff --git a/style/base.css b/style/base.css index c5be4e9..a425c4d 100644 --- a/style/base.css +++ b/style/base.css @@ -36,7 +36,7 @@ padding-right: 8px; .cols { - padding-right:0px; + padding-right: 0px; } } From e179a876f5e76485846972798ec1b46c1331802f Mon Sep 17 00:00:00 2001 From: Anastasiia Sliusar Date: Tue, 6 Jan 2026 14:41:00 +0100 Subject: [PATCH 7/8] refactoring according to last changes --- src/model.ts | 8 -------- src/toolbar.ts | 18 +++++++++--------- src/widget.ts | 8 ++++---- 3 files changed, 13 insertions(+), 21 deletions(-) diff --git a/src/model.ts b/src/model.ts index ec296f0..51c2782 100644 --- a/src/model.ts +++ b/src/model.ts @@ -135,14 +135,6 @@ export class ArrowModel extends DataModel { } } - get cols() { - return this._numCols; - } - - get rows() { - return this._numRows; - } - private dataBody(row: number, col: number): string { const chunkIdx = this._chunks.getChunkIdx({ rowIdx: row, colIdx: col }); diff --git a/src/toolbar.ts b/src/toolbar.ts index 62979d4..e03f537 100644 --- a/src/toolbar.ts +++ b/src/toolbar.ts @@ -163,10 +163,10 @@ export class CsvToolbar extends DropdownToolbar { this._gridViewer.updateFileReadOptions({ delimiter: newValue }); await this._gridViewer.ready; - const cols = this._gridViewer.cols; - const rows = this._gridViewer.rows; + const numCols = this._gridViewer.numCols; + const numRows = this._gridViewer.numRows; - this.updateToolbar(cols, rows, this._translator); + this.updateToolbar(numCols, numRows, this._translator); } protected updateToolbar(cols: number, rows: number, translator?: ITranslator) { const colsAndRows = this.node.getElementsByClassName("toolbar-group-cols-rows")[0]; @@ -208,9 +208,9 @@ export class SqliteToolbar extends DropdownToolbar { protected async onChange(newValue: string): Promise { this._gridViewer.updateFileReadOptions({ table_name: newValue }); await this._gridViewer.ready; - const cols = this._gridViewer.cols; - const rows = this._gridViewer.rows; - this.updateToolbar(cols, rows, this._translator); + const numCols = this._gridViewer.numCols; + const numRows = this._gridViewer.numRows; + this.updateToolbar(numCols, numRows, this._translator); } protected updateToolbar(cols: number, rows: number, translator?: ITranslator) { @@ -241,8 +241,8 @@ export function createToolbar( fileOptions: FileReadOptionsFor, fileInfo: FileInfoFor, ): Widget | null { - const cols = options.gridViewer.cols; - const rows = options.gridViewer.rows; + const numCols = options.gridViewer.numCols; + const numRows = options.gridViewer.numRows; let widget = null; switch (fileType) { case FileType.Csv: @@ -260,7 +260,7 @@ export function createToolbar( widget.addClass("arrow-viewer-toolbar"); break; } - widget.node.appendChild(addColsRows(cols, rows, options.translator)); + widget.node.appendChild(addColsRows(numCols, numRows, options.translator)); return widget; } diff --git a/src/widget.ts b/src/widget.ts index 9940783..5e05ded 100644 --- a/src/widget.ts +++ b/src/widget.ts @@ -163,12 +163,12 @@ export class ArrowGridViewer extends Panel { }; } - get cols() { - return this.dataModel.cols; + get numCols() { + return this.dataModel.numCols; } - get rows() { - return this.dataModel.rows; + get numRows() { + return this.dataModel.numRows; } /** From 82e8f98f7612768c29779a70b55430fb93be29c6 Mon Sep 17 00:00:00 2001 From: Anastasiia Sliusar Date: Wed, 7 Jan 2026 11:03:44 +0100 Subject: [PATCH 8/8] create InfoOnlyToolBar and refactoring --- src/toolbar.ts | 119 +++++++++++++++++++++++++------------------------ src/widget.ts | 4 +- 2 files changed, 62 insertions(+), 61 deletions(-) diff --git a/src/toolbar.ts b/src/toolbar.ts index e03f537..dbdc914 100644 --- a/src/toolbar.ts +++ b/src/toolbar.ts @@ -16,14 +16,66 @@ import type { } from "./file-options"; import type { ArrowGridViewer } from "./widget"; +abstract class InfoOnlyToolbar extends Widget { + constructor(options: ToolbarOptions) { + super(); + this._gridViewer = options.gridViewer; + this._translator = options.translator; + this._colsRowsNode = this.addColsRows( + this._gridViewer.numCols, + this._gridViewer.numRows, + this._translator, + ); + this.node.appendChild(this._colsRowsNode); + } + + protected updateToolbar(): void { + const newNode = this.addColsRows( + this._gridViewer.numCols, + this._gridViewer.numRows, + this._translator, + ); + this.node.replaceChild(newNode, this._colsRowsNode); + this._colsRowsNode = newNode; + } + + protected addColsRows(cols: number, rows: number, translator?: ITranslator): HTMLDivElement { + translator = translator || nullTranslator; + const trans = translator.load("jupyterlab"); + + const div = document.createElement("div"); + div.className = "toolbar-group-cols-rows"; + const labelCols = document.createElement("span"); + const labelRows = document.createElement("span"); + + labelCols.textContent = trans.__(`${cols} column${cols > 1 ? "s" : ""}`); + labelRows.textContent = trans.__(`${rows} row${rows > 1 ? "s" : ""};`); + + labelCols.classList.add("toolbar-label", "cols"); + labelRows.className = "toolbar-label"; + div.appendChild(labelRows); + div.appendChild(labelCols); + return div; + } + + protected _translator?: ITranslator | undefined; + protected _gridViewer: ArrowGridViewer; + private _colsRowsNode: HTMLDivElement; +} /** * Base toolbar class for a dropdown selector with error recovery. * Maintain a value synchronized with the UI and falls back to the previous value on error. */ -abstract class DropdownToolbar extends Widget { - constructor(labelName: string, options: Array<[string, string]>, selected: string) { +abstract class DropdownToolbar extends InfoOnlyToolbar { + constructor( + labelName: string, + options: Array<[string, string]>, + selected: string, + toolbarOptions: ToolbarOptions, + ) { + super(toolbarOptions); const node = DropdownToolbar.createDropdownNode(labelName, options, selected); - super({ node }); + this.node.insertBefore(node, this.node.firstChild); this._currentValue = selected; this._labelName = labelName; this.addClass("arrow-viewer-toolbar"); @@ -37,7 +89,6 @@ abstract class DropdownToolbar extends Widget { options: Array<[string, string]>, selected: string, ): HTMLElement { - const div = document.createElement("div"); const selectDiv = document.createElement("div"); selectDiv.className = "toolbar-select"; const label = document.createElement("span"); @@ -58,8 +109,7 @@ abstract class DropdownToolbar extends Widget { const node = Styling.wrapSelect(select); node.classList.add("toolbar-dropdown"); selectDiv.appendChild(node); - div.appendChild(selectDiv); - return div; + return selectDiv; } /** @@ -100,6 +150,7 @@ abstract class DropdownToolbar extends Widget { try { await this.onChange(newValue); this._currentValue = newValue; + this.updateToolbar(); } catch (error) { // Reset the selector value this.value = previousValue; @@ -148,9 +199,8 @@ export class CsvToolbar extends DropdownToolbar { const translator = options.translator || nullTranslator; const trans = translator.load("jupyterlab"); const delimiterOptions: [string, string][] = fileInfo.delimiters.map((delim) => [delim, delim]); - super(trans.__("Delimiter"), delimiterOptions, fileOptions.delimiter); + super(trans.__("Delimiter"), delimiterOptions, fileOptions.delimiter, options); this._gridViewer = options.gridViewer; - this._translator = options.translator; } get fileOptions(): CsvReadOptions { @@ -162,20 +212,7 @@ export class CsvToolbar extends DropdownToolbar { protected async onChange(newValue: string): Promise { this._gridViewer.updateFileReadOptions({ delimiter: newValue }); await this._gridViewer.ready; - - const numCols = this._gridViewer.numCols; - const numRows = this._gridViewer.numRows; - - this.updateToolbar(numCols, numRows, this._translator); - } - protected updateToolbar(cols: number, rows: number, translator?: ITranslator) { - const colsAndRows = this.node.getElementsByClassName("toolbar-group-cols-rows")[0]; - this.node.removeChild(colsAndRows); - this.node.appendChild(addColsRows(cols, rows, translator)); } - - private _gridViewer: ArrowGridViewer; - private _translator?: ITranslator; } export namespace SqliteToolbar { @@ -194,9 +231,7 @@ export class SqliteToolbar extends DropdownToolbar { const translator = options.translator || nullTranslator; const trans = translator.load("jupyterlab"); const tableOptions: [string, string][] = fileInfo.table_names.map((name) => [name, name]); - super(trans.__("Table"), tableOptions, fileOptions.table_name); - this._gridViewer = options.gridViewer; - this._translator = options.translator; + super(trans.__("Table"), tableOptions, fileOptions.table_name, options); } get fileOptions(): SqliteReadOptions { @@ -208,19 +243,7 @@ export class SqliteToolbar extends DropdownToolbar { protected async onChange(newValue: string): Promise { this._gridViewer.updateFileReadOptions({ table_name: newValue }); await this._gridViewer.ready; - const numCols = this._gridViewer.numCols; - const numRows = this._gridViewer.numRows; - this.updateToolbar(numCols, numRows, this._translator); - } - - protected updateToolbar(cols: number, rows: number, translator?: ITranslator) { - const colsAndRows = this.node.getElementsByClassName("toolbar-group-cols-rows")[0]; - this.node.removeChild(colsAndRows); - this.node.appendChild(addColsRows(cols, rows, translator)); } - - private _gridViewer: ArrowGridViewer; - private _translator?: ITranslator; } /** @@ -241,8 +264,6 @@ export function createToolbar( fileOptions: FileReadOptionsFor, fileInfo: FileInfoFor, ): Widget | null { - const numCols = options.gridViewer.numCols; - const numRows = options.gridViewer.numRows; let widget = null; switch (fileType) { case FileType.Csv: @@ -256,30 +277,10 @@ export function createToolbar( ); break; default: - widget = new Widget(); + widget = new (class extends InfoOnlyToolbar {})(options); widget.addClass("arrow-viewer-toolbar"); break; } - widget.node.appendChild(addColsRows(numCols, numRows, options.translator)); return widget; } - -function addColsRows(cols: number, rows: number, translator?: ITranslator) { - translator = translator || nullTranslator; - const trans = translator.load("jupyterlab"); - - const div = document.createElement("div"); - div.className = "toolbar-group-cols-rows"; - const labelCols = document.createElement("span"); - const labelRows = document.createElement("span"); - - labelCols.textContent = trans.__(`${cols} column${cols > 1 ? "s" : ""}`); - labelRows.textContent = trans.__(`${rows} row${rows > 1 ? "s" : ""};`); - - labelCols.classList.add("toolbar-label", "cols"); - labelRows.className = "toolbar-label"; - div.appendChild(labelRows); - div.appendChild(labelCols); - return div; -} diff --git a/src/widget.ts b/src/widget.ts index 5e05ded..522eba0 100644 --- a/src/widget.ts +++ b/src/widget.ts @@ -163,11 +163,11 @@ export class ArrowGridViewer extends Panel { }; } - get numCols() { + get numCols(): number { return this.dataModel.numCols; } - get numRows() { + get numRows(): number { return this.dataModel.numRows; }