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.
- package/common.d.ts +1 -1
- package/common.js +3 -0
- package/components/AppConnect.svelte +2 -2
- package/components/ArgInput.svelte +1 -1
- package/components/CronInput.svelte +54 -53
- package/components/Dropdown.svelte +21 -9
- package/components/Editor.svelte +10 -10
- package/components/EditorBar.svelte +2 -2
- package/components/FlowBuilder.svelte +41 -25
- package/components/FlowGraphViewer.svelte +6 -2
- package/components/FlowMetadata.svelte +8 -3
- package/components/FlowViewer.svelte +2 -2
- package/components/FolderEditor.svelte +299 -0
- package/components/FolderEditor.svelte.d.ts +16 -0
- package/components/FolderInfo.svelte +13 -0
- package/components/FolderInfo.svelte.d.ts +16 -0
- package/components/FolderUsageInfo.svelte +17 -0
- package/components/FolderUsageInfo.svelte.d.ts +16 -0
- package/components/GroupEditor.svelte +287 -0
- package/components/GroupEditor.svelte.d.ts +18 -0
- package/components/GroupInfo.svelte +22 -0
- package/components/GroupInfo.svelte.d.ts +16 -0
- package/components/InputTransformForm.svelte +16 -7
- package/components/MoveDrawer.svelte +75 -0
- package/components/MoveDrawer.svelte.d.ts +19 -0
- package/components/Path.svelte +243 -96
- package/components/Path.svelte.d.ts +1 -4
- package/components/RadioButton.svelte +2 -0
- package/components/RadioButton.svelte.d.ts +1 -0
- package/components/ResourceEditor.svelte +11 -16
- package/components/RunForm.svelte +21 -4
- package/components/RunForm.svelte.d.ts +1 -1
- package/components/ScheduleEditor.svelte +226 -0
- package/components/ScheduleEditor.svelte.d.ts +26 -0
- package/components/ScriptBuilder.svelte +109 -114
- package/components/ScriptEditor.svelte +17 -14
- package/components/ScriptEditor.svelte.d.ts +1 -0
- package/components/ScriptPicker.svelte +55 -29
- package/components/ScriptPicker.svelte.d.ts +1 -0
- package/components/ShareModal.svelte +94 -73
- package/components/ShareModal.svelte.d.ts +2 -4
- package/components/SimpleEditor.svelte +15 -10
- package/components/TemplateEditor.svelte +496 -0
- package/components/TemplateEditor.svelte.d.ts +25 -0
- package/components/TestJobLoader.svelte +1 -1
- package/components/VariableEditor.svelte +2 -1
- package/components/apps/CreateApp.svelte +1 -1
- package/components/apps/components/buttons/AppButton.svelte +3 -3
- package/components/apps/components/dataDisplay/AppBarChart.svelte +5 -4
- package/components/apps/components/dataDisplay/AppPieChart.svelte +3 -3
- package/components/apps/components/dateInputs/AppDateInput.svelte +34 -0
- package/components/apps/components/dateInputs/AppDateInput.svelte.d.ts +22 -0
- package/components/apps/components/form/AppForm.svelte +4 -5
- package/components/apps/components/form/AppForm.svelte.d.ts +0 -1
- package/components/apps/components/helpers/AlignWrapper.svelte +3 -4
- package/components/apps/components/helpers/AlignWrapper.svelte.d.ts +2 -3
- package/components/apps/components/helpers/InputValue.svelte +54 -5
- package/components/apps/components/helpers/InputValue.svelte.d.ts +1 -0
- package/components/apps/components/helpers/NonRunnableComponent.svelte +2 -1
- package/components/apps/components/helpers/RefreshButton.svelte +20 -0
- package/components/apps/components/helpers/RefreshButton.svelte.d.ts +16 -0
- package/components/apps/components/helpers/RunnableComponent.svelte +38 -42
- package/components/apps/components/helpers/RunnableWrapper.svelte +6 -3
- package/components/apps/components/numberInputs/AppNumberInput.svelte +8 -11
- package/components/apps/components/numberInputs/AppNumberInput.svelte.d.ts +1 -0
- package/components/apps/components/selectInputs/AppCheckbox.svelte +1 -1
- package/components/apps/components/selectInputs/AppSelect.svelte +26 -0
- package/components/apps/components/selectInputs/AppSelect.svelte.d.ts +22 -0
- package/components/apps/components/table/AppTable.svelte +159 -0
- package/components/apps/components/{dataDisplay → table}/AppTable.svelte.d.ts +0 -0
- package/components/apps/components/table/AppTableFooter.svelte +54 -0
- package/components/apps/components/table/AppTableFooter.svelte.d.ts +20 -0
- package/components/apps/components/table/tableOptions.d.ts +10 -0
- package/components/apps/components/table/tableOptions.js +11 -0
- package/components/apps/components/textInputs/AppTextInput.svelte +17 -10
- package/components/apps/components/textInputs/AppTextInput.svelte.d.ts +2 -0
- package/components/apps/editor/AppEditor.svelte +35 -20
- package/components/apps/editor/AppEditorHeader.svelte +15 -7
- package/components/apps/editor/AppPreview.svelte +5 -3
- package/components/apps/editor/AppPreview.svelte.d.ts +4 -1
- package/components/apps/editor/ComponentEditor.svelte +21 -3
- package/components/apps/editor/ComponentEditor.svelte.d.ts +2 -0
- package/components/apps/editor/ComponentHeader.svelte +21 -4
- package/components/apps/editor/ComponentHeader.svelte.d.ts +2 -0
- package/components/apps/editor/GridEditor.svelte +40 -20
- package/components/apps/editor/RecomputeAllComponents.svelte +5 -7
- package/components/apps/editor/componentsPanel/ComponentList.svelte +30 -82
- package/components/apps/editor/componentsPanel/data.js +78 -29
- package/components/apps/editor/contextPanel/ComponentOutputViewer.svelte +5 -1
- package/components/apps/editor/contextPanel/ContextPanel.svelte +35 -152
- package/components/apps/editor/contextPanel/ContextPanel.svelte.d.ts +1 -3
- package/components/apps/editor/inlineScriptsPanel/EmptyInlineScript.svelte +64 -0
- package/components/apps/editor/inlineScriptsPanel/EmptyInlineScript.svelte.d.ts +18 -0
- package/components/apps/editor/inlineScriptsPanel/InlineScriptEditor.svelte +95 -0
- package/components/apps/editor/inlineScriptsPanel/InlineScriptEditor.svelte.d.ts +20 -0
- package/components/apps/editor/inlineScriptsPanel/InlineScriptEditorDrawer.svelte +32 -0
- package/components/apps/editor/inlineScriptsPanel/InlineScriptEditorDrawer.svelte.d.ts +19 -0
- package/components/apps/editor/inlineScriptsPanel/InlineScriptEditorPanel.svelte +63 -0
- package/components/apps/editor/inlineScriptsPanel/InlineScriptEditorPanel.svelte.d.ts +17 -0
- package/components/apps/editor/inlineScriptsPanel/InlineScriptsPanel.svelte +44 -0
- package/components/apps/editor/inlineScriptsPanel/InlineScriptsPanel.svelte.d.ts +14 -0
- package/components/apps/editor/inlineScriptsPanel/InlineScriptsPanelList.svelte +126 -0
- package/components/apps/editor/inlineScriptsPanel/InlineScriptsPanelList.svelte.d.ts +16 -0
- package/components/apps/editor/settingsPanel/AlignmentEditor.svelte +41 -0
- package/components/apps/editor/settingsPanel/AlignmentEditor.svelte.d.ts +17 -0
- package/components/apps/editor/settingsPanel/ComponentInputTypeEditor.svelte +44 -0
- package/components/apps/editor/settingsPanel/ComponentInputTypeEditor.svelte.d.ts +18 -0
- package/components/apps/editor/settingsPanel/ComponentPanel.svelte +48 -130
- package/components/apps/editor/settingsPanel/ComponentPanel.svelte.d.ts +3 -0
- package/components/apps/editor/settingsPanel/InputsSpecEditor.svelte +2 -2
- package/components/apps/editor/settingsPanel/InputsSpecsEditor.svelte +1 -1
- package/components/apps/editor/settingsPanel/Recompute.svelte +2 -2
- package/components/apps/editor/settingsPanel/SelectedRunnable.svelte +46 -0
- package/components/apps/editor/settingsPanel/SelectedRunnable.svelte.d.ts +17 -0
- package/components/apps/editor/settingsPanel/SubTypeEditor.svelte +1 -1
- package/components/apps/editor/settingsPanel/common/PanelSection.svelte +1 -1
- package/components/apps/editor/settingsPanel/{ConnectedInputEditor.svelte → inputEditor/ConnectedInputEditor.svelte} +1 -2
- package/components/apps/editor/settingsPanel/{ConnectedInputEditor.svelte.d.ts → inputEditor/ConnectedInputEditor.svelte.d.ts} +1 -1
- package/components/apps/editor/settingsPanel/inputEditor/RunnableInputEditor.svelte +12 -0
- package/components/apps/editor/settingsPanel/inputEditor/RunnableInputEditor.svelte.d.ts +17 -0
- package/components/apps/editor/settingsPanel/{StaticInputEditor.svelte → inputEditor/StaticInputEditor.svelte} +5 -5
- package/components/apps/editor/settingsPanel/{StaticInputEditor.svelte.d.ts → inputEditor/StaticInputEditor.svelte.d.ts} +1 -1
- package/components/apps/editor/settingsPanel/mainInput/InlineScriptList.svelte +6 -3
- package/components/apps/editor/settingsPanel/mainInput/RunnableSelector.svelte +66 -22
- package/components/apps/editor/settingsPanel/mainInput/RunnableSelector.svelte.d.ts +2 -3
- package/components/apps/editor/settingsPanel/mainInput/WorkspaceFlowList.svelte +1 -1
- package/components/apps/gridUtils.d.ts +3 -1
- package/components/apps/gridUtils.js +16 -1
- package/components/apps/inputType.d.ts +10 -4
- package/components/apps/rx.d.ts +8 -8
- package/components/apps/rx.js +17 -9
- package/components/apps/types.d.ts +14 -2
- package/components/apps/utils.d.ts +4 -3
- package/components/apps/utils.js +37 -5
- package/components/common/drawer/Drawer.svelte +1 -1
- package/components/common/drawer/Drawer.svelte.d.ts +1 -0
- package/components/common/popup/Popup.svelte +0 -2
- package/components/common/popup/Popup.svelte.d.ts +0 -4
- package/components/common/table/FlowRow.svelte +21 -7
- package/components/common/table/FlowRow.svelte.d.ts +2 -0
- package/components/common/table/ScriptRow.svelte +22 -7
- package/components/common/table/ScriptRow.svelte.d.ts +2 -0
- package/components/common/toggleButton/ToggleButton.svelte +1 -1
- package/components/common/toggleButton/ToggleButtonGroup.svelte +1 -1
- package/components/common/toggleButton/ToggleButtonGroup.svelte.d.ts +1 -0
- package/components/flows/content/FlowEditorPanel.svelte +10 -16
- package/components/flows/content/FlowInputs.svelte +18 -4
- package/components/flows/content/FlowInputs.svelte.d.ts +1 -0
- package/components/flows/content/FlowModuleComponent.svelte +1 -1
- package/components/flows/content/FlowModuleWrapper.svelte +26 -1
- package/components/flows/content/FlowSchedules.svelte +5 -0
- package/components/flows/content/FlowSettings.svelte +16 -24
- package/components/flows/content/FlowSettings.svelte.d.ts +0 -1
- package/components/flows/header/FlowPreviewButtons.svelte +13 -10
- package/components/flows/map/FlowErrorHandlerItem.svelte +1 -1
- package/components/flows/map/FlowModuleSchemaMap.svelte +12 -3
- package/components/flows/map/FlowSettingsItem.svelte +8 -15
- package/components/flows/map/InsertModuleButton.svelte +29 -2
- package/components/flows/map/InsertModuleButton.svelte.d.ts +3 -1
- package/components/flows/map/MapItem.svelte +2 -1
- package/components/flows/map/MapItem.svelte.d.ts +1 -0
- package/components/flows/pickers/WorkspaceScriptPicker.svelte +3 -0
- package/components/flows/previousResults.js +1 -1
- package/components/graph/FlowGraph.svelte +15 -15
- package/components/graph/model.d.ts +35 -1
- package/components/home/ItemsList.svelte +20 -12
- package/components/jobs/JobDetail.svelte +9 -3
- package/components/sidebar/SidebarContent.svelte +4 -3
- package/components/sidebar/UserMenu.svelte +1 -1
- package/editorUtils.d.ts +7 -1
- package/editorUtils.js +98 -3
- package/es5.d.ts.txt +4526 -0
- package/gen/index.d.ts +2 -0
- package/gen/index.js +1 -0
- package/gen/models/CompletedJob.d.ts +1 -0
- package/gen/models/EditSchedule.d.ts +0 -2
- package/gen/models/Folder.d.ts +5 -0
- package/gen/models/Folder.js +4 -0
- package/gen/models/QueuedJob.d.ts +1 -0
- package/gen/models/Script.d.ts +1 -1
- package/gen/models/User.d.ts +1 -0
- package/gen/services/FolderService.d.ts +128 -0
- package/gen/services/FolderService.js +151 -0
- package/gen/services/GranularAclService.d.ts +3 -3
- package/gen/services/GroupService.d.ts +5 -1
- package/gen/services/GroupService.js +4 -1
- package/gen/services/JobService.d.ts +25 -5
- package/gen/services/JobService.js +10 -5
- package/gen/services/ScriptService.d.ts +2 -1
- package/gen/services/UserService.d.ts +9 -0
- package/gen/services/UserService.js +15 -0
- package/package.json +485 -461
- package/script_helpers.d.ts +2 -2
- package/script_helpers.js +4 -4
- package/stores.d.ts +1 -0
- package/utils.d.ts +3 -0
- package/utils.js +44 -7
- package/components/GroupModal.svelte +0 -98
- package/components/GroupModal.svelte.d.ts +0 -17
- package/components/apps/components/dataDisplay/AppTable.svelte +0 -132
- package/components/apps/components/dataDisplay/app.md +0 -49
- package/components/apps/editor/contextPanel/InlineScriptCreationPanel.svelte +0 -29
- 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 <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 <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 <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 {};
|