@almadar/std 16.235.0 → 16.236.0
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.
- package/behaviors/behaviors-registry.json +4402 -1898
- package/behaviors/lolo/infra/atoms/std-approval-gate.lolo +25 -41
- package/behaviors/lolo/infra/atoms/std-audit-capture.lolo +0 -5
- package/behaviors/lolo/infra/atoms/std-cache-aside.lolo +0 -24
- package/behaviors/lolo/infra/atoms/std-circuit-breaker.lolo +1 -17
- package/behaviors/lolo/infra/atoms/std-data-erasure.lolo +17 -24
- package/behaviors/lolo/infra/atoms/std-data-import.lolo +8 -11
- package/behaviors/lolo/infra/atoms/std-game-clock.lolo +2 -0
- package/behaviors/lolo/infra/atoms/std-knowledge-loop.lolo +0 -5
- package/behaviors/lolo/infra/atoms/std-lifecycle.lolo +3 -1
- package/behaviors/lolo/infra/atoms/std-mod-queue.lolo +40 -18
- package/behaviors/lolo/infra/atoms/std-notification-preferences.lolo +20 -11
- package/behaviors/lolo/infra/atoms/std-notify-on-event.lolo +0 -5
- package/behaviors/lolo/infra/atoms/std-permission-matrix.lolo +23 -11
- package/behaviors/lolo/infra/atoms/std-rate-limiter.lolo +84 -22
- package/behaviors/lolo/infra/atoms/std-status-lifecycle.lolo +1 -6
- package/behaviors/lolo/ml/atoms/std-graph-builder.lolo +3 -1
- package/behaviors/lolo/ml/atoms/std-ml-classify.lolo +0 -4
- package/behaviors/lolo/ml/atoms/std-ml-similarity.lolo +0 -4
- package/behaviors/lolo/ui/avl/atoms/ui-avl-state-machine.lolo +12 -0
- package/behaviors/lolo/ui/core/atoms/std-app-layout.lolo +55 -9
- package/behaviors/lolo/ui/core/atoms/std-app-search.lolo +6 -2
- package/behaviors/lolo/ui/core/atoms/std-billable-hour.lolo +19 -14
- package/behaviors/lolo/ui/core/atoms/std-board.lolo +77 -27
- package/behaviors/lolo/ui/core/atoms/std-browse.lolo +44 -28
- package/behaviors/lolo/ui/core/atoms/std-calendar.lolo +7 -3
- package/behaviors/lolo/ui/core/atoms/std-esign-flow.lolo +25 -13
- package/behaviors/lolo/ui/core/atoms/std-esign-request.lolo +5 -0
- package/behaviors/lolo/ui/core/atoms/std-event-log.lolo +0 -5
- package/behaviors/lolo/ui/core/atoms/std-export.lolo +0 -10
- package/behaviors/lolo/ui/core/atoms/std-file-store.lolo +7 -3
- package/behaviors/lolo/ui/core/atoms/std-form-advanced.lolo +1 -6
- package/behaviors/lolo/ui/core/atoms/std-geosearch.lolo +1 -0
- package/behaviors/lolo/ui/core/atoms/std-graphs.lolo +20 -4
- package/behaviors/lolo/ui/core/atoms/std-import.lolo +0 -5
- package/behaviors/lolo/ui/core/atoms/std-list.lolo +46 -32
- package/behaviors/lolo/ui/core/atoms/std-modal-editor.lolo +2 -2
- package/behaviors/lolo/ui/core/atoms/std-rating-review.lolo +12 -13
- package/behaviors/lolo/ui/core/atoms/std-record-detail.lolo +16 -12
- package/behaviors/lolo/ui/core/atoms/std-recurrence.lolo +10 -1
- package/behaviors/lolo/ui/core/atoms/std-role-gate.lolo +39 -0
- package/behaviors/lolo/ui/core/atoms/std-saved-search.lolo +78 -16
- package/behaviors/lolo/ui/core/atoms/std-selection.lolo +15 -10
- package/behaviors/lolo/ui/core/atoms/std-stats.lolo +5 -5
- package/behaviors/lolo/ui/core/atoms/std-tag-taxonomy.lolo +3 -0
- package/behaviors/lolo/ui/core/atoms/std-thread.lolo +41 -73
- package/behaviors/lolo/ui/core/atoms/std-version-history.lolo +20 -11
- package/behaviors/lolo/ui/core/atoms/std-vote.lolo +0 -4
- package/behaviors/lolo/ui/core/atoms/std-wizard.lolo +3 -3
- package/behaviors/lolo/ui/core/atoms/ui-presence.lolo +21 -0
- package/behaviors/lolo/ui/core/molecules/ui-breadcrumb.lolo +6 -1
- package/behaviors/lolo/ui/core/molecules/ui-chart.lolo +11 -1
- package/behaviors/lolo/ui/core/molecules/ui-code-block.lolo +13 -8
- package/behaviors/lolo/ui/core/molecules/ui-command-palette.lolo +7 -2
- package/behaviors/lolo/ui/core/molecules/ui-commit-row.lolo +2 -2
- package/behaviors/lolo/ui/core/molecules/ui-confirm-dialog.lolo +8 -0
- package/behaviors/lolo/ui/core/molecules/ui-data-grid.lolo +41 -3
- package/behaviors/lolo/ui/core/molecules/ui-data-list.lolo +41 -3
- package/behaviors/lolo/ui/core/molecules/ui-document-details.lolo +30 -9
- package/behaviors/lolo/ui/core/molecules/ui-document-panel.lolo +8 -3
- package/behaviors/lolo/ui/core/molecules/ui-document-viewer.lolo +6 -1
- package/behaviors/lolo/ui/core/molecules/ui-drawer.lolo +13 -0
- package/behaviors/lolo/ui/core/molecules/ui-floating-action-button.lolo +6 -1
- package/behaviors/lolo/ui/core/molecules/ui-floating-toolbar.lolo +6 -1
- package/behaviors/lolo/ui/core/molecules/ui-form-actions.lolo +6 -1
- package/behaviors/lolo/ui/core/molecules/ui-graph-canvas.lolo +6 -1
- package/behaviors/lolo/ui/core/molecules/ui-menu.lolo +6 -1
- package/behaviors/lolo/ui/core/molecules/ui-meter.lolo +6 -1
- package/behaviors/lolo/ui/core/molecules/ui-modal.lolo +5 -0
- package/behaviors/lolo/ui/core/molecules/ui-page-header.lolo +11 -1
- package/behaviors/lolo/ui/core/molecules/ui-page-transition.lolo +1 -1
- package/behaviors/lolo/ui/core/molecules/ui-swipeable-row.lolo +44 -15
- package/behaviors/lolo/ui/core/molecules/ui-table-view.lolo +41 -3
- package/behaviors/lolo/ui/core/molecules/ui-tabs.lolo +8 -2
- package/behaviors/lolo/ui/core/organisms/ui-detail-panel.lolo +66 -12
- package/behaviors/lolo/ui/core/organisms/ui-entity-cards.lolo +9 -3
- package/behaviors/lolo/ui/core/organisms/ui-entity-list.lolo +9 -3
- package/behaviors/lolo/ui/core/organisms/ui-entity-table.lolo +18 -9
- package/behaviors/lolo/ui/core/organisms/ui-form-section.lolo +55 -10
- package/behaviors/lolo/ui/core/organisms/ui-form.lolo +55 -10
- package/behaviors/lolo/ui/core/organisms/ui-media-gallery.lolo +8 -3
- package/behaviors/lolo/ui/core/organisms/ui-state-machine-view.lolo +12 -0
- package/behaviors/lolo/ui/core/organisms/ui-timeline.lolo +8 -3
- package/behaviors/lolo/ui/core/templates/ui-counter-template.lolo +2 -44
- package/behaviors/lolo/ui/core/templates/ui-dashboard-layout.lolo +6 -1
- package/behaviors/lolo/ui/core/templates/ui-generic-app-template.lolo +2 -37
- package/behaviors/lolo/ui/game/atoms/ui-game-menu.lolo +8 -2
- package/behaviors/lolo/ui/game/organisms/std-arcade-board-3d.lolo +2 -2
- package/behaviors/lolo/ui/game/organisms/std-crew-board-2d.lolo +0 -4
- package/behaviors/lolo/ui/game/organisms/std-platformer-puzzle.lolo +2 -66
- package/behaviors/lolo/ui/game/organisms/std-tactics-board-2d.lolo +0 -4
- package/behaviors/lolo/ui/game/organisms/std-worldmap-board-2d.lolo +0 -4
- package/behaviors/lolo/ui/learning/atoms/std-learn-stepper.lolo +6 -6
- package/behaviors/lolo-behavior-contracts.json +1 -1
- package/behaviors/registry/factory-signatures.json +1 -1
- package/behaviors/registry/infra/atoms/std-approval-gate.orb +124 -67
- package/behaviors/registry/infra/atoms/std-audit-capture.orb +0 -8
- package/behaviors/registry/infra/atoms/std-cache-aside.orb +0 -84
- package/behaviors/registry/infra/atoms/std-circuit-breaker.orb +1 -44
- package/behaviors/registry/infra/atoms/std-data-erasure.orb +124 -55
- package/behaviors/registry/infra/atoms/std-data-import.orb +12 -11
- package/behaviors/registry/infra/atoms/std-game-clock.orb +31 -0
- package/behaviors/registry/infra/atoms/std-knowledge-loop.orb +0 -57
- package/behaviors/registry/infra/atoms/std-lifecycle.orb +43 -0
- package/behaviors/registry/infra/atoms/std-mod-queue.orb +379 -103
- package/behaviors/registry/infra/atoms/std-notification-preferences.orb +126 -12
- package/behaviors/registry/infra/atoms/std-notify-on-event.orb +0 -11
- package/behaviors/registry/infra/atoms/std-permission-matrix.orb +128 -12
- package/behaviors/registry/infra/atoms/std-rate-limiter.orb +287 -72
- package/behaviors/registry/infra/atoms/std-status-lifecycle.orb +5 -8
- package/behaviors/registry/ml/atoms/std-graph-builder.orb +11 -0
- package/behaviors/registry/ml/atoms/std-ml-classify.orb +0 -7
- package/behaviors/registry/ml/atoms/std-ml-similarity.orb +0 -7
- package/behaviors/registry/ui/avl/atoms/ui-avl-state-machine.orb +82 -0
- package/behaviors/registry/ui/core/atoms/std-app-layout.orb +417 -9
- package/behaviors/registry/ui/core/atoms/std-app-search.orb +53 -1
- package/behaviors/registry/ui/core/atoms/std-billable-hour.orb +209 -19
- package/behaviors/registry/ui/core/atoms/std-board.orb +242 -61
- package/behaviors/registry/ui/core/atoms/std-browse.orb +295 -41
- package/behaviors/registry/ui/core/atoms/std-calendar.orb +96 -2
- package/behaviors/registry/ui/core/atoms/std-esign-flow.orb +122 -15
- package/behaviors/registry/ui/core/atoms/std-esign-request.orb +11 -0
- package/behaviors/registry/ui/core/atoms/std-event-log.orb +0 -8
- package/behaviors/registry/ui/core/atoms/std-export.orb +0 -16
- package/behaviors/registry/ui/core/atoms/std-file-store.orb +109 -2
- package/behaviors/registry/ui/core/atoms/std-form-advanced.orb +1 -43
- package/behaviors/registry/ui/core/atoms/std-geosearch.orb +5 -0
- package/behaviors/registry/ui/core/atoms/std-graphs.orb +173 -66
- package/behaviors/registry/ui/core/atoms/std-import.orb +0 -8
- package/behaviors/registry/ui/core/atoms/std-list.orb +226 -34
- package/behaviors/registry/ui/core/atoms/std-modal-editor.orb +10 -1
- package/behaviors/registry/ui/core/atoms/std-rating-review.orb +37 -19
- package/behaviors/registry/ui/core/atoms/std-record-detail.orb +204 -11
- package/behaviors/registry/ui/core/atoms/std-recurrence.orb +89 -4
- package/behaviors/registry/ui/core/atoms/std-role-gate.orb +217 -0
- package/behaviors/registry/ui/core/atoms/std-saved-search.orb +419 -19
- package/behaviors/registry/ui/core/atoms/std-selection.orb +140 -10
- package/behaviors/registry/ui/core/atoms/std-stats.orb +73 -1
- package/behaviors/registry/ui/core/atoms/std-tag-taxonomy.orb +3 -0
- package/behaviors/registry/ui/core/atoms/std-thread.orb +190 -115
- package/behaviors/registry/ui/core/atoms/std-version-history.orb +127 -13
- package/behaviors/registry/ui/core/atoms/std-vote.orb +0 -9
- package/behaviors/registry/ui/core/atoms/std-wizard.orb +33 -3
- package/behaviors/registry/ui/core/atoms/ui-presence.orb +59 -0
- package/behaviors/registry/ui/core/molecules/ui-breadcrumb.orb +53 -1
- package/behaviors/registry/ui/core/molecules/ui-chart.orb +68 -1
- package/behaviors/registry/ui/core/molecules/ui-code-block.orb +291 -8
- package/behaviors/registry/ui/core/molecules/ui-command-palette.orb +87 -2
- package/behaviors/registry/ui/core/molecules/ui-commit-row.orb +3 -2
- package/behaviors/registry/ui/core/molecules/ui-confirm-dialog.orb +32 -0
- package/behaviors/registry/ui/core/molecules/ui-data-grid.orb +189 -3
- package/behaviors/registry/ui/core/molecules/ui-data-list.orb +189 -3
- package/behaviors/registry/ui/core/molecules/ui-document-details.orb +81 -24
- package/behaviors/registry/ui/core/molecules/ui-document-panel.orb +121 -3
- package/behaviors/registry/ui/core/molecules/ui-document-viewer.orb +53 -1
- package/behaviors/registry/ui/core/molecules/ui-drawer.orb +40 -0
- package/behaviors/registry/ui/core/molecules/ui-floating-action-button.orb +53 -1
- package/behaviors/registry/ui/core/molecules/ui-floating-toolbar.orb +53 -1
- package/behaviors/registry/ui/core/molecules/ui-form-actions.orb +53 -1
- package/behaviors/registry/ui/core/molecules/ui-graph-canvas.orb +53 -1
- package/behaviors/registry/ui/core/molecules/ui-menu.orb +57 -1
- package/behaviors/registry/ui/core/molecules/ui-meter.orb +53 -1
- package/behaviors/registry/ui/core/molecules/ui-modal.orb +8 -0
- package/behaviors/registry/ui/core/molecules/ui-page-header.orb +60 -1
- package/behaviors/registry/ui/core/molecules/ui-page-transition.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-swipeable-row.orb +393 -23
- package/behaviors/registry/ui/core/molecules/ui-table-view.orb +189 -3
- package/behaviors/registry/ui/core/molecules/ui-tabs.orb +99 -2
- package/behaviors/registry/ui/core/organisms/ui-detail-panel.orb +282 -20
- package/behaviors/registry/ui/core/organisms/ui-entity-cards.orb +130 -3
- package/behaviors/registry/ui/core/organisms/ui-entity-list.orb +130 -3
- package/behaviors/registry/ui/core/organisms/ui-entity-table.orb +367 -9
- package/behaviors/registry/ui/core/organisms/ui-form-section.orb +104 -13
- package/behaviors/registry/ui/core/organisms/ui-form.orb +104 -13
- package/behaviors/registry/ui/core/organisms/ui-media-gallery.orb +121 -3
- package/behaviors/registry/ui/core/organisms/ui-state-machine-view.orb +82 -0
- package/behaviors/registry/ui/core/organisms/ui-timeline.orb +121 -3
- package/behaviors/registry/ui/core/templates/ui-counter-template.orb +1 -172
- package/behaviors/registry/ui/core/templates/ui-dashboard-layout.orb +53 -1
- package/behaviors/registry/ui/core/templates/ui-generic-app-template.orb +1 -116
- package/behaviors/registry/ui/game/atoms/ui-game-menu.orb +99 -2
- package/behaviors/registry/ui/game/organisms/std-arcade-board-3d.orb +10 -0
- package/behaviors/registry/ui/game/organisms/std-crew-board-2d.orb +0 -7
- package/behaviors/registry/ui/game/organisms/std-platformer-puzzle.orb +1 -807
- package/behaviors/registry/ui/game/organisms/std-tactics-board-2d.orb +0 -7
- package/behaviors/registry/ui/game/organisms/std-worldmap-board-2d.orb +0 -7
- package/behaviors/registry/ui/learning/atoms/std-learn-stepper.orb +6 -0
- package/canonical-operators.json +18 -1
- package/dist/behaviors/exports-reader.js +7662 -3762
- package/dist/behaviors/functions/index.d.ts +309 -104
- package/dist/behaviors/functions/index.js +7651 -3762
- package/dist/behaviors/index.d.ts +1 -1
- package/dist/behaviors/index.js +7663 -3763
- package/dist/behaviors/query.js +7662 -3762
- package/dist/behaviors-embeddings.hash.json +3 -3
- package/dist/behaviors-embeddings.json +35 -27
- package/dist/behaviors-registry.json +4402 -1898
- package/dist/index.d.ts +3 -3
- package/dist/index.js +7680 -3763
- package/dist/knob-embeddings.hash.json +3 -3
- package/dist/knob-embeddings.json +612 -352
- package/dist/modules/anim.d.ts +1 -1
- package/dist/modules/array.d.ts +1 -1
- package/dist/modules/array.js +15 -0
- package/dist/modules/async.d.ts +1 -1
- package/dist/modules/behavior.d.ts +1 -1
- package/dist/modules/browser.d.ts +1 -1
- package/dist/modules/composition.d.ts +1 -1
- package/dist/modules/contract.d.ts +1 -1
- package/dist/modules/core.d.ts +1 -1
- package/dist/modules/core.js +2 -0
- package/dist/modules/data.d.ts +1 -1
- package/dist/modules/ease.d.ts +1 -1
- package/dist/modules/format.d.ts +1 -1
- package/dist/modules/geo.d.ts +1 -1
- package/dist/modules/graph.d.ts +1 -1
- package/dist/modules/grid.d.ts +1 -1
- package/dist/modules/index.d.ts +1 -1
- package/dist/modules/index.js +17 -0
- package/dist/modules/integration.d.ts +1 -1
- package/dist/modules/json.d.ts +1 -1
- package/dist/modules/llm.d.ts +1 -1
- package/dist/modules/math.d.ts +1 -1
- package/dist/modules/memory.d.ts +1 -1
- package/dist/modules/nn.d.ts +1 -1
- package/dist/modules/noise.d.ts +1 -1
- package/dist/modules/object.d.ts +1 -1
- package/dist/modules/os.d.ts +1 -1
- package/dist/modules/path.d.ts +1 -1
- package/dist/modules/prob.d.ts +1 -1
- package/dist/modules/session.d.ts +1 -1
- package/dist/modules/str.d.ts +1 -1
- package/dist/modules/tensor.d.ts +1 -1
- package/dist/modules/time.d.ts +1 -1
- package/dist/modules/trace.d.ts +1 -1
- package/dist/modules/train.d.ts +1 -1
- package/dist/modules/validate.d.ts +1 -1
- package/dist/modules/vector.d.ts +1 -1
- package/dist/modules/workspace.d.ts +1 -1
- package/dist/registry/factory-signatures.json +1 -1
- package/dist/registry.d.ts +2 -2
- package/dist/registry.js +17 -0
- package/dist/{types-Ggla7OK7.d.ts → types-DLx38UFZ.d.ts} +23 -3
- package/package.json +2 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
app std-graphs "2.0.0"
|
|
2
|
-
"std-graphs — embeddable chart atom. ITEMS_LOADED
|
|
2
|
+
"std-graphs — embeddable chart atom. ITEMS_LOADED keeps the rows whose @config.filterField equals @config.filterValue (blank = all), groups them by @config.categoryField, or (timeAxis=true) by the @config.period bucket of @config.timeField — rows without a time value have no place on a time axis and are left out — and aggregates per bucket. Multi-series rendering via @config.series (preformatted ChartSeries shape). Histograms via chartType=histogram pass pre-binned @payload.data through unchanged. Stacked / 100% stacked bars via @config.stack. Post-process sort + limit. Clicking a data point emits UI:@config.drillEvent with { label, value, seriesLabel? }. Drop into a dashboard alongside std-stats / std-browse."
|
|
3
3
|
type ObjectSpec = { id : string, label : string, value : string }
|
|
4
4
|
orbital GraphItemOrbital {
|
|
5
5
|
type ChartPoint = { label : string!, value : number! }
|
|
@@ -27,17 +27,22 @@ orbital GraphItemOrbital {
|
|
|
27
27
|
stack: @config.stack
|
|
28
28
|
subtitle: @config.subtitle
|
|
29
29
|
timeAxis: @config.timeAxis
|
|
30
|
+
period: @config.period
|
|
30
31
|
title: @config.title
|
|
31
32
|
type: @config.viewPattern
|
|
32
33
|
})
|
|
33
34
|
ITEMS_LOADED -> idle
|
|
34
|
-
(
|
|
35
|
+
(let (
|
|
36
|
+
(rows (if ["=", @config.filterField, ""] ?data (array/filter ?data (fn row (= (object/get @row @config.filterField) @config.filterValue)))))
|
|
37
|
+
)
|
|
38
|
+
(set @entity.chartData (if ["=", @config.chartType, histogram] (array/map @rows (fn p {
|
|
35
39
|
label: (object/get @p label)
|
|
36
40
|
value: (object/get @p value)
|
|
37
|
-
})) (array/map (object/entries (array/groupBy
|
|
41
|
+
})) (array/map (object/entries (if @config.timeAxis (array/groupBy (array/map (array/filter @rows (fn row (object/get @row @config.timeField))) (fn row (object/set @row "periodStart" (time/startOf (time/parse (object/get @row @config.timeField)) @config.period)))) "periodStart") (array/groupBy @rows @config.categoryField))) (fn entry {
|
|
38
42
|
label: (object/get @entry "0")
|
|
39
43
|
value: (if ["=", @config.aggregation, sum] (array/sum (object/get @entry "1") @config.valueField) (if ["=", @config.aggregation, avg] (array/avg (object/get @entry "1") @config.valueField) (if ["=", @config.aggregation, min] (array/min (object/get @entry "1") @config.valueField) (if ["=", @config.aggregation, max] (array/max (object/get @entry "1") @config.valueField) (array/len (object/get @entry "1"))))))
|
|
40
|
-
}))))
|
|
44
|
+
})))))
|
|
45
|
+
(set @entity.chartData (if @config.timeAxis (array/sort @entity.chartData label asc) @entity.chartData))
|
|
41
46
|
(set @entity.chartData (if ["!=", @config.sortField, none] (array/sort @entity.chartData @config.sortField @config.sortDir) @entity.chartData))
|
|
42
47
|
(set @entity.chartData (if [">", @config.limit, 0] (array/take @entity.chartData @config.limit) @entity.chartData))
|
|
43
48
|
(render-ui main {
|
|
@@ -51,6 +56,7 @@ orbital GraphItemOrbital {
|
|
|
51
56
|
stack: @config.stack
|
|
52
57
|
subtitle: @config.subtitle
|
|
53
58
|
timeAxis: @config.timeAxis
|
|
59
|
+
period: @config.period
|
|
54
60
|
title: @config.title
|
|
55
61
|
type: @config.viewPattern
|
|
56
62
|
})
|
|
@@ -92,6 +98,16 @@ orbital GraphItemOrbital {
|
|
|
92
98
|
@description "Group by month, quarter, week, day, or year — the calendar bucket the chart groups data into. Set ALONGSIDE timeAxis=true whenever the user says 'group by <time-unit>' or 'by <time-unit>' or 'rebucket to <time-unit>' or 'instead of <other-time-unit>'."
|
|
93
99
|
@synonyms "regroup / rebucket / change bucket / group differently. user phrases: 'group by month' / 'by month' / 'monthly' / 'monthly buckets' / 'switch to monthly' / 'instead of quarter' -> month; 'group by quarter' / 'by quarter' / 'quarterly' -> quarter; 'group by week' / 'by week' / 'weekly' / 'weekly buckets' -> week; 'group by day' / 'by day' / 'daily' / 'daily buckets' -> day; 'group by year' / 'by year' / 'yearly' / 'annually' -> year. Whenever the user voices 'group by <time-unit>' BOTH period AND timeAxis=true should be set."
|
|
94
100
|
@tier "presentation"
|
|
101
|
+
filterField : string = ""
|
|
102
|
+
@label "Only count rows where field"
|
|
103
|
+
@description "Row field a row must match to be charted (blank = every row), compared with filterValue — e.g. status + paid charts paid invoices only"
|
|
104
|
+
@synonyms "only include, where, filter by, restrict to. user phrases: 'only paid invoices' -> filterField=status + filterValue=paid; 'just the open deals' -> filterField=status + filterValue=open"
|
|
105
|
+
@tier "presentation"
|
|
106
|
+
filterValue : string = ""
|
|
107
|
+
@label "Equals"
|
|
108
|
+
@description "The value filterField must equal for a row to be charted"
|
|
109
|
+
@synonyms "the kept value. user phrases: 'only paid' -> paid; 'just active ones' -> active"
|
|
110
|
+
@tier "presentation"
|
|
95
111
|
valueField : string = ""
|
|
96
112
|
@label "Value field"
|
|
97
113
|
@description "Numeric field aggregated per bucket (blank = row count)"
|
|
@@ -107,11 +107,6 @@ orbital ImportOrbital {
|
|
|
107
107
|
@description "Text shown on the toolbar button that opens the import source popover"
|
|
108
108
|
@synonyms "the text on the import trigger button. user phrases: 'rename import button to X' / 'set the button label to X' -> X (e.g. 'Import Data', 'Add Sources')"
|
|
109
109
|
@tier "presentation"
|
|
110
|
-
event : string = IMPORT_SOURCE_PICKED
|
|
111
|
-
@label "Source-picked event"
|
|
112
|
-
@description "Event emitted when the user picks a source. Each entry in sources[] carries its own literal event field (no per-item templating in .lolo) — overriding this alone does not retarget the click; also set sources[].event to match."
|
|
113
|
-
@synonyms "bus event name. internal wiring; users rarely target directly"
|
|
114
|
-
@tier "internal"
|
|
115
110
|
sources : [SourceOption] = [{
|
|
116
111
|
event: IMPORT_SOURCE_PICKED
|
|
117
112
|
id: paste
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
app std-list "1.0.0"
|
|
2
2
|
"std-list as a Function"
|
|
3
3
|
type FilterSpec = { field : string!, label : string, options : [string] }
|
|
4
|
+
type ItemAction = { label : string!, event : event, variant : string, roles : [string], when : SExpr }
|
|
4
5
|
;;
|
|
5
6
|
;; Daisy-chain composition showcase: no `on EVENT { ... }` trait-ref overrides.
|
|
6
7
|
;; Modal + Confirmation trait refs are configured via `config: { ... }` at the
|
|
@@ -11,6 +12,10 @@ type FilterSpec = { field : string!, label : string, options : [string] }
|
|
|
11
12
|
;; old version had — form-section's mode set only supports "create" | "edit",
|
|
12
13
|
;; and a dedicated detail-view pattern is tracked separately (std-detail).
|
|
13
14
|
orbital ListItemOrbital {
|
|
15
|
+
uses RoleGate from "std/behaviors/std-role-gate"
|
|
16
|
+
|
|
17
|
+
uses Button from "std/behaviors/ui-button"
|
|
18
|
+
|
|
14
19
|
uses Confirmation from "std/behaviors/std-confirmation"
|
|
15
20
|
|
|
16
21
|
uses Modal from "std/behaviors/std-modal"
|
|
@@ -61,13 +66,7 @@ orbital ListItemOrbital {
|
|
|
61
66
|
direction: horizontal
|
|
62
67
|
gap: md
|
|
63
68
|
type: stack
|
|
64
|
-
},
|
|
65
|
-
action: CREATE
|
|
66
|
-
icon: plus
|
|
67
|
-
label: Create
|
|
68
|
-
type: button
|
|
69
|
-
variant: primary
|
|
70
|
-
}]
|
|
69
|
+
}, <trait.ListItemCreateGate />]
|
|
71
70
|
direction: horizontal
|
|
72
71
|
gap: md
|
|
73
72
|
justify: between
|
|
@@ -118,15 +117,7 @@ orbital ListItemOrbital {
|
|
|
118
117
|
name: status
|
|
119
118
|
variant: badge
|
|
120
119
|
}]
|
|
121
|
-
itemActions: [
|
|
122
|
-
event: EDIT
|
|
123
|
-
label: Edit
|
|
124
|
-
variant: ghost
|
|
125
|
-
}, {
|
|
126
|
-
event: DELETE
|
|
127
|
-
label: Delete
|
|
128
|
-
variant: danger
|
|
129
|
-
}]
|
|
120
|
+
itemActions: (array/filter @config.itemActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
|
|
130
121
|
pageSize: @config.displayPageSize
|
|
131
122
|
type: data-grid
|
|
132
123
|
}]
|
|
@@ -208,13 +199,7 @@ orbital ListItemOrbital {
|
|
|
208
199
|
direction: horizontal
|
|
209
200
|
gap: md
|
|
210
201
|
type: stack
|
|
211
|
-
},
|
|
212
|
-
action: CREATE
|
|
213
|
-
icon: plus
|
|
214
|
-
label: Create
|
|
215
|
-
type: button
|
|
216
|
-
variant: primary
|
|
217
|
-
}]
|
|
202
|
+
}, <trait.ListItemCreateGate />]
|
|
218
203
|
direction: horizontal
|
|
219
204
|
gap: md
|
|
220
205
|
justify: between
|
|
@@ -265,15 +250,7 @@ orbital ListItemOrbital {
|
|
|
265
250
|
name: status
|
|
266
251
|
variant: badge
|
|
267
252
|
}]
|
|
268
|
-
itemActions: [
|
|
269
|
-
event: EDIT
|
|
270
|
-
label: Edit
|
|
271
|
-
variant: ghost
|
|
272
|
-
}, {
|
|
273
|
-
event: DELETE
|
|
274
|
-
label: Delete
|
|
275
|
-
variant: danger
|
|
276
|
-
}]
|
|
253
|
+
itemActions: (array/filter @config.itemActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
|
|
277
254
|
pageSize: @config.displayPageSize
|
|
278
255
|
type: data-grid
|
|
279
256
|
}]
|
|
@@ -392,6 +369,43 @@ orbital ListItemOrbital {
|
|
|
392
369
|
@description "Rows visible per page before the data-grid's own pagination control appears — 20 matches the CRUD-list density sweet spot (Miller's law, 10-25 rows)."
|
|
393
370
|
@synonyms "visible rows, items per page, display limit, show per page"
|
|
394
371
|
@tier "presentation"
|
|
372
|
+
itemActions : [ItemAction] = [{
|
|
373
|
+
event: EDIT
|
|
374
|
+
label: Edit
|
|
375
|
+
variant: ghost
|
|
376
|
+
}, {
|
|
377
|
+
event: DELETE
|
|
378
|
+
label: Delete
|
|
379
|
+
variant: danger
|
|
380
|
+
}]
|
|
381
|
+
@label "Row actions"
|
|
382
|
+
@description "Actions offered on each row; give an item `roles` to show it only to those viewer roles."
|
|
383
|
+
@tier "presentation"
|
|
384
|
+
viewerRole : string = ""
|
|
385
|
+
@label "Viewer's role"
|
|
386
|
+
@description "The signed-in viewer's role that each action's `roles` is checked against. Bind it explicitly at the call site (e.g. `viewerRole: @user.role`) in an app whose identity carries a role; left empty, only actions with no `roles` show."
|
|
387
|
+
@tier "policy"
|
|
388
|
+
createRoles : [string] = []
|
|
389
|
+
@label "Roles that can create"
|
|
390
|
+
@description "Roles (matched against viewerRole) that see the Create button. Empty = everyone."
|
|
391
|
+
@tier "policy"
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
trait ListItemCreateButton = Button.traits.ButtonRender {
|
|
396
|
+
config {
|
|
397
|
+
action: CREATE
|
|
398
|
+
icon: plus
|
|
399
|
+
label: Create
|
|
400
|
+
variant: primary
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
trait ListItemCreateGate = RoleGate.traits.RoleGate {
|
|
405
|
+
config {
|
|
406
|
+
roles: @config.createRoles
|
|
407
|
+
viewerRole: @config.viewerRole
|
|
408
|
+
content: <trait.ListItemCreateButton />
|
|
395
409
|
}
|
|
396
410
|
}
|
|
397
411
|
|
|
@@ -293,7 +293,7 @@ orbital ModalEditorOrbital {
|
|
|
293
293
|
(set @entity.cmdline "")
|
|
294
294
|
(emit SET_MODE { editorId: ?editorId, mode: "NORMAL", caret: "block" })
|
|
295
295
|
|
|
296
|
-
KEY -> COMMAND when (and ["!=", ?key, "Enter"] ["!=", ?key, "Escape"] ["!=", ?key, "Backspace"])
|
|
296
|
+
KEY -> COMMAND when (and (array/includes (object/get @config.keymap "COMMAND") ?key) ["!=", ?key, "Enter"] ["!=", ?key, "Escape"] ["!=", ?key, "Backspace"])
|
|
297
297
|
(set @entity.cmdline (str/concat @entity.cmdline ?key))
|
|
298
298
|
|
|
299
299
|
EDITOR_FOCUS -> COMMAND
|
|
@@ -312,7 +312,7 @@ orbital ModalEditorOrbital {
|
|
|
312
312
|
meta : boolean
|
|
313
313
|
repeat : boolean
|
|
314
314
|
}
|
|
315
|
-
@description "One physical keydown, delivered by the host's keyboard router. The host decides preventDefault from config.keymap;
|
|
315
|
+
@description "One physical keydown, delivered by the host's keyboard router. The host decides preventDefault from config.keymap; the command line accepts only keys config.keymap captures in COMMAND."
|
|
316
316
|
EDITOR_FOCUS {
|
|
317
317
|
editorId : string
|
|
318
318
|
}
|
|
@@ -312,6 +312,7 @@ orbital RatingReviewOrbital {
|
|
|
312
312
|
mode: edit
|
|
313
313
|
submitEvent: SUBMIT_REVIEW
|
|
314
314
|
submitLabel: @config.submitLabel
|
|
315
|
+
cancelLabel: @config.cancelLabel
|
|
315
316
|
type: form-section
|
|
316
317
|
}]
|
|
317
318
|
direction: vertical
|
|
@@ -1114,6 +1115,7 @@ orbital RatingReviewOrbital {
|
|
|
1114
1115
|
mode: edit
|
|
1115
1116
|
submitEvent: SUBMIT_REVIEW
|
|
1116
1117
|
submitLabel: @config.submitLabel
|
|
1118
|
+
cancelLabel: @config.cancelLabel
|
|
1117
1119
|
type: form-section
|
|
1118
1120
|
}]
|
|
1119
1121
|
direction: vertical
|
|
@@ -1426,10 +1428,11 @@ orbital RatingReviewOrbital {
|
|
|
1426
1428
|
}, {
|
|
1427
1429
|
cancelEvent: CANCEL_REVIEW
|
|
1428
1430
|
entity: @entity
|
|
1429
|
-
fields: (draftComment)
|
|
1431
|
+
fields: (if @config.allowComment ["draftComment"] [])
|
|
1430
1432
|
mode: edit
|
|
1431
1433
|
submitEvent: SUBMIT_REVIEW
|
|
1432
1434
|
submitLabel: @config.submitLabel
|
|
1435
|
+
cancelLabel: @config.cancelLabel
|
|
1433
1436
|
type: form-section
|
|
1434
1437
|
}]
|
|
1435
1438
|
direction: vertical
|
|
@@ -1455,10 +1458,11 @@ orbital RatingReviewOrbital {
|
|
|
1455
1458
|
}, {
|
|
1456
1459
|
cancelEvent: CANCEL_REVIEW
|
|
1457
1460
|
entity: @entity
|
|
1458
|
-
fields: (draftComment)
|
|
1461
|
+
fields: (if @config.allowComment ["draftComment"] [])
|
|
1459
1462
|
mode: edit
|
|
1460
1463
|
submitEvent: SUBMIT_REVIEW
|
|
1461
1464
|
submitLabel: @config.submitLabel
|
|
1465
|
+
cancelLabel: @config.cancelLabel
|
|
1462
1466
|
type: form-section
|
|
1463
1467
|
}]
|
|
1464
1468
|
direction: vertical
|
|
@@ -1504,10 +1508,11 @@ orbital RatingReviewOrbital {
|
|
|
1504
1508
|
}, {
|
|
1505
1509
|
cancelEvent: CANCEL_REVIEW
|
|
1506
1510
|
entity: @entity
|
|
1507
|
-
fields: (draftComment)
|
|
1511
|
+
fields: (if @config.allowComment ["draftComment"] [])
|
|
1508
1512
|
mode: edit
|
|
1509
1513
|
submitEvent: SUBMIT_REVIEW
|
|
1510
1514
|
submitLabel: @config.submitLabel
|
|
1515
|
+
cancelLabel: @config.cancelLabel
|
|
1511
1516
|
type: form-section
|
|
1512
1517
|
}]
|
|
1513
1518
|
direction: vertical
|
|
@@ -1569,10 +1574,11 @@ orbital RatingReviewOrbital {
|
|
|
1569
1574
|
}, {
|
|
1570
1575
|
cancelEvent: CANCEL_REVIEW
|
|
1571
1576
|
entity: @entity
|
|
1572
|
-
fields: (draftComment)
|
|
1577
|
+
fields: (if @config.allowComment ["draftComment"] [])
|
|
1573
1578
|
mode: edit
|
|
1574
1579
|
submitEvent: SUBMIT_REVIEW
|
|
1575
1580
|
submitLabel: @config.submitLabel
|
|
1581
|
+
cancelLabel: @config.cancelLabel
|
|
1576
1582
|
type: form-section
|
|
1577
1583
|
}]
|
|
1578
1584
|
direction: vertical
|
|
@@ -1600,10 +1606,11 @@ orbital RatingReviewOrbital {
|
|
|
1600
1606
|
}, {
|
|
1601
1607
|
cancelEvent: CANCEL_REVIEW
|
|
1602
1608
|
entity: @entity
|
|
1603
|
-
fields: (draftComment)
|
|
1609
|
+
fields: (if @config.allowComment ["draftComment"] [])
|
|
1604
1610
|
mode: edit
|
|
1605
1611
|
submitEvent: SUBMIT_REVIEW
|
|
1606
1612
|
submitLabel: @config.submitLabel
|
|
1613
|
+
cancelLabel: @config.cancelLabel
|
|
1607
1614
|
type: form-section
|
|
1608
1615
|
}]
|
|
1609
1616
|
direction: vertical
|
|
@@ -1696,10 +1703,6 @@ orbital RatingReviewOrbital {
|
|
|
1696
1703
|
@label "Cancel button"
|
|
1697
1704
|
@description "Label on the cancel button"
|
|
1698
1705
|
@tier "presentation"
|
|
1699
|
-
submitEvent : string = SUBMIT_REVIEW
|
|
1700
|
-
@label "Submit event"
|
|
1701
|
-
@description "Event emitted when the user submits the form"
|
|
1702
|
-
@tier "internal"
|
|
1703
1706
|
maxStars : number = 5
|
|
1704
1707
|
@label "Max stars"
|
|
1705
1708
|
@description "Top of the rating scale (typically 5)"
|
|
@@ -1708,10 +1711,6 @@ orbital RatingReviewOrbital {
|
|
|
1708
1711
|
@label "Allow comment"
|
|
1709
1712
|
@description "Show a free-text comment field below the stars"
|
|
1710
1713
|
@tier "presentation"
|
|
1711
|
-
allowPhotos : boolean = false
|
|
1712
|
-
@label "Allow photos"
|
|
1713
|
-
@description "Let the user attach photos to the review"
|
|
1714
|
-
@tier "presentation"
|
|
1715
1714
|
cardLook : "elevated" | "flat-bordered" | "borderless-divider" | "ticket" | "invoice" | "chip" | "tile-image-first" = elevated
|
|
1716
1715
|
@label "Card look"
|
|
1717
1716
|
@description "Visual style of the wrapper card. Layer 2 cardLook knob — render-ui references @config.cardLook on the compose card."
|
|
@@ -2,7 +2,7 @@ app std-record-detail "1.0.0"
|
|
|
2
2
|
"std-record-detail — single primitive: detail-panel. Owns the fetch-one-record state machine (loading → viewing → error, with RETRY), the record counterpart to std-browse's collection machine. Consumers configure fields/sections/actions and the title/subtitle/status bindings; the atom fetches by the id (or, for slug-routed records, the slug) carried on INIT and renders the panel. `detailLook` (panel default / slide-over / page / document) selects the render body, exactly as std-browse's browseLook selects a collection shape. The `document` look is for records whose shape IS a document (wiki page, note, article): the pure writing surface — a big inline-editable title with the rich-text body DIRECTLY beneath it, Edit/Done and the actions menu tucked into the header corner — where clicking the body drops a cursor in, every typing pause autosaves (CONTENT_SAVED, which the host persists QUIETLY — no refetch, or the editor unmounts mid-keystroke), and Done emits CONTENT_COMMITTED (the host refetches and snapshots version history on this one). Metadata never sits between the title and the words: compose the sibling RecordItemDetails trait beside the doc for a Gutenberg-style settings rail. A row minted blank by a document-first create arrives with draft=1 on INIT and opens straight in the editor. Pair with std-detail-layout for the back + breadcrumb chrome — that atom owns navigation, this one owns the record — exactly as a list page pairs std-browse with std-app-layout."
|
|
3
3
|
;; @capabilities "record detail, single record view, entity detail panel, drill-down record, show one record, record profile, detail page, view details, document editor, wiki page, note taking, article body, rich text editing, write and edit content"
|
|
4
4
|
orbital RecordItemOrbital {
|
|
5
|
-
type RecordAction = { label : string!, event : event!, icon : string, variant : primary | secondary | ghost | danger }
|
|
5
|
+
type RecordAction = { label : string!, event : event!, icon : string, variant : primary | secondary | ghost | danger, roles : [string], when : SExpr }
|
|
6
6
|
type RecordFieldSpec = { key : string!, header : string, format : date | currency | number | boolean | percent }
|
|
7
7
|
type MetaFieldSpec = { key : string!, label : string, kind : text | boolean | select | readonly, options : [string], icon : string, format : date | currency | number | boolean | percent }
|
|
8
8
|
type RecordSection = { title : string!, fields : [string] }
|
|
@@ -481,6 +481,10 @@ orbital RecordItemOrbital {
|
|
|
481
481
|
@description "Buttons on the panel header. One primary at most; the rest collapse past maxInlineActions."
|
|
482
482
|
@synonyms "record actions, detail actions, panel buttons"
|
|
483
483
|
@tier "presentation"
|
|
484
|
+
viewerRole : string = ""
|
|
485
|
+
@label "Viewer's role"
|
|
486
|
+
@description "The signed-in viewer's role that each action's `roles` is checked against. Bind it explicitly at the call site (e.g. `viewerRole: @user.role`) in an app whose identity carries a role; left empty, only actions with no `roles` show."
|
|
487
|
+
@tier "policy"
|
|
484
488
|
maxInlineActions : number = 3
|
|
485
489
|
@label "How many actions before collapsing?"
|
|
486
490
|
@description "Actions beyond this count collapse into a '⋯' overflow menu."
|
|
@@ -560,10 +564,10 @@ orbital RecordItemOrbital {
|
|
|
560
564
|
@tier "presentation"
|
|
561
565
|
bodyContent : render-ui = {
|
|
562
566
|
children: [{
|
|
563
|
-
actions: @config.actions
|
|
564
|
-
entity:
|
|
567
|
+
actions: (array/filter @config.actions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
|
|
568
|
+
entity: @entity.loadedRow
|
|
565
569
|
fields: @config.fields
|
|
566
|
-
initialData:
|
|
570
|
+
initialData: @entity.loadedRow
|
|
567
571
|
maxInlineActions: @config.maxInlineActions
|
|
568
572
|
sections: @config.sections
|
|
569
573
|
showActions: @config.showActions
|
|
@@ -580,10 +584,10 @@ orbital RecordItemOrbital {
|
|
|
580
584
|
@tier "internal"
|
|
581
585
|
slideOverBodyContent : render-ui = {
|
|
582
586
|
children: [{
|
|
583
|
-
actions: @config.actions
|
|
584
|
-
entity:
|
|
587
|
+
actions: (array/filter @config.actions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
|
|
588
|
+
entity: @entity.loadedRow
|
|
585
589
|
fields: @config.fields
|
|
586
|
-
initialData:
|
|
590
|
+
initialData: @entity.loadedRow
|
|
587
591
|
maxInlineActions: @config.maxInlineActions
|
|
588
592
|
sections: @config.sections
|
|
589
593
|
showActions: @config.showActions
|
|
@@ -601,10 +605,10 @@ orbital RecordItemOrbital {
|
|
|
601
605
|
@tier "internal"
|
|
602
606
|
pageBodyContent : render-ui = {
|
|
603
607
|
children: [{
|
|
604
|
-
actions: @config.actions
|
|
605
|
-
entity:
|
|
608
|
+
actions: (array/filter @config.actions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
|
|
609
|
+
entity: @entity.loadedRow
|
|
606
610
|
fields: @config.fields
|
|
607
|
-
initialData:
|
|
611
|
+
initialData: @entity.loadedRow
|
|
608
612
|
maxInlineActions: @config.maxInlineActions
|
|
609
613
|
sections: @config.sections
|
|
610
614
|
showActions: @config.showActions
|
|
@@ -621,7 +625,7 @@ orbital RecordItemOrbital {
|
|
|
621
625
|
@description "Render-ui SExpr rendered after the record loads when detailLook = page: a full record page, width-capped so field rows do not stretch past a readable measure (Almadar_UI_Beauty.md §3)."
|
|
622
626
|
@tier "internal"
|
|
623
627
|
documentBodyContent : render-ui = {
|
|
624
|
-
actions: @config.actions
|
|
628
|
+
actions: (array/filter @config.actions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
|
|
625
629
|
coverImage: @entity.coverUrl
|
|
626
630
|
icon: @entity.iconName
|
|
627
631
|
editEvent: (if @config.allowEdit EDIT_CONTENT null)
|
|
@@ -640,7 +644,7 @@ orbital RecordItemOrbital {
|
|
|
640
644
|
@description "Render-ui SExpr for detailLook = document while reading: the pure writing surface — editable title with the rich-text body DIRECTLY beneath it, Edit and the actions menu tucked into the header corner. Metadata never sits between title and content; compose the sibling RecordItemDetails trait beside this one for the settings rail. Binds only @entity fields, never ?data, because it is also painted by arms whose payload is not the record."
|
|
641
645
|
@tier "internal"
|
|
642
646
|
documentEditingContent : render-ui = {
|
|
643
|
-
actions: @config.actions
|
|
647
|
+
actions: (array/filter @config.actions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
|
|
644
648
|
coverImage: @entity.coverUrl
|
|
645
649
|
icon: @entity.iconName
|
|
646
650
|
autosaveHint: @config.autosaveHint
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
app std-recurrence "2.1.0"
|
|
2
2
|
"std-recurrence — recurring-rule definition + upcoming runs (Stripe Subscriptions / Cron Hub style). The viewing state shows a plain-English rule sentence and the next N dated runs as an agenda timeline. Per-run exception modal supports skip / reschedule. Topology = loading / defining_rule / viewing / awaiting_exception_decision / cancelled / error."
|
|
3
3
|
type ObjectSpec = { id : string, label : string, value : string }
|
|
4
|
+
type ItemAction = { label : string!, event : event, roles : [string] }
|
|
4
5
|
orbital RecurrenceOrbital {
|
|
5
6
|
type OccurrenceItem = { id : string!, title : string!, description : string, date : string, status : "complete" | "active" | "pending" | "error", rawStatus : "scheduled" | "skipped" | "completed" | "rescheduled" }
|
|
6
7
|
|
|
@@ -139,7 +140,7 @@ orbital RecurrenceOrbital {
|
|
|
139
140
|
}, {
|
|
140
141
|
entity: @entity.occurrences
|
|
141
142
|
fields: (title description date status)
|
|
142
|
-
itemActions: [
|
|
143
|
+
itemActions: (array/filter @config.itemActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
|
|
143
144
|
look: @config.timelineLook
|
|
144
145
|
type: timeline
|
|
145
146
|
}, {
|
|
@@ -543,6 +544,14 @@ orbital RecurrenceOrbital {
|
|
|
543
544
|
@label "Timeline look"
|
|
544
545
|
@description "Layer 2 visual treatment for the timeline."
|
|
545
546
|
@tier "presentation"
|
|
547
|
+
itemActions : [ItemAction] = [{ event: OPEN_EXCEPTION, label: Manage }]
|
|
548
|
+
@label "Row actions"
|
|
549
|
+
@description "Actions offered on each row; give an item `roles` to show it only to those viewer roles."
|
|
550
|
+
@tier "presentation"
|
|
551
|
+
viewerRole : string = ""
|
|
552
|
+
@label "Viewer's role"
|
|
553
|
+
@description "The signed-in viewer's role that each action's `roles` is checked against. Bind it explicitly at the call site (e.g. `viewerRole: @user.role`) in an app whose identity carries a role; left empty, only actions with no `roles` show."
|
|
554
|
+
@tier "policy"
|
|
546
555
|
}
|
|
547
556
|
}
|
|
548
557
|
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
app std-role-gate "1.0.0"
|
|
2
|
+
"std-role-gate — explicit role gate around ONE piece of UI. Renders its `content` trait only when `roles` is empty or lists the viewer's role; any other viewer gets nothing rendered. Wrap a single button, FAB or panel in it, bind `viewerRole` at the call site (e.g. `viewerRole: @user.role`), and list the roles that may see it."
|
|
3
|
+
;; @capabilities "role gate, only for roles, hide for role, permission wrapper, restrict button to role, show only to admins, role-based visibility"
|
|
4
|
+
;; @synonyms "role guard, permission gate, access gate, visible to roles, hide unless role, admin only"
|
|
5
|
+
orbital RoleGateOrbital {
|
|
6
|
+
entity RoleGateData [runtime] {
|
|
7
|
+
id : string!
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
trait RoleGate -> @rebindable RoleGateData [interaction, instance] {
|
|
11
|
+
initial: idle
|
|
12
|
+
|
|
13
|
+
state idle {
|
|
14
|
+
INIT -> idle when (or (= (array/len @config.roles) 0) (array/includes @config.roles @config.viewerRole))
|
|
15
|
+
(render-ui main { children: [@config.content], type: box })
|
|
16
|
+
INIT -> idle when (not (or (= (array/len @config.roles) 0) (array/includes @config.roles @config.viewerRole)))
|
|
17
|
+
(render-ui main null)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
config {
|
|
21
|
+
content : trait
|
|
22
|
+
@label "Gated content"
|
|
23
|
+
@description "The trait rendered when the viewer's role is allowed, e.g. a button or panel trait ref."
|
|
24
|
+
@synonyms "wrapped content, guarded element, protected button"
|
|
25
|
+
@tier "presentation"
|
|
26
|
+
roles : [string] = []
|
|
27
|
+
@label "Visible to roles"
|
|
28
|
+
@description "Roles (matched against viewerRole) that see the content. Empty = everyone; any other viewer sees nothing."
|
|
29
|
+
@synonyms "allowed roles, only for, who can see, permitted roles"
|
|
30
|
+
@tier "policy"
|
|
31
|
+
viewerRole : string = ""
|
|
32
|
+
@label "Viewer's role"
|
|
33
|
+
@description "The signed-in viewer's role that `roles` is checked against. Bind it explicitly at the call site (e.g. `viewerRole: @user.role`); left empty, only an ungated (empty `roles`) gate renders."
|
|
34
|
+
@tier "policy"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
page "/role-gate" as RoleGatePage -> RoleGate
|
|
39
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
app std-saved-search "1.0.0"
|
|
2
2
|
"std-saved-search — persisted query + alert subscription. Owns a SavedSearch entity (one row per saved query) and a single manage trait that lists saved searches in a data-grid, lets users toggle their alert subscription / rename the search / delete it, and persists each change."
|
|
3
|
+
type ItemAction = { label : string!, event : event, variant : string, icon : string, roles : [string], when : SExpr }
|
|
3
4
|
orbital SavedSearchOrbital {
|
|
4
5
|
type SavedSearchLoaded = Event { data : [SavedSearch] } "Fired when the saved-search collection finishes loading"
|
|
5
6
|
|
|
@@ -9,6 +10,8 @@ orbital SavedSearchOrbital {
|
|
|
9
10
|
|
|
10
11
|
type SavedSearchDeleted = Event { id : string! } "Fired after a saved-search row is deleted"
|
|
11
12
|
|
|
13
|
+
type SavedSearchCreated = Event SavedSearch "Fired after the current search is saved as a new row"
|
|
14
|
+
|
|
12
15
|
entity SavedSearch [persistent: savedsearches] {
|
|
13
16
|
id : string!
|
|
14
17
|
name : string! @description "A user-defined label for the saved search." @synonyms "title, label, search name"
|
|
@@ -74,22 +77,7 @@ orbital SavedSearchOrbital {
|
|
|
74
77
|
variant: badge
|
|
75
78
|
}]
|
|
76
79
|
gap: sm
|
|
77
|
-
itemActions: [
|
|
78
|
-
event: TOGGLE_ALERT
|
|
79
|
-
icon: bell
|
|
80
|
-
label: "Toggle alert"
|
|
81
|
-
variant: secondary
|
|
82
|
-
}, {
|
|
83
|
-
event: EDIT
|
|
84
|
-
icon: pencil
|
|
85
|
-
label: Edit
|
|
86
|
-
variant: secondary
|
|
87
|
-
}, {
|
|
88
|
-
event: DELETE
|
|
89
|
-
icon: trash-2
|
|
90
|
-
label: Delete
|
|
91
|
-
variant: danger
|
|
92
|
-
}]
|
|
80
|
+
itemActions: (array/filter @config.itemActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
|
|
93
81
|
look: @config.tableLook
|
|
94
82
|
type: data-grid
|
|
95
83
|
}]
|
|
@@ -137,6 +125,24 @@ orbital SavedSearchOrbital {
|
|
|
137
125
|
(persist delete SavedSearch ?id {
|
|
138
126
|
emit: { failure: SavedSearchLoadFailed, success: SavedSearchDeleted }
|
|
139
127
|
})
|
|
128
|
+
;; The page's live search, fed by whichever search/filter traits the
|
|
129
|
+
;; consumer wires in, so SAVE_CURRENT captures what the viewer sees.
|
|
130
|
+
TRACK_QUERY -> browsing
|
|
131
|
+
(set @entity.query ?query)
|
|
132
|
+
;; One filter change at a time (std-filter's FILTER shape); an empty
|
|
133
|
+
;; value clears that filter, matching std-browse's REFETCH_FILTER.
|
|
134
|
+
TRACK_FILTERS -> browsing
|
|
135
|
+
(set @entity.filters (if ["=", ?value, ""] (object/omit @entity.filters [?field]) (object/set @entity.filters ?field ?value)))
|
|
136
|
+
SAVE_CURRENT -> browsing
|
|
137
|
+
(persist create SavedSearch {
|
|
138
|
+
name: (if @entity.query @entity.query @config.defaultSearchName)
|
|
139
|
+
query: @entity.query
|
|
140
|
+
filters: @entity.filters
|
|
141
|
+
userId: @user.id
|
|
142
|
+
createdAt: @now
|
|
143
|
+
} {
|
|
144
|
+
emit: { failure: SavedSearchLoadFailed, success: SavedSearchCreated }
|
|
145
|
+
})
|
|
140
146
|
EDIT -> editing
|
|
141
147
|
(set @entity.id ?id)
|
|
142
148
|
(render-ui main {
|
|
@@ -194,6 +200,10 @@ orbital SavedSearchOrbital {
|
|
|
194
200
|
(fetch SavedSearch {
|
|
195
201
|
emit: { failure: SavedSearchLoadFailed, success: SavedSearchLoaded }
|
|
196
202
|
})
|
|
203
|
+
SavedSearchCreated -> loading
|
|
204
|
+
(fetch SavedSearch {
|
|
205
|
+
emit: { failure: SavedSearchLoadFailed, success: SavedSearchLoaded }
|
|
206
|
+
})
|
|
197
207
|
;; editing.SAVE -> browsing lands here before the persist resolves; a
|
|
198
208
|
;; failure must be caught here too, not just by loading's twin arm.
|
|
199
209
|
SavedSearchLoadFailed -> error
|
|
@@ -280,6 +290,10 @@ orbital SavedSearchOrbital {
|
|
|
280
290
|
@description "Indicates a failure to load saved search data."
|
|
281
291
|
@synonyms "error, failure, load error"
|
|
282
292
|
@tier "internal"
|
|
293
|
+
SavedSearchCreated
|
|
294
|
+
@description "Indicates the current search has been saved as a new row."
|
|
295
|
+
@synonyms "saved, created, bookmarked"
|
|
296
|
+
@tier "presentation"
|
|
283
297
|
SavedSearchUpdated
|
|
284
298
|
@description "Indicates a saved search has been modified and persisted."
|
|
285
299
|
@synonyms "modified, changed, updated, persisted"
|
|
@@ -332,6 +346,27 @@ orbital SavedSearchOrbital {
|
|
|
332
346
|
@description "Aborts the current operation or view."
|
|
333
347
|
@synonyms "dismiss, close, undo"
|
|
334
348
|
@tier "domain"
|
|
349
|
+
TRACK_QUERY {
|
|
350
|
+
query : string
|
|
351
|
+
}
|
|
352
|
+
@description "The page's current search text changed."
|
|
353
|
+
@synonyms "search changed, query changed, typed search"
|
|
354
|
+
@tier "domain"
|
|
355
|
+
TRACK_FILTERS {
|
|
356
|
+
field : string!
|
|
357
|
+
value : string!
|
|
358
|
+
}
|
|
359
|
+
@description "The page's current filters changed."
|
|
360
|
+
@synonyms "filters changed, criteria changed"
|
|
361
|
+
@tier "domain"
|
|
362
|
+
SAVE_CURRENT
|
|
363
|
+
@description "Save the page's current search and filters as a new saved search."
|
|
364
|
+
@synonyms "save search, bookmark search, remember search"
|
|
365
|
+
@tier "domain"
|
|
366
|
+
SavedSearchCreated
|
|
367
|
+
@description "The current search was saved as a new row."
|
|
368
|
+
@synonyms "saved, created, bookmarked"
|
|
369
|
+
@tier "presentation"
|
|
335
370
|
SavedSearchLoaded {
|
|
336
371
|
data : [SavedSearch]
|
|
337
372
|
}
|
|
@@ -366,6 +401,33 @@ orbital SavedSearchOrbital {
|
|
|
366
401
|
@label "Table look"
|
|
367
402
|
@description "Layer 2 visual treatment for the data table rendered by this atom."
|
|
368
403
|
@tier "presentation"
|
|
404
|
+
defaultSearchName : string = "Saved search"
|
|
405
|
+
@label "Default saved-search name"
|
|
406
|
+
@description "Name given to a saved search when the current search has no query text (filters only). Renamable afterwards."
|
|
407
|
+
@tier "presentation"
|
|
408
|
+
itemActions : [ItemAction] = [{
|
|
409
|
+
event: TOGGLE_ALERT
|
|
410
|
+
icon: bell
|
|
411
|
+
label: "Toggle alert"
|
|
412
|
+
variant: secondary
|
|
413
|
+
}, {
|
|
414
|
+
event: EDIT
|
|
415
|
+
icon: pencil
|
|
416
|
+
label: Edit
|
|
417
|
+
variant: secondary
|
|
418
|
+
}, {
|
|
419
|
+
event: DELETE
|
|
420
|
+
icon: trash-2
|
|
421
|
+
label: Delete
|
|
422
|
+
variant: danger
|
|
423
|
+
}]
|
|
424
|
+
@label "Row actions"
|
|
425
|
+
@description "Actions offered on each row; give an item `roles` to show it only to those viewer roles."
|
|
426
|
+
@tier "presentation"
|
|
427
|
+
viewerRole : string = ""
|
|
428
|
+
@label "Viewer's role"
|
|
429
|
+
@description "The signed-in viewer's role that each action's `roles` is checked against. Bind it explicitly at the call site (e.g. `viewerRole: @user.role`) in an app whose identity carries a role; left empty, only actions with no `roles` show."
|
|
430
|
+
@tier "policy"
|
|
369
431
|
}
|
|
370
432
|
}
|
|
371
433
|
|