blixify-ui-web-mcp 0.1.42 → 0.1.43

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1095,7 +1095,6 @@ Which field types can be edited from the list table, and how. Types not listed u
1095
1095
  | `groupIdCollapsible` | `{ [key: string]: boolean }` | Initial collapsed/expanded state per group ID |
1096
1096
  | `sortGroupByAlphabetically` | `boolean` | Sorts group-by values alphabetically |
1097
1097
  | `unionCollections` | `any[]` | Additional collections to union-query alongside the main collection |
1098
- | `unionPagination` | `boolean` | Opt in to paging a union list: sends the page offset as `skip` and adds `_id` to the sort as a tie-break (default `false`). See *Union Collections* in the DataWrapper README |
1099
1098
  | `moreSettings` | `{ text: string; onClick: () => void }[]` | Extra items appended to the "more" dropdown menu |
1100
1099
  | `exportSettings` | `ExportSettings` | See Export Settings below |
1101
1100
  | `onChangeSort` | `(value: Sort) => void` | Called when the user changes the sort |
@@ -1017,28 +1017,23 @@ organise={{
1017
1017
 
1018
1018
  ---
1019
1019
 
1020
- ### Paging a union list — `unionPagination`
1020
+ ### Paging a union list
1021
1021
 
1022
- A union list does not page on its own. The DTW sends `skip: 0` for every union request, so page 2 (or the next scroll load) returns the first rows again. If the app fetches the whole union in one request and pages it itself, that is fine and nothing changes.
1022
+ A union list pages on the server like any other list. Each page request:
1023
1023
 
1024
- Set `organise.unionPagination` to let the server do the paging instead. It is **off by default**, so upgrading the library changes nothing until you opt in.
1024
+ - sends `skip = pageIndex × limit` (the first page is `0`);
1025
+ - sends the sort followed by `_id` in the same direction, e.g. `[{ sortId: "sortDate", type: "asc" }, { sortId: "_id", type: "asc" }]`. Every page is a separate request, and two rows with the same sort value have no fixed order between requests, so without the tie-break a row can appear on two pages or on none. With no sort set, the server default (`date` descending) is kept and `_id` is added after it.
1025
1026
 
1026
1027
  ```tsx
1027
1028
  organise={{
1028
1029
  unionCollections: [/* ... */],
1029
- unionPagination: true,
1030
1030
  paginationType: "scroll", // or "page"
1031
1031
  sort: { sortId: "sortDate", type: "asc" },
1032
1032
  }}
1033
1033
  limit={20}
1034
1034
  ```
1035
1035
 
1036
- With it on, each page request:
1037
-
1038
- - sends `skip = pageIndex × limit` (the first page is `0`);
1039
- - sends the sort followed by `_id` in the same direction, e.g. `[{ sortId: "sortDate", type: "asc" }, { sortId: "_id", type: "asc" }]`. Every page is a separate request, and two rows with the same sort value have no fixed order between requests, so without the tie-break a row can appear on two pages or on none. With no sort set, the server default (`date` descending) is kept and `_id` is added after it.
1040
-
1041
- It only applies with `unionCollections`. Calendar, map and timeline views fetch the full set and are not affected.
1036
+ Calendar, map, timeline and `groupId` views fetch the full set and are not paged.
1042
1037
 
1043
1038
  ---
1044
1039
 
@@ -0,0 +1,122 @@
1
+ import axios from "axios";
2
+ import MockAdapter from "axios-mock-adapter";
3
+ import React, { useEffect, useMemo, useState } from "react";
4
+ import { DataTemplateWrapper } from ".";
5
+ import {
6
+ DEFAULT_VIEWS,
7
+ DEMO_ENDPOINT,
8
+ DEMO_SCHEMA,
9
+ demoDevSettings,
10
+ renderDemoRecords,
11
+ } from "../dataTemplate/savedViewsDemo.fixtures";
12
+
13
+ const meta = { title: "Data/Data Wrapper/Scroll Filters" };
14
+ export default meta;
15
+
16
+ const COLLECTION = "demo-scroll-filter-tasks";
17
+
18
+ // INFO: an unfiltered read answers slower than a filtered one, so applying a
19
+ // view while the first load is in flight makes the old answer land last —
20
+ // the order that put rows from an earlier filter on screen
21
+ const UNFILTERED_DELAY = 1500;
22
+ const FILTERED_DELAY = 100;
23
+
24
+ const workspace = {
25
+ apiEndpointType: "mongoDB" as const,
26
+ apiEndpoint: DEMO_ENDPOINT,
27
+ apiEndpointToken: "",
28
+ apiUserToken: "",
29
+ assetEndpoint: "",
30
+ assetUploadEndpoint: "",
31
+ };
32
+
33
+ const handleInstallScrollMock = (store: any[]) => {
34
+ const mock = new MockAdapter(axios, { onNoMatch: "passthrough" });
35
+ mock.onPost(`${DEMO_ENDPOINT}/${COLLECTION}/list`).reply((config) => {
36
+ let body: any = {};
37
+ try {
38
+ body = JSON.parse(config?.data ?? "{}");
39
+ } catch (err) {
40
+ body = {};
41
+ }
42
+ const stageQuery = (body.query ?? []).find(
43
+ (eachQuery: any) => eachQuery?.queryId === "stage",
44
+ );
45
+ const rows = stageQuery
46
+ ? store.filter((each) => each.stage === stageQuery.value)
47
+ : store;
48
+ const cursor = typeof body.cursor === "number" ? body.cursor : 0;
49
+ const limit = typeof body.limit === "number" ? body.limit : rows.length;
50
+ return new Promise((resolve) =>
51
+ setTimeout(
52
+ () =>
53
+ resolve([
54
+ 200,
55
+ { data: rows.slice(cursor, cursor + limit), count: rows.length },
56
+ ]),
57
+ stageQuery ? FILTERED_DELAY : UNFILTERED_DELAY,
58
+ ),
59
+ );
60
+ });
61
+ mock
62
+ .onPost(`${DEMO_ENDPOINT}/spaces/list`)
63
+ .reply(200, { data: [], count: 0 });
64
+ return mock;
65
+ };
66
+
67
+ const ScrollFiltersDemo = () => {
68
+ const [isMockReady, setIsMockReady] = useState(false);
69
+ const store = useMemo(() => renderDemoRecords(), []);
70
+
71
+ // INFO: in an effect so it survives StrictMode's double mount
72
+ useEffect(() => {
73
+ const mock = handleInstallScrollMock(store);
74
+ setIsMockReady(true);
75
+ return () => {
76
+ mock.restore();
77
+ setIsMockReady(false);
78
+ };
79
+ }, [store]);
80
+
81
+ if (!isMockReady) return null;
82
+ return (
83
+ <DataTemplateWrapper
84
+ title="Tasks"
85
+ description="40 offline records"
86
+ type="list"
87
+ collectionId={COLLECTION}
88
+ schema={DEMO_SCHEMA}
89
+ workspace={workspace}
90
+ devSettings={{
91
+ schemaEndpoint: demoDevSettings.schemaEndpoint,
92
+ currentUser: demoDevSettings.currentUser,
93
+ }}
94
+ limit={10}
95
+ organise={{
96
+ breadcrumbType: "hidden",
97
+ paginationType: "scroll",
98
+ savedViews: true,
99
+ defaultSavedViews: DEFAULT_VIEWS,
100
+ }}
101
+ bareSettings={{
102
+ bareNewDTW: true,
103
+ bareFlexFilters: true,
104
+ }}
105
+ />
106
+ );
107
+ };
108
+
109
+ export const ScrollFilters = () => (
110
+ <div className="w-full">
111
+ <div className="font-semibold mb-1 text-gray-900">
112
+ DataTemplateWrapper — scroll list with flex filters
113
+ </div>
114
+ <div className="text-sm mb-4 text-gray-600">
115
+ A scroll-paginated list where an unfiltered read answers slower than a
116
+ filtered one. Apply “In progress” during the first load, or clear the
117
+ filter afterwards: the table must show only the rows of the current
118
+ filter, and the result count must match the rows on screen.
119
+ </div>
120
+ <ScrollFiltersDemo />
121
+ </div>
122
+ );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blixify-ui-web-mcp",
3
- "version": "0.1.42",
3
+ "version": "0.1.43",
4
4
  "license": "MIT",
5
5
  "main": "lib/mcp/server.js",
6
6
  "bin": {