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
- createdAt: new Date(Date.now() - (index % 7) * 24 * 60 * 60 * 1000),
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: "=" for chart groups, "search" for the search box — enough to show
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
- if (eachQuery.type === "=")
560
- return record[eachQuery.queryId] === eachQuery.value;
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 |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blixify-ui-web-mcp",
3
- "version": "0.1.59",
3
+ "version": "0.1.61",
4
4
  "license": "MIT",
5
5
  "main": "lib/mcp/server.js",
6
6
  "bin": {