Skip to content
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

Ensure follow behavior works when streaming to paginated Tabulator #7084

Merged
merged 3 commits into from
Aug 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 19 additions & 8 deletions panel/models/tabulator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1034,25 +1034,36 @@ export class DataTabulatorView extends HTMLBoxView {
}

// Update table
setData(): void {
setData(): Promise<void> {
if (this._initializing || this._building || !this.tabulator.initialized) {
return
return Promise.resolve(undefined)
}
const data = this.getData()
if (this.model.pagination != null) {
this.tabulator.rowManager.setData(data, true, false)
return this.tabulator.rowManager.setData(data, true, false)
} else {
this.tabulator.setData(data)
return this.tabulator.setData(data)
}
}

addData(): void {
const rows = this.tabulator.rowManager.getRows()
const last_row = rows[rows.length-1]
const start = ((last_row?.data._index) || 0)
this.setData()
if (this.model.follow && last_row) {
this.tabulator.scrollToRow(start, "top", false)
this._updating_page = true
const promise = this.setData()
if (this.model.follow) {
promise.then(() => {
if (this.model.pagination) {
this.tabulator.setPage(Math.ceil(this.tabulator.rowManager.getDataCount() / (this.model.page_size || 20)))
}
if (last_row) {
this.tabulator.scrollToRow(start, "top", false)
}
this._updating_page = false
})
} else {
this._updating_page = true
}
}

Expand Down Expand Up @@ -1099,7 +1110,7 @@ export class DataTabulatorView extends HTMLBoxView {
}

updatePage(pageno: number): void {
if (this.model.pagination === "local" && this.model.page !== pageno) {
if (this.model.pagination === "local" && this.model.page !== pageno && !this._updating_page) {
this._updating_page = true
this.model.page = pageno
this._updating_page = false
Expand Down
19 changes: 18 additions & 1 deletion panel/tests/ui/widgets/test_tabulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@
widget.param.trigger('value')
wait_until(lambda: page.locator('text="AA"') is not None, page)
changed_cell = page.locator('text="AA"')
expect(changed_cell).to_have_count(1)

Check failure on line 173 in panel/tests/ui/widgets/test_tabulator.py

View workflow job for this annotation

GitHub Actions / ui:test-ui:ubuntu-latest

test_tabulator_value_changed AssertionError: Locator expected to have count '1' Actual value: 0 Call log: LocatorAssertions.to_have_count with timeout 5000ms - waiting for locator("text=\"AA\"") - locator resolved to 0 elements - unexpected value "0" - locator resolved to 0 elements - unexpected value "0" - locator resolved to 0 elements - unexpected value "0" - locator resolved to 0 elements - unexpected value "0" - locator resolved to 0 elements - unexpected value "0" - locator resolved to 0 elements - unexpected value "0" - locator resolved to 0 elements - unexpected value "0" - locator resolved to 0 elements - unexpected value "0" - locator resolved to 0 elements - unexpected value "0"


def test_tabulator_disabled(page, df_mixed):
Expand Down Expand Up @@ -2116,7 +2116,6 @@

height_start = page.locator('.pnx-tabulator.tabulator').bounding_box()['height']


def stream_data():
widget.stream(df) # follow is True by default

Expand All @@ -2131,6 +2130,24 @@
assert page.locator('.pnx-tabulator.tabulator').bounding_box()['height'] > height_start


@pytest.mark.parametrize('pagination', ['remote', 'local'])
def test_tabulator_streaming_follow_pagination(page, pagination):
df = pd.DataFrame(np.random.random((3, 2)), columns=['A', 'B'])
widget = Tabulator(df, pagination=pagination, page_size=3)

serve_component(page, widget)

expect(page.locator('.tabulator-row')).to_have_count(len(df))

widget.stream(df)

expect(page.locator('.tabulator-page.active')).to_have_text('2')

widget.stream(df)

expect(page.locator('.tabulator-page.active')).to_have_text('3')


def test_tabulator_streaming_no_follow(page):
nrows1 = 10
arr = np.random.randint(10, 20, (nrows1, 2))
Expand Down Expand Up @@ -3332,7 +3349,7 @@
assert table_values == list(df2['x'].sort_values(ascending=False))
else:
return False
wait_until(x_values, page)

Check failure on line 3352 in panel/tests/ui/widgets/test_tabulator.py

View workflow job for this annotation

GitHub Actions / ui:test-ui:ubuntu-latest

test_tabulator_sorter_default_number TimeoutError: wait_until timed out in 5000 milliseconds


def test_tabulator_update_hidden_columns(page):
Expand Down
10 changes: 6 additions & 4 deletions panel/widgets/tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -1565,8 +1565,10 @@ def _stream(self, stream, rollover=None, follow=True):
length = self._length
nrows = self.page_size or self.initial_page_size
max_page = max(length//nrows + bool(length%nrows), 1)
if self.page != max_page:
if self.page != max_page and not follow:
return
self._processed, _ = self._get_data()
return
super()._stream(stream, rollover)
self._update_style()
self._update_selectable()
Expand All @@ -1575,13 +1577,13 @@ def _stream(self, stream, rollover=None, follow=True):
def stream(self, stream_value, rollover=None, reset_index=True, follow=True):
for ref, (model, _) in self._models.items():
self._apply_update([], {'follow': follow}, model, ref)
super().stream(stream_value, rollover, reset_index)
if follow and self.pagination:
self._update_max_page()
if follow and self.pagination:
length = self._length
nrows = self.page_size or self.initial_page_size
self.page = max(length//nrows + bool(length%nrows), 1)
super().stream(stream_value, rollover, reset_index)
if follow and self.pagination:
self._update_max_page()

@updating
def _patch(self, patch):
Expand Down
Loading