fsanyoto commited on
Commit
2f6862d
Β·
verified Β·
1 Parent(s): c27b755

Deploy AIOS web (React glide grid + FastAPI slice)

Browse files
web/src/customer-grid/ColumnMenu.tsx CHANGED
@@ -330,11 +330,10 @@ interface ColumnMenuProps {
330
  * DIFFERENT ACT from `onDelete`, and therefore a different door: it destroys no definition and
331
  * no values, and pointing "Remove from my fields" at the delete handler would be a benign word
332
  * on a destructive action.
333
- * A host supplies this only when it has a real self-removal server door. The current API does
334
- * not permit a grantee to withdraw only themself, so the grid intentionally leaves the row
335
- * absent instead of wiring it to a toast or a destructive share rewrite.
336
  */
337
- onRemoveFromMine?: () => void;
338
  /** ⭐⭐ Wave-34 (R13) β€” run this AI enrichment column over many rows.
339
  * `scope` is `"blank"` (only cells still empty) or `"always"` (every row the AI
340
  * wrote). OPTIONAL for `onDelete`'s reason: a host that has not wired the door shows
 
330
  * DIFFERENT ACT from `onDelete`, and therefore a different door: it destroys no definition and
331
  * no values, and pointing "Remove from my fields" at the delete handler would be a benign word
332
  * on a destructive action.
333
+ * The grid's dedicated `DELETE /share/field/{oid}/mine` door removes only the current direct
334
+ * grantee, so both mounted menus can call a real, non-destructive action.
 
335
  */
336
+ onRemoveFromMine: () => void;
337
  /** ⭐⭐ Wave-34 (R13) β€” run this AI enrichment column over many rows.
338
  * `scope` is `"blank"` (only cells still empty) or `"always"` (every row the AI
339
  * wrote). OPTIONAL for `onDelete`'s reason: a host that has not wired the door shows
web/src/customer-grid/CustomerGrid.tsx CHANGED
@@ -9689,14 +9689,10 @@ function CustomerGridSurface({
9689
  }
9690
  : undefined
9691
  }
9692
- onRemoveFromMine={
9693
- menuField.shared && menuField.sharedRole !== "owner"
9694
- ? () => {
9695
- removeFieldFromMine(menuField);
9696
- setColumnMenu(null);
9697
- }
9698
- : undefined
9699
- }
9700
  onDuplicate={
9701
  // Creatable strata only β€” a base Odoo field offers no Duplicate (contract).
9702
  menuField.custom && !menuField.shared ? () => duplicateField(menuField) : undefined
@@ -9804,8 +9800,14 @@ function CustomerGridSurface({
9804
  onNote={() => undefined}
9805
  onHide={() => undefined}
9806
  onCreate={createField}
9807
- /* Keep the twin aligned: no self-removal affordance without a safe server door. */
9808
- onRemoveFromMine={undefined}
 
 
 
 
 
 
9809
  geocodable={true}
9810
  onChangeField={() => undefined}
9811
  onCreateAndSwap={() => undefined}
 
9689
  }
9690
  : undefined
9691
  }
9692
+ onRemoveFromMine={() => {
9693
+ removeFieldFromMine(menuField);
9694
+ setColumnMenu(null);
9695
+ }}
 
 
 
 
9696
  onDuplicate={
9697
  // Creatable strata only β€” a base Odoo field offers no Duplicate (contract).
9698
  menuField.custom && !menuField.shared ? () => duplicateField(menuField) : undefined
 
9800
  onNote={() => undefined}
9801
  onHide={() => undefined}
9802
  onCreate={createField}
9803
+ /* This create-only mount normally cannot expose the row, but it still receives the
9804
+ same real self-removal door as the ordinary menu. Keeping both mounts wired makes
9805
+ a future affordance change safe instead of silently inert. */
9806
+ onRemoveFromMine={() => {
9807
+ const field = fieldByKey.get(lockedKey);
9808
+ if (field) removeFieldFromMine(field);
9809
+ setPlusMenu(null);
9810
+ }}
9811
  geocodable={true}
9812
  onChangeField={() => undefined}
9813
  onCreateAndSwap={() => undefined}
web/wiring_rows/wave42_c.py CHANGED
@@ -146,9 +146,17 @@ ROWS: list[tuple[str, str, str, str, str]] = [
146
  # a silent one, with the whole battery green. The bundle door is the only thing on this
147
  # surface that speaks the refusal out loud, so pinning it pins the behaviour.
148
  ("W42-T13 a shared grantee's ColumnMenu reaches self-removal",
149
- "customer-grid/ColumnMenu.tsx", r"onRemoveFromMine\?: \(\) => void;",
150
  "customer-grid/CustomerGrid.tsx",
151
- r"onRemoveFromMine=\{[\s\S]*removeFieldFromMine\(menuField\)"),
 
 
 
 
 
 
 
 
152
 
153
  # ⭐⭐ W42-T58 (contract C4) β€” THE PER KEY VERDICT IS DECLARED IN ONE FILE AND READ IN ANOTHER.
154
  #
 
146
  # a silent one, with the whole battery green. The bundle door is the only thing on this
147
  # surface that speaks the refusal out loud, so pinning it pins the behaviour.
148
  ("W42-T13 a shared grantee's ColumnMenu reaches self-removal",
149
+ "customer-grid/ColumnMenu.tsx", r"onRemoveFromMine: \(\) => void;",
150
  "customer-grid/CustomerGrid.tsx",
151
+ r"onRemoveFromMine=\{[\s\S]*removeFieldFromMine\(menuField\)[\s\S]*onRemoveFromMine=\{[\s\S]*removeFieldFromMine\(field\)"),
152
+
153
+ # W42-T35 β€” link conditions are not useful unless the edit modal receives both the
154
+ # predicate and its conjunction. Keeping this cross-fence pin beside T13 prevents the
155
+ # component-only editor proof from going green while the linked-record picker ignores it.
156
+ ("W42-T35 LinkGridModal receives the saved link conditions",
157
+ "customer-grid/CustomerGrid.tsx", r"interface LinkGridModalProps[\s\S]*conditions\?: readonly RollupCondition\[\][\s\S]*conditionConj\?: \"and\" \| \"or\";",
158
+ "customer-grid/CustomerGrid.tsx",
159
+ r"<LinkGridModal[\s\S]*conditions=\{linkField\.link\?\.conditions\}[\s\S]*conditionConj=\{linkField\.link\?\.conditionConj\}"),
160
 
161
  # ⭐⭐ W42-T58 (contract C4) β€” THE PER KEY VERDICT IS DECLARED IN ONE FILE AND READ IN ANOTHER.
162
  #