blixify-ui-web-mcp 0.1.57 → 0.1.58

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.
@@ -729,6 +729,28 @@ Use `organise.additionalQuery` to add filter controls above the list. Each entry
729
729
 
730
730
  ---
731
731
 
732
+ ### Formula column
733
+
734
+ A `type: "formula"` column is a monday.com-style formula. It is worked out from the row whenever the row is shown — table, kanban, grid and read view — and never stored on the record. It is a column type of its own: `math` columns and their `mathExpression` are untouched by it.
735
+
736
+ ```tsx
737
+ {
738
+ id: "spendStatus",
739
+ name: "Spend Status",
740
+ type: "formula",
741
+ formulaExpression: 'IF({spent} > {budget}, "Over budget", "Under budget")',
742
+ }
743
+ ```
744
+
745
+ - **Syntax** follows [monday's formula column](https://support.monday.com/hc/en-us/articles/360001235445-The-Formula-Column): `{Column}` references a column (the builder shows names, the schema stores ids, so renaming a column never breaks a formula), text in quotes, `=` / `<>` compare, `&` joins text (below `+`/`-`, above comparisons, as in monday), `+ - * / ^ %` and `( )`.
746
+ - **Functions** — monday's library, in `src/components/data/formula/functions.ts`: text (`CONCATENATE`, `LEFT`, `LEN`, `REPLACE`, `SEARCH`, `SUBSTITUTE`, `TEXT`, `TRIM` …), logical (`IF`, `SWITCH`, `AND`, `OR`, `XOR`, `NOT`, `EXACT`), numeric (`SUM`, `AVERAGE`, `ROUND`, `ROUNDUP`, `ROUNDDOWN`, `MOD`, `POWER` …), date (`TODAY`, `NOW`, `DAYS`, `WORKDAYS`, `ADD_DAYS`, `FORMAT_DATE`, `WEEKNUM` …) and `PI` / `TRUE` / `FALSE`. Text results are capped at 10,000 characters.
747
+ - **Values:** an empty cell is blank text, 0 in arithmetic and equal to 0 in a comparison with a number. Reference and role columns read their label; a math column reads the number it shows. A formula can read another formula; a circular reference shows `Error`. Files, images, addresses, objects, passwords, signatures, canvas and gantt columns cannot be used.
748
+ - **Adding:** with `bareAddColumns`, pick **Formula** as the type in the header + panel. The builder lists columns and functions with an example of each, validates as you type and previews the first row.
749
+ - **Sort and filter** use the computed value, as monday does: header / view settings sort, and the flex filters. Either makes the list read the matching rows — at most `FORMULA_VIEW_MAX_ROWS` (5,000), in a fixed order, with a notice when there are more — and filter, order and page them locally. The cap also applies to the calendar, map, timeline and legacy grouped views, which otherwise read every row. On Firebase and union lists formula columns are not offered for sorting or filtering. CSV export sends the rows a formula filter kept, by id; "Select all pages" is off in a formula view, and the selection callbacks' query does not carry formula conditions.
750
+ - **Earlier library versions** have no case for `formula`, so they show its cell blank. Apps that build schemas with `parseSpaceToDataStructure` need this version to receive `formulaExpression`; a consumer with its own `DataType` list (blixify-space-next `models/Data.ts`) adds `"formula"` to it.
751
+
752
+ ---
753
+
732
754
  ### With activity log (comments + audit trail)
733
755
 
734
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.
@@ -1084,7 +1106,7 @@ Which field types can be edited from the list table, and how. Types not listed u
1084
1106
 
1085
1107
  | Edited **in the cell** | Edited **in a modal** (cell click opens it) | Read-only in list | Never rendered as a list column |
1086
1108
  | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------- | ----------------------------- | ------------------------------- |
1087
- | `string`, `contact`, `email`, `textArea`, `number`, `boolean` (checkbox and radio commit on select), `date`, `list`, `multipleList`, `person`, `listPerson`, `roles`, `reference`, `listReference`, `referenceSelection` | `image`, `multipleImage`, `address`, `object`, `listObject`, `markdown`, `signature`, `file`, `multipleFile`, `listAddress` | `math` (computed), `password` | `canvas`, `ganttchart` |
1109
+ | `string`, `contact`, `email`, `textArea`, `number`, `boolean` (checkbox and radio commit on select), `date`, `list`, `multipleList`, `person`, `listPerson`, `roles`, `reference`, `listReference`, `referenceSelection` | `image`, `multipleImage`, `address`, `object`, `listObject`, `markdown`, `signature`, `file`, `multipleFile`, `listAddress` | `math` (computed), `formula` (computed), `password` | `canvas`, `ganttchart` |
1088
1110
 
1089
1111
  - **Why some types edit in a modal:** their editor is bigger than one line. An
1090
1112
  `address` is a Places autocomplete plus a map with a draggable pin plus
@@ -538,6 +538,97 @@ export const DTWInlineEditMatrix = () => {
538
538
  );
539
539
  };
