Pipelines.svelte 6.59 KB
Newer Older
Timothy J. Baek's avatar
Timothy J. Baek committed
1
2
3
<script lang="ts">
	import { v4 as uuidv4 } from 'uuid';

4
5
	import { toast } from 'svelte-sonner';
	import { models } from '$lib/stores';
6
	import { getContext, onMount, tick } from 'svelte';
Timothy J. Baek's avatar
Timothy J. Baek committed
7
8
	import type { Writable } from 'svelte/store';
	import type { i18n as i18nType } from 'i18next';
9
10
11
12
	import {
		getPipelineValves,
		getPipelineValvesSpec,
		updatePipelineValves,
Timothy J. Baek's avatar
Timothy J. Baek committed
13
		getPipelines,
14
15
		getModels,
		getPipelinesList
16
	} from '$lib/apis';
17

Timothy J. Baek's avatar
Timothy J. Baek committed
18
19
	import Spinner from '$lib/components/common/Spinner.svelte';

Timothy J. Baek's avatar
Timothy J. Baek committed
20
21
22
23
	const i18n: Writable<i18nType> = getContext('i18n');

	export let saveHandler: Function;

24
25
26
	let PIPELINES_LIST = null;
	let selectedPipelinesUrlIdx = '';

Timothy J. Baek's avatar
Timothy J. Baek committed
27
	let pipelines = null;
28

Timothy J. Baek's avatar
Timothy J. Baek committed
29
	let valves = null;
30
31
32
33
34
	let valves_spec = null;
	let selectedPipelineIdx = null;

	const updateHandler = async () => {
		const pipeline = pipelines[selectedPipelineIdx];
Timothy J. Baek's avatar
Timothy J. Baek committed
35

36
		if (pipeline && (pipeline?.pipeline?.valves ?? false)) {
37
38
39
40
			if (valves?.pipelines ?? false) {
				valves.pipelines = valves.pipelines.split(',').map((v) => v.trim());
			}

41
42
43
44
45
			const res = await updatePipelineValves(localStorage.token, pipeline.id, valves).catch(
				(error) => {
					toast.error(error);
				}
			);
Timothy J. Baek's avatar
Timothy J. Baek committed
46

47
48
			if (res) {
				toast.success('Valves updated successfully');
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
49
				setPipelines();
Timothy J. Baek's avatar
Timothy J. Baek committed
50
				models.set(await getModels(localStorage.token));
51
52
53
54
55
56
				saveHandler();
			}
		} else {
			toast.error('No valves to update');
		}
	};
Timothy J. Baek's avatar
Timothy J. Baek committed
57

Timothy J. Baek's avatar
Timothy J. Baek committed
58
	const getValves = async (idx) => {
59
60
61
		valves = null;
		valves_spec = null;

Timothy J. Baek's avatar
Timothy J. Baek committed
62
63
		valves_spec = await getPipelineValvesSpec(localStorage.token, pipelines[idx].id);
		valves = await getPipelineValves(localStorage.token, pipelines[idx].id);
64
65
66
67

		if (valves?.pipelines ?? false) {
			valves.pipelines = valves.pipelines.join(',');
		}
Timothy J. Baek's avatar
Timothy J. Baek committed
68
69
	};

Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
70
	const setPipelines = async () => {
71
72
73
74
75
		pipelines = null;
		valves = null;
		valves_spec = null;

		pipelines = await getPipelines(localStorage.token, selectedPipelinesUrlIdx);
76
77
78

		if (pipelines.length > 0) {
			selectedPipelineIdx = 0;
Timothy J. Baek's avatar
Timothy J. Baek committed
79
			await getValves(selectedPipelineIdx);
80
		}
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
81
82
83
	};

	onMount(async () => {
84
85
86
87
88
89
		PIPELINES_LIST = await getPipelinesList(localStorage.token);

		if (PIPELINES_LIST.length > 0) {
			selectedPipelinesUrlIdx = PIPELINES_LIST[0]['idx'];
		}

Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
90
		setPipelines();
Timothy J. Baek's avatar
Timothy J. Baek committed
91
92
93
94
95
96
	});
</script>

<form
	class="flex flex-col h-full justify-between space-y-3 text-sm"
	on:submit|preventDefault={async () => {
97
		updateHandler();
Timothy J. Baek's avatar
Timothy J. Baek committed
98
99
	}}
>
Timothy J. Baek's avatar
Timothy J. Baek committed
100
	<div class=" space-y-2 pr-1.5 overflow-y-scroll max-h-80 h-full">
