windmill-components 1.55.0 → 1.55.2

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.
Files changed (203) hide show
  1. package/common.d.ts +1 -1
  2. package/common.js +3 -0
  3. package/components/AppConnect.svelte +2 -2
  4. package/components/ArgInput.svelte +1 -1
  5. package/components/CronInput.svelte +54 -53
  6. package/components/Dropdown.svelte +21 -9
  7. package/components/Editor.svelte +10 -10
  8. package/components/EditorBar.svelte +2 -2
  9. package/components/FlowBuilder.svelte +41 -25
  10. package/components/FlowGraphViewer.svelte +6 -2
  11. package/components/FlowMetadata.svelte +8 -3
  12. package/components/FlowViewer.svelte +2 -2
  13. package/components/FolderEditor.svelte +299 -0
  14. package/components/FolderEditor.svelte.d.ts +16 -0
  15. package/components/FolderInfo.svelte +13 -0
  16. package/components/FolderInfo.svelte.d.ts +16 -0
  17. package/components/FolderUsageInfo.svelte +17 -0
  18. package/components/FolderUsageInfo.svelte.d.ts +16 -0
  19. package/components/GroupEditor.svelte +287 -0
  20. package/components/GroupEditor.svelte.d.ts +18 -0
  21. package/components/GroupInfo.svelte +22 -0
  22. package/components/GroupInfo.svelte.d.ts +16 -0
  23. package/components/InputTransformForm.svelte +16 -7
  24. package/components/MoveDrawer.svelte +75 -0
  25. package/components/MoveDrawer.svelte.d.ts +19 -0
  26. package/components/Path.svelte +243 -96
  27. package/components/Path.svelte.d.ts +1 -4
  28. package/components/RadioButton.svelte +2 -0
  29. package/components/RadioButton.svelte.d.ts +1 -0
  30. package/components/ResourceEditor.svelte +11 -16
  31. package/components/RunForm.svelte +21 -4
  32. package/components/RunForm.svelte.d.ts +1 -1
  33. package/components/ScheduleEditor.svelte +226 -0
  34. package/components/ScheduleEditor.svelte.d.ts +26 -0
  35. package/components/ScriptBuilder.svelte +109 -114
  36. package/components/ScriptEditor.svelte +17 -14
  37. package/components/ScriptEditor.svelte.d.ts +1 -0
  38. package/components/ScriptPicker.svelte +55 -29
  39. package/components/ScriptPicker.svelte.d.ts +1 -0
  40. package/components/ShareModal.svelte +94 -73
  41. package/components/ShareModal.svelte.d.ts +2 -4
  42. package/components/SimpleEditor.svelte +15 -10
  43. package/components/TemplateEditor.svelte +496 -0
  44. package/components/TemplateEditor.svelte.d.ts +25 -0
  45. package/components/TestJobLoader.svelte +1 -1
  46. package/components/VariableEditor.svelte +2 -1
  47. package/components/apps/CreateApp.svelte +1 -1
  48. package/components/apps/components/buttons/AppButton.svelte +3 -3
  49. package/components/apps/components/dataDisplay/AppBarChart.svelte +5 -4
  50. package/components/apps/components/dataDisplay/AppPieChart.svelte +3 -3
  51. package/components/apps/components/dateInputs/AppDateInput.svelte +34 -0
  52. package/components/apps/components/dateInputs/AppDateInput.svelte.d.ts +22 -0
  53. package/components/apps/components/form/AppForm.svelte +4 -5
  54. package/components/apps/components/form/AppForm.svelte.d.ts +0 -1
  55. package/components/apps/components/helpers/AlignWrapper.svelte +3 -4
  56. package/components/apps/components/helpers/AlignWrapper.svelte.d.ts +2 -3
  57. package/components/apps/components/helpers/InputValue.svelte +54 -5
  58. package/components/apps/components/helpers/InputValue.svelte.d.ts +1 -0
  59. package/components/apps/components/helpers/NonRunnableComponent.svelte +2 -1
  60. package/components/apps/components/helpers/RefreshButton.svelte +20 -0
  61. package/components/apps/components/helpers/RefreshButton.svelte.d.ts +16 -0
  62. package/components/apps/components/helpers/RunnableComponent.svelte +38 -42
  63. package/components/apps/components/helpers/RunnableWrapper.svelte +6 -3
  64. package/components/apps/components/numberInputs/AppNumberInput.svelte +8 -11
  65. package/components/apps/components/numberInputs/AppNumberInput.svelte.d.ts +1 -0
  66. package/components/apps/components/selectInputs/AppCheckbox.svelte +1 -1
  67. package/components/apps/components/selectInputs/AppSelect.svelte +26 -0
  68. package/components/apps/components/selectInputs/AppSelect.svelte.d.ts +22 -0
  69. package/components/apps/components/table/AppTable.svelte +159 -0
  70. package/components/apps/components/{dataDisplay → table}/AppTable.svelte.d.ts +0 -0
  71. package/components/apps/components/table/AppTableFooter.svelte +54 -0
  72. package/components/apps/components/table/AppTableFooter.svelte.d.ts +20 -0
  73. package/components/apps/components/table/tableOptions.d.ts +10 -0
  74. package/components/apps/components/table/tableOptions.js +11 -0
  75. package/components/apps/components/textInputs/AppTextInput.svelte +17 -10
  76. package/components/apps/components/textInputs/AppTextInput.svelte.d.ts +2 -0
  77. package/components/apps/editor/AppEditor.svelte +35 -20
  78. package/components/apps/editor/AppEditorHeader.svelte +15 -7
  79. package/components/apps/editor/AppPreview.svelte +5 -3
  80. package/components/apps/editor/AppPreview.svelte.d.ts +4 -1
  81. package/components/apps/editor/ComponentEditor.svelte +21 -3
  82. package/components/apps/editor/ComponentEditor.svelte.d.ts +2 -0
  83. package/components/apps/editor/ComponentHeader.svelte +21 -4
  84. package/components/apps/editor/ComponentHeader.svelte.d.ts +2 -0
  85. package/components/apps/editor/GridEditor.svelte +40 -20
  86. package/components/apps/editor/RecomputeAllComponents.svelte +5 -7
  87. package/components/apps/editor/componentsPanel/ComponentList.svelte +30 -82
  88. package/components/apps/editor/componentsPanel/data.js +78 -29
  89. package/components/apps/editor/contextPanel/ComponentOutputViewer.svelte +5 -1
  90. package/components/apps/editor/contextPanel/ContextPanel.svelte +35 -152
  91. package/components/apps/editor/contextPanel/ContextPanel.svelte.d.ts +1 -3
  92. package/components/apps/editor/inlineScriptsPanel/EmptyInlineScript.svelte +64 -0
  93. package/components/apps/editor/inlineScriptsPanel/EmptyInlineScript.svelte.d.ts +18 -0
  94. package/components/apps/editor/inlineScriptsPanel/InlineScriptEditor.svelte +95 -0
  95. package/components/apps/editor/inlineScriptsPanel/InlineScriptEditor.svelte.d.ts +20 -0
  96. package/components/apps/editor/inlineScriptsPanel/InlineScriptEditorDrawer.svelte +32 -0
  97. package/components/apps/editor/inlineScriptsPanel/InlineScriptEditorDrawer.svelte.d.ts +19 -0
  98. package/components/apps/editor/inlineScriptsPanel/InlineScriptEditorPanel.svelte +63 -0
  99. package/components/apps/editor/inlineScriptsPanel/InlineScriptEditorPanel.svelte.d.ts +17 -0
  100. package/components/apps/editor/inlineScriptsPanel/InlineScriptsPanel.svelte +44 -0
  101. package/components/apps/editor/inlineScriptsPanel/InlineScriptsPanel.svelte.d.ts +14 -0
  102. package/components/apps/editor/inlineScriptsPanel/InlineScriptsPanelList.svelte +126 -0
  103. package/components/apps/editor/inlineScriptsPanel/InlineScriptsPanelList.svelte.d.ts +16 -0
  104. package/components/apps/editor/settingsPanel/AlignmentEditor.svelte +41 -0
  105. package/components/apps/editor/settingsPanel/AlignmentEditor.svelte.d.ts +17 -0
  106. package/components/apps/editor/settingsPanel/ComponentInputTypeEditor.svelte +44 -0
  107. package/components/apps/editor/settingsPanel/ComponentInputTypeEditor.svelte.d.ts +18 -0
  108. package/components/apps/editor/settingsPanel/ComponentPanel.svelte +48 -130
  109. package/components/apps/editor/settingsPanel/ComponentPanel.svelte.d.ts +3 -0
  110. package/components/apps/editor/settingsPanel/InputsSpecEditor.svelte +2 -2
  111. package/components/apps/editor/settingsPanel/InputsSpecsEditor.svelte +1 -1
  112. package/components/apps/editor/settingsPanel/Recompute.svelte +2 -2
  113. package/components/apps/editor/settingsPanel/SelectedRunnable.svelte +46 -0
  114. package/components/apps/editor/settingsPanel/SelectedRunnable.svelte.d.ts +17 -0
  115. package/components/apps/editor/settingsPanel/SubTypeEditor.svelte +1 -1
  116. package/components/apps/editor/settingsPanel/common/PanelSection.svelte +1 -1
  117. package/components/apps/editor/settingsPanel/{ConnectedInputEditor.svelte → inputEditor/ConnectedInputEditor.svelte} +1 -2
  118. package/components/apps/editor/settingsPanel/{ConnectedInputEditor.svelte.d.ts → inputEditor/ConnectedInputEditor.svelte.d.ts} +1 -1
  119. package/components/apps/editor/settingsPanel/inputEditor/RunnableInputEditor.svelte +12 -0
  120. package/components/apps/editor/settingsPanel/inputEditor/RunnableInputEditor.svelte.d.ts +17 -0
  121. package/components/apps/editor/settingsPanel/{StaticInputEditor.svelte → inputEditor/StaticInputEditor.svelte} +5 -5
  122. package/components/apps/editor/settingsPanel/{StaticInputEditor.svelte.d.ts → inputEditor/StaticInputEditor.svelte.d.ts} +1 -1
  123. package/components/apps/editor/settingsPanel/mainInput/InlineScriptList.svelte +6 -3
  124. package/components/apps/editor/settingsPanel/mainInput/RunnableSelector.svelte +66 -22
  125. package/components/apps/editor/settingsPanel/mainInput/RunnableSelector.svelte.d.ts +2 -3
  126. package/components/apps/editor/settingsPanel/mainInput/WorkspaceFlowList.svelte +1 -1
  127. package/components/apps/gridUtils.d.ts +3 -1
  128. package/components/apps/gridUtils.js +16 -1
  129. package/components/apps/inputType.d.ts +10 -4
  130. package/components/apps/rx.d.ts +8 -8
  131. package/components/apps/rx.js +17 -9
  132. package/components/apps/types.d.ts +14 -2
  133. package/components/apps/utils.d.ts +4 -3
  134. package/components/apps/utils.js +37 -5
  135. package/components/common/drawer/Drawer.svelte +1 -1
  136. package/components/common/drawer/Drawer.svelte.d.ts +1 -0
  137. package/components/common/popup/Popup.svelte +0 -2
  138. package/components/common/popup/Popup.svelte.d.ts +0 -4
  139. package/components/common/table/FlowRow.svelte +21 -7
  140. package/components/common/table/FlowRow.svelte.d.ts +2 -0
  141. package/components/common/table/ScriptRow.svelte +22 -7
  142. package/components/common/table/ScriptRow.svelte.d.ts +2 -0
  143. package/components/common/toggleButton/ToggleButton.svelte +1 -1
  144. package/components/common/toggleButton/ToggleButtonGroup.svelte +1 -1
  145. package/components/common/toggleButton/ToggleButtonGroup.svelte.d.ts +1 -0
  146. package/components/flows/content/FlowEditorPanel.svelte +10 -16
  147. package/components/flows/content/FlowInputs.svelte +18 -4
  148. package/components/flows/content/FlowInputs.svelte.d.ts +1 -0
  149. package/components/flows/content/FlowModuleComponent.svelte +1 -1
  150. package/components/flows/content/FlowModuleWrapper.svelte +26 -1
  151. package/components/flows/content/FlowSchedules.svelte +5 -0
  152. package/components/flows/content/FlowSettings.svelte +16 -24
  153. package/components/flows/content/FlowSettings.svelte.d.ts +0 -1
  154. package/components/flows/header/FlowPreviewButtons.svelte +13 -10
  155. package/components/flows/map/FlowErrorHandlerItem.svelte +1 -1
  156. package/components/flows/map/FlowModuleSchemaMap.svelte +12 -3
  157. package/components/flows/map/FlowSettingsItem.svelte +8 -15
  158. package/components/flows/map/InsertModuleButton.svelte +29 -2
  159. package/components/flows/map/InsertModuleButton.svelte.d.ts +3 -1
  160. package/components/flows/map/MapItem.svelte +2 -1
  161. package/components/flows/map/MapItem.svelte.d.ts +1 -0
  162. package/components/flows/pickers/WorkspaceScriptPicker.svelte +3 -0
  163. package/components/flows/previousResults.js +1 -1
  164. package/components/graph/FlowGraph.svelte +15 -15
  165. package/components/graph/model.d.ts +35 -1
  166. package/components/home/ItemsList.svelte +20 -12
  167. package/components/jobs/JobDetail.svelte +9 -3
  168. package/components/sidebar/SidebarContent.svelte +4 -3
  169. package/components/sidebar/UserMenu.svelte +1 -1
  170. package/editorUtils.d.ts +7 -1
  171. package/editorUtils.js +98 -3
  172. package/es5.d.ts.txt +4526 -0
  173. package/gen/index.d.ts +2 -0
  174. package/gen/index.js +1 -0
  175. package/gen/models/CompletedJob.d.ts +1 -0
  176. package/gen/models/EditSchedule.d.ts +0 -2
  177. package/gen/models/Folder.d.ts +5 -0
  178. package/gen/models/Folder.js +4 -0
  179. package/gen/models/QueuedJob.d.ts +1 -0
  180. package/gen/models/Script.d.ts +1 -1
  181. package/gen/models/User.d.ts +1 -0
  182. package/gen/services/FolderService.d.ts +128 -0
  183. package/gen/services/FolderService.js +151 -0
  184. package/gen/services/GranularAclService.d.ts +3 -3
  185. package/gen/services/GroupService.d.ts +5 -1
  186. package/gen/services/GroupService.js +4 -1
  187. package/gen/services/JobService.d.ts +25 -5
  188. package/gen/services/JobService.js +10 -5
  189. package/gen/services/ScriptService.d.ts +2 -1
  190. package/gen/services/UserService.d.ts +9 -0
  191. package/gen/services/UserService.js +15 -0
  192. package/package.json +485 -461
  193. package/script_helpers.d.ts +2 -2
  194. package/script_helpers.js +4 -4
  195. package/stores.d.ts +1 -0
  196. package/utils.d.ts +3 -0
  197. package/utils.js +44 -7
  198. package/components/GroupModal.svelte +0 -98
  199. package/components/GroupModal.svelte.d.ts +0 -17
  200. package/components/apps/components/dataDisplay/AppTable.svelte +0 -132
  201. package/components/apps/components/dataDisplay/app.md +0 -49
  202. package/components/apps/editor/contextPanel/InlineScriptCreationPanel.svelte +0 -29
  203. package/components/apps/editor/contextPanel/InlineScriptCreationPanel.svelte.d.ts +0 -16
