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,95 @@
|
|
|
1
|
+
<script>import { faPlus } from '@fortawesome/free-solid-svg-icons';
|
|
2
|
+
import { emptySchema, loadSchema } from '../../utils';
|
|
3
|
+
import Icon from 'svelte-awesome';
|
|
4
|
+
import { FlowModuleValue, ScriptService } from '../../gen';
|
|
5
|
+
import SchemaEditor from './SchemaEditor.svelte';
|
|
6
|
+
import { workspaceStore } from '../../stores';
|
|
7
|
+
import ModuleStep from './ModuleStep.svelte';
|
|
8
|
+
import FlowPreview from './FlowPreview.svelte';
|
|
9
|
+
export let flow;
|
|
10
|
+
let args = {};
|
|
11
|
+
let schemas = [];
|
|
12
|
+
let schemaForms = [];
|
|
13
|
+
export async function loadSchemas() {
|
|
14
|
+
await Promise.all(flow.value.modules.map(async (x, i) => {
|
|
15
|
+
if (x.value.path) {
|
|
16
|
+
const schema = await loadSchema(x.value.path ?? '');
|
|
17
|
+
if (JSON.stringify(Object.keys(schema?.properties ?? {}).sort()) !=
|
|
18
|
+
JSON.stringify(Object.keys(x.input_transform).sort())) {
|
|
19
|
+
let it = {};
|
|
20
|
+
Object.keys(schema?.properties ?? {}).map((x) => (it[x] = {
|
|
21
|
+
type: 'static',
|
|
22
|
+
value: ''
|
|
23
|
+
}));
|
|
24
|
+
schemaForms[i]?.setArgs(it);
|
|
25
|
+
}
|
|
26
|
+
schemas[i] = schema ?? emptySchema();
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
schemaForms[i]?.setArgs({});
|
|
30
|
+
schemas[i] = emptySchema();
|
|
31
|
+
}
|
|
32
|
+
}));
|
|
33
|
+
schemas = schemas;
|
|
34
|
+
if (flow.value.modules.length == 0) {
|
|
35
|
+
addModule();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function addModule() {
|
|
39
|
+
schemaForms.push(undefined);
|
|
40
|
+
let newModule = {
|
|
41
|
+
value: { type: FlowModuleValue.type.SCRIPT, path: '' },
|
|
42
|
+
input_transform: {}
|
|
43
|
+
};
|
|
44
|
+
flow.value.modules = flow.value.modules.concat(newModule);
|
|
45
|
+
schemas.push(emptySchema());
|
|
46
|
+
}
|
|
47
|
+
$: $workspaceStore && loadSchemas();
|
|
48
|
+
</script>
|
|
49
|
+
|
|
50
|
+
<!-- <PageHeader title="Flow" /> -->
|
|
51
|
+
<div class="flow-root bg-gray-50 rounded-xl border border-gray-200">
|
|
52
|
+
<ul class="relative -mt-10">
|
|
53
|
+
<span class="absolute top-0 left-1/2 h-full w-1 bg-gray-400" aria-hidden="true" />
|
|
54
|
+
<div class="relative">
|
|
55
|
+
<li class="flex flex-row flex-shrink max-w-full mx-auto mt-20">
|
|
56
|
+
<div class="bg-white border border-gray xl-rounded shadow-lg w-full mx-4 xl:mx-20">
|
|
57
|
+
<div
|
|
58
|
+
class="flex items-center justify-between flex-wra px-4 py-5 border-b border-gray-200 sm:px-6"
|
|
59
|
+
>
|
|
60
|
+
<h3 class="text-lg leading-6 font-medium text-gray-900">Flow Input</h3>
|
|
61
|
+
<button
|
|
62
|
+
class="text-xs default-button-secondary max-h-6 place-self-end"
|
|
63
|
+
disabled={flow.value.modules.length == 0 ||
|
|
64
|
+
flow.value.modules[0].value.path == undefined}
|
|
65
|
+
on:click={async () => {
|
|
66
|
+
flow.schema = await loadSchema(flow.value.modules[0].value.path ?? '')
|
|
67
|
+
}}
|
|
68
|
+
>Copy from step 1's schema
|
|
69
|
+
</button>
|
|
70
|
+
</div>
|
|
71
|
+
<div class="p-4">
|
|
72
|
+
<SchemaEditor bind:schema={flow.schema} />
|
|
73
|
+
<div class="my-4" />
|
|
74
|
+
<FlowPreview {flow} i={flow.value.modules.length - 1} bind:args />
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
</li>
|
|
78
|
+
{#each flow.value.modules as mod, i}
|
|
79
|
+
<ModuleStep bind:flow bind:mod bind:schemas bind:schemaForms bind:args {i} />
|
|
80
|
+
{/each}
|
|
81
|
+
<li class="relative m-20 ">
|
|
82
|
+
<div class="absolute inset-0 flex items-center" aria-hidden="true">
|
|
83
|
+
<div class="w-full border-t border-gray-300" />
|
|
84
|
+
</div>
|
|
85
|
+
<div class="relative flex justify-center">
|
|
86
|
+
<button
|
|
87
|
+
class="default-button h-10 w-10 shadow-blue-600/40 border-blue-600 shadow"
|
|
88
|
+
on:click={addModule}><Icon class="text-white mb-1" data={faPlus} scale={0.9} /></button
|
|
89
|
+
>
|
|
90
|
+
</div>
|
|
91
|
+
</li>
|
|
92
|
+
</div>
|
|
93
|
+
</ul>
|
|
94
|
+
</div>
|
|
95
|
+
<div class="py-10 bg-white" />
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
<script>import { faChevronDown, faChevronUp } from '@fortawesome/free-solid-svg-icons';
|
|
2
|
+
import { sendUserToast, truncateRev } from '../../utils';
|
|
3
|
+
import Icon from 'svelte-awesome';
|
|
4
|
+
import { Job, JobService, InputTransform } from '../../gen';
|
|
5
|
+
import { workspaceStore } from '../../stores';
|
|
6
|
+
import RunForm from './RunForm.svelte';
|
|
7
|
+
import FlowStatusViewer from './FlowStatusViewer.svelte';
|
|
8
|
+
import { onDestroy } from 'svelte';
|
|
9
|
+
import ChevronButton from './ChevronButton.svelte';
|
|
10
|
+
import DisplayResult from './DisplayResult.svelte';
|
|
11
|
+
import Tabs from './Tabs.svelte';
|
|
12
|
+
export let i;
|
|
13
|
+
export let flow;
|
|
14
|
+
export let schemas = [];
|
|
15
|
+
export let args = {};
|
|
16
|
+
let stepArgs = {};
|
|
17
|
+
let tab = 'upto';
|
|
18
|
+
let viewPreview = false;
|
|
19
|
+
let intervalId;
|
|
20
|
+
let uptoText = i == flow.value.modules.length - 1 ? 'Preview whole flow' : 'Preview up to this step';
|
|
21
|
+
let job;
|
|
22
|
+
let jobs = [];
|
|
23
|
+
let jobId;
|
|
24
|
+
async function runPreview(args) {
|
|
25
|
+
intervalId && clearInterval(intervalId);
|
|
26
|
+
const newFlow = tab == 'upto' ? truncateFlow(flow) : extractStep(flow);
|
|
27
|
+
jobId = await JobService.runFlowPreview({
|
|
28
|
+
workspace: $workspaceStore ?? '',
|
|
29
|
+
requestBody: {
|
|
30
|
+
args,
|
|
31
|
+
value: newFlow.value,
|
|
32
|
+
path: newFlow.path
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
jobs = [];
|
|
36
|
+
intervalId = setInterval(loadJob, 1000);
|
|
37
|
+
sendUserToast(`started preview ${truncateRev(jobId, 10)}`);
|
|
38
|
+
}
|
|
39
|
+
function truncateFlow(flow) {
|
|
40
|
+
const localFlow = JSON.parse(JSON.stringify(flow));
|
|
41
|
+
localFlow.value.modules = flow.value.modules.slice(0, i + 1);
|
|
42
|
+
return localFlow;
|
|
43
|
+
}
|
|
44
|
+
function extractStep(flow) {
|
|
45
|
+
const localFlow = JSON.parse(JSON.stringify(flow));
|
|
46
|
+
localFlow.value.modules = flow.value.modules.slice(i, i + 1);
|
|
47
|
+
localFlow.schema = schemas[i];
|
|
48
|
+
stepArgs = {};
|
|
49
|
+
Object.entries(flow.value.modules[i].input_transform).forEach((x) => {
|
|
50
|
+
if (x[1].type == InputTransform.type.STATIC) {
|
|
51
|
+
stepArgs[x[0]] = x[1].value;
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
return localFlow;
|
|
55
|
+
}
|
|
56
|
+
async function loadJob() {
|
|
57
|
+
try {
|
|
58
|
+
job = await JobService.getJob({ workspace: $workspaceStore, id: jobId });
|
|
59
|
+
if (job?.type == 'CompletedJob') {
|
|
60
|
+
//only CompletedJob has success property
|
|
61
|
+
clearInterval(intervalId);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
sendUserToast(err, true);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
onDestroy(() => {
|
|
69
|
+
intervalId && clearInterval(intervalId);
|
|
70
|
+
});
|
|
71
|
+
</script>
|
|
72
|
+
|
|
73
|
+
<h2 class="mb-5 mt-2">
|
|
74
|
+
<button
|
|
75
|
+
type="submit"
|
|
76
|
+
class="underline text-gray-700 inline-flex items-center"
|
|
77
|
+
on:click={() => {
|
|
78
|
+
viewPreview = !viewPreview
|
|
79
|
+
}}
|
|
80
|
+
>
|
|
81
|
+
<div>
|
|
82
|
+
Preview mode<Icon class="ml-1" data={viewPreview ? faChevronUp : faChevronDown} scale={1} />
|
|
83
|
+
</div>
|
|
84
|
+
</button>
|
|
85
|
+
</h2>
|
|
86
|
+
|
|
87
|
+
{#if viewPreview}
|
|
88
|
+
{#if i != flow.value.modules.length - 1}
|
|
89
|
+
<Tabs
|
|
90
|
+
tabs={[
|
|
91
|
+
['upto', uptoText],
|
|
92
|
+
['justthis', 'preview just this step']
|
|
93
|
+
]}
|
|
94
|
+
bind:tab
|
|
95
|
+
/>
|
|
96
|
+
{/if}
|
|
97
|
+
<div class="my-2" />
|
|
98
|
+
{#if tab == 'upto'}
|
|
99
|
+
<RunForm
|
|
100
|
+
runnable={truncateFlow(flow)}
|
|
101
|
+
runAction={(_, args) => runPreview(args)}
|
|
102
|
+
schedulable={false}
|
|
103
|
+
buttonText={uptoText}
|
|
104
|
+
detailed={false}
|
|
105
|
+
bind:args
|
|
106
|
+
/>
|
|
107
|
+
{:else}
|
|
108
|
+
<RunForm
|
|
109
|
+
runnable={extractStep(flow)}
|
|
110
|
+
runAction={(_, args) => runPreview(args)}
|
|
111
|
+
schedulable={false}
|
|
112
|
+
buttonText="Preview just this step"
|
|
113
|
+
detailed={false}
|
|
114
|
+
args={stepArgs}
|
|
115
|
+
/>
|
|
116
|
+
{/if}
|
|
117
|
+
|
|
118
|
+
{#if job}
|
|
119
|
+
<div class="w-full flex justify-center">
|
|
120
|
+
<FlowStatusViewer {job} bind:jobs />
|
|
121
|
+
</div>
|
|
122
|
+
{#if `result` in job}
|
|
123
|
+
<div class="flex flex-col ml-10">
|
|
124
|
+
<div>
|
|
125
|
+
<ChevronButton text="result" viewOptions={true}>
|
|
126
|
+
<div class="text-xs">
|
|
127
|
+
<DisplayResult result={job.result} />
|
|
128
|
+
</div>
|
|
129
|
+
</ChevronButton>
|
|
130
|
+
</div>
|
|
131
|
+
<div>
|
|
132
|
+
<ChevronButton text="logs" viewOptions={true}>
|
|
133
|
+
<div class="text-xs p-4 bg-gray-50 overflow-auto max-h-lg">
|
|
134
|
+
<pre class="w-full">{job.logs}</pre>
|
|
135
|
+
</div>
|
|
136
|
+
</ChevronButton>
|
|
137
|
+
</div>
|
|
138
|
+
</div>
|
|
139
|
+
{/if}
|
|
140
|
+
{/if}
|
|
141
|
+
{/if}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
<script>import { faHourglassHalf, faSpinner, faTimes } from '@fortawesome/free-solid-svg-icons';
|
|
2
|
+
import { truncateRev } from '../../utils';
|
|
3
|
+
import Icon from 'svelte-awesome';
|
|
4
|
+
import { check } from 'svelte-awesome/icons';
|
|
5
|
+
import { CompletedJob, FlowModuleValue, FlowStatusModule, JobService, QueuedJob } from '../../gen';
|
|
6
|
+
import { workspaceStore } from '../../stores';
|
|
7
|
+
import DisplayResult from './DisplayResult.svelte';
|
|
8
|
+
import ChevronButton from './ChevronButton.svelte';
|
|
9
|
+
import JobStatus from './JobStatus.svelte';
|
|
10
|
+
export let job;
|
|
11
|
+
export let jobs;
|
|
12
|
+
function loadResults() {
|
|
13
|
+
job?.flow_status?.modules?.forEach(async (x, i) => {
|
|
14
|
+
if ((i >= jobs.length && x.type == FlowStatusModule.type.SUCCESS) ||
|
|
15
|
+
x.type == FlowStatusModule.type.FAILURE) {
|
|
16
|
+
jobs.push(undefined);
|
|
17
|
+
jobs[i] = await JobService.getCompletedJob({ workspace: $workspaceStore, id: x.job });
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
$: $workspaceStore && job && loadResults();
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<div class="flow-root max-w-lg w-full p-4">
|
|
25
|
+
<div class="flex flex-row-reverse">
|
|
26
|
+
{#if job}
|
|
27
|
+
<div class="flex-col">
|
|
28
|
+
<a href="/run/{job?.id}" class="font-medium text-blue-600"
|
|
29
|
+
>{truncateRev(job?.id ?? '', 10)}</a
|
|
30
|
+
>
|
|
31
|
+
<div>
|
|
32
|
+
<JobStatus {job} />
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
{/if}
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
<p class="text-gray-500 mb-6 w-full text-center">
|
|
39
|
+
Step
|
|
40
|
+
<span class="font-medium text-gray-900"
|
|
41
|
+
>{Math.min((job?.flow_status?.step ?? 0) + 1, job?.raw_flow?.modules.length ?? 0)}</span
|
|
42
|
+
>
|
|
43
|
+
out of <span class="font-medium text-gray-900">{job?.raw_flow?.modules.length}</span>
|
|
44
|
+
<span class="mt-4" />
|
|
45
|
+
</p>
|
|
46
|
+
<ul role="list" class="-mb-8 w-full">
|
|
47
|
+
{#each job?.raw_flow?.modules ?? [] as mod, i}
|
|
48
|
+
<li class="w-full">
|
|
49
|
+
<div class="relative pb-8 w-full">
|
|
50
|
+
{#if i < (job?.raw_flow?.modules ?? []).length - 1}
|
|
51
|
+
<span
|
|
52
|
+
class="absolute top-4 left-4 -ml-px h-full w-0.5 bg-gray-200"
|
|
53
|
+
aria-hidden="true"
|
|
54
|
+
/>
|
|
55
|
+
{/if}
|
|
56
|
+
<div class="relative flex space-x-3">
|
|
57
|
+
<div>
|
|
58
|
+
{#if job.flow_status?.modules[i].type == FlowStatusModule.type.SUCCESS}
|
|
59
|
+
<span
|
|
60
|
+
class="h-8 w-8 rounded-full bg-green-600 flex items-center justify-center ring-8 ring-white"
|
|
61
|
+
>
|
|
62
|
+
<Icon
|
|
63
|
+
class="text-white"
|
|
64
|
+
data={check}
|
|
65
|
+
scale={0.8}
|
|
66
|
+
label="Job completed successfully"
|
|
67
|
+
/>
|
|
68
|
+
</span>
|
|
69
|
+
{:else if job.flow_status?.modules[i].type == FlowStatusModule.type.FAILURE}
|
|
70
|
+
<span
|
|
71
|
+
class="h-8 w-8 rounded-full bg-red-600 flex items-center justify-center ring-8 ring-white"
|
|
72
|
+
>
|
|
73
|
+
<Icon class="text-white" data={faTimes} scale={0.8} label="Job failed" />
|
|
74
|
+
</span>
|
|
75
|
+
{:else if job.flow_status?.modules[i].type == FlowStatusModule.type.IN_PROGRESS}
|
|
76
|
+
<span
|
|
77
|
+
class="h-8 w-8 rounded-full bg-yellow-500 flex items-center justify-center ring-8 ring-white"
|
|
78
|
+
>
|
|
79
|
+
<Icon
|
|
80
|
+
class="text-white animate-spin"
|
|
81
|
+
data={faSpinner}
|
|
82
|
+
scale={1}
|
|
83
|
+
label="Job failed"
|
|
84
|
+
/>
|
|
85
|
+
</span>
|
|
86
|
+
{:else}
|
|
87
|
+
<span
|
|
88
|
+
class="h-8 w-8 rounded-full bg-gray-400 flex items-center justify-center ring-8 ring-white"
|
|
89
|
+
>
|
|
90
|
+
<Icon class="text-white" data={faHourglassHalf} scale={1} label="Job failed" />
|
|
91
|
+
</span>
|
|
92
|
+
{/if}
|
|
93
|
+
</div>
|
|
94
|
+
<div class="min-w-0 flex-1 pt-1.5 flex justify-between space-x-4 w-full">
|
|
95
|
+
<div class="w-full">
|
|
96
|
+
<p class="text-sm text-gray-500">
|
|
97
|
+
{#if mod.value.type == FlowModuleValue.type.SCRIPT}
|
|
98
|
+
Script at path <a
|
|
99
|
+
href="/scripts/get/{mod.value.path}"
|
|
100
|
+
class="font-medium text-gray-900">{mod.value.path}</a
|
|
101
|
+
>
|
|
102
|
+
{/if}
|
|
103
|
+
</p>
|
|
104
|
+
</div>
|
|
105
|
+
<div class="text-right text-sm whitespace-nowrap text-gray-500">
|
|
106
|
+
{job.flow_status?.modules[i].type}
|
|
107
|
+
{#if job.flow_status?.modules[i].job}
|
|
108
|
+
<a href="/run/{job.flow_status?.modules[i].job}" class="font-medium text-blue-600"
|
|
109
|
+
>{truncateRev(job.flow_status?.modules[i].job ?? '', 10)}</a
|
|
110
|
+
>
|
|
111
|
+
{/if}
|
|
112
|
+
</div>
|
|
113
|
+
</div>
|
|
114
|
+
</div>
|
|
115
|
+
{#if i < jobs.length && jobs[i] != undefined}
|
|
116
|
+
<div class="flex flex-col ml-10">
|
|
117
|
+
<div>
|
|
118
|
+
<ChevronButton text="result" viewOptions={true}>
|
|
119
|
+
<div class="text-xs">
|
|
120
|
+
<DisplayResult result={jobs[i]?.result} />
|
|
121
|
+
</div>
|
|
122
|
+
</ChevronButton>
|
|
123
|
+
</div>
|
|
124
|
+
<div>
|
|
125
|
+
<ChevronButton text="logs">
|
|
126
|
+
<div class="text-xs p-4 bg-gray-50 overflow-auto max-h-lg">
|
|
127
|
+
<pre class="w-full">{jobs[i]?.logs}</pre>
|
|
128
|
+
</div>
|
|
129
|
+
</ChevronButton>
|
|
130
|
+
</div>
|
|
131
|
+
</div>
|
|
132
|
+
{/if}
|
|
133
|
+
</div>
|
|
134
|
+
</li>
|
|
135
|
+
{/each}
|
|
136
|
+
</ul>
|
|
137
|
+
</div>
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
<script>import { userStore, workspaceStore } from '../../stores';
|
|
2
|
+
import Modal from './Modal.svelte';
|
|
3
|
+
import { GroupService, UserService } from '../../gen';
|
|
4
|
+
import AutoComplete from 'simple-svelte-autocomplete';
|
|
5
|
+
import PageHeader from './PageHeader.svelte';
|
|
6
|
+
import TableCustom from './TableCustom.svelte';
|
|
7
|
+
import { canWrite } from '../../utils';
|
|
8
|
+
let name = '';
|
|
9
|
+
let modal;
|
|
10
|
+
let can_write = false;
|
|
11
|
+
let group;
|
|
12
|
+
let members = [];
|
|
13
|
+
let usernames = [];
|
|
14
|
+
let username = '';
|
|
15
|
+
async function loadUsernames() {
|
|
16
|
+
usernames = await UserService.listUsernames({ workspace: $workspaceStore });
|
|
17
|
+
}
|
|
18
|
+
$: {
|
|
19
|
+
if (group && $workspaceStore && userStore) {
|
|
20
|
+
members = (group.members ?? []).map((x) => {
|
|
21
|
+
return {
|
|
22
|
+
name: x,
|
|
23
|
+
isAdmin: x in (group?.extra_perms ?? {}) && (group?.extra_perms ?? {})[name]
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export function openModal(newName) {
|
|
29
|
+
name = newName;
|
|
30
|
+
loadGroup();
|
|
31
|
+
loadUsernames();
|
|
32
|
+
modal.openModal();
|
|
33
|
+
}
|
|
34
|
+
async function addToGroup() {
|
|
35
|
+
await GroupService.addUserToGroup({
|
|
36
|
+
workspace: $workspaceStore ?? '',
|
|
37
|
+
name,
|
|
38
|
+
requestBody: { username }
|
|
39
|
+
});
|
|
40
|
+
loadGroup();
|
|
41
|
+
}
|
|
42
|
+
async function loadGroup() {
|
|
43
|
+
group = await GroupService.getGroup({ workspace: $workspaceStore, name });
|
|
44
|
+
can_write = canWrite(group.name, group.extra_perms ?? {}, $userStore);
|
|
45
|
+
}
|
|
46
|
+
</script>
|
|
47
|
+
|
|
48
|
+
<Modal bind:this={modal}>
|
|
49
|
+
<div slot="title">group {name}</div>
|
|
50
|
+
<div slot="content">
|
|
51
|
+
<PageHeader title="Summary" />
|
|
52
|
+
<p>{group?.summary ?? 'No summary'}</p>
|
|
53
|
+
<PageHeader title="Members">
|
|
54
|
+
{#if can_write}
|
|
55
|
+
<div>
|
|
56
|
+
<AutoComplete items={usernames} bind:selectedItem={username} />
|
|
57
|
+
<button class="default-button ml-4" on:click={addToGroup}>Add member</button>
|
|
58
|
+
</div>
|
|
59
|
+
{/if}
|
|
60
|
+
</PageHeader>
|
|
61
|
+
<TableCustom>
|
|
62
|
+
<tr slot="header-row">
|
|
63
|
+
<th>user</th>
|
|
64
|
+
<th>admin of group</th>
|
|
65
|
+
<th />
|
|
66
|
+
</tr>
|
|
67
|
+
<tbody slot="body">
|
|
68
|
+
{#each members as { name, isAdmin }}<tr>
|
|
69
|
+
<td>{name}</td>
|
|
70
|
+
<td> {isAdmin ? 'admin' : ''} </td>
|
|
71
|
+
<td>
|
|
72
|
+
{#if can_write}
|
|
73
|
+
<button
|
|
74
|
+
class="ml-2 text-red-500"
|
|
75
|
+
on:click={async () => {
|
|
76
|
+
await GroupService.removeUserToGroup({
|
|
77
|
+
workspace: $workspaceStore ?? '',
|
|
78
|
+
name: group?.name ?? '',
|
|
79
|
+
requestBody: { username: name }
|
|
80
|
+
})
|
|
81
|
+
loadGroup()
|
|
82
|
+
}}>remove</button
|
|
83
|
+
>
|
|
84
|
+
{/if}</td
|
|
85
|
+
>
|
|
86
|
+
</tr>{/each}
|
|
87
|
+
</tbody></TableCustom
|
|
88
|
+
>
|
|
89
|
+
</div>
|
|
90
|
+
</Modal>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<script>import Mysql from './icons/Mysql.svelte';
|
|
2
|
+
import Mail from './icons/Mail.svelte';
|
|
3
|
+
import DbIcon from './icons/DbIcon.svelte';
|
|
4
|
+
import PostgresIcon from './icons/PostgresIcon.svelte';
|
|
5
|
+
import Icon from 'svelte-awesome';
|
|
6
|
+
import { faSlack } from '@fortawesome/free-brands-svg-icons';
|
|
7
|
+
import Slack from './icons/Slack.svelte';
|
|
8
|
+
export let name;
|
|
9
|
+
export let after = false;
|
|
10
|
+
export let height = '24px';
|
|
11
|
+
export let width = '24px';
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<div class="flex flex-row gap-2">
|
|
15
|
+
{#if !after}
|
|
16
|
+
{name}
|
|
17
|
+
{/if}
|
|
18
|
+
{#if name === 'postgres'}
|
|
19
|
+
<PostgresIcon {height} {width} />
|
|
20
|
+
{:else if name === 'mysql'}
|
|
21
|
+
<Mysql {height} {width} />
|
|
22
|
+
{:else if name === 'SMTP'}
|
|
23
|
+
<Mail {height} {width} />
|
|
24
|
+
{:else if name === 'mongodb'}
|
|
25
|
+
<DbIcon {height} {width} />
|
|
26
|
+
{:else if name === 'slack'}
|
|
27
|
+
<Slack {height} {width} />
|
|
28
|
+
{/if}
|
|
29
|
+
{#if after}
|
|
30
|
+
{name}
|
|
31
|
+
{/if}
|
|
32
|
+
</div>
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<script>import { sendUserToast } from '../../utils';
|
|
2
|
+
import Switch from './Switch.svelte';
|
|
3
|
+
import { createEventDispatcher } from 'svelte';
|
|
4
|
+
import { UserService } from '../../gen';
|
|
5
|
+
const dispatch = createEventDispatcher();
|
|
6
|
+
let valid = true;
|
|
7
|
+
let modal;
|
|
8
|
+
export function openModal() {
|
|
9
|
+
modal.openModal();
|
|
10
|
+
}
|
|
11
|
+
let email;
|
|
12
|
+
let is_super_admin = false;
|
|
13
|
+
let password;
|
|
14
|
+
let name;
|
|
15
|
+
let company;
|
|
16
|
+
function handleKeyUp(event) {
|
|
17
|
+
const key = event.key || event.keyCode;
|
|
18
|
+
if (key === 13 || key === 'Enter') {
|
|
19
|
+
event.preventDefault();
|
|
20
|
+
addUser();
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
async function addUser() {
|
|
24
|
+
await UserService.createUserGlobally({
|
|
25
|
+
requestBody: {
|
|
26
|
+
email,
|
|
27
|
+
password,
|
|
28
|
+
super_admin: is_super_admin,
|
|
29
|
+
name,
|
|
30
|
+
company
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
sendUserToast(`Successfully added ${email}. Welcome to them!`);
|
|
34
|
+
dispatch('new');
|
|
35
|
+
}
|
|
36
|
+
</script>
|
|
37
|
+
|
|
38
|
+
<div class="flex flex-row">
|
|
39
|
+
<input on:keyup={handleKeyUp} placeholder="email" bind:value={email} />
|
|
40
|
+
|
|
41
|
+
<Switch class="ml-2" bind:checked={is_super_admin} horizontal={true} label={'admin: '} />
|
|
42
|
+
<input on:keyup={handleKeyUp} type="password" placeholder="" bind:value={password} />
|
|
43
|
+
<input on:keyup={handleKeyUp} placeholder="name" bind:value={name} />
|
|
44
|
+
<input on:keyup={handleKeyUp} placeholder="company" bind:value={company} />
|
|
45
|
+
|
|
46
|
+
<button
|
|
47
|
+
class="ml-4 w-40 {valid ? 'default-button' : 'default-button-disabled'}"
|
|
48
|
+
type="button"
|
|
49
|
+
on:click={() => {
|
|
50
|
+
addUser()
|
|
51
|
+
}}
|
|
52
|
+
disabled={email == undefined || password == undefined}
|
|
53
|
+
>
|
|
54
|
+
Add
|
|
55
|
+
</button>
|
|
56
|
+
</div>
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<script>import { sendUserToast } from '../../utils';
|
|
2
|
+
import Switch from './Switch.svelte';
|
|
3
|
+
import { createEventDispatcher } from 'svelte';
|
|
4
|
+
import { workspaceStore } from '../../stores';
|
|
5
|
+
import { WorkspaceService } from '../../gen';
|
|
6
|
+
const dispatch = createEventDispatcher();
|
|
7
|
+
let valid = true;
|
|
8
|
+
let modal;
|
|
9
|
+
export function openModal() {
|
|
10
|
+
modal.openModal();
|
|
11
|
+
}
|
|
12
|
+
let email;
|
|
13
|
+
let is_admin = false;
|
|
14
|
+
function handleKeyUp(event) {
|
|
15
|
+
const key = event.key || event.keyCode;
|
|
16
|
+
if (key === 13 || key === 'Enter') {
|
|
17
|
+
event.preventDefault();
|
|
18
|
+
inviteUser();
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
async function inviteUser() {
|
|
22
|
+
await WorkspaceService.inviteUser({
|
|
23
|
+
workspace: $workspaceStore,
|
|
24
|
+
requestBody: {
|
|
25
|
+
email,
|
|
26
|
+
is_admin
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
sendUserToast(`Successfully invited ${email}. Welcome to them!`);
|
|
30
|
+
dispatch('new');
|
|
31
|
+
}
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<div class="flex flex-row">
|
|
35
|
+
<input on:keyup={handleKeyUp} placeholder="email" bind:value={email} />
|
|
36
|
+
|
|
37
|
+
<Switch class="ml-2" bind:checked={is_admin} horizontal={true} label={'admin: '} />
|
|
38
|
+
<button
|
|
39
|
+
class="ml-4 w-40 {valid ? 'default-button' : 'default-button-disabled'}"
|
|
40
|
+
type="button"
|
|
41
|
+
on:click={() => {
|
|
42
|
+
inviteUser()
|
|
43
|
+
}}
|
|
44
|
+
disabled={email == undefined}
|
|
45
|
+
>
|
|
46
|
+
Invite
|
|
47
|
+
</button>
|
|
48
|
+
</div>
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
<script>import Fuse from 'fuse.js';
|
|
2
|
+
import Modal from './Modal.svelte';
|
|
3
|
+
export let pickCallback;
|
|
4
|
+
export let loadItems;
|
|
5
|
+
export let extraField;
|
|
6
|
+
export let itemName;
|
|
7
|
+
export let closeOnClick = true;
|
|
8
|
+
let items = [];
|
|
9
|
+
let filteredItems = [];
|
|
10
|
+
let itemsFilter = '';
|
|
11
|
+
const fuseOptions = {
|
|
12
|
+
includeScore: false,
|
|
13
|
+
keys: ['path', extraField]
|
|
14
|
+
};
|
|
15
|
+
const fuse = new Fuse(items, fuseOptions);
|
|
16
|
+
export function openModal() {
|
|
17
|
+
loadItems().then((v) => {
|
|
18
|
+
items = v;
|
|
19
|
+
fuse.setCollection(items);
|
|
20
|
+
});
|
|
21
|
+
modal.openModal();
|
|
22
|
+
}
|
|
23
|
+
$: filteredItems =
|
|
24
|
+
itemsFilter.length > 0 ? fuse.search(itemsFilter).map((value) => value.item) : items;
|
|
25
|
+
let modal;
|
|
26
|
+
</script>
|
|
27
|
+
|
|
28
|
+
<Modal bind:this={modal} z="z-30">
|
|
29
|
+
<div slot="title">search a {itemName}</div>
|
|
30
|
+
<div slot="content">
|
|
31
|
+
<div class="w-12/12 pb-4">
|
|
32
|
+
<input placeholder="Search {itemName}" bind:value={itemsFilter} class="search-item" />
|
|
33
|
+
</div>
|
|
34
|
+
<ul class="divide-y divide-gray-200">
|
|
35
|
+
{#each filteredItems as obj}
|
|
36
|
+
<li
|
|
37
|
+
class="py-4 px-1 gap-1 flex flex-col hover:bg-white hover:border text-black cursor-pointer"
|
|
38
|
+
on:click={() => {
|
|
39
|
+
if (closeOnClick) {
|
|
40
|
+
modal.closeModal()
|
|
41
|
+
}
|
|
42
|
+
pickCallback(obj['path'], obj[extraField])
|
|
43
|
+
}}
|
|
44
|
+
>
|
|
45
|
+
<p class="text-sm font-semibold">
|
|
46
|
+
<span class="mr-2">{obj[extraField]}</span><span class="font-normal whitespace-nowrap"
|
|
47
|
+
>{obj['path'] ?? ''}</span
|
|
48
|
+
>
|
|
49
|
+
</p>
|
|
50
|
+
<p class="text-xs italic">{obj['description'] ?? ''}</p>
|
|
51
|
+
</li>
|
|
52
|
+
{/each}
|
|
53
|
+
</ul>
|
|
54
|
+
</div>
|
|
55
|
+
<span slot="submission">
|
|
56
|
+
<slot name="submission" />
|
|
57
|
+
</span>
|
|
58
|
+
</Modal>
|