windmill-components 1.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +661 -0
- package/common.d.ts +29 -0
- package/components/ArgInfo.svelte +48 -0
- package/components/ArgInput.svelte +277 -0
- package/components/AutosizedTextarea.svelte +34 -0
- package/components/Badge.svelte +12 -0
- package/components/Button.svelte +82 -0
- package/components/ButtonAndDropdown.svelte +25 -0
- package/components/CenteredPage.svelte +5 -0
- package/components/ChevronButton.svelte +21 -0
- package/components/DisplayResult.svelte +101 -0
- package/components/Dropdown.svelte +108 -0
- package/components/Editor.svelte +370 -0
- package/components/FieldHeader.svelte +21 -0
- package/components/FlowBuilder.svelte +202 -0
- package/components/FlowEditor.svelte +95 -0
- package/components/FlowPreview.svelte +141 -0
- package/components/FlowStatusViewer.svelte +137 -0
- package/components/GroupModal.svelte +90 -0
- package/components/IconedResourceType.svelte +32 -0
- package/components/InviteGlobalUser.svelte +56 -0
- package/components/InviteUser.svelte +48 -0
- package/components/ItemPicker.svelte +58 -0
- package/components/JobStatus.svelte +38 -0
- package/components/Modal.svelte +94 -0
- package/components/ModuleStep.svelte +64 -0
- package/components/Multiselect.svelte +327 -0
- package/components/ObjectResourceInput.svelte +62 -0
- package/components/ObjectTypeNarrowing.svelte +25 -0
- package/components/PageHeader.svelte +29 -0
- package/components/Password.svelte +45 -0
- package/components/Path.svelte +129 -0
- package/components/RadioButton.svelte +117 -0
- package/components/Required.svelte +11 -0
- package/components/ResourceEditor.svelte +260 -0
- package/components/ResourcePicker.svelte +21 -0
- package/components/ResourceTypePicker.svelte +71 -0
- package/components/RunForm.svelte +127 -0
- package/components/SchemaEditor.svelte +221 -0
- package/components/SchemaForm.svelte +166 -0
- package/components/SchemaModal.svelte +160 -0
- package/components/SchemaViewer.svelte +76 -0
- package/components/ScriptBuilder.svelte +293 -0
- package/components/ScriptEditor.svelte +669 -0
- package/components/ScriptPicker.svelte +110 -0
- package/components/ScriptSchema.svelte +71 -0
- package/components/ShareModal.svelte +135 -0
- package/components/SharedBadge.svelte +54 -0
- package/components/StringTypeNarrowing.svelte +101 -0
- package/components/Switch.svelte +61 -0
- package/components/TableCustom.svelte +39 -0
- package/components/TableSimple.svelte +66 -0
- package/components/Tabs.svelte +21 -0
- package/components/Tooltip.svelte +93 -0
- package/components/VariableEditor.svelte +159 -0
- package/components/icons/DbIcon.svelte +12 -0
- package/components/icons/Mail.svelte +62 -0
- package/components/icons/Mysql.svelte +77 -0
- package/components/icons/PostgresIcon.svelte +57 -0
- package/components/icons/Slack.svelte +26 -0
- package/gen/core/ApiError.d.ts +8 -0
- package/gen/core/ApiRequestOptions.d.ts +13 -0
- package/gen/core/ApiResult.d.ts +7 -0
- package/gen/core/CancelablePromise.d.ts +26 -0
- package/gen/core/OpenAPI.d.ts +16 -0
- package/gen/core/request.d.ts +13 -0
- package/gen/index.d.ts +59 -0
- package/gen/models/AuditLog.d.ts +32 -0
- package/gen/models/CompletedJob.d.ts +48 -0
- package/gen/models/ContextualVariable.d.ts +5 -0
- package/gen/models/CreateResource.d.ts +6 -0
- package/gen/models/CreateVariable.d.ts +6 -0
- package/gen/models/CreateWorkspace.d.ts +6 -0
- package/gen/models/EditResource.d.ts +5 -0
- package/gen/models/EditResourceType.d.ts +4 -0
- package/gen/models/EditSchedule.d.ts +7 -0
- package/gen/models/EditVariable.d.ts +6 -0
- package/gen/models/EditWorkspaceUser.d.ts +3 -0
- package/gen/models/Flow.d.ts +13 -0
- package/gen/models/FlowModule.d.ts +6 -0
- package/gen/models/FlowModuleValue.d.ts +10 -0
- package/gen/models/FlowPreview.d.ts +7 -0
- package/gen/models/FlowStatus.d.ts +6 -0
- package/gen/models/FlowStatusModule.d.ts +15 -0
- package/gen/models/FlowValue.d.ts +5 -0
- package/gen/models/GlobalUserInfo.d.ts +14 -0
- package/gen/models/Group.d.ts +6 -0
- package/gen/models/InputTransform.d.ts +12 -0
- package/gen/models/Job.d.ts +11 -0
- package/gen/models/ListableVariable.d.ts +8 -0
- package/gen/models/Login.d.ts +4 -0
- package/gen/models/MainArgSignature.d.ts +14 -0
- package/gen/models/NewSchedule.d.ts +9 -0
- package/gen/models/NewToken.d.ts +4 -0
- package/gen/models/NewUser.d.ts +5 -0
- package/gen/models/Preview.d.ts +13 -0
- package/gen/models/QueuedJob.d.ts +47 -0
- package/gen/models/Resource.d.ts +8 -0
- package/gen/models/ResourceType.d.ts +6 -0
- package/gen/models/Schedule.d.ts +13 -0
- package/gen/models/Script.d.ts +29 -0
- package/gen/models/ScriptArgs.d.ts +1 -0
- package/gen/models/TruncatedToken.d.ts +7 -0
- package/gen/models/User.d.ts +10 -0
- package/gen/models/UserWorkspaceList.d.ts +8 -0
- package/gen/models/WorkerPing.d.ts +8 -0
- package/gen/models/Workspace.d.ts +6 -0
- package/gen/models/WorkspaceInvite.d.ts +5 -0
- package/gen/services/AdminService.d.ts +35 -0
- package/gen/services/AuditService.d.ts +37 -0
- package/gen/services/FlowService.d.ts +82 -0
- package/gen/services/GranularAclService.d.ts +42 -0
- package/gen/services/GroupService.d.ts +94 -0
- package/gen/services/JobService.d.ts +217 -0
- package/gen/services/ResourceService.d.ts +116 -0
- package/gen/services/ScheduleService.d.ts +73 -0
- package/gen/services/ScriptService.d.ts +165 -0
- package/gen/services/SettingsService.d.ts +15 -0
- package/gen/services/UserService.d.ts +211 -0
- package/gen/services/VariableService.d.ts +66 -0
- package/gen/services/WorkerService.d.ts +15 -0
- package/gen/services/WorkspaceService.d.ts +137 -0
- package/infer.d.ts +2 -0
- package/lib/components/ArgInfo.svelte.d.ts +16 -0
- package/lib/components/ArgInput.svelte.d.ts +37 -0
- package/lib/components/AutosizedTextarea.svelte.d.ts +19 -0
- package/lib/components/Badge.svelte.d.ts +20 -0
- package/lib/components/Button.svelte.d.ts +23 -0
- package/lib/components/ButtonAndDropdown.svelte.d.ts +23 -0
- package/lib/components/CenteredPage.svelte.d.ts +23 -0
- package/lib/components/ChevronButton.svelte.d.ts +19 -0
- package/lib/components/DisplayResult.svelte.d.ts +16 -0
- package/lib/components/Dropdown.svelte.d.ts +22 -0
- package/lib/components/Editor.svelte.d.ts +38 -0
- package/lib/components/FieldHeader.svelte.d.ts +23 -0
- package/lib/components/FlowBuilder.svelte.d.ts +18 -0
- package/lib/components/FlowEditor.svelte.d.ts +19 -0
- package/lib/components/FlowPreview.svelte.d.ts +21 -0
- package/lib/components/FlowStatusViewer.svelte.d.ts +18 -0
- package/lib/components/GroupModal.svelte.d.ts +17 -0
- package/lib/components/IconedResourceType.svelte.d.ts +19 -0
- package/lib/components/InviteGlobalUser.svelte.d.ts +19 -0
- package/lib/components/InviteUser.svelte.d.ts +19 -0
- package/lib/components/ItemPicker.svelte.d.ts +24 -0
- package/lib/components/JobStatus.svelte.d.ts +17 -0
- package/lib/components/Modal.svelte.d.ts +28 -0
- package/lib/components/ModuleStep.svelte.d.ts +26 -0
- package/lib/components/Multiselect.svelte.d.ts +33 -0
- package/lib/components/ObjectResourceInput.svelte.d.ts +17 -0
- package/lib/components/ObjectTypeNarrowing.svelte.d.ts +16 -0
- package/lib/components/PageHeader.svelte.d.ts +20 -0
- package/lib/components/Password.svelte.d.ts +18 -0
- package/lib/components/Path.svelte.d.ts +26 -0
- package/lib/components/RadioButton.svelte.d.ts +21 -0
- package/lib/components/Required.svelte.d.ts +17 -0
- package/lib/components/ResourceEditor.svelte.d.ts +22 -0
- package/lib/components/ResourcePicker.svelte.d.ts +17 -0
- package/lib/components/ResourceTypePicker.svelte.d.ts +19 -0
- package/lib/components/RunForm.svelte.d.ts +22 -0
- package/lib/components/SchemaEditor.svelte.d.ts +22 -0
- package/lib/components/SchemaForm.svelte.d.ts +23 -0
- package/lib/components/SchemaModal.svelte.d.ts +44 -0
- package/lib/components/SchemaViewer.svelte.d.ts +17 -0
- package/lib/components/ScriptBuilder.svelte.d.ts +20 -0
- package/lib/components/ScriptEditor.svelte.d.ts +28 -0
- package/lib/components/ScriptPicker.svelte.d.ts +21 -0
- package/lib/components/ScriptSchema.svelte.d.ts +22 -0
- package/lib/components/ShareModal.svelte.d.ts +21 -0
- package/lib/components/SharedBadge.svelte.d.ts +17 -0
- package/lib/components/StringTypeNarrowing.svelte.d.ts +18 -0
- package/lib/components/Switch.svelte.d.ts +31 -0
- package/lib/components/TableCustom.svelte.d.ts +25 -0
- package/lib/components/TableSimple.svelte.d.ts +24 -0
- package/lib/components/Tabs.svelte.d.ts +20 -0
- package/lib/components/Tooltip.svelte.d.ts +20 -0
- package/lib/components/VariableEditor.svelte.d.ts +21 -0
- package/lib/components/icons/DbIcon.svelte.d.ts +17 -0
- package/lib/components/icons/Mail.svelte.d.ts +17 -0
- package/lib/components/icons/Mysql.svelte.d.ts +17 -0
- package/lib/components/icons/PostgresIcon.svelte.d.ts +17 -0
- package/lib/components/icons/Slack.svelte.d.ts +17 -0
- package/package.json +110 -0
- package/stores.d.ts +19 -0
- package/utils.d.ts +60 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
<script>import { pathToMeta } from '../../common';
|
|
2
|
+
import { GroupService } from '../../gen';
|
|
3
|
+
import Tooltip from './Tooltip.svelte';
|
|
4
|
+
import { userStore, workspaceStore } from '../../stores';
|
|
5
|
+
import { sleep } from '../../utils';
|
|
6
|
+
export let meta = {
|
|
7
|
+
ownerKind: 'user',
|
|
8
|
+
owner: '',
|
|
9
|
+
name: ''
|
|
10
|
+
};
|
|
11
|
+
export let namePlaceholder = '';
|
|
12
|
+
export let initialPath;
|
|
13
|
+
export let path = '';
|
|
14
|
+
let groups = [];
|
|
15
|
+
let error = '';
|
|
16
|
+
$: {
|
|
17
|
+
path = [meta.ownerKind === 'group' ? 'g' : 'u', meta.owner, meta.name].join('/');
|
|
18
|
+
}
|
|
19
|
+
export function getPath() {
|
|
20
|
+
return path;
|
|
21
|
+
}
|
|
22
|
+
export async function reset() {
|
|
23
|
+
if (path == '' || path == 'u//') {
|
|
24
|
+
meta.ownerKind = 'user';
|
|
25
|
+
while ($userStore == undefined) {
|
|
26
|
+
await sleep(500);
|
|
27
|
+
}
|
|
28
|
+
meta.owner = $userStore.username;
|
|
29
|
+
meta.name = '';
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
meta = pathToMeta(path);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
$: validateName(meta);
|
|
36
|
+
async function loadGroups() {
|
|
37
|
+
groups = await GroupService.listGroups({ workspace: $workspaceStore });
|
|
38
|
+
}
|
|
39
|
+
function validateName(meta) {
|
|
40
|
+
if (meta.name == undefined || meta.name == '') {
|
|
41
|
+
error = 'choose a name';
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const regex = new RegExp(/^[\w-]+(\/[\w-]+)*$/);
|
|
45
|
+
if (regex.test(meta.name)) {
|
|
46
|
+
error = '';
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
error = 'This name is not valid. ';
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
$: {
|
|
53
|
+
if ($workspaceStore) {
|
|
54
|
+
loadGroups();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
$: {
|
|
58
|
+
if (initialPath == undefined || initialPath == '') {
|
|
59
|
+
reset();
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
meta = pathToMeta(initialPath);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
</script>
|
|
66
|
+
|
|
67
|
+
<div>
|
|
68
|
+
<div class="flex flex-col sm:grid sm:grid-cols-4 sm:gap-4 pb-0 mb-1">
|
|
69
|
+
<label class="block">
|
|
70
|
+
<span class="text-gray-700 text-sm">
|
|
71
|
+
Owner Kind<Tooltip class="mx-1">
|
|
72
|
+
<slot name="ownerToolkit" />
|
|
73
|
+
</Tooltip>
|
|
74
|
+
</span>
|
|
75
|
+
|
|
76
|
+
<select
|
|
77
|
+
bind:value={meta.ownerKind}
|
|
78
|
+
on:change={() => {
|
|
79
|
+
if (meta.ownerKind === 'group') {
|
|
80
|
+
meta.owner = 'all'
|
|
81
|
+
} else {
|
|
82
|
+
meta.owner = $userStore?.username ?? ''
|
|
83
|
+
}
|
|
84
|
+
}}
|
|
85
|
+
>
|
|
86
|
+
<option>user</option>
|
|
87
|
+
<option>group</option>
|
|
88
|
+
</select>
|
|
89
|
+
</label>
|
|
90
|
+
{#if meta.ownerKind === 'user'}
|
|
91
|
+
<label class="block">
|
|
92
|
+
<span class="text-sm text-gray-700">Owner</span>
|
|
93
|
+
<input
|
|
94
|
+
bind:value={meta.owner}
|
|
95
|
+
placeholder={$userStore?.username ?? ''}
|
|
96
|
+
disabled={!($userStore?.is_admin ?? false)}
|
|
97
|
+
/>
|
|
98
|
+
</label>
|
|
99
|
+
{:else}
|
|
100
|
+
<label class="block">
|
|
101
|
+
<span class="text-sm text-gray-700">Owner</span>
|
|
102
|
+
<select bind:value={meta.owner}>
|
|
103
|
+
{#each groups as g}
|
|
104
|
+
<option>{g.name}</option>
|
|
105
|
+
{/each}
|
|
106
|
+
</select>
|
|
107
|
+
</label>
|
|
108
|
+
{/if}
|
|
109
|
+
<label class="block col-span-2">
|
|
110
|
+
<span class="text-gray-700 text-sm">Name<span class="text-red-600 text-sm">*</span></span>
|
|
111
|
+
<input
|
|
112
|
+
bind:value={meta.name}
|
|
113
|
+
placeholder={namePlaceholder}
|
|
114
|
+
class={error === ''
|
|
115
|
+
? ''
|
|
116
|
+
: 'border border-red-700 bg-red-100 border-opacity-30 focus:border-red-700 focus:border-opacity-30 focus-visible:ring-red-700 focus-visible:ring-opacity-25 focus-visible:border-red-700'}
|
|
117
|
+
/>
|
|
118
|
+
</label>
|
|
119
|
+
</div>
|
|
120
|
+
<div class="pt-0 text-xs px-1 flex flex-col-reverse sm:grid sm:grid-cols-4 sm:gap-4 w-full">
|
|
121
|
+
<div class="col-span-2">Path: <span class="font-mono">{path}</span></div>
|
|
122
|
+
<div class="text-purple-500 text-2xs col-span-2">{error}</div>
|
|
123
|
+
</div>
|
|
124
|
+
</div>
|
|
125
|
+
|
|
126
|
+
<style>
|
|
127
|
+
input:disabled {
|
|
128
|
+
background: rgba(200, 200, 200, 0.267);
|
|
129
|
+
}</style>
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
<script>export let label = '';
|
|
2
|
+
export let options;
|
|
3
|
+
export let value;
|
|
4
|
+
export let small = false;
|
|
5
|
+
import { createEventDispatcher } from 'svelte';
|
|
6
|
+
const dispatch = createEventDispatcher();
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<fieldset>
|
|
10
|
+
<legend class="sr-only">{label}</legend>
|
|
11
|
+
<div class="flex flex-row gap-2">
|
|
12
|
+
{#each options as [label, val]}
|
|
13
|
+
<label class:selected={val == value} class={small ? 'py-0' : 'py-3'}>
|
|
14
|
+
<input
|
|
15
|
+
type="radio"
|
|
16
|
+
value={val}
|
|
17
|
+
class="sr-only"
|
|
18
|
+
bind:group={value}
|
|
19
|
+
aria-labelledby="memory-option-0-label"
|
|
20
|
+
on:click={() => dispatch('change', val)}
|
|
21
|
+
/>
|
|
22
|
+
<p>{label}</p>
|
|
23
|
+
</label>
|
|
24
|
+
{/each}
|
|
25
|
+
</div>
|
|
26
|
+
</fieldset>
|
|
27
|
+
|
|
28
|
+
<style>
|
|
29
|
+
label {
|
|
30
|
+
|
|
31
|
+
display: flex;
|
|
32
|
+
|
|
33
|
+
cursor: pointer;
|
|
34
|
+
|
|
35
|
+
align-items: center;
|
|
36
|
+
|
|
37
|
+
justify-content: center;
|
|
38
|
+
|
|
39
|
+
border-radius: 0.375rem;
|
|
40
|
+
|
|
41
|
+
border-width: 1px;
|
|
42
|
+
|
|
43
|
+
padding-left: 0.75rem;
|
|
44
|
+
|
|
45
|
+
padding-right: 0.75rem;
|
|
46
|
+
|
|
47
|
+
font-size: 0.875rem;
|
|
48
|
+
|
|
49
|
+
line-height: 1.25rem;
|
|
50
|
+
|
|
51
|
+
font-weight: 500;
|
|
52
|
+
|
|
53
|
+
text-transform: uppercase
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
label:focus {
|
|
57
|
+
|
|
58
|
+
outline: 2px solid transparent;
|
|
59
|
+
|
|
60
|
+
outline-offset: 2px
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
@media (min-width: 640px) {
|
|
64
|
+
|
|
65
|
+
label {
|
|
66
|
+
|
|
67
|
+
flex: 1 1 0%
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
label.selected {
|
|
72
|
+
|
|
73
|
+
display: flex;
|
|
74
|
+
|
|
75
|
+
cursor: pointer;
|
|
76
|
+
|
|
77
|
+
align-items: center;
|
|
78
|
+
|
|
79
|
+
justify-content: center;
|
|
80
|
+
|
|
81
|
+
border-radius: 0.375rem;
|
|
82
|
+
|
|
83
|
+
border-width: 1px;
|
|
84
|
+
|
|
85
|
+
background-color: rgb(59 130 246 / 0.9);
|
|
86
|
+
|
|
87
|
+
padding-left: 0.75rem;
|
|
88
|
+
|
|
89
|
+
padding-right: 0.75rem;
|
|
90
|
+
|
|
91
|
+
font-size: 0.875rem;
|
|
92
|
+
|
|
93
|
+
line-height: 1.25rem;
|
|
94
|
+
|
|
95
|
+
font-weight: 500;
|
|
96
|
+
|
|
97
|
+
text-transform: uppercase;
|
|
98
|
+
|
|
99
|
+
--tw-text-opacity: 1;
|
|
100
|
+
|
|
101
|
+
color: rgb(255 255 255 / var(--tw-text-opacity))
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
label.selected:focus {
|
|
105
|
+
|
|
106
|
+
outline: 2px solid transparent;
|
|
107
|
+
|
|
108
|
+
outline-offset: 2px
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
@media (min-width: 640px) {
|
|
112
|
+
|
|
113
|
+
label.selected {
|
|
114
|
+
|
|
115
|
+
flex: 1 1 0%
|
|
116
|
+
}
|
|
117
|
+
}</style>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<script>export let required;
|
|
2
|
+
export let detail = '';
|
|
3
|
+
</script>
|
|
4
|
+
|
|
5
|
+
{#if required}
|
|
6
|
+
<span class="text-red-600 font-normal">*</span>
|
|
7
|
+
{:else}
|
|
8
|
+
<span class="text-sm text-gray-500 ml-2 font-normal"
|
|
9
|
+
>(optional{detail != '' ? `, ${detail}` : ''})</span
|
|
10
|
+
>
|
|
11
|
+
{/if}
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
<script>import { ResourceService, VariableService } from '../../gen';
|
|
2
|
+
import { allTrue, emptySchema, sendUserToast } from '../../utils';
|
|
3
|
+
import { createEventDispatcher } from 'svelte';
|
|
4
|
+
import Modal from './Modal.svelte';
|
|
5
|
+
import Path from './Path.svelte';
|
|
6
|
+
import ArgInput from './ArgInput.svelte';
|
|
7
|
+
import AutosizedTextarea from './AutosizedTextarea.svelte';
|
|
8
|
+
import ItemPicker from './ItemPicker.svelte';
|
|
9
|
+
import VariableEditor from './VariableEditor.svelte';
|
|
10
|
+
import Required from './Required.svelte';
|
|
11
|
+
import { workspaceStore } from '../../stores';
|
|
12
|
+
import ResourceTypePicker from './ResourceTypePicker.svelte';
|
|
13
|
+
let path = '';
|
|
14
|
+
let initialPath = '';
|
|
15
|
+
let step = 1;
|
|
16
|
+
let resourceToEdit;
|
|
17
|
+
let description = '';
|
|
18
|
+
let DESCRIPTION_PLACEHOLDER = `You can use markdown to style your description.
|
|
19
|
+
A good way to make resources user friendly is to link to a default script for your resource [example](scripts/add?template=f2d1dc8df796d9e8)`;
|
|
20
|
+
let selectedResourceType;
|
|
21
|
+
let resourceType;
|
|
22
|
+
let resourceSchema;
|
|
23
|
+
let args = {};
|
|
24
|
+
let error;
|
|
25
|
+
let pickForField;
|
|
26
|
+
let itemPicker;
|
|
27
|
+
let variableEditor;
|
|
28
|
+
let modal;
|
|
29
|
+
const dispatch = createEventDispatcher();
|
|
30
|
+
export async function initNew() {
|
|
31
|
+
selectedResourceType = undefined;
|
|
32
|
+
step = 1;
|
|
33
|
+
args = {};
|
|
34
|
+
path = '';
|
|
35
|
+
description = '';
|
|
36
|
+
initialPath = '';
|
|
37
|
+
resourceSchema = emptySchema();
|
|
38
|
+
resourceToEdit = undefined;
|
|
39
|
+
modal.openModal();
|
|
40
|
+
}
|
|
41
|
+
export async function initEdit(p) {
|
|
42
|
+
initialPath = p;
|
|
43
|
+
path = p;
|
|
44
|
+
step = 2;
|
|
45
|
+
resourceToEdit = await ResourceService.getResource({ workspace: $workspaceStore, path: p });
|
|
46
|
+
description = resourceToEdit.description ?? '';
|
|
47
|
+
selectedResourceType = resourceToEdit.resource_type;
|
|
48
|
+
await loadResourceType();
|
|
49
|
+
args = resourceToEdit.value;
|
|
50
|
+
modal.openModal();
|
|
51
|
+
}
|
|
52
|
+
async function createResource() {
|
|
53
|
+
try {
|
|
54
|
+
await ResourceService.createResource({
|
|
55
|
+
workspace: $workspaceStore,
|
|
56
|
+
requestBody: { path, value: args, description, resource_type: resourceType.name }
|
|
57
|
+
});
|
|
58
|
+
sendUserToast(`Successfully created resource at ${path}`);
|
|
59
|
+
dispatch('refresh');
|
|
60
|
+
modal.closeModal();
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
sendUserToast(`${err}`, true);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
async function editResource() {
|
|
67
|
+
try {
|
|
68
|
+
if (resourceToEdit) {
|
|
69
|
+
await ResourceService.updateResource({
|
|
70
|
+
workspace: $workspaceStore,
|
|
71
|
+
path: resourceToEdit.path,
|
|
72
|
+
requestBody: { path, value: args, description }
|
|
73
|
+
});
|
|
74
|
+
sendUserToast(`Successfully updated resource at ${path}`);
|
|
75
|
+
dispatch('refresh');
|
|
76
|
+
modal.closeModal();
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
throw Error('Cannot edit undefined resourceToEdit');
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
sendUserToast(`${err}`, true);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async function loadResourceType() {
|
|
87
|
+
if (selectedResourceType) {
|
|
88
|
+
resourceType = await ResourceService.getResourceType({
|
|
89
|
+
workspace: $workspaceStore,
|
|
90
|
+
path: selectedResourceType
|
|
91
|
+
});
|
|
92
|
+
if (resourceType.schema) {
|
|
93
|
+
resourceSchema = resourceType.schema;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
sendUserToast(`ResourceType cannot be undefined.`, true);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
let inputCheck = {};
|
|
101
|
+
$: isValid = allTrue(inputCheck) ?? false;
|
|
102
|
+
</script>
|
|
103
|
+
|
|
104
|
+
<Modal
|
|
105
|
+
bind:this={modal}
|
|
106
|
+
on:close={() => {
|
|
107
|
+
dispatch('close')
|
|
108
|
+
}}
|
|
109
|
+
>
|
|
110
|
+
<div slot="title">{resourceToEdit ? 'Edit ' + resourceToEdit.path : 'Add a resource'}</div>
|
|
111
|
+
<div slot="content">
|
|
112
|
+
<!-- content -->
|
|
113
|
+
{#if step === 1}
|
|
114
|
+
<div class="flex flex-col gap-3 px-6 py-3 bg-gray-50 text-gray-700">
|
|
115
|
+
<div>
|
|
116
|
+
<span class="text-purple-500 text-2xs grow">{error ?? ''}</span>
|
|
117
|
+
<span class="mb-1 font-semibold text-gray-700">Path</span>
|
|
118
|
+
<Path bind:path {initialPath} namePlaceholder="my/resource">
|
|
119
|
+
<div slot="ownerToolkit" class="text-gray-700 text-2xs">
|
|
120
|
+
Resource permissions depend on their path. Select the group <span class="font-mono"
|
|
121
|
+
>all</span
|
|
122
|
+
>
|
|
123
|
+
to share it, and <span class="font-mono">user</span> to keep it private.
|
|
124
|
+
<a href="https://docs.windmill.dev/docs/reference/namespaces">docs</a>
|
|
125
|
+
</div>
|
|
126
|
+
</Path>
|
|
127
|
+
</div>
|
|
128
|
+
<span class=" mt-3 font-semibold text-gray-700 "
|
|
129
|
+
>Description <Required required={false} />
|
|
130
|
+
</span>
|
|
131
|
+
<AutosizedTextarea
|
|
132
|
+
bind:value={description}
|
|
133
|
+
placeholder={DESCRIPTION_PLACEHOLDER}
|
|
134
|
+
minRows={3}
|
|
135
|
+
/>
|
|
136
|
+
<div>
|
|
137
|
+
<div class="mb-1 font-semibold text-gray-700">
|
|
138
|
+
Resource type<Required required={true} />
|
|
139
|
+
</div>
|
|
140
|
+
<ResourceTypePicker
|
|
141
|
+
bind:value={selectedResourceType}
|
|
142
|
+
notPickable={resourceToEdit != undefined}
|
|
143
|
+
on:click={() => {
|
|
144
|
+
args = {}
|
|
145
|
+
}}
|
|
146
|
+
/>
|
|
147
|
+
</div>
|
|
148
|
+
</div>
|
|
149
|
+
{:else}
|
|
150
|
+
<div class="text-sm">
|
|
151
|
+
{#if resourceSchema && resourceSchema?.properties}
|
|
152
|
+
{#each Object.keys(resourceSchema.properties) as fieldName}
|
|
153
|
+
<div class="flex flex-row w-full items-end justify-between">
|
|
154
|
+
<ArgInput
|
|
155
|
+
label={fieldName}
|
|
156
|
+
description={resourceSchema.properties[fieldName]?.description}
|
|
157
|
+
bind:value={args[fieldName]}
|
|
158
|
+
type={resourceSchema.properties[fieldName]?.type}
|
|
159
|
+
required={resourceSchema.required.includes(fieldName)}
|
|
160
|
+
pattern={resourceSchema.properties[fieldName]?.pattern}
|
|
161
|
+
bind:valid={inputCheck[fieldName]}
|
|
162
|
+
defaultValue={resourceSchema.properties[fieldName]?.default}
|
|
163
|
+
enum_={resourceSchema.properties[fieldName]?.enum}
|
|
164
|
+
contentEncoding={resourceSchema.properties[fieldName]?.contentEncoding}
|
|
165
|
+
itemsType={resourceSchema.properties[fieldName]?.items}
|
|
166
|
+
format={resourceSchema.properties[fieldName]?.format}
|
|
167
|
+
/>
|
|
168
|
+
<div class="pb-3 ml-2 relative">
|
|
169
|
+
<button
|
|
170
|
+
class="default-button-secondary min-w-min items-center leading-4 py-0"
|
|
171
|
+
on:click={() => {
|
|
172
|
+
pickForField = fieldName
|
|
173
|
+
itemPicker.openModal()
|
|
174
|
+
}}>insert variable</button
|
|
175
|
+
>
|
|
176
|
+
</div>
|
|
177
|
+
</div>
|
|
178
|
+
{/each}
|
|
179
|
+
{:else}
|
|
180
|
+
<div>Invalid schema</div>
|
|
181
|
+
{/if}
|
|
182
|
+
</div>
|
|
183
|
+
{/if}
|
|
184
|
+
</div>
|
|
185
|
+
<span slot="submission">
|
|
186
|
+
{#if step === 1}
|
|
187
|
+
{#if selectedResourceType && path != undefined && path != '' && path.split('/')[2] != ''}
|
|
188
|
+
<button
|
|
189
|
+
class="default-button px-4 py-2 font-semibold"
|
|
190
|
+
on:click={async () => {
|
|
191
|
+
await loadResourceType()
|
|
192
|
+
step = 2
|
|
193
|
+
}}
|
|
194
|
+
>
|
|
195
|
+
Next
|
|
196
|
+
</button>
|
|
197
|
+
{:else}
|
|
198
|
+
<button class="default-button-disabled px-4 py-2 font-semibold">Next</button>
|
|
199
|
+
{/if}
|
|
200
|
+
{:else}
|
|
201
|
+
<button
|
|
202
|
+
class="default-button-secondary px-4 py-2 font-semibold"
|
|
203
|
+
on:click={() => {
|
|
204
|
+
step = 1
|
|
205
|
+
}}
|
|
206
|
+
>
|
|
207
|
+
Back
|
|
208
|
+
</button>
|
|
209
|
+
<button
|
|
210
|
+
disabled={!isValid}
|
|
211
|
+
class="default-button px-4 py-2 font-semibold"
|
|
212
|
+
on:click={() => {
|
|
213
|
+
if (resourceToEdit) {
|
|
214
|
+
editResource()
|
|
215
|
+
} else {
|
|
216
|
+
createResource()
|
|
217
|
+
}
|
|
218
|
+
}}
|
|
219
|
+
>
|
|
220
|
+
Save
|
|
221
|
+
</button>
|
|
222
|
+
{/if}
|
|
223
|
+
</span>
|
|
224
|
+
</Modal>
|
|
225
|
+
|
|
226
|
+
<ItemPicker
|
|
227
|
+
bind:this={itemPicker}
|
|
228
|
+
pickCallback={(path, _) => {
|
|
229
|
+
if (pickForField) {
|
|
230
|
+
args[pickForField] = '$var:' + path
|
|
231
|
+
}
|
|
232
|
+
}}
|
|
233
|
+
itemName="Variable"
|
|
234
|
+
extraField="name"
|
|
235
|
+
loadItems={async () =>
|
|
236
|
+
(await VariableService.listVariable({ workspace: $workspaceStore ?? '' })).map((x) => ({
|
|
237
|
+
name: x.path,
|
|
238
|
+
...x
|
|
239
|
+
}))}
|
|
240
|
+
>
|
|
241
|
+
<div
|
|
242
|
+
slot="submission"
|
|
243
|
+
class="flex flex-row-reverse w-full p-5 bg-white border-t border-gray-200 rounded-bl-lg rounded-br-lg"
|
|
244
|
+
>
|
|
245
|
+
<button
|
|
246
|
+
class="default-button-secondary"
|
|
247
|
+
type="button"
|
|
248
|
+
on:click={() => {
|
|
249
|
+
variableEditor.initNew()
|
|
250
|
+
}}
|
|
251
|
+
>
|
|
252
|
+
Create a new variable
|
|
253
|
+
</button>
|
|
254
|
+
<div class="text-xs mr-2 align-middle">
|
|
255
|
+
The variable you were looking for does not exist yet?
|
|
256
|
+
</div>
|
|
257
|
+
</div>
|
|
258
|
+
</ItemPicker>
|
|
259
|
+
|
|
260
|
+
<VariableEditor bind:this={variableEditor} on:create={itemPicker.openModal} />
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<script>import { ResourceService } from '../../gen';
|
|
2
|
+
import { workspaceStore } from '../../stores';
|
|
3
|
+
let resources = [];
|
|
4
|
+
export let value;
|
|
5
|
+
export let resourceType;
|
|
6
|
+
async function loadResources(resourceType) {
|
|
7
|
+
resources = await ResourceService.listResource({ workspace: $workspaceStore, resourceType });
|
|
8
|
+
}
|
|
9
|
+
$: {
|
|
10
|
+
if ($workspaceStore) {
|
|
11
|
+
loadResources(resourceType);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<select class="mt-1" bind:value placeholder="Pick a resource {resourceType}">
|
|
17
|
+
<option value={undefined} />
|
|
18
|
+
{#each resources as r}
|
|
19
|
+
<option value={r.path}>{r.path}{r.description ? ' | ' + r.description : ''}</option>
|
|
20
|
+
{/each}
|
|
21
|
+
</select>
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
<script>import { createEventDispatcher } from 'svelte';
|
|
2
|
+
import { ResourceService } from '../../gen';
|
|
3
|
+
import { workspaceStore } from '../../stores';
|
|
4
|
+
import IconedResourceType from './IconedResourceType.svelte';
|
|
5
|
+
let resources = [];
|
|
6
|
+
export let value;
|
|
7
|
+
export let notPickable = false;
|
|
8
|
+
async function loadResources() {
|
|
9
|
+
resources = await ResourceService.listResourceTypeNames({ workspace: $workspaceStore });
|
|
10
|
+
}
|
|
11
|
+
const dispatch = createEventDispatcher();
|
|
12
|
+
$: {
|
|
13
|
+
if ($workspaceStore) {
|
|
14
|
+
loadResources();
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<div class="grid sm:grid-cols-2 md:grid-cols-3 gap-x-2 gap-y-1 items-center mb-2">
|
|
20
|
+
{#each resources as r}
|
|
21
|
+
<button
|
|
22
|
+
class="px-4 h-8 {r == value
|
|
23
|
+
? 'item-button-selected'
|
|
24
|
+
: notPickable
|
|
25
|
+
? 'item-button-disabled'
|
|
26
|
+
: 'item-button'}"
|
|
27
|
+
on:click={() => {
|
|
28
|
+
value = r
|
|
29
|
+
dispatch('click')
|
|
30
|
+
}}
|
|
31
|
+
>
|
|
32
|
+
<IconedResourceType name={r} after={true} />
|
|
33
|
+
</button>
|
|
34
|
+
{/each}
|
|
35
|
+
</div>
|
|
36
|
+
|
|
37
|
+
<style>
|
|
38
|
+
.item-button {
|
|
39
|
+
padding-top: 0.25rem;
|
|
40
|
+
padding-bottom: 0.25rem;
|
|
41
|
+
border-width: 1px;
|
|
42
|
+
border-radius: 0.125rem
|
|
43
|
+
}
|
|
44
|
+
.item-button-selected {
|
|
45
|
+
padding-top: 0.25rem;
|
|
46
|
+
padding-bottom: 0.25rem;
|
|
47
|
+
border-width: 1px;
|
|
48
|
+
--tw-border-opacity: 1;
|
|
49
|
+
border-color: rgb(59 130 246 / var(--tw-border-opacity));
|
|
50
|
+
--tw-bg-opacity: 1;
|
|
51
|
+
background-color: rgb(239 246 255 / var(--tw-bg-opacity));
|
|
52
|
+
border-radius: 0.125rem
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.item-button-disabled {
|
|
56
|
+
padding-top: 0.25rem;
|
|
57
|
+
padding-bottom: 0.25rem;
|
|
58
|
+
border-width: 1px;
|
|
59
|
+
--tw-bg-opacity: 1;
|
|
60
|
+
background-color: rgb(243 244 246 / var(--tw-bg-opacity));
|
|
61
|
+
--tw-text-opacity: 1;
|
|
62
|
+
color: rgb(209 213 219 / var(--tw-text-opacity));
|
|
63
|
+
border-radius: 0.125rem
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.selected:hover {
|
|
67
|
+
border-radius: 0.375rem;
|
|
68
|
+
border-width: 1px;
|
|
69
|
+
border-color: rgb(156 163 175 / var(--tw-border-opacity));
|
|
70
|
+
--tw-border-opacity: 0.5
|
|
71
|
+
}</style>
|