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
|
|
1020
|
+
### Paging a union list
|
|
1021
1021
|
|
|
1022
|
-
A union list
|
|
1022
|
+
A union list pages on the server like any other list. Each page request:
|
|
1023
1023
|
|
|
1024
|
-
|
|
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
|
-
|
|
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
|
+
);
|