540
540
 
541
+ // INFO: a formula column the monday.com way — added from the header +, written
542
+ // with {Column} references, sorted and filtered on its computed value. Formula
543
+ // rows are read in full (stopLimit) so a sort orders every row, not one page.
544
+ export const DTWFormulaColumn = () => {
545
+ // 1. State
546
+ const [mount, setMount] = useState<boolean>(false);
547
+ const [schema, setSchema] = useState<any[]>(() => [
548
+ ...InlineEditMatrixSchema.filter((each) =>
549
+ ["name", "qty", "status", "due", "owner", "site"].includes(each.id),
550
+ ),
551
+ {
552
+ id: "spend",
553
+ name: "Spend Status",
554
+ type: "formula" as const,
555
+ formulaExpression: 'IF({qty} > 20, "Over budget", "Under budget")',
556
+ optional: true,
557
+ },
558
+ ]);
559
+ const [, setTick] = useState<number>(0);
560
+
561
+ // 2. Refs
562
+ const storeRef = useRef<any[]>(handleBuildMatrixRecords());
563
+ const ownersRef = useRef<any[]>(handleBuildMatrixOwners());
564
+ const countersRef = useRef({ list: 0, update: 0, ownerList: 0 });
565
+ const mockRef = useRef<any>(null);
566
+
567
+ // 4. Effects
568
+ useEffect(() => {
569
+ mockRef.current = handleInstallMatrixMock(
570
+ storeRef.current,
571
+ ownersRef.current,
572
+ countersRef.current,
573
+ () => setTick((previous) => previous + 1),
574
+ );
575
+ setMount(true);
576
+ return () => {
577
+ mockRef.current?.restore();
578
+ mockRef.current = null;
579
+ };
580
+ }, []);
581
+
582
+ // 7. Return
583
+ if (!mount) return <Loading />;
584
+
585
+ return (
586
+ <div className="w-full">
587
+ <div className="font-semibold mb-1 text-gray-900">DTW Formula Column</div>
588
+ <div className="text-sm font-light mb-4 text-gray-500">
589
+ Spend Status is IF({"{Qty}"} &gt; 20, &quot;Over budget&quot;,
590
+ &quot;Under budget&quot;). Add another formula from the header +, pick
591
+ Formula as the type and reference columns in braces. Sort a formula from
592
+ its header or filter it from the flex filters — both run on the computed
593
+ value.
594
+ </div>
595
+ <div className="mb-3 text-xs text-gray-600 font-mono">
596
+ list calls:{" "}
597
+ <span data-testid="formula-list-count">{countersRef.current.list}</span>
598
+ </div>
599
+ <DataTemplateWrapper
600
+ title="Budget"
601
+ type="list"
602
+ collectionId={MATRIX_COLLECTION}
603
+ schema={schema}
604
+ workspace={{
605
+ apiEndpointType: "mongoDB",
606
+ apiEndpoint: MATRIX_ENDPOINT,
607
+ apiEndpointToken: "",
608
+ apiUserToken: "",
609
+ assetEndpoint: "",
610
+ assetUploadEndpoint: "",
611
+ }}
612
+ edit={{ allEditable: true, listEditable: true, deleteBtn: false }}
613
+ bareSettings={{
614
+ bareNewDTW: true,
615
+ bareCompactMode: true,
616
+ bareAddColumns: true,
617
+ bareFlexFilters: true,
618
+ }}
619
+ organise={{
620
+ // INFO: holds the sort the header sets, as an app's saved view would
621
+ persistViewState: "session",
622
+ breadcrumbType: "button",
623
+ onAddColumns: (model) => setSchema(model),
624
+ }}
625
+ handleNavigate={() => {}}
626
+ limit={5}
627
+ />
628
+ </div>
629
+ );
630
+ };
631
+
541
632
  /**
542
633
  * INFO: the shape blixify-space-next actually runs — a live database embedded in
543
634
  * a document, with columns addable from the table and rows addable inline.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blixify-ui-web-mcp",
3
- "version": "0.1.57",
3
+ "version": "0.1.58",
4
4
  "license": "MIT",
5
5
  "main": "lib/mcp/server.js",
6
6
  "bin": {