@@ -0,0 +1,299 @@
1
+ <script>import { userStore, workspaceStore } from '../stores';
2
+ import { FolderService, UserService, GranularAclService, GroupService } from '../gen';
3
+ import AutoComplete from 'simple-svelte-autocomplete';
4
+ import TableCustom from './TableCustom.svelte';
5
+ import { Alert, Button, ToggleButton, ToggleButtonGroup } from './common';
6
+ import Skeleton from './common/skeleton/Skeleton.svelte';
7
+ import Tooltip from './Tooltip.svelte';
8
+ export let name;
9
+ let can_write = false;
10
+ let folder;
11
+ let perms = undefined;
12
+ let managing_folders = [];
13
+ let usernames = [];
14
+ let groups = [];
15
+ let ownerItem = '';
16
+ let folders = [];
17
+ async function loadUsernames() {
18
+ usernames = await UserService.listUsernames({ workspace: $workspaceStore });
19
+ }
20
+ async function loadGroups() {
21
+ groups = await GroupService.listGroupNames({ workspace: $workspaceStore });
22
+ }
23
+ $: {
24
+ if ($workspaceStore && $userStore) {
25
+ load();
26
+ }
27
+ }
28
+ async function load() {
29
+ loadUsernames();
30
+ loadGroups();
31
+ loadFolders();
32
+ await loadFolder();
33
+ }
34
+ async function loadFolders() {
35
+ folders = (await FolderService.listFolders({ workspace: $workspaceStore })).map((x) => x.name);
36
+ }
37
+ async function addToFolder() {
38
+ await GranularAclService.addGranularAcls({
39
+ workspace: $workspaceStore ?? '',
40
+ path: name,
41
+ kind: 'folder',
42
+ requestBody: {
43
+ owner: (ownerKind == 'user' ? 'u/' : 'g/') + ownerItem
44
+ }
45
+ });
46
+ loadFolder();
47
+ }
48
+ async function loadFolder() {
49
+ folder = await FolderService.getFolder({ workspace: $workspaceStore, name });
50
+ can_write =
51
+ $userStore != undefined &&
52
+ (folder?.owners.includes('u/' + $userStore.username) ||
53
+ ($userStore.is_admin ?? false) ||
54
+ $userStore.pgroups.findIndex((x) => folder?.owners.includes(x)) != -1);
55
+ perms = Array.from(new Set(Object.entries(folder?.extra_perms ?? {})
56
+ .map((x) => x[0])
57
+ .concat(folder?.owners ?? []))).map((x) => {
58
+ return {
59
+ owner_name: x,
60
+ role: getRole(x)
61
+ };
62
+ });
63
+ managing_folders = Object.entries(folder?.extra_perms ?? {})
64
+ .filter(([k, v]) => k.startsWith('g/') && v)
65
+ .map(([k, v]) => k);
66
+ }
67
+ function getRole(x) {
68
+ const viewer = x in (folder?.extra_perms ?? {});
69
+ const writer = viewer && (folder?.extra_perms ?? {})[x];
70
+ const owner = folder?.owners?.includes(x);
71
+ if (owner) {
72
+ return 'admin';
73
+ }
74
+ else if (writer) {
75
+ return 'writer';
76
+ }
77
+ else {
78
+ return 'viewer';
79
+ }
80
+ }
81
+ let ownerKind = 'user';
82
+ </script>
83
+
84
+ <div class="flex flex-col gap-6">
85
+ <h1>{name}</h1>
86
+ <h2>Permissions ({perms?.length ?? 0})</h2>
87
+ {#if can_write}
88
+ <Alert role="info" title="New permissions may take up to 60s to apply"
89
+ ><span class="text-xs text-gray-500">Due to permissions cache invalidation</span></Alert
90
+ >
91
+ <div class="flex items-center gap-1">
92
+ <div>
93
+ <ToggleButtonGroup bind:selected={ownerKind} on:selected={() => (ownerItem = '')}>
94
+ <ToggleButton position="left" value="user" size="xs">User</ToggleButton>
95
+ <ToggleButton position="right" value="group" size="xs">Group</ToggleButton>
96
+ </ToggleButtonGroup>
97
+ </div>
98
+ {#key ownerKind}
99
+ <AutoComplete
100
+ items={ownerKind === 'user' ? usernames : groups}
101
+ bind:selectedItem={ownerItem}
102
+ />
103
+ {/key}
104
+ <Button
105
+ disabled={ownerItem == ''}
106
+ variant="contained"
107
+ color="blue"
108
+ size="sm"
109
+ on:click={addToFolder}
110
+ >
111
+ Grant permission to folder
112
+ </Button>
113
+ </div>
114
+ {/if}
115
+ {#if perms}
116
+ <TableCustom>
117
+ <tr slot="header-row">
118
+ <th>user</th>
119
+ <th />
120
+ <th />
121
+ </tr>
122
+ <tbody slot="body">
123
+ {#each perms as { owner_name, role }}<tr>
124
+ <td>{owner_name}</td>
125
+ <td>
126
+ {#if can_write}
127
+ <div>
128
+ <ToggleButtonGroup
129
+ selected={role}
130
+ on:selected={async (e) => {
131
+ const role = e.detail
132
+ // const wasInFolder = (folder?.owners ?? []).includes(folder)
133
+ // const inAcl = (
134
+ // folder?.extra_perms ? Object.keys(folder?.extra_perms) : []
135
+ // ).includes(folder)
136
+ if (role == 'admin') {
137
+ await FolderService.addOwnerToFolder({
138
+ workspace: $workspaceStore ?? '',
139
+ name,
140
+ requestBody: {
141
+ owner: owner_name
142
+ }
143
+ })
144
+ await GranularAclService.addGranularAcls({
145
+ workspace: $workspaceStore ?? '',
146
+ path: name,
147
+ kind: 'folder',
148
+ requestBody: {
149
+ owner: owner_name
150
+ }
151
+ })
152
+ } else if (role == 'writer') {
153
+ await FolderService.removeOwnerToFolder({
154
+ workspace: $workspaceStore ?? '',
155
+ name,
156
+ requestBody: {
157
+ owner: owner_name
158
+ }
159
+ })
160
+ await GranularAclService.addGranularAcls({
161
+ workspace: $workspaceStore ?? '',
162
+ path: name,
163
+ kind: 'folder',
164
+ requestBody: {
165
+ owner: owner_name,
166
+ write: true
167
+ }
168
+ })
169
+ } else if (role == 'viewer') {
170
+ await FolderService.removeOwnerToFolder({
171
+ workspace: $workspaceStore ?? '',
172
+ name,
173
+ requestBody: {
174
+ owner: owner_name
175
+ }
176
+ })
177
+ await GranularAclService.addGranularAcls({
178
+ workspace: $workspaceStore ?? '',
179
+ path: name,
180
+ kind: 'folder',
181
+ requestBody: {
182
+ owner: owner_name,
183
+ write: false
184
+ }
185
+ })
186
+ }
187
+ loadFolder()
188
+ }}
189
+ >
190
+ <ToggleButton position="left" value="viewer" size="xs"
191
+ >Viewer&nbsp;<Tooltip
192
+ >A viewer of a folder has read-only access to all the elements
193
+ (scripts/flows/apps/schedules/resources/variables) inside the folder</Tooltip
194
+ ></ToggleButton
195
+ >
196
+ <ToggleButton position="center" value="writer" size="xs"
197
+ >Writer&nbsp;<Tooltip
198
+ >A viewer of a folder has read AND write access to all the elements
199
+ (scripts/flows/apps/schedules/resources/variables) inside the folder</Tooltip
200
+ ></ToggleButton
201
+ >
202
+ <ToggleButton position="right" value="admin" size="xs"
203
+ >Admin&nbsp;<Tooltip
204
+ >An admin of a folder has read AND write access to all the elements inside
205
+ the folders and can manage the permissions as well as add new admins</Tooltip
206
+ ></ToggleButton
207
+ >
208
+ </ToggleButtonGroup>
209
+ </div>
210
+ {:else}
211
+ {role}
212
+ {/if}</td
213
+ >
214
+ <td>
215
+ {#if can_write}
216
+ <button
217
+ class="ml-2 text-red-500"
218
+ on:click={async () => {
219
+ await FolderService.removeOwnerToFolder({
220
+ workspace: $workspaceStore ?? '',
221
+ name,
222
+ requestBody: { owner: owner_name }
223
+ })
224
+ await GranularAclService.removeGranularAcls({
225
+ workspace: $workspaceStore ?? '',
226
+ path: name,
227
+ kind: 'folder',
228
+ requestBody: {
229
+ owner: owner_name
230
+ }
231
+ })
232
+ loadFolder()
233
+ }}>remove</button
234
+ >
235
+ {/if}</td
236
+ >
237
+ </tr>{/each}
238
+ </tbody>
239
+ </TableCustom>
240
+ <!-- <h2 class="mt-10"
241
+ >Folders managing this folder <Tooltip
242
+ >Any owner of those folders can manage this folder</Tooltip
243
+ ></h2
244
+ >
245
+ {#if can_write}
246
+ <div class="flex items-start">
247
+ <AutoComplete items={folders} bind:selectedItem={new_managing_folder} />
248
+ <Button
249
+ variant="contained"
250
+ color="blue"
251
+ size="sm"
252
+ btnClasses="!ml-4"
253
+ on:click={addToManagingFolder}
254
+ >
255
+ Add folder managing this folder
256
+ </Button>
257
+ </div>
258
+ {/if} -->
259
+ <!-- {#if managing_folders.length == 0}
260
+ <p class="text-gray-600 text-sm">No folder is managing this folder</p>
261
+ {:else}
262
+ <TableCustom>
263
+ <tr slot="header-row">
264
+ <th>folder</th>
265
+ <th />
266
+ </tr>
267
+ <tbody slot="body">
268
+ {#each managing_folders as managing_folder}<tr>
269
+ <td>{managing_folder.split('/')[1]}</td>
270
+ <td>
271
+ {#if can_write}
272
+ <button
273
+ class="ml-2 text-red-500"
274
+ on:click={async () => {
275
+ await GranularAclService.removeGranularAcls({
276
+ workspace: $workspaceStore ?? '',
277
+ path: name,
278
+ kind: 'folder',
279
+ requestBody: {
280
+ owner: managing_folder
281
+ }
282
+ })
283
+ loadFolder()
284
+ }}>remove</button
285
+ >
286
+ {/if}</td
287
+ >
288
+ </tr>{/each}
289
+ </tbody>
290
+ </TableCustom>
291
+ {/if} -->
292
+ {:else}
293
+ <div class="flex flex-col">
294
+ {#each new Array(6) as _}
295
+ <Skeleton layout={[[2], 0.7]} />
296
+ {/each}
297
+ </div>
298
+ {/if}
299
+ </div>
@@ -0,0 +1,16 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ declare const __propDef: {
3
+ props: {
4
+ name: string;
5
+ };
6
+ events: {
7
+ [evt: string]: CustomEvent<any>;
8
+ };
9
+ slots: {};
10
+ };
11
+ export type FolderEditorProps = typeof __propDef.props;
12
+ export type FolderEditorEvents = typeof __propDef.events;
13
+ export type FolderEditorSlots = typeof __propDef.slots;
14
+ export default class FolderEditor extends SvelteComponentTyped<FolderEditorProps, FolderEditorEvents, FolderEditorSlots> {
15
+ }
16
+ export {};
@@ -0,0 +1,13 @@
1
+ <script>import Popover from './Popover.svelte';
2
+ export let members;
3
+ </script>
4
+
5
+ <Popover
6
+ ><div class="inline-flex gap-1 items-end"
7
+ ><span class="text-gray-500 text-xs mb-0.5">({members.length})</span>
8
+ <div class="max-w-xs truncate"
9
+ ><span class="text-gray-600 text-xs ">{members?.join(', ')}</span></div
10
+ ></div
11
+ >
12
+ <span slot="text">{members?.join(', ')}</span></Popover
13
+ >
@@ -0,0 +1,16 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ declare const __propDef: {
3
+ props: {
4
+ members: string[];
5
+ };
6
+ events: {
7
+ [evt: string]: CustomEvent<any>;
8
+ };
9
+ slots: {};
10
+ };
11
+ export type FolderInfoProps = typeof __propDef.props;
12
+ export type FolderInfoEvents = typeof __propDef.events;
13
+ export type FolderInfoSlots = typeof __propDef.slots;
14
+ export default class FolderInfo extends SvelteComponentTyped<FolderInfoProps, FolderInfoEvents, FolderInfoSlots> {
15
+ }
16
+ export {};
@@ -0,0 +1,17 @@
1
+ <script>import { FolderService, GroupService } from '../gen';
2
+ import { workspaceStore } from '../stores';
3
+ export let name;
4
+ $: $workspaceStore && loadUsage();
5
+ let usage = {};
6
+ async function loadUsage() {
7
+ usage = await FolderService.getFolderUsage({ workspace: $workspaceStore, name });
8
+ }
9
+ </script>
10
+
11
+ <div class="flex flex-col text-xs text-gray-600">
12
+ {#each Object.entries(usage) as [k, v]}
13
+ <div>
14
+ {k}: {v}
15
+ </div>
16
+ {/each}
17
+ </div>
@@ -0,0 +1,16 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ declare const __propDef: {
3
+ props: {
4
+ name: string;
5
+ };
6
+ events: {
7
+ [evt: string]: CustomEvent<any>;
8
+ };
9
+ slots: {};
10
+ };
11
+ export type FolderUsageInfoProps = typeof __propDef.props;
12
+ export type FolderUsageInfoEvents = typeof __propDef.events;
13
+ export type FolderUsageInfoSlots = typeof __propDef.slots;
14
+ export default class FolderUsageInfo extends SvelteComponentTyped<FolderUsageInfoProps, FolderUsageInfoEvents, FolderUsageInfoSlots> {
15
+ }
16
+ export {};
@@ -0,0 +1,287 @@
1
+ <script>import { userStore, workspaceStore } from '../stores';
2
+ import { GroupService, UserService, GranularAclService } from '../gen';
3
+ import AutoComplete from 'simple-svelte-autocomplete';
4
+ import TableCustom from './TableCustom.svelte';
5
+ import { canWrite, sendUserToast } from '../utils';
6
+ import { Button, ToggleButton, ToggleButtonGroup } from './common';
7
+ import Skeleton from './common/skeleton/Skeleton.svelte';
8
+ import Tooltip from './Tooltip.svelte';
9
+ import autosize from 'svelte-autosize';
10
+ import { createEventDispatcher } from 'svelte';
11
+ export let name;
12
+ let can_write = false;
13
+ let group;
14
+ let members = undefined;
15
+ let managing_groups = [];
16
+ let usernames = [];
17
+ let username = '';
18
+ let groups = [];
19
+ const dispatch = createEventDispatcher();
20
+ async function loadUsernames() {
21
+ usernames = await UserService.listUsernames({ workspace: $workspaceStore });
22
+ }
23
+ $: {
24
+ if ($workspaceStore && $userStore) {
25
+ load();
26
+ }
27
+ }
28
+ async function load() {
29
+ loadGroups();
30
+ await loadGroup();
31
+ loadUsernames();
32
+ }
33
+ async function loadGroups() {
34
+ groups = (await GroupService.listGroups({ workspace: $workspaceStore })).map((x) => x.name);
35
+ }
36
+ async function addToGroup() {
37
+ await GroupService.addUserToGroup({
38
+ workspace: $workspaceStore ?? '',
39
+ name,
40
+ requestBody: { username }
41
+ });
42
+ loadGroup();
43
+ }
44
+ async function loadGroup() {
45
+ group = await GroupService.getGroup({ workspace: $workspaceStore, name });
46
+ can_write = canWrite(name, group.extra_perms ?? {}, $userStore);
47
+ members = Array.from(new Set(Object.entries(group?.extra_perms ?? {})
48
+ .filter(([k, v]) => k.startsWith('u/') && v)
49
+ .map(([k, _]) => k.split('/')[1])
50
+ .concat(group?.members ?? []))).map((x) => {
51
+ return {
52
+ member_name: x,
53
+ role: getRole(x)
54
+ };
55
+ });
56
+ managing_groups = Object.entries(group?.extra_perms ?? {})
57
+ .filter(([k, v]) => k.startsWith('g/') && v)
58
+ .map(([k, v]) => k);
59
+ }
60
+ function getRole(x) {
61
+ const writer = 'u/' + x in (group?.extra_perms ?? {}) && (group?.extra_perms ?? {})['u/' + x];
62
+ const member = group?.members?.includes(x);
63
+ if (writer && member) {
64
+ return 'admin';
65
+ }
66
+ else if (writer) {
67
+ return 'manager';
68
+ }
69
+ else {
70
+ return 'member';
71
+ }
72
+ }
73
+ </script>
74
+
75
+ <div class="flex flex-col gap-6">
76
+ <h1>{name}</h1>
77
+ {#if group}
78
+ <div class="flex flex-col gap-1">
79
+ <textarea
80
+ disabled={!can_write}
81
+ rows="2"
82
+ type="text"
83
+ use:autosize
84
+ bind:value={group.summary}
85
+ placeholder="Summary of the group"
86
+ />
87
+ <Button
88
+ size="xs"
89
+ on:click={async () => {
90
+ await GroupService.updateGroup({
91
+ workspace: $workspaceStore ?? '',
92
+ name,
93
+ requestBody: { summary: group?.summary }
94
+ })
95
+ dispatch('update')
96
+ sendUserToast('New summary saved')
97
+ }}>Save Summary</Button
98
+ >
99
+ </div>
100
+ {:else}
101
+ <Skeleton layout={[[4]]} />
102
+ {/if}
103
+ <h2>Members ({members?.length ?? 0})</h2>
104
+ {#if can_write}
105
+ <div class="flex items-start">
106
+ <AutoComplete items={usernames} bind:selectedItem={username} />
107
+ <Button variant="contained" color="blue" size="sm" btnClasses="!ml-4" on:click={addToGroup}>
108
+ Add member
109
+ </Button>
110
+ </div>
111
+ {/if}
112
+ {#if members}
113
+ <TableCustom>
114
+ <tr slot="header-row">
115
+ <th>user</th>
116
+ <th />
117
+ <th />
118
+ </tr>
119
+ <tbody slot="body">
120
+ {#each members as { member_name, role }}<tr>
121
+ <td>{member_name}</td>
122
+ <td>
123
+ {#if can_write}
124
+ <div>
125
+ <ToggleButtonGroup
126
+ selected={role}
127
+ on:selected={async (e) => {
128
+ const role = e.detail
129
+ // const wasInGroup = (group?.members ?? []).includes(group)
130
+ // const inAcl = (
131
+ // group?.extra_perms ? Object.keys(group?.extra_perms) : []
132
+ // ).includes(group)
133
+ if (role == 'member') {
134
+ await GroupService.addUserToGroup({
135
+ workspace: $workspaceStore ?? '',
136
+ name,
137
+ requestBody: {
138
+ username: member_name
139
+ }
140
+ })
141
+ await GranularAclService.removeGranularAcls({
142
+ workspace: $workspaceStore ?? '',
143
+ path: name,
144
+ kind: 'group_',
145
+ requestBody: {
146
+ owner: 'u/' + member_name
147
+ }
148
+ })
149
+ } else if (role == 'manager') {
150
+ await GroupService.removeUserToGroup({
151
+ workspace: $workspaceStore ?? '',
152
+ name,
153
+ requestBody: {
154
+ username: member_name
155
+ }
156
+ })
157
+ await GranularAclService.addGranularAcls({
158
+ workspace: $workspaceStore ?? '',
159
+ path: name,
160
+ kind: 'group_',
161
+ requestBody: {
162
+ owner: 'u/' + member_name,
163
+ write: true
164
+ }
165
+ })
166
+ } else if (role == 'admin') {
167
+ await GroupService.addUserToGroup({
168
+ workspace: $workspaceStore ?? '',
169
+ name,
170
+ requestBody: {
171
+ username: member_name
172
+ }
173
+ })
174
+ await GranularAclService.addGranularAcls({
175
+ workspace: $workspaceStore ?? '',
176
+ path: name,
177
+ kind: 'group_',
178
+ requestBody: {
179
+ owner: 'u/' + member_name,
180
+ write: true
181
+ }
182
+ })
183
+ }
184
+ loadGroup()
185
+ }}
186
+ >
187
+ <ToggleButton position="left" value="member" size="xs"
188
+ >Member <Tooltip
189
+ >A Member of a group can see everything the group can see, write to
190
+ everything the group can write, and generally act on behalf of the group</Tooltip
191
+ ></ToggleButton
192
+ >
193
+ <!-- <ToggleButton position="center" value="manager" size="xs"
194
+ >Manager <Tooltip
195
+ >A manager of a group can manage the group, adding and removing users and
196
+ change their roles. Being a manager does not make you a member.</Tooltip
197
+ ></ToggleButton
198
+ > -->
199
+ <ToggleButton position="right" value="admin" size="xs"
200
+ >Admin <Tooltip
201
+ >An admin of a group is a member of a group that can also add and remove
202
+ members to the group, or make them admin.</Tooltip
203
+ ></ToggleButton
204
+ >
205
+ </ToggleButtonGroup>
206
+ </div>
207
+ {:else}
208
+ {role}
209
+ {/if}</td
210
+ >
211
+ <td>
212
+ {#if can_write}
213
+ <button
214
+ class="ml-2 text-red-500"
215
+ on:click={async () => {
216
+ await GroupService.removeUserToGroup({
217
+ workspace: $workspaceStore ?? '',
218
+ name,
219
+ requestBody: { username: member_name }
220
+ })
221
+ loadGroup()
222
+ }}>remove</button
223
+ >
224
+ {/if}</td
225
+ >
226
+ </tr>{/each}
227
+ </tbody>
228
+ </TableCustom>
229
+ <!-- <h2 class="mt-10"
230
+ >Groups managing this group <Tooltip>Any member of those groups can manage this group</Tooltip
231
+ ></h2
232
+ >
233
+ {#if can_write}
234
+ <div class="flex items-start">
235
+ <AutoComplete items={groups} bind:selectedItem={new_managing_group} />
236
+ <Button
237
+ variant="contained"
238
+ color="blue"
239
+ size="sm"
240
+ btnClasses="!ml-4"
241
+ on:click={addToManagingGroup}
242
+ >
243
+ Add group managing this group
244
+ </Button>
245
+ </div>
246
+ {/if}
247
+ {#if managing_groups.length == 0}
248
+ <p class="text-gray-600 text-sm">No group is managing this group</p>
249
+ {:else}
250
+ <TableCustom>
251
+ <tr slot="header-row">
252
+ <th>group</th>
253
+ <th />
254
+ </tr>
255
+ <tbody slot="body">
256
+ {#each managing_groups as managing_group}<tr>
257
+ <td>{managing_group.split('/')[1]}</td>
258
+ <td>
259
+ {#if can_write}
260
+ <button
261
+ class="ml-2 text-red-500"
262
+ on:click={async () => {
263
+ await GranularAclService.removeGranularAcls({
264
+ workspace: $workspaceStore ?? '',
265
+ path: name,
266
+ kind: 'group_',
267
+ requestBody: {
268
+ owner: managing_group
269
+ }
270
+ })
271
+ loadGroup()
272
+ }}>remove</button
273
+ >
274
+ {/if}</td
275
+ >
276
+ </tr>{/each}
277
+ </tbody>
278
+ </TableCustom>
279
+ {/if} -->
280
+ {:else}
281
+ <div class="flex flex-col">
282
+ {#each new Array(6) as _}
283
+ <Skeleton layout={[[2], 0.7]} />
284
+ {/each}
285
+ </div>
286
+ {/if}
287
+ </div>
@@ -0,0 +1,18 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ declare const __propDef: {
3
+ props: {
4
+ name: string;
5
+ };
6
+ events: {
7
+ update: CustomEvent<any>;
8
+ } & {
9
+ [evt: string]: CustomEvent<any>;
10
+ };
11
+ slots: {};
12
+ };
13
+ export type GroupEditorProps = typeof __propDef.props;
14
+ export type GroupEditorEvents = typeof __propDef.events;
15
+ export type GroupEditorSlots = typeof __propDef.slots;
16
+ export default class GroupEditor extends SvelteComponentTyped<GroupEditorProps, GroupEditorEvents, GroupEditorSlots> {
17
+ }
18
+ export {};