-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Persist column width preferences #211
Changes from 4 commits
4dec67f
55875d7
7a09878
0a9415c
26bf7bc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"ember-headless-table": minor | ||
--- | ||
|
||
Persists resized column widths to preferences | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -133,5 +133,8 @@ | |
"ember-headless-table": { | ||
"injected": true | ||
} | ||
}, | ||
"volta": { | ||
"extends": "../package.json" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -262,6 +262,7 @@ function columnsFor<DataType = any>( | |
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This method upsets me. lol (I wrote it) It was meant to be temporary. I need to see how TanStack Table handles their column dependency calculations |
||
let visibility = findPlugin(table.plugins, 'columnVisibility'); | ||
let reordering = findPlugin(table.plugins, 'columnOrder'); | ||
let sizing = findPlugin(table.plugins, 'columnResizing'); | ||
|
||
// TODO: actually resolve the graph, rather than use the hardcoded feature names | ||
// atm, this only "happens" to work based on expectations of | ||
|
@@ -274,6 +275,10 @@ function columnsFor<DataType = any>( | |
table.plugins.some((plugin) => plugin instanceof (requester as Class<Plugin>)) | ||
); | ||
|
||
if (sizing && sizing.constructor === requester) { | ||
return table.columns.values(); | ||
} | ||
|
||
if (visibility && visibility.constructor === requester) { | ||
return table.columns.values(); | ||
} | ||
|
@@ -309,6 +314,15 @@ function columnsFor<DataType = any>( | |
return visibility.columns; | ||
} | ||
|
||
if (sizing) { | ||
assert( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: do we need to test for this new assert? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we currently test for any of the other asserts in this function |
||
`<#${sizing.name}> defined a 'columns' property, but did not return valid data.`, | ||
sizing.columns && Array.isArray(sizing.columns) | ||
); | ||
|
||
return sizing.columns; | ||
} | ||
|
||
return table.columns.values(); | ||
} | ||
|
||
|
@@ -334,6 +348,15 @@ function columnsFor<DataType = any>( | |
return visibility.columns; | ||
} | ||
|
||
if (sizing) { | ||
assert( | ||
`<#${sizing.name}> defined a 'columns' property, but did not return valid data.`, | ||
sizing.columns && Array.isArray(sizing.columns) | ||
); | ||
|
||
return sizing.columns; | ||
} | ||
|
||
return table.columns.values(); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,13 +2,29 @@ import { cached, tracked } from '@glimmer/tracking'; | |
import { assert } from '@ember/debug'; | ||
import { action } from '@ember/object'; | ||
|
||
import { preferences } from '[public-plugin-types]'; | ||
|
||
import { BasePlugin, columns, meta, options } from '../-private/base'; | ||
import { applyStyles } from '../-private/utils'; | ||
import { getAccurateClientHeight, getAccurateClientWidth, totalGapOf } from './utils'; | ||
|
||
import type { ColumnApi } from '[public-plugin-types]'; | ||
import type { ColumnApi, PluginPreferences } from '[public-plugin-types]'; | ||
import type { Column, Table } from '[public-types]'; | ||
|
||
interface ColumnResizePreferences extends PluginPreferences { | ||
columns: { | ||
[columnKey: string]: { | ||
width?: number; | ||
}; | ||
}; | ||
} | ||
|
||
declare module 'ember-headless-table/plugins' { | ||
interface Registry { | ||
ColumnResize?: ColumnResizePreferences; | ||
} | ||
} | ||
|
||
export interface ColumnOptions { | ||
/** | ||
* Force a starting width | ||
|
@@ -94,6 +110,15 @@ export class ColumnResizing extends BasePlugin<Signature> { | |
let tableMeta = meta.forTable(this.table, ColumnResizing); | ||
|
||
tableMeta.reset(); | ||
|
||
for (let column of this.table.columns) { | ||
let defaultValue = options.forColumn(column, ColumnResizing)?.width; | ||
let current = meta.forColumn(column, ColumnResizing).width; | ||
|
||
if (defaultValue !== current) { | ||
preferences.forTable(this.table, ColumnResizing).delete('width'); | ||
} | ||
} | ||
} | ||
} | ||
|
||
|
@@ -135,12 +160,24 @@ export class ColumnMeta { | |
}; | ||
} | ||
|
||
get key() { | ||
return this.column.key; | ||
} | ||
|
||
get minWidth() { | ||
return this.options.minWidth; | ||
} | ||
|
||
get initialWidth() { | ||
return this.options.width; | ||
let savedWidth = preferences.forColumn(this.column, ColumnResizing).get('width'); | ||
|
||
if (!savedWidth) { | ||
return this.options.width; | ||
} | ||
|
||
assert('saved width must be a string', typeof savedWidth === 'string'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit (non-blocking): do we need to test for this assert? |
||
|
||
return parseInt(savedWidth, 10); | ||
} | ||
|
||
get canShrink() { | ||
|
@@ -192,6 +229,11 @@ export class ColumnMeta { | |
resize(delta: number) { | ||
this.tableMeta.resizeColumn(this.column, delta); | ||
} | ||
|
||
@action | ||
save() { | ||
this.tableMeta.saveColWidths(this.tableMeta.visibleColumnMetas); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: do we need to test for this save action? |
||
} | ||
} | ||
|
||
/** | ||
|
@@ -270,6 +312,23 @@ export class TableMeta { | |
return this.visibleColumnMetas.reduce((acc, column) => (acc += column.width ?? 0), 0); | ||
} | ||
|
||
@action | ||
saveColWidths(visibleColumnMetas: ColumnMeta[]) { | ||
let availableColumns = columns.for(this.table, ColumnResizing); | ||
|
||
for (let column of visibleColumnMetas) { | ||
let columnToUpdate = availableColumns.find((c) => { | ||
return c.key === column.key; | ||
}); | ||
|
||
assert('column must exist', columnToUpdate); | ||
|
||
let colPreferences = preferences.forColumn(columnToUpdate, ColumnResizing); | ||
|
||
colPreferences.set('width', column.width.toString()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should this width be a percentage so that when the table is loaded on a different sized browser, the columns have the same way of being sized? I could see the argument either way. like,
|
||
} | ||
} | ||
|
||
@action | ||
reset() { | ||
if (!this.scrollContainerWidth) return; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,6 +28,9 @@ export function createHelpers(selectors: Selectors) { | |
|
||
triggerEvent(element, 'mousedown', { clientX: startX, button: 0 }); | ||
triggerEvent(element, 'mousemove', { clientX: targetX, button: 0 }); | ||
|
||
await new Promise((resolve) => setTimeout(resolve, 50)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What does this do? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just curious as it seems like something I could reuse in the future... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's a workaround that ensures that the calculation of the column width styles are complete and the DOM is updated before the test continues. It's tracked to fix in #215 but is a necessary workaround for now. |
||
|
||
triggerEvent(element, 'mouseup', { clientX: targetX, button: 0 }); | ||
|
||
await settled(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: should mention the newly added
save
action and related asserts, i.e. will error if the column width is not a string.