101
		{#if PIPELINES_LIST !== null}
Timothy J. Baek's avatar
Timothy J. Baek committed
102
103
			<div class="flex w-full justify-between mb-2">
				<div class=" self-center text-sm font-semibold">
104
					{$i18n.t('Manage Pipelines')}
Timothy J. Baek's avatar
Timothy J. Baek committed
105
106
				</div>
			</div>
107
108
109

			{#if PIPELINES_LIST.length > 0}
				<div class="space-y-1">
Timothy J. Baek's avatar
Timothy J. Baek committed
110
					<div class="flex gap-2">
111
						<div class="flex-1">
Timothy J. Baek's avatar
Timothy J. Baek committed
112
113
							<select
								class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
114
115
								bind:value={selectedPipelinesUrlIdx}
								placeholder={$i18n.t('Select a pipeline url')}
116
117
								on:change={async () => {
									await tick();
118
									await setPipelines();
119
								}}
Timothy J. Baek's avatar
Timothy J. Baek committed
120
							>
121
122
123
124
125
126
127
								<option value="" selected disabled class="bg-gray-100 dark:bg-gray-700"
									>{$i18n.t('Select a pipeline url')}</option
								>

								{#each PIPELINES_LIST as pipelines, idx}
									<option value={pipelines.idx} class="bg-gray-100 dark:bg-gray-700"
										>{pipelines.url}</option
128
									>
Timothy J. Baek's avatar
Timothy J. Baek committed
129
130
131
								{/each}
							</select>
						</div>
Timothy J. Baek's avatar
Timothy J. Baek committed
132
					</div>
133
134
				</div>
			{/if}
Timothy J. Baek's avatar
Timothy J. Baek committed
135

136
			<hr class=" dark:border-gray-800 my-3 w-full" />
Timothy J. Baek's avatar
Timothy J. Baek committed
137

138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
			{#if pipelines !== null}
				{#if pipelines.length > 0}
					<div class="flex w-full justify-between mb-2">
						<div class=" self-center text-sm font-semibold">
							{$i18n.t('Pipelines Valves')}
						</div>
					</div>
					<div class="space-y-1">
						{#if pipelines.length > 0}
							<div class="flex gap-2">
								<div class="flex-1 pb-1">
									<select
										class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
										bind:value={selectedPipelineIdx}
										placeholder={$i18n.t('Select a pipeline')}
										on:change={async () => {
											await tick();
											await getValves(selectedPipelineIdx);
										}}
									>
										{#each pipelines as pipeline, idx}
											<option value={idx} class="bg-gray-100 dark:bg-gray-700"
												>{pipeline.name} ({pipeline.pipeline.type ?? 'pipe'})</option
											>
										{/each}
									</select>
								</div>
							</div>
						{/if}
167

168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
						<div class="space-y-1">
							{#if pipelines[selectedPipelineIdx].pipeline.valves}
								{#if valves}
									{#each Object.keys(valves_spec.properties) as property, idx}
										<div class=" py-0.5 w-full justify-between">
											<div class="flex w-full justify-between">
												<div class=" self-center text-xs font-medium">
													{valves_spec.properties[property].title}
												</div>

												<button
													class="p-1 px-3 text-xs flex rounded transition"
													type="button"
													on:click={() => {
														valves[property] = (valves[property] ?? null) === null ? '' : null;
													}}
												>
													{#if (valves[property] ?? null) === null}
														<span class="ml-2 self-center"> {$i18n.t('None')} </span>
													{:else}
														<span class="ml-2 self-center"> {$i18n.t('Custom')} </span>
													{/if}
												</button>
191
											</div>
192
193
194
195
196
197
198
199
200
201
202
203
204
205

											{#if (valves[property] ?? null) !== null}
												<div class="flex mt-0.5 space-x-2">
													<div class=" flex-1">
														<input
															class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
															type="text"
															placeholder={valves_spec.properties[property].title}
															bind:value={valves[property]}
															autocomplete="off"
														/>
													</div>
												</div>
											{/if}
206
										</div>
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
									{/each}
								{:else}
									<Spinner className="size-5" />
								{/if}
							{:else}
								<div>No valves</div>
							{/if}
						</div>
					</div>
				{:else if pipelines.length === 0}
					<div>Pipelines Not Detected</div>
				{/if}
			{:else}
				<div class="flex justify-center">
					<div class="my-auto">
						<Spinner className="size-4" />
					</div>
Timothy J. Baek's avatar
Timothy J. Baek committed
224
				</div>
225
			{/if}
Timothy J. Baek's avatar
Timothy J. Baek committed
226
		{:else}
227
			<div class="flex justify-center h-full">
Timothy J. Baek's avatar
Timothy J. Baek committed
228
229
230
				<div class="my-auto">
					<Spinner className="size-6" />
				</div>
Timothy J. Baek's avatar
Timothy J. Baek committed
231
			</div>
Timothy J. Baek's avatar
Timothy J. Baek committed
232
		{/if}
Timothy J. Baek's avatar
Timothy J. Baek committed
233
	</div>
234

Timothy J. Baek's avatar
Timothy J. Baek committed
235
236
237
238
239
240
241
242
243
	<div class="flex justify-end pt-3 text-sm font-medium">
		<button
			class=" px-4 py-2 bg-emerald-700 hover:bg-emerald-800 text-gray-100 transition rounded-lg"
			type="submit"
		>
			Save
		</button>
	</div>
</form>