blixify-ui-web-mcp 0.1.59 → 0.1.61
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.
|
@@ -89,6 +89,46 @@ Radar chart comparing multiple attributes across query groups:
|
|
|
89
89
|
}
|
|
90
90
|
```
|
|
91
91
|
|
|
92
|
+
Grouped by any column, top 5 with the rest as "Others", highest first:
|
|
93
|
+
|
|
94
|
+
```jsx
|
|
95
|
+
{
|
|
96
|
+
gridSize: 2,
|
|
97
|
+
type: "table",
|
|
98
|
+
title: "Leads by Agent",
|
|
99
|
+
spaceId: "leads",
|
|
100
|
+
query: [],
|
|
101
|
+
queryBaseType: "count",
|
|
102
|
+
groupBy: "agent",
|
|
103
|
+
sortBy: "value",
|
|
104
|
+
sortDirection: "desc",
|
|
105
|
+
topN: 5,
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Revenue per month as a running total, split by status:
|
|
110
|
+
|
|
111
|
+
```jsx
|
|
112
|
+
{
|
|
113
|
+
gridSize: 2,
|
|
114
|
+
type: "bar",
|
|
115
|
+
title: "Revenue per Month",
|
|
116
|
+
spaceId: "orders",
|
|
117
|
+
query: [],
|
|
118
|
+
queryBaseType: "sum",
|
|
119
|
+
queryAttributeId: ["amount"],
|
|
120
|
+
queryBaseDateId: "paidAt",
|
|
121
|
+
queryDateInterval: "month",
|
|
122
|
+
cumulative: true,
|
|
123
|
+
segmentBy: "status",
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
A chart that can't load or draw shows an error card in its place — a plain
|
|
128
|
+
message, Retry, and the technical cause under Details — and the other charts
|
|
129
|
+
keep drawing. Pass `structure` so a sum or average of a text column is caught
|
|
130
|
+
before any request is sent.
|
|
131
|
+
|
|
92
132
|
Custom layout via renderSettings:
|
|
93
133
|
|
|
94
134
|
```jsx
|
|
@@ -114,6 +154,9 @@ Custom layout via renderSettings:
|
|
|
114
154
|
| ---------------- | ------------------------------------------ | ------- | -------------------------------------------------------------------------------------------------------------------------------------- |
|
|
115
155
|
| `gridSize` | `2 \| 3` | — | Override the grid column layout. Default is a responsive `1 → 2 → 4` column grid. `2` forces 2 cols, `3` forces 3 cols. |
|
|
116
156
|
| `renderSettings` | `(charts: ReactElement, data: any) => any` | — | Custom render function. Receives the rendered charts element and the raw analytics data object. Use to wrap charts in a custom layout. |
|
|
157
|
+
| `structure` | `DataStructure[]` | — | The datasheet's columns. Groups read by their labels, and a chart measuring a column that is not a number shows why before any request. |
|
|
158
|
+
| `personOptions` | `Option[]` | — | Names for the user ids a `person` column groups by. |
|
|
159
|
+
| `onDrillDown` | `(drillDown: ChartDrillDown) => void` | — | Called when a bar, slice or table row is clicked, with its label and the query that finds its records. |
|
|
117
160
|
|
|
118
161
|
##### Charts
|
|
119
162
|
|
|
@@ -139,6 +182,13 @@ Custom layout via renderSettings:
|
|
|
139
182
|
| `colors` | `string[]` | Custom color array for chart segments/bars/lines |
|
|
140
183
|
| `orientation` | `"col" \| "row"` | Bar chart orientation. Defaults to `"row"`. |
|
|
141
184
|
| `stackedVertical` | `boolean` | Enables stacked bars on bar charts |
|
|
185
|
+
| `groupBy` | `string` | Column of any type to group by in one request. A `reference` or `person` column reads by name. |
|
|
186
|
+
| `queryDateInterval`| `"day" \| "week" \| "month"` | With `queryBaseDateId`, buckets records by day, week or month. Defaults to the last 30 days, 12 weeks or 12 months. |
|
|
187
|
+
| `segmentBy` | `string` | Second column split into stacked series (bar, line, table), at most 10 values plus "Others". |
|
|
188
|
+
| `sortBy` | `"value" \| "label"` | Sort the groups. `sortDirection` is `"asc"` or `"desc"` (default). |
|
|
189
|
+
| `topN` | `number` | Keep the first N groups; the rest are added up as "Others" unless `showOthers` is `false` (averages never get "Others"). |
|
|
190
|
+
| `showPercent` | `boolean` | Show each group as a percentage of the total (count and sum, unsplit charts). |
|
|
191
|
+
| `cumulative` | `boolean` | Running total over the date buckets. |
|
|
142
192
|
|
|
143
193
|
##### WorkspaceDevSettings
|
|
144
194
|
|
|
@@ -753,7 +753,7 @@ A `type: "formula"` column is a monday.com-style formula. It is worked out from
|
|
|
753
753
|
|
|
754
754
|
### With activity log (comments + audit trail)
|
|
755
755
|
|
|
756
|
-
Enable `edit.activityLog` to open the activity panel from list and read views. It uses the new feeds and pagination UI, an inline comment composer, editable comments, confirmed deletion, and before/after audit values. It follows `organise.darkMode`, including when opened from a legacy table.
|
|
756
|
+
Enable `edit.activityLog` to open the activity panel from list and read views, in a drawer on the right (a bottom sheet on phones). In the new table each record also gets a chat bubble beside its title, for anyone who can see the row. It uses the new feeds and pagination UI, an inline comment composer, editable comments, confirmed deletion, and before/after audit values. It follows `organise.darkMode`, including when opened from a legacy table.
|
|
757
757
|
|
|
758
758
|
In the modern table (`bareNewDTW`), the outlined chat bubble at the right of the first visible column opens that data's Comments first without navigating away. The column is pinned by default when no left pins are configured; mobile cards put the icon beside the title. Read views use the same outlined chat bubble with an accessible Comments and activity label. The collection-wide clock opens Logs first. Both entry points retain both enabled tabs, falling back to the available tab if only one is enabled.
|
|
759
759
|
|
|
@@ -513,14 +513,24 @@ const CHART_SCHEMA: DataStructure[] = [
|
|
|
513
513
|
listSelection: ["web", "store", "phone"],
|
|
514
514
|
listSelectionLabel: ["Web", "Store", "Phone"],
|
|
515
515
|
},
|
|
516
|
+
{ id: "agent", name: "Agent", type: "person" },
|
|
516
517
|
{ id: "amount", name: "Amount", type: "number" },
|
|
517
518
|
{ id: "items", name: "Items", type: "number" },
|
|
518
519
|
{ id: "createdAt", name: "Created At", type: "date" },
|
|
519
520
|
];
|
|
520
521
|
|
|
522
|
+
const CHART_MEMBERS = [
|
|
523
|
+
{ key: "u1", label: "Aisha" },
|
|
524
|
+
{ key: "u2", label: "Ben" },
|
|
525
|
+
{ key: "u3", label: "Chong" },
|
|
526
|
+
{ key: "u4", label: "Devi" },
|
|
527
|
+
{ key: "u5", label: "Eli" },
|
|
528
|
+
];
|
|
529
|
+
|
|
521
530
|
const renderChartRecords = () => {
|
|
522
531
|
const statuses = ["pending", "paid", "shipped", "cancelled"];
|
|
523
532
|
const channels = ["web", "store", "phone"];
|
|
533
|
+
const agents = ["u1", "u2", "u3", "u1", "u4", "u1", "u2", "u5"];
|
|
524
534
|
return Array.from({ length: 40 }, (_, index) => ({
|
|
525
535
|
_id: `o${index + 1}`,
|
|
526
536
|
orderNo: `ORD-${1000 + index}`,
|
|
@@ -528,7 +538,16 @@ const renderChartRecords = () => {
|
|
|
528
538
|
channel: channels[(index * 5) % channels.length],
|
|
529
539
|
amount: 20 + ((index * 37) % 180),
|
|
530
540
|
items: 1 + ((index * 3) % 6),
|
|
531
|
-
|
|
541
|
+
agent: index % 9 === 0 ? undefined : agents[index % agents.length],
|
|
542
|
+
// INFO: half in the last week for the daily line, the rest over months
|
|
543
|
+
createdAt: new Date(
|
|
544
|
+
Date.now() -
|
|
545
|
+
(index % 2 === 0 ? index % 7 : (index * 11) % 300) *
|
|
546
|
+
24 *
|
|
547
|
+
60 *
|
|
548
|
+
60 *
|
|
549
|
+
1000,
|
|
550
|
+
),
|
|
532
551
|
}));
|
|
533
552
|
};
|
|
534
553
|
|
|
@@ -552,12 +571,26 @@ const handleInstallChartMock = (store: any[]) => {
|
|
|
552
571
|
return {};
|
|
553
572
|
}
|
|
554
573
|
};
|
|
555
|
-
// INFO:
|
|
574
|
+
// INFO: the conditions charts and their drill-downs send — enough to show
|
|
556
575
|
// the table's filters reaching the charts
|
|
557
576
|
const handleMatch = (record: any, query: any[] = []) =>
|
|
558
577
|
query.every((eachQuery) => {
|
|
559
|
-
|
|
560
|
-
|
|
578
|
+
const value = record[eachQuery.queryId];
|
|
579
|
+
// INFO: null matches a missing value too, as Mongo's { column: null }
|
|
580
|
+
if (eachQuery.type === "=") return (value ?? null) === eachQuery.value;
|
|
581
|
+
if (eachQuery.type === "in")
|
|
582
|
+
return eachQuery.value.includes(value ?? null);
|
|
583
|
+
if (eachQuery.type === "!in")
|
|
584
|
+
return !eachQuery.value.includes(value ?? null);
|
|
585
|
+
if (eachQuery.type === "exists")
|
|
586
|
+
return (value !== undefined && value !== null) === eachQuery.value;
|
|
587
|
+
if (eachQuery.type === "><")
|
|
588
|
+
return (
|
|
589
|
+
new Date(value) >= new Date(eachQuery.value[0]) &&
|
|
590
|
+
new Date(value) <= new Date(eachQuery.value[1])
|
|
591
|
+
);
|
|
592
|
+
if (eachQuery.type === "<")
|
|
593
|
+
return new Date(value) < new Date(eachQuery.value);
|
|
561
594
|
if (eachQuery.type === "search")
|
|
562
595
|
return Object.values(record).some((eachValue) =>
|
|
563
596
|
String(eachValue)
|
|
@@ -602,6 +635,20 @@ const handleInstallChartMock = (store: any[]) => {
|
|
|
602
635
|
);
|
|
603
636
|
})
|
|
604
637
|
: matched;
|
|
638
|
+
if (body.aggregate.groupId) {
|
|
639
|
+
const groups = new Map<any, any[]>();
|
|
640
|
+
inRange.forEach((eachRecord) => {
|
|
641
|
+
const key = eachRecord[body.aggregate.groupId] ?? null;
|
|
642
|
+
groups.set(key, [...(groups.get(key) ?? []), eachRecord]);
|
|
643
|
+
});
|
|
644
|
+
return {
|
|
645
|
+
_id: eachRange,
|
|
646
|
+
value: Array.from(groups.entries()).map(([key, records]) => ({
|
|
647
|
+
_id: key,
|
|
648
|
+
value: handleAggregate(records, body.aggregate),
|
|
649
|
+
})),
|
|
650
|
+
};
|
|
651
|
+
}
|
|
605
652
|
return {
|
|
606
653
|
_id: eachRange,
|
|
607
654
|
value: handleAggregate(inRange, body.aggregate),
|
|
@@ -705,6 +752,55 @@ const ChartViewDemo = () => {
|
|
|
705
752
|
seriesLabels: ["Pending", "Paid", "Shipped", "Cancelled"],
|
|
706
753
|
queryBaseType: "count",
|
|
707
754
|
},
|
|
755
|
+
{
|
|
756
|
+
title: "Top Agents",
|
|
757
|
+
type: "table",
|
|
758
|
+
gridSize: 2,
|
|
759
|
+
spaceId: CHART_COLLECTION,
|
|
760
|
+
query: [],
|
|
761
|
+
queryBaseType: "count",
|
|
762
|
+
groupBy: "agent",
|
|
763
|
+
sortBy: "value",
|
|
764
|
+
sortDirection: "desc",
|
|
765
|
+
topN: 3,
|
|
766
|
+
},
|
|
767
|
+
{
|
|
768
|
+
title: "Revenue Per Month",
|
|
769
|
+
type: "bar",
|
|
770
|
+
orientation: "col",
|
|
771
|
+
gridSize: 2,
|
|
772
|
+
spaceId: CHART_COLLECTION,
|
|
773
|
+
query: [],
|
|
774
|
+
queryBaseType: "sum",
|
|
775
|
+
queryAttributeId: ["amount"],
|
|
776
|
+
queryBaseDateId: "createdAt",
|
|
777
|
+
queryDateInterval: "month",
|
|
778
|
+
cumulative: true,
|
|
779
|
+
},
|
|
780
|
+
{
|
|
781
|
+
title: "Channel By Status",
|
|
782
|
+
type: "bar",
|
|
783
|
+
orientation: "col",
|
|
784
|
+
gridSize: 2,
|
|
785
|
+
spaceId: CHART_COLLECTION,
|
|
786
|
+
query: ["web", "store", "phone"].map((eachValue) => ({
|
|
787
|
+
type: "=" as const,
|
|
788
|
+
queryId: "channel",
|
|
789
|
+
value: eachValue,
|
|
790
|
+
})),
|
|
791
|
+
seriesLabels: ["Web", "Store", "Phone"],
|
|
792
|
+
queryBaseType: "count",
|
|
793
|
+
segmentBy: "status",
|
|
794
|
+
},
|
|
795
|
+
{
|
|
796
|
+
title: "Sum Of Order No",
|
|
797
|
+
type: "card",
|
|
798
|
+
gridSize: 2,
|
|
799
|
+
spaceId: CHART_COLLECTION,
|
|
800
|
+
query: [],
|
|
801
|
+
queryBaseType: "sum",
|
|
802
|
+
queryAttributeId: ["orderNo"],
|
|
803
|
+
},
|
|
708
804
|
],
|
|
709
805
|
},
|
|
710
806
|
]);
|
|
@@ -719,7 +815,7 @@ const ChartViewDemo = () => {
|
|
|
719
815
|
collectionId={CHART_COLLECTION}
|
|
720
816
|
model={CHART_SCHEMA}
|
|
721
817
|
localURLEndpoint=""
|
|
722
|
-
devSettings={demoDevSettings}
|
|
818
|
+
devSettings={{ ...demoDevSettings, organisationMembers: CHART_MEMBERS }}
|
|
723
819
|
lib={{ axios, Menu, Transition, papaParser: Papa }}
|
|
724
820
|
limit={10}
|
|
725
821
|
edit={{ allEditable: true }}
|
|
@@ -6,6 +6,10 @@ Tabular display with a List-shaped mobile breakpoint. The architectural key: **`
|
|
|
6
6
|
|
|
7
7
|
Pass `onRowActivity={(id) => ...}` to show a keyboard-accessible chat button at the right of the first visible cell (beside the title on mobile cards). It stops row navigation and does not enter inline editing. When no left pins are configured, the first ungrouped column is pinned automatically; existing pin configurations are preserved. DTW wires this callback automatically when `edit.activityLog` is enabled with `bareNewDTW`.
|
|
8
8
|
|
|
9
|
+
## Adding a row
|
|
10
|
+
|
|
11
|
+
With `addable.active`, a `+` row at the bottom starts a new record where the click lands. While it is filled in, ✓ and ✕ sit in the Actions column and **Save** and **Cancel** are repeated under the row, held at the left edge as the table scrolls sideways. Enter saves and opens the next row, Escape cancels, and clicking another row saves it.
|
|
12
|
+
|
|
9
13
|
## Mobile column flags
|
|
10
14
|
|
|
11
15
|
Columns expose three optional booleans that map them to the `NewListItem` shape:
|
|
@@ -75,7 +79,7 @@ used, not only inside a DataTemplate.
|
|
|
75
79
|
|
|
76
80
|
##### Adding a column from the table
|
|
77
81
|
|
|
78
|
-
`advSettings.addColumnEnabled` puts a `+` at the end of the header row. It opens a portalled popover beside the button on desktop and a modal on mobile — the panel has to be portalled or the table's own scroll container clips it. What it
|
|
82
|
+
`advSettings.addColumnEnabled` puts a `+` at the end of the header row, pinned at the right edge (just left of the Actions column) so it stays in view on a wide table. It opens a portalled popover beside the button on desktop and a modal on mobile — the panel has to be portalled or the table's own scroll container clips it. What it
|
|
79
83
|
opens depends on which callback you give it:
|
|
80
84
|
|
|
81
85
|
| Provide | You get |
|