@aglyn/plugins-workflows 1.0.0-beta.206 → 1.0.0-beta.207
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/package.json +12 -12
- package/src/lib/components/staff-automations-card.component.d.ts +13 -0
- package/src/lib/components/staff-automations-card.component.js +329 -0
- package/src/lib/components/staff-automations-card.component.js.map +1 -0
- package/src/lib/plugin.js +15 -0
- package/src/lib/plugin.js.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aglyn/plugins-workflows",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.207",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"homepage": "https://aglyn.com",
|
|
6
6
|
"repository": {
|
|
@@ -25,17 +25,17 @@
|
|
|
25
25
|
"./package.json": "./package.json"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@aglyn/aglyn": "1.0.0-beta.
|
|
29
|
-
"@aglyn/shared-data-mdi": "1.0.0-beta.
|
|
30
|
-
"@aglyn/shared-ui-jsx": "1.0.0-beta.
|
|
31
|
-
"@aglyn/shared-ui-next": "1.0.0-beta.
|
|
32
|
-
"@aglyn/shared-ui-snackstack": "1.0.0-beta.
|
|
33
|
-
"@aglyn/shared-util-email": "1.0.0-beta.
|
|
34
|
-
"@aglyn/shared-util-http": "1.0.0-beta.
|
|
35
|
-
"@aglyn/shared-util-timestamp": "1.0.0-beta.
|
|
36
|
-
"@aglyn/tenant-data-admin": "1.0.0-beta.
|
|
37
|
-
"@aglyn/tenant-feature-instance": "1.0.0-beta.
|
|
38
|
-
"@aglyn/tenant-runtime": "1.0.0-beta.
|
|
28
|
+
"@aglyn/aglyn": "1.0.0-beta.207",
|
|
29
|
+
"@aglyn/shared-data-mdi": "1.0.0-beta.207",
|
|
30
|
+
"@aglyn/shared-ui-jsx": "1.0.0-beta.207",
|
|
31
|
+
"@aglyn/shared-ui-next": "1.0.0-beta.207",
|
|
32
|
+
"@aglyn/shared-ui-snackstack": "1.0.0-beta.207",
|
|
33
|
+
"@aglyn/shared-util-email": "1.0.0-beta.207",
|
|
34
|
+
"@aglyn/shared-util-http": "1.0.0-beta.207",
|
|
35
|
+
"@aglyn/shared-util-timestamp": "1.0.0-beta.207",
|
|
36
|
+
"@aglyn/tenant-data-admin": "1.0.0-beta.207",
|
|
37
|
+
"@aglyn/tenant-feature-instance": "1.0.0-beta.207",
|
|
38
|
+
"@aglyn/tenant-runtime": "1.0.0-beta.207",
|
|
39
39
|
"@swc/helpers": "0.5.23"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The staff site page's automations (`staffSite` zone): the site's own
|
|
3
|
+
* automations, the organization automations that run on it, and its
|
|
4
|
+
* workflows.
|
|
5
|
+
*/
|
|
6
|
+
export declare function StaffSiteAutomationsCard(props: {
|
|
7
|
+
hostId: string;
|
|
8
|
+
orgId?: string;
|
|
9
|
+
}): import("react").JSX.Element;
|
|
10
|
+
/** The staff organization page's automations (`adminOrgDetail` zone). */
|
|
11
|
+
export declare function StaffOrgAutomationsCard(props: {
|
|
12
|
+
orgId: string;
|
|
13
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/ 'use client';
|
|
17
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
18
|
+
import { pluginDocsHelp } from "@aglyn/aglyn/app-utils/docs-help";
|
|
19
|
+
import { mdiEyeOutline } from "@aglyn/shared-data-mdi";
|
|
20
|
+
import { CardDisplay } from "@aglyn/shared-ui-jsx";
|
|
21
|
+
import { ListPagination } from "@aglyn/shared-ui-jsx/components/list-pagination.component";
|
|
22
|
+
import { ListRowActions, ListTable, listActionsColumn } from "@aglyn/shared-ui-jsx/components/list-table.component";
|
|
23
|
+
import { TABLE_ROW_HEIGHT } from "@aglyn/shared-ui-jsx/const/table-pagination";
|
|
24
|
+
import { useFirestore, usePagedCollection } from "@aglyn/tenant-feature-instance";
|
|
25
|
+
import { Box, Button, Chip, Dialog, DialogActions, DialogContent, DialogTitle, Stack, Typography } from "@mui/material";
|
|
26
|
+
import { collection, documentId, limit, orderBy, query, where } from "firebase/firestore";
|
|
27
|
+
import { useMemo, useState } from "react";
|
|
28
|
+
const nameOf = (row)=>String(row['name'] || row['displayName'] || row.$id);
|
|
29
|
+
const whenOf = (value)=>typeof (value == null ? void 0 : value.toDate) === 'function' ? value.toDate().toLocaleString() : '—';
|
|
30
|
+
/** The trigger and the steps of one automation, read-only. */ function StepsDialog(props) {
|
|
31
|
+
var _ref;
|
|
32
|
+
var _row_trigger, _row_trigger1;
|
|
33
|
+
const { row, onClose } = props;
|
|
34
|
+
const steps = Array.isArray(row == null ? void 0 : row['steps']) ? row['steps'] : [];
|
|
35
|
+
return /*#__PURE__*/ _jsxs(Dialog, {
|
|
36
|
+
open: Boolean(row),
|
|
37
|
+
onClose: onClose,
|
|
38
|
+
maxWidth: "md",
|
|
39
|
+
fullWidth: true,
|
|
40
|
+
children: [
|
|
41
|
+
/*#__PURE__*/ _jsx(DialogTitle, {
|
|
42
|
+
children: row ? nameOf(row) : ''
|
|
43
|
+
}),
|
|
44
|
+
/*#__PURE__*/ _jsx(DialogContent, {
|
|
45
|
+
children: /*#__PURE__*/ _jsxs(Stack, {
|
|
46
|
+
spacing: 2,
|
|
47
|
+
children: [
|
|
48
|
+
/*#__PURE__*/ _jsxs(Box, {
|
|
49
|
+
children: [
|
|
50
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
51
|
+
variant: "overline",
|
|
52
|
+
color: "text.secondary",
|
|
53
|
+
children: 'Trigger'
|
|
54
|
+
}),
|
|
55
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
56
|
+
variant: "body2",
|
|
57
|
+
children: (_ref = row == null ? void 0 : (_row_trigger = row['trigger']) == null ? void 0 : _row_trigger.event) != null ? _ref : 'Manual — runs only when called'
|
|
58
|
+
}),
|
|
59
|
+
(row == null ? void 0 : (_row_trigger1 = row['trigger']) == null ? void 0 : _row_trigger1.filter) ? /*#__PURE__*/ _jsx(Typography, {
|
|
60
|
+
variant: "caption",
|
|
61
|
+
sx: {
|
|
62
|
+
fontFamily: 'monospace'
|
|
63
|
+
},
|
|
64
|
+
children: `when ${row['trigger'].filter}`
|
|
65
|
+
}) : null
|
|
66
|
+
]
|
|
67
|
+
}),
|
|
68
|
+
/*#__PURE__*/ _jsxs(Box, {
|
|
69
|
+
children: [
|
|
70
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
71
|
+
variant: "overline",
|
|
72
|
+
color: "text.secondary",
|
|
73
|
+
children: `Steps (${steps.length})`
|
|
74
|
+
}),
|
|
75
|
+
/*#__PURE__*/ _jsx(Box, {
|
|
76
|
+
component: "pre",
|
|
77
|
+
sx: {
|
|
78
|
+
m: 0,
|
|
79
|
+
p: 1.5,
|
|
80
|
+
borderRadius: 1,
|
|
81
|
+
bgcolor: 'action.hover',
|
|
82
|
+
fontSize: 12,
|
|
83
|
+
overflow: 'auto',
|
|
84
|
+
maxHeight: 420
|
|
85
|
+
},
|
|
86
|
+
children: JSON.stringify(steps, null, 2)
|
|
87
|
+
})
|
|
88
|
+
]
|
|
89
|
+
})
|
|
90
|
+
]
|
|
91
|
+
})
|
|
92
|
+
}),
|
|
93
|
+
/*#__PURE__*/ _jsx(DialogActions, {
|
|
94
|
+
children: /*#__PURE__*/ _jsx(Button, {
|
|
95
|
+
onClick: onClose,
|
|
96
|
+
children: 'Close'
|
|
97
|
+
})
|
|
98
|
+
})
|
|
99
|
+
]
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
/** One paged, read-only table of automations. */ function AutomationTable(props) {
|
|
103
|
+
const { title, buildQuery, deps, hostId, emptyLabel, onOpen } = props;
|
|
104
|
+
const firestore = useFirestore();
|
|
105
|
+
const paged = usePagedCollection((pageLimit)=>buildQuery(firestore, pageLimit), [
|
|
106
|
+
firestore,
|
|
107
|
+
...deps
|
|
108
|
+
], {
|
|
109
|
+
idField: '$id'
|
|
110
|
+
});
|
|
111
|
+
const byId = useMemo(()=>new Map(paged.rows.map((row)=>[
|
|
112
|
+
row.$id,
|
|
113
|
+
row
|
|
114
|
+
])), [
|
|
115
|
+
paged.rows
|
|
116
|
+
]);
|
|
117
|
+
const columns = useMemo(()=>[
|
|
118
|
+
{
|
|
119
|
+
field: 'name',
|
|
120
|
+
headerName: 'Automation',
|
|
121
|
+
flex: 1.4,
|
|
122
|
+
minWidth: 200,
|
|
123
|
+
valueGetter: (_value, row)=>nameOf(row)
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
field: 'status',
|
|
127
|
+
headerName: 'Status',
|
|
128
|
+
flex: 1.2,
|
|
129
|
+
minWidth: 200,
|
|
130
|
+
valueGetter: (_value, row)=>{
|
|
131
|
+
var _ref;
|
|
132
|
+
var _row_trigger;
|
|
133
|
+
return String((_ref = (_row_trigger = row['trigger']) == null ? void 0 : _row_trigger.event) != null ? _ref : 'manual');
|
|
134
|
+
},
|
|
135
|
+
renderCell: ({ row })=>{
|
|
136
|
+
var _ref;
|
|
137
|
+
var _row_trigger;
|
|
138
|
+
const paused = Array.isArray(row['pausedHostIds']) ? row['pausedHostIds'] : [];
|
|
139
|
+
return /*#__PURE__*/ _jsxs(Stack, {
|
|
140
|
+
direction: "row",
|
|
141
|
+
spacing: 0.5,
|
|
142
|
+
useFlexGap: true,
|
|
143
|
+
sx: {
|
|
144
|
+
alignItems: 'center',
|
|
145
|
+
height: '100%',
|
|
146
|
+
flexWrap: 'wrap'
|
|
147
|
+
},
|
|
148
|
+
children: [
|
|
149
|
+
/*#__PURE__*/ _jsx(Chip, {
|
|
150
|
+
size: "small",
|
|
151
|
+
variant: "outlined",
|
|
152
|
+
label: (_ref = (_row_trigger = row['trigger']) == null ? void 0 : _row_trigger.event) != null ? _ref : 'manual'
|
|
153
|
+
}),
|
|
154
|
+
row['enabled'] === false ? /*#__PURE__*/ _jsx(Chip, {
|
|
155
|
+
size: "small",
|
|
156
|
+
color: "warning",
|
|
157
|
+
label: "off"
|
|
158
|
+
}) : /*#__PURE__*/ _jsx(Chip, {
|
|
159
|
+
size: "small",
|
|
160
|
+
color: "success",
|
|
161
|
+
label: "on"
|
|
162
|
+
}),
|
|
163
|
+
hostId && paused.includes(hostId) ? /*#__PURE__*/ _jsx(Chip, {
|
|
164
|
+
size: "small",
|
|
165
|
+
color: "warning",
|
|
166
|
+
label: "paused here"
|
|
167
|
+
}) : !hostId && paused.length ? /*#__PURE__*/ _jsx(Chip, {
|
|
168
|
+
size: "small",
|
|
169
|
+
color: "warning",
|
|
170
|
+
label: `paused on ${paused.length}`
|
|
171
|
+
}) : null,
|
|
172
|
+
row['deletedAt'] ? /*#__PURE__*/ _jsx(Chip, {
|
|
173
|
+
size: "small",
|
|
174
|
+
color: "error",
|
|
175
|
+
label: "deleted"
|
|
176
|
+
}) : null
|
|
177
|
+
]
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
field: 'updatedAt',
|
|
183
|
+
headerName: 'Updated',
|
|
184
|
+
flex: 0.9,
|
|
185
|
+
minWidth: 160,
|
|
186
|
+
valueGetter: (_value, row)=>whenOf(row['updatedAt'])
|
|
187
|
+
},
|
|
188
|
+
listActionsColumn((row)=>/*#__PURE__*/ _jsx(ListRowActions, {
|
|
189
|
+
label: nameOf(row),
|
|
190
|
+
quick: {
|
|
191
|
+
icon: mdiEyeOutline.path,
|
|
192
|
+
label: 'View steps',
|
|
193
|
+
onClick: ()=>onOpen(row)
|
|
194
|
+
},
|
|
195
|
+
items: []
|
|
196
|
+
}), {
|
|
197
|
+
width: 110
|
|
198
|
+
})
|
|
199
|
+
], [
|
|
200
|
+
hostId,
|
|
201
|
+
onOpen
|
|
202
|
+
]);
|
|
203
|
+
return /*#__PURE__*/ _jsxs(Stack, {
|
|
204
|
+
spacing: 1,
|
|
205
|
+
children: [
|
|
206
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
207
|
+
variant: "subtitle2",
|
|
208
|
+
children: title
|
|
209
|
+
}),
|
|
210
|
+
/*#__PURE__*/ _jsx(ListTable, {
|
|
211
|
+
rows: paged.rows,
|
|
212
|
+
columns: columns,
|
|
213
|
+
loading: paged.status === 'loading',
|
|
214
|
+
disableColumnSorting: true,
|
|
215
|
+
noRowsLabel: emptyLabel,
|
|
216
|
+
onOpen: (id)=>{
|
|
217
|
+
const row = byId.get(String(id));
|
|
218
|
+
if (row) onOpen(row);
|
|
219
|
+
},
|
|
220
|
+
hideFooter: true,
|
|
221
|
+
rowHeight: TABLE_ROW_HEIGHT
|
|
222
|
+
}),
|
|
223
|
+
/*#__PURE__*/ _jsx(ListPagination, {
|
|
224
|
+
page: paged.page,
|
|
225
|
+
pageSize: paged.pageSize,
|
|
226
|
+
rowCount: paged.rows.length,
|
|
227
|
+
hasMore: paged.hasMore,
|
|
228
|
+
onPageChange: paged.setPage,
|
|
229
|
+
onPageSizeChange: paged.setPageSize
|
|
230
|
+
})
|
|
231
|
+
]
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
const inIdOrder = (source, pageLimit)=>query(source, orderBy(documentId()), limit(pageLimit));
|
|
235
|
+
/**
|
|
236
|
+
* The staff site page's automations (`staffSite` zone): the site's own
|
|
237
|
+
* automations, the organization automations that run on it, and its
|
|
238
|
+
* workflows.
|
|
239
|
+
*/ export function StaffSiteAutomationsCard(props) {
|
|
240
|
+
const { hostId, orgId } = props;
|
|
241
|
+
const [open, setOpen] = useState(null);
|
|
242
|
+
return /*#__PURE__*/ _jsxs(_Fragment, {
|
|
243
|
+
children: [
|
|
244
|
+
/*#__PURE__*/ _jsx(CardDisplay, {
|
|
245
|
+
header: 'Automations',
|
|
246
|
+
help: pluginDocsHelp('staffConsole', {
|
|
247
|
+
anchor: '#staff-automations',
|
|
248
|
+
excerpt: "The site's automations, the organization automations that run on it, and its workflows — read-only, each opening its trigger and steps."
|
|
249
|
+
}),
|
|
250
|
+
contentGutterX: true,
|
|
251
|
+
contentGutterY: true,
|
|
252
|
+
children: /*#__PURE__*/ _jsxs(Stack, {
|
|
253
|
+
spacing: 3,
|
|
254
|
+
children: [
|
|
255
|
+
/*#__PURE__*/ _jsx(AutomationTable, {
|
|
256
|
+
title: "Site automations",
|
|
257
|
+
buildQuery: (firestore, pageLimit)=>hostId ? inIdOrder(collection(firestore, 'hosts', hostId, 'actions'), pageLimit) : null,
|
|
258
|
+
deps: [
|
|
259
|
+
hostId
|
|
260
|
+
],
|
|
261
|
+
hostId: hostId,
|
|
262
|
+
emptyLabel: "No automations on this site",
|
|
263
|
+
onOpen: setOpen
|
|
264
|
+
}),
|
|
265
|
+
/*#__PURE__*/ _jsx(AutomationTable, {
|
|
266
|
+
title: "Organization automations that run here",
|
|
267
|
+
buildQuery: (firestore, pageLimit)=>orgId && hostId ? inIdOrder(query(collection(firestore, 'orgs', orgId, 'automations'), where('visibleTo', 'array-contains-any', [
|
|
268
|
+
'org',
|
|
269
|
+
`host:${hostId}`
|
|
270
|
+
])), pageLimit) : null,
|
|
271
|
+
deps: [
|
|
272
|
+
orgId,
|
|
273
|
+
hostId
|
|
274
|
+
],
|
|
275
|
+
hostId: hostId,
|
|
276
|
+
emptyLabel: "No organization automation runs on this site",
|
|
277
|
+
onOpen: setOpen
|
|
278
|
+
}),
|
|
279
|
+
/*#__PURE__*/ _jsx(AutomationTable, {
|
|
280
|
+
title: "Workflows",
|
|
281
|
+
buildQuery: (firestore, pageLimit)=>hostId ? inIdOrder(collection(firestore, 'hosts', hostId, 'workflows'), pageLimit) : null,
|
|
282
|
+
deps: [
|
|
283
|
+
hostId
|
|
284
|
+
],
|
|
285
|
+
emptyLabel: "No workflows on this site",
|
|
286
|
+
onOpen: setOpen
|
|
287
|
+
})
|
|
288
|
+
]
|
|
289
|
+
})
|
|
290
|
+
}),
|
|
291
|
+
/*#__PURE__*/ _jsx(StepsDialog, {
|
|
292
|
+
row: open,
|
|
293
|
+
onClose: ()=>setOpen(null)
|
|
294
|
+
})
|
|
295
|
+
]
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
/** The staff organization page's automations (`adminOrgDetail` zone). */ export function StaffOrgAutomationsCard(props) {
|
|
299
|
+
const { orgId } = props;
|
|
300
|
+
const [open, setOpen] = useState(null);
|
|
301
|
+
return /*#__PURE__*/ _jsxs(_Fragment, {
|
|
302
|
+
children: [
|
|
303
|
+
/*#__PURE__*/ _jsx(CardDisplay, {
|
|
304
|
+
header: 'Organization automations',
|
|
305
|
+
help: pluginDocsHelp('staffConsole', {
|
|
306
|
+
anchor: '#staff-automations',
|
|
307
|
+
excerpt: "The organization's automations, whether each is on and where it is paused — read-only, each opening its trigger and steps."
|
|
308
|
+
}),
|
|
309
|
+
contentGutterX: true,
|
|
310
|
+
contentGutterY: true,
|
|
311
|
+
children: /*#__PURE__*/ _jsx(AutomationTable, {
|
|
312
|
+
title: "Automations",
|
|
313
|
+
buildQuery: (firestore, pageLimit)=>orgId ? inIdOrder(collection(firestore, 'orgs', orgId, 'automations'), pageLimit) : null,
|
|
314
|
+
deps: [
|
|
315
|
+
orgId
|
|
316
|
+
],
|
|
317
|
+
emptyLabel: "This organization has no automations",
|
|
318
|
+
onOpen: setOpen
|
|
319
|
+
})
|
|
320
|
+
}),
|
|
321
|
+
/*#__PURE__*/ _jsx(StepsDialog, {
|
|
322
|
+
row: open,
|
|
323
|
+
onClose: ()=>setOpen(null)
|
|
324
|
+
})
|
|
325
|
+
]
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
//# sourceMappingURL=staff-automations-card.component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/workflows/src/lib/components/staff-automations-card.component.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport { pluginDocsHelp } from '@aglyn/aglyn/app-utils/docs-help'\nimport { mdiEyeOutline } from '@aglyn/shared-data-mdi'\nimport { CardDisplay } from '@aglyn/shared-ui-jsx'\nimport { ListPagination } from '@aglyn/shared-ui-jsx/components/list-pagination.component'\nimport {\n ListRowActions,\n ListTable,\n listActionsColumn,\n} from '@aglyn/shared-ui-jsx/components/list-table.component'\nimport { TABLE_ROW_HEIGHT } from '@aglyn/shared-ui-jsx/const/table-pagination'\nimport { useFirestore, usePagedCollection } from '@aglyn/tenant-feature-instance'\nimport {\n Box,\n Button,\n Chip,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n Stack,\n Typography,\n} from '@mui/material'\nimport type { GridColDef } from '@mui/x-data-grid'\nimport {\n collection,\n documentId,\n type Firestore,\n limit,\n orderBy,\n query,\n type Query,\n where,\n} from 'firebase/firestore'\nimport { useMemo, useState } from 'react'\n\n/*\n * AUTOMATIONS, AS STAFF SEE THEM (AGL-3379).\n *\n * The staff site and organization pages are about a customer the staffer is\n * not a member of, so nothing here edits, runs or pauses: each table is a\n * paged walk of one collection in document-id order, and a row opens a\n * read-only view of the trigger and the steps. The rules admit staff reads on\n * every site and organization subcollection.\n */\n\ntype AutomationRow = { $id: string } & Record<string, any>\n\nconst nameOf = (row: AutomationRow): string => String(row['name'] || row['displayName'] || row.$id)\n\nconst whenOf = (value: any): string =>\n typeof value?.toDate === 'function' ? value.toDate().toLocaleString() : '—'\n\n/** The trigger and the steps of one automation, read-only. */\nfunction StepsDialog(props: { row: AutomationRow | null; onClose: () => void }) {\n const { row, onClose } = props\n const steps: unknown[] = Array.isArray(row?.['steps']) ? row['steps'] : []\n return (\n <Dialog open={Boolean(row)} onClose={onClose} maxWidth=\"md\" fullWidth>\n <DialogTitle>{row ? nameOf(row) : ''}</DialogTitle>\n <DialogContent>\n <Stack spacing={2}>\n <Box>\n <Typography variant=\"overline\" color=\"text.secondary\">\n {'Trigger'}\n </Typography>\n <Typography variant=\"body2\">\n {row?.['trigger']?.event ?? 'Manual — runs only when called'}\n </Typography>\n {row?.['trigger']?.filter ? (\n <Typography variant=\"caption\" sx={{ fontFamily: 'monospace' }}>\n {`when ${row['trigger'].filter}`}\n </Typography>\n ) : null}\n </Box>\n <Box>\n <Typography variant=\"overline\" color=\"text.secondary\">\n {`Steps (${steps.length})`}\n </Typography>\n <Box\n component=\"pre\"\n sx={{\n m: 0,\n p: 1.5,\n borderRadius: 1,\n bgcolor: 'action.hover',\n fontSize: 12,\n overflow: 'auto',\n maxHeight: 420,\n }}\n >\n {JSON.stringify(steps, null, 2)}\n </Box>\n </Box>\n </Stack>\n </DialogContent>\n <DialogActions>\n <Button onClick={onClose}>{'Close'}</Button>\n </DialogActions>\n </Dialog>\n )\n}\n\n/** One paged, read-only table of automations. */\nfunction AutomationTable(props: {\n title: string\n buildQuery: (firestore: Firestore, pageLimit: number) => Query | null\n deps: readonly unknown[]\n /** The site the table is read for, to mark what it has paused. */\n hostId?: string\n emptyLabel: string\n onOpen: (row: AutomationRow) => void\n}) {\n const { title, buildQuery, deps, hostId, emptyLabel, onOpen } = props\n const firestore = useFirestore()\n const paged = usePagedCollection<AutomationRow>(\n (pageLimit) => buildQuery(firestore, pageLimit),\n [firestore, ...deps],\n { idField: '$id' },\n )\n const byId = useMemo(() => new Map(paged.rows.map((row) => [row.$id, row])), [paged.rows])\n const columns: GridColDef[] = useMemo(\n () => [\n {\n field: 'name',\n headerName: 'Automation',\n flex: 1.4,\n minWidth: 200,\n valueGetter: (_value, row: AutomationRow) => nameOf(row),\n },\n {\n field: 'status',\n headerName: 'Status',\n flex: 1.2,\n minWidth: 200,\n valueGetter: (_value, row: AutomationRow) => String(row['trigger']?.event ?? 'manual'),\n renderCell: ({ row }: { row: AutomationRow }) => {\n const paused: string[] = Array.isArray(row['pausedHostIds']) ? row['pausedHostIds'] : []\n return (\n <Stack\n direction=\"row\"\n spacing={0.5}\n useFlexGap\n sx={{ alignItems: 'center', height: '100%', flexWrap: 'wrap' }}\n >\n <Chip size=\"small\" variant=\"outlined\" label={row['trigger']?.event ?? 'manual'} />\n {row['enabled'] === false ? (\n <Chip size=\"small\" color=\"warning\" label=\"off\" />\n ) : (\n <Chip size=\"small\" color=\"success\" label=\"on\" />\n )}\n {hostId && paused.includes(hostId) ? (\n <Chip size=\"small\" color=\"warning\" label=\"paused here\" />\n ) : !hostId && paused.length ? (\n <Chip size=\"small\" color=\"warning\" label={`paused on ${paused.length}`} />\n ) : null}\n {row['deletedAt'] ? <Chip size=\"small\" color=\"error\" label=\"deleted\" /> : null}\n </Stack>\n )\n },\n },\n {\n field: 'updatedAt',\n headerName: 'Updated',\n flex: 0.9,\n minWidth: 160,\n valueGetter: (_value, row: AutomationRow) => whenOf(row['updatedAt']),\n },\n listActionsColumn(\n (row: AutomationRow) => (\n <ListRowActions\n label={nameOf(row)}\n quick={{ icon: mdiEyeOutline.path, label: 'View steps', onClick: () => onOpen(row) }}\n items={[]}\n />\n ),\n { width: 110 },\n ),\n ],\n [hostId, onOpen],\n )\n return (\n <Stack spacing={1}>\n <Typography variant=\"subtitle2\">{title}</Typography>\n <ListTable\n rows={paged.rows}\n columns={columns}\n loading={paged.status === 'loading'}\n disableColumnSorting\n noRowsLabel={emptyLabel}\n onOpen={(id) => {\n const row = byId.get(String(id))\n if (row) onOpen(row)\n }}\n hideFooter\n rowHeight={TABLE_ROW_HEIGHT}\n />\n <ListPagination\n page={paged.page}\n pageSize={paged.pageSize}\n rowCount={paged.rows.length}\n hasMore={paged.hasMore}\n onPageChange={paged.setPage}\n onPageSizeChange={paged.setPageSize}\n />\n </Stack>\n )\n}\n\nconst inIdOrder = (source: Query, pageLimit: number) =>\n query(source, orderBy(documentId()), limit(pageLimit))\n\n/**\n * The staff site page's automations (`staffSite` zone): the site's own\n * automations, the organization automations that run on it, and its\n * workflows.\n */\nexport function StaffSiteAutomationsCard(props: { hostId: string; orgId?: string }) {\n const { hostId, orgId } = props\n const [open, setOpen] = useState<AutomationRow | null>(null)\n return (\n <>\n <CardDisplay\n header={'Automations'}\n help={pluginDocsHelp('staffConsole', {\n anchor: '#staff-automations',\n excerpt:\n \"The site's automations, the organization automations that run on it, and its workflows — read-only, each opening its trigger and steps.\",\n })}\n contentGutterX\n contentGutterY\n >\n <Stack spacing={3}>\n <AutomationTable\n title=\"Site automations\"\n buildQuery={(firestore, pageLimit) =>\n hostId ? inIdOrder(collection(firestore, 'hosts', hostId, 'actions'), pageLimit) : null\n }\n deps={[hostId]}\n hostId={hostId}\n emptyLabel=\"No automations on this site\"\n onOpen={setOpen}\n />\n <AutomationTable\n title=\"Organization automations that run here\"\n buildQuery={(firestore, pageLimit) =>\n orgId && hostId\n ? inIdOrder(\n query(\n collection(firestore, 'orgs', orgId, 'automations'),\n where('visibleTo', 'array-contains-any', ['org', `host:${hostId}`]),\n ),\n pageLimit,\n )\n : null\n }\n deps={[orgId, hostId]}\n hostId={hostId}\n emptyLabel=\"No organization automation runs on this site\"\n onOpen={setOpen}\n />\n <AutomationTable\n title=\"Workflows\"\n buildQuery={(firestore, pageLimit) =>\n hostId ? inIdOrder(collection(firestore, 'hosts', hostId, 'workflows'), pageLimit) : null\n }\n deps={[hostId]}\n emptyLabel=\"No workflows on this site\"\n onOpen={setOpen}\n />\n </Stack>\n </CardDisplay>\n <StepsDialog row={open} onClose={() => setOpen(null)} />\n </>\n )\n}\n\n/** The staff organization page's automations (`adminOrgDetail` zone). */\nexport function StaffOrgAutomationsCard(props: { orgId: string }) {\n const { orgId } = props\n const [open, setOpen] = useState<AutomationRow | null>(null)\n return (\n <>\n <CardDisplay\n header={'Organization automations'}\n help={pluginDocsHelp('staffConsole', {\n anchor: '#staff-automations',\n excerpt:\n \"The organization's automations, whether each is on and where it is paused — read-only, each opening its trigger and steps.\",\n })}\n contentGutterX\n contentGutterY\n >\n <AutomationTable\n title=\"Automations\"\n buildQuery={(firestore, pageLimit) =>\n orgId ? inIdOrder(collection(firestore, 'orgs', orgId, 'automations'), pageLimit) : null\n }\n deps={[orgId]}\n emptyLabel=\"This organization has no automations\"\n onOpen={setOpen}\n />\n </CardDisplay>\n <StepsDialog row={open} onClose={() => setOpen(null)} />\n </>\n )\n}\n"],"names":["pluginDocsHelp","mdiEyeOutline","CardDisplay","ListPagination","ListRowActions","ListTable","listActionsColumn","TABLE_ROW_HEIGHT","useFirestore","usePagedCollection","Box","Button","Chip","Dialog","DialogActions","DialogContent","DialogTitle","Stack","Typography","collection","documentId","limit","orderBy","query","where","useMemo","useState","nameOf","row","String","$id","whenOf","value","toDate","toLocaleString","StepsDialog","props","onClose","steps","Array","isArray","open","Boolean","maxWidth","fullWidth","spacing","variant","color","event","filter","sx","fontFamily","length","component","m","p","borderRadius","bgcolor","fontSize","overflow","maxHeight","JSON","stringify","onClick","AutomationTable","title","buildQuery","deps","hostId","emptyLabel","onOpen","firestore","paged","pageLimit","idField","byId","Map","rows","map","columns","field","headerName","flex","minWidth","valueGetter","_value","renderCell","paused","direction","useFlexGap","alignItems","height","flexWrap","size","label","includes","quick","icon","path","items","width","loading","status","disableColumnSorting","noRowsLabel","id","get","hideFooter","rowHeight","page","pageSize","rowCount","hasMore","onPageChange","setPage","onPageSizeChange","setPageSize","inIdOrder","source","StaffSiteAutomationsCard","orgId","setOpen","header","help","anchor","excerpt","contentGutterX","contentGutterY","StaffOrgAutomationsCard"],"mappings":"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"}
|
package/src/lib/plugin.js
CHANGED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
import { mdiSitemap } from "@aglyn/shared-data-mdi";
|
|
18
18
|
import { lazy } from "react";
|
|
19
19
|
import { HostActivityCard } from "./components/host-activity-card.component.js";
|
|
20
|
+
import { StaffOrgAutomationsCard, StaffSiteAutomationsCard } from "./components/staff-automations-card.component.js";
|
|
20
21
|
import { WORKFLOWS_CONSOLE_SECTIONS, WORKFLOWS_ORG_CONSOLE_SECTIONS } from "./components/workflows-console-sections.js";
|
|
21
22
|
import { registerPluginZone } from "@aglyn/aglyn/plugin-manager/plugin-zones";
|
|
22
23
|
import { WORKFLOW_USAGE_ZONE } from "./components/workflow-zones.js";
|
|
@@ -54,6 +55,20 @@ import { BUNDLE_ID } from "./constants/bundle-common.js";
|
|
|
54
55
|
widgetId: 'workflows-host-activity',
|
|
55
56
|
title: 'Recent Activity',
|
|
56
57
|
Component: HostActivityCard
|
|
58
|
+
},
|
|
59
|
+
// The staff site and organization pages' automations (AGL-3379), read
|
|
60
|
+
// only: staff see what runs on a site without joining it.
|
|
61
|
+
{
|
|
62
|
+
slot: Aglyn.CONSOLE_WIDGET_SLOTS.staffSite,
|
|
63
|
+
widgetId: 'workflows-staff-site-automations',
|
|
64
|
+
title: 'Automations',
|
|
65
|
+
Component: StaffSiteAutomationsCard
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
slot: Aglyn.CONSOLE_WIDGET_SLOTS.adminOrgDetail,
|
|
69
|
+
widgetId: 'workflows-staff-org-automations',
|
|
70
|
+
title: 'Organization automations',
|
|
71
|
+
Component: StaffOrgAutomationsCard
|
|
57
72
|
}
|
|
58
73
|
],
|
|
59
74
|
pluginId: BUNDLE_ID,
|
package/src/lib/plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../libs/plugins/workflows/src/lib/plugin.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport * as Aglyn from '@aglyn/aglyn'\nimport { mdiSitemap } from '@aglyn/shared-data-mdi'\nimport { lazy } from 'react'\nimport { HostActivityCard } from './components/host-activity-card.component'\nimport {\n WORKFLOWS_CONSOLE_SECTIONS,\n WORKFLOWS_ORG_CONSOLE_SECTIONS,\n} from './components/workflows-console-sections'\nimport { registerPluginZone } from '@aglyn/aglyn/plugin-manager/plugin-zones'\nimport { WORKFLOW_USAGE_ZONE } from './components/workflow-zones'\nimport { BUNDLE_ID } from './constants/bundle-common'\n\n/** Code-split: the Automation console page only loads when opened. */\nconst WorkflowsConsolePage = lazy(\n () => import('./components/workflows-console-page'),\n)\n\n/**\n * Workflows feature plugin (AGL-395). Console-only — workflows, actions,\n * and webhooks run server-side (event pipelines, `/api/hooks`), not through\n * a canvas element, so there is no UI bundle. The console half declares the\n * Automation nav + page through the ConsoleExtension registry, gated by the\n * `workflows` entitlement (the Actions/Webhooks tabs run their own per-plan\n * checks off the passed `org`). Where a workflow is used is asked of the\n * platform's scan and drawn in a zone this plugin hosts.\n *\n * `pluginId`, `featureFlag` and `navTabId` all still read `workflows`: they\n * are stored — an org's enabled-plugin ids, the plan's entitlement flags, the\n * Remote Config release flag — and a section's name is not a reason to orphan\n * them. Only what a reader sees carries the new name.\n */\nexport function registerWorkflowsConsole(): void {\n registerPluginZone(\n {\n zone: WORKFLOW_USAGE_ZONE,\n label: 'Where a workflow is used',\n surface: 'console',\n description:\n 'On the Automation page, after a reader asks where a workflow is used. A widget here lays out the scan the page already ran; it is handed the site, the answer and a way to close, and it writes nothing.',\n },\n // Named, because a spec calls this registrar without the loader.\n { pluginId: BUNDLE_ID },\n )\n Aglyn.registerConsoleExtension({\n // Host activity feed (AGL-419): rendered by the shell's\n // 'hostActivity' widget slot (dashboard + editor view page).\n widgets: [\n {\n slot: 'hostActivity',\n widgetId: 'workflows-host-activity',\n title: 'Recent Activity',\n Component: HostActivityCard,\n },\n ],\n pluginId: BUNDLE_ID,\n displayName: 'Automation',\n featureFlag: 'workflows',\n navItems: [\n {\n label: 'Automation',\n // Workflows, Actions and Webhooks are the tabs INSIDE this section, so\n // the section is named for what they have in common. `/workflows` —\n // the address before the section had its own name — is redirected here\n // by the console (see `Route.HOST_WORKFLOWS`).\n href: '/automation',\n // Sections as ROUTES (AGL-2501): each is a real URL the shell\n // resolves and gates, so the page mounts the one being read.\n sections: WORKFLOWS_CONSOLE_SECTIONS,\n // Reuse the existing release-flag nav-tab so staff-preview gating is\n // unchanged now that the tab comes from the plugin (AGL-395).\n navTabId: 'nav-tab-workflows',\n icon: { path: mdiSitemap.path },\n header: {\n title: 'Automation',\n icon: { path: mdiSitemap.path },\n docsTopic: 'workflows',\n },\n Component: WorkflowsConsolePage,\n },\n ],\n /*\n * The ORGANIZATION's Automation hub (AGL-3302), at `/[orgSlug]/automation`:\n * the org automations placed across the organization's sites, and every\n * site's own workflows, actions and webhooks side by side. The same page\n * component, mounted with no site; the site tab's release flag gates both\n * levels, so one flag rolls the surface out at once.\n */\n orgNavItems: [\n {\n label: 'Automation',\n href: '/automation',\n sections: WORKFLOWS_ORG_CONSOLE_SECTIONS,\n navTabId: 'nav-tab-workflows',\n icon: { path: mdiSitemap.path },\n header: {\n title: 'Automation',\n icon: { path: mdiSitemap.path },\n docsTopic: 'workflows',\n },\n Component: WorkflowsConsolePage,\n },\n ],\n })\n}\n\n// Activity feed consumed directly by the app (dashboard + screen view).\nexport { default as HostActivityCard } from './components/host-activity-card.component'\nexport type { HostActivityCardProps } from './components/host-activity-card.component'\n"],"names":["Aglyn","mdiSitemap","lazy","HostActivityCard","WORKFLOWS_CONSOLE_SECTIONS","WORKFLOWS_ORG_CONSOLE_SECTIONS","registerPluginZone","WORKFLOW_USAGE_ZONE","BUNDLE_ID","WorkflowsConsolePage","registerWorkflowsConsole","zone","label","surface","description","pluginId","registerConsoleExtension","widgets","slot","widgetId","title","Component","displayName","featureFlag","navItems","href","sections","navTabId","icon","path","header","docsTopic","orgNavItems","default"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED,YAAYA,WAAW,eAAc;AACrC,SAASC,UAAU,QAAQ,yBAAwB;AACnD,SAASC,IAAI,QAAQ,QAAO;AAC5B,SAASC,gBAAgB,QAAQ,+CAA2C;AAC5E,SACEC,0BAA0B,EAC1BC,8BAA8B,QACzB,6CAAyC;AAChD,SAASC,kBAAkB,QAAQ,2CAA0C;AAC7E,SAASC,mBAAmB,QAAQ,iCAA6B;AACjE,SAASC,SAAS,QAAQ,+BAA2B;AAErD,oEAAoE,GACpE,MAAMC,
|
|
1
|
+
{"version":3,"sources":["../../../../../../libs/plugins/workflows/src/lib/plugin.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport * as Aglyn from '@aglyn/aglyn'\nimport { mdiSitemap } from '@aglyn/shared-data-mdi'\nimport { lazy } from 'react'\nimport { HostActivityCard } from './components/host-activity-card.component'\nimport {\n StaffOrgAutomationsCard,\n StaffSiteAutomationsCard,\n} from './components/staff-automations-card.component'\nimport {\n WORKFLOWS_CONSOLE_SECTIONS,\n WORKFLOWS_ORG_CONSOLE_SECTIONS,\n} from './components/workflows-console-sections'\nimport { registerPluginZone } from '@aglyn/aglyn/plugin-manager/plugin-zones'\nimport { WORKFLOW_USAGE_ZONE } from './components/workflow-zones'\nimport { BUNDLE_ID } from './constants/bundle-common'\n\n/** Code-split: the Automation console page only loads when opened. */\nconst WorkflowsConsolePage = lazy(\n () => import('./components/workflows-console-page'),\n)\n\n/**\n * Workflows feature plugin (AGL-395). Console-only — workflows, actions,\n * and webhooks run server-side (event pipelines, `/api/hooks`), not through\n * a canvas element, so there is no UI bundle. The console half declares the\n * Automation nav + page through the ConsoleExtension registry, gated by the\n * `workflows` entitlement (the Actions/Webhooks tabs run their own per-plan\n * checks off the passed `org`). Where a workflow is used is asked of the\n * platform's scan and drawn in a zone this plugin hosts.\n *\n * `pluginId`, `featureFlag` and `navTabId` all still read `workflows`: they\n * are stored — an org's enabled-plugin ids, the plan's entitlement flags, the\n * Remote Config release flag — and a section's name is not a reason to orphan\n * them. Only what a reader sees carries the new name.\n */\nexport function registerWorkflowsConsole(): void {\n registerPluginZone(\n {\n zone: WORKFLOW_USAGE_ZONE,\n label: 'Where a workflow is used',\n surface: 'console',\n description:\n 'On the Automation page, after a reader asks where a workflow is used. A widget here lays out the scan the page already ran; it is handed the site, the answer and a way to close, and it writes nothing.',\n },\n // Named, because a spec calls this registrar without the loader.\n { pluginId: BUNDLE_ID },\n )\n Aglyn.registerConsoleExtension({\n // Host activity feed (AGL-419): rendered by the shell's\n // 'hostActivity' widget slot (dashboard + editor view page).\n widgets: [\n {\n slot: 'hostActivity',\n widgetId: 'workflows-host-activity',\n title: 'Recent Activity',\n Component: HostActivityCard,\n },\n // The staff site and organization pages' automations (AGL-3379), read\n // only: staff see what runs on a site without joining it.\n {\n slot: Aglyn.CONSOLE_WIDGET_SLOTS.staffSite,\n widgetId: 'workflows-staff-site-automations',\n title: 'Automations',\n Component: StaffSiteAutomationsCard,\n },\n {\n slot: Aglyn.CONSOLE_WIDGET_SLOTS.adminOrgDetail,\n widgetId: 'workflows-staff-org-automations',\n title: 'Organization automations',\n Component: StaffOrgAutomationsCard,\n },\n ],\n pluginId: BUNDLE_ID,\n displayName: 'Automation',\n featureFlag: 'workflows',\n navItems: [\n {\n label: 'Automation',\n // Workflows, Actions and Webhooks are the tabs INSIDE this section, so\n // the section is named for what they have in common. `/workflows` —\n // the address before the section had its own name — is redirected here\n // by the console (see `Route.HOST_WORKFLOWS`).\n href: '/automation',\n // Sections as ROUTES (AGL-2501): each is a real URL the shell\n // resolves and gates, so the page mounts the one being read.\n sections: WORKFLOWS_CONSOLE_SECTIONS,\n // Reuse the existing release-flag nav-tab so staff-preview gating is\n // unchanged now that the tab comes from the plugin (AGL-395).\n navTabId: 'nav-tab-workflows',\n icon: { path: mdiSitemap.path },\n header: {\n title: 'Automation',\n icon: { path: mdiSitemap.path },\n docsTopic: 'workflows',\n },\n Component: WorkflowsConsolePage,\n },\n ],\n /*\n * The ORGANIZATION's Automation hub (AGL-3302), at `/[orgSlug]/automation`:\n * the org automations placed across the organization's sites, and every\n * site's own workflows, actions and webhooks side by side. The same page\n * component, mounted with no site; the site tab's release flag gates both\n * levels, so one flag rolls the surface out at once.\n */\n orgNavItems: [\n {\n label: 'Automation',\n href: '/automation',\n sections: WORKFLOWS_ORG_CONSOLE_SECTIONS,\n navTabId: 'nav-tab-workflows',\n icon: { path: mdiSitemap.path },\n header: {\n title: 'Automation',\n icon: { path: mdiSitemap.path },\n docsTopic: 'workflows',\n },\n Component: WorkflowsConsolePage,\n },\n ],\n })\n}\n\n// Activity feed consumed directly by the app (dashboard + screen view).\nexport { default as HostActivityCard } from './components/host-activity-card.component'\nexport type { HostActivityCardProps } from './components/host-activity-card.component'\n"],"names":["Aglyn","mdiSitemap","lazy","HostActivityCard","StaffOrgAutomationsCard","StaffSiteAutomationsCard","WORKFLOWS_CONSOLE_SECTIONS","WORKFLOWS_ORG_CONSOLE_SECTIONS","registerPluginZone","WORKFLOW_USAGE_ZONE","BUNDLE_ID","WorkflowsConsolePage","registerWorkflowsConsole","zone","label","surface","description","pluginId","registerConsoleExtension","widgets","slot","widgetId","title","Component","CONSOLE_WIDGET_SLOTS","staffSite","adminOrgDetail","displayName","featureFlag","navItems","href","sections","navTabId","icon","path","header","docsTopic","orgNavItems","default"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED,YAAYA,WAAW,eAAc;AACrC,SAASC,UAAU,QAAQ,yBAAwB;AACnD,SAASC,IAAI,QAAQ,QAAO;AAC5B,SAASC,gBAAgB,QAAQ,+CAA2C;AAC5E,SACEC,uBAAuB,EACvBC,wBAAwB,QACnB,mDAA+C;AACtD,SACEC,0BAA0B,EAC1BC,8BAA8B,QACzB,6CAAyC;AAChD,SAASC,kBAAkB,QAAQ,2CAA0C;AAC7E,SAASC,mBAAmB,QAAQ,iCAA6B;AACjE,SAASC,SAAS,QAAQ,+BAA2B;AAErD,oEAAoE,GACpE,MAAMC,uBAAuBT,KAC3B,IAAM,MAAM,CAAC;AAGf;;;;;;;;;;;;;CAaC,GACD,OAAO,SAASU;IACdJ,mBACE;QACEK,MAAMJ;QACNK,OAAO;QACPC,SAAS;QACTC,aACE;IACJ,GACA,iEAAiE;IACjE;QAAEC,UAAUP;IAAU;IAExBV,MAAMkB,wBAAwB,CAAC;QAC7B,wDAAwD;QACxD,6DAA6D;QAC7DC,SAAS;YACP;gBACEC,MAAM;gBACNC,UAAU;gBACVC,OAAO;gBACPC,WAAWpB;YACb;YACA,sEAAsE;YACtE,0DAA0D;YAC1D;gBACEiB,MAAMpB,MAAMwB,oBAAoB,CAACC,SAAS;gBAC1CJ,UAAU;gBACVC,OAAO;gBACPC,WAAWlB;YACb;YACA;gBACEe,MAAMpB,MAAMwB,oBAAoB,CAACE,cAAc;gBAC/CL,UAAU;gBACVC,OAAO;gBACPC,WAAWnB;YACb;SACD;QACDa,UAAUP;QACViB,aAAa;QACbC,aAAa;QACbC,UAAU;YACR;gBACEf,OAAO;gBACP,uEAAuE;gBACvE,oEAAoE;gBACpE,uEAAuE;gBACvE,+CAA+C;gBAC/CgB,MAAM;gBACN,8DAA8D;gBAC9D,6DAA6D;gBAC7DC,UAAUzB;gBACV,qEAAqE;gBACrE,8DAA8D;gBAC9D0B,UAAU;gBACVC,MAAM;oBAAEC,MAAMjC,WAAWiC,IAAI;gBAAC;gBAC9BC,QAAQ;oBACNb,OAAO;oBACPW,MAAM;wBAAEC,MAAMjC,WAAWiC,IAAI;oBAAC;oBAC9BE,WAAW;gBACb;gBACAb,WAAWZ;YACb;SACD;QACD;;;;;;KAMC,GACD0B,aAAa;YACX;gBACEvB,OAAO;gBACPgB,MAAM;gBACNC,UAAUxB;gBACVyB,UAAU;gBACVC,MAAM;oBAAEC,MAAMjC,WAAWiC,IAAI;gBAAC;gBAC9BC,QAAQ;oBACNb,OAAO;oBACPW,MAAM;wBAAEC,MAAMjC,WAAWiC,IAAI;oBAAC;oBAC9BE,WAAW;gBACb;gBACAb,WAAWZ;YACb;SACD;IACH;AACF;AAEA,wEAAwE;AACxE,SAAS2B,WAAWnC,gBAAgB,QAAQ,+CAA2C"}
|