Skip to content

Commit abc75b7

Browse files
feat(client): Add column and row numbers (#53)
1 parent f1b064e commit abc75b7

3 files changed

Lines changed: 98 additions & 17 deletions

File tree

‎src/toolbar.ts‎

Lines changed: 74 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,66 @@ import type {
1616
} from "./file-options";
1717
import type { ArrowGridViewer } from "./widget";
1818

19+
abstract class InfoOnlyToolbar extends Widget {
20+
constructor(options: ToolbarOptions) {
21+
super();
22+
this._gridViewer = options.gridViewer;
23+
this._translator = options.translator;
24+
this._colsRowsNode = this.addColsRows(
25+
this._gridViewer.numCols,
26+
this._gridViewer.numRows,
27+
this._translator,
28+
);
29+
this.node.appendChild(this._colsRowsNode);
30+
}
31+
32+
protected updateToolbar(): void {
33+
const newNode = this.addColsRows(
34+
this._gridViewer.numCols,
35+
this._gridViewer.numRows,
36+
this._translator,
37+
);
38+
this.node.replaceChild(newNode, this._colsRowsNode);
39+
this._colsRowsNode = newNode;
40+
}
41+
42+
protected addColsRows(cols: number, rows: number, translator?: ITranslator): HTMLDivElement {
43+
translator = translator || nullTranslator;
44+
const trans = translator.load("jupyterlab");
45+
46+
const div = document.createElement("div");
47+
div.className = "toolbar-group-cols-rows";
48+
const labelCols = document.createElement("span");
49+
const labelRows = document.createElement("span");
50+
51+
labelCols.textContent = trans.__(`${cols} column${cols > 1 ? "s" : ""}`);
52+
labelRows.textContent = trans.__(`${rows} row${rows > 1 ? "s" : ""};`);
53+
54+
labelCols.classList.add("toolbar-label", "cols");
55+
labelRows.className = "toolbar-label";
56+
div.appendChild(labelRows);
57+
div.appendChild(labelCols);
58+
return div;
59+
}
60+
61+
protected _translator?: ITranslator | undefined;
62+
protected _gridViewer: ArrowGridViewer;
63+
private _colsRowsNode: HTMLDivElement;
64+
}
1965
/**
2066
* Base toolbar class for a dropdown selector with error recovery.
2167
* Maintain a value synchronized with the UI and falls back to the previous value on error.
2268
*/
23-
abstract class DropdownToolbar extends Widget {
24-
constructor(labelName: string, options: Array<[string, string]>, selected: string) {
69+
abstract class DropdownToolbar extends InfoOnlyToolbar {
70+
constructor(
71+
labelName: string,
72+
options: Array<[string, string]>,
73+
selected: string,
74+
toolbarOptions: ToolbarOptions,
75+
) {
76+
super(toolbarOptions);
2577
const node = DropdownToolbar.createDropdownNode(labelName, options, selected);
26-
super({ node });
78+
this.node.insertBefore(node, this.node.firstChild);
2779
this._currentValue = selected;
2880
this._labelName = labelName;
2981
this.addClass("arrow-viewer-toolbar");
@@ -37,7 +89,8 @@ abstract class DropdownToolbar extends Widget {
3789
options: Array<[string, string]>,
3890
selected: string,
3991
): HTMLElement {
40-
const div = document.createElement("div");
92+
const selectDiv = document.createElement("div");
93+
selectDiv.className = "toolbar-select";
4194
const label = document.createElement("span");
4295
const select = document.createElement("select");
4396
label.textContent = `${labelName}: `;
@@ -51,11 +104,12 @@ abstract class DropdownToolbar extends Widget {
51104
}
52105
select.appendChild(option);
53106
}
54-
div.appendChild(label);
107+
selectDiv.appendChild(label);
108+
55109
const node = Styling.wrapSelect(select);
56110
node.classList.add("toolbar-dropdown");
57-
div.appendChild(node);
58-
return div;
111+
selectDiv.appendChild(node);
112+
return selectDiv;
59113
}
60114

61115
/**
@@ -96,6 +150,7 @@ abstract class DropdownToolbar extends Widget {
96150
try {
97151
await this.onChange(newValue);
98152
this._currentValue = newValue;
153+
this.updateToolbar();
99154
} catch (error) {
100155
// Reset the selector value
101156
this.value = previousValue;
@@ -144,7 +199,7 @@ export class CsvToolbar extends DropdownToolbar {
144199
const translator = options.translator || nullTranslator;
145200
const trans = translator.load("jupyterlab");
146201
const delimiterOptions: [string, string][] = fileInfo.delimiters.map((delim) => [delim, delim]);
147-
super(trans.__("Delimiter"), delimiterOptions, fileOptions.delimiter);
202+
super(trans.__("Delimiter"), delimiterOptions, fileOptions.delimiter, options);
148203
this._gridViewer = options.gridViewer;
149204
}
150205

@@ -158,8 +213,6 @@ export class CsvToolbar extends DropdownToolbar {
158213
this._gridViewer.updateFileReadOptions({ delimiter: newValue });
159214
await this._gridViewer.ready;
160215
}
161-
162-
private _gridViewer: ArrowGridViewer;
163216
}
164217

165218
export namespace SqliteToolbar {
@@ -178,8 +231,7 @@ export class SqliteToolbar extends DropdownToolbar {
178231
const translator = options.translator || nullTranslator;
179232
const trans = translator.load("jupyterlab");
180233
const tableOptions: [string, string][] = fileInfo.table_names.map((name) => [name, name]);
181-
super(trans.__("Table"), tableOptions, fileOptions.table_name);
182-
this._gridViewer = options.gridViewer;
234+
super(trans.__("Table"), tableOptions, fileOptions.table_name, options);
183235
}
184236

185237
get fileOptions(): SqliteReadOptions {
@@ -192,8 +244,6 @@ export class SqliteToolbar extends DropdownToolbar {
192244
this._gridViewer.updateFileReadOptions({ table_name: newValue });
193245
await this._gridViewer.ready;
194246
}
195-
196-
private _gridViewer: ArrowGridViewer;
197247
}
198248

199249
/**
@@ -214,16 +264,23 @@ export function createToolbar<T extends FileType>(
214264
fileOptions: FileReadOptionsFor<T>,
215265
fileInfo: FileInfoFor<T>,
216266
): Widget | null {
267+
let widget = null;
217268
switch (fileType) {
218269
case FileType.Csv:
219-
return new CsvToolbar(options, fileOptions as CsvReadOptions, fileInfo as CsvFileInfo);
270+
widget = new CsvToolbar(options, fileOptions as CsvReadOptions, fileInfo as CsvFileInfo);
271+
break;
220272
case FileType.Sqlite:
221-
return new SqliteToolbar(
273+
widget = new SqliteToolbar(
222274
options,
223275
fileOptions as SqliteReadOptions,
224276
fileInfo as SqliteFileInfo,
225277
);
278+
break;
226279
default:
227-
return null;
280+
widget = new (class extends InfoOnlyToolbar {})(options);
281+
widget.addClass("arrow-viewer-toolbar");
282+
break;
228283
}
284+
285+
return widget;
229286
}

‎src/widget.ts‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,14 @@ export class ArrowGridViewer extends Panel {
163163
};
164164
}
165165

166+
get numCols(): number {
167+
return this.dataModel.numCols;
168+
}
169+
170+
get numRows(): number {
171+
return this.dataModel.numRows;
172+
}
173+
166174
/**
167175
* The style used by the data grid.
168176
*/

‎style/base.css‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
}
1414

1515
.arrow-viewer-toolbar {
16+
width: 99%;
1617
display: flex;
1718
flex: 0 0 auto;
1819
flex-direction: row;
@@ -21,11 +22,22 @@
2122
background: var(--jp-toolbar-background);
2223
z-index: 1;
2324

25+
.toolbar-select {
26+
display: flex;
27+
flex-direction: row;
28+
flex: 1;
29+
align-items: center;
30+
}
31+
2432
.toolbar-label {
2533
color: var(--jp-ui-font-color1);
2634
font-size: var(--jp-ui-font-size1);
2735
padding-left: 8px;
2836
padding-right: 8px;
37+
38+
.cols {
39+
padding-right: 0px;
40+
}
2941
}
3042

3143
.toolbar-dropdown {
@@ -45,5 +57,9 @@
4557
padding-right: 20px;
4658
}
4759
}
60+
61+
.toolbar-group-cols-rows {
62+
margin-left: auto;
63+
}
4864
}
4965
}

0 commit comments

Comments
 (0)