mirror of
				https://github.com/open-webui/open-webui
				synced 2025-06-26 18:26:48 +00:00 
			
		
		
		
	fix: pipelines
This commit is contained in:
		
							parent
							
								
									7cec88c776
								
							
						
					
					
						commit
						4715160b53
					
				@ -219,7 +219,7 @@ def merge_models_lists(model_lists):
 | 
			
		||||
    return merged_list
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
async def get_all_models():
 | 
			
		||||
async def get_all_models(raw: bool = False):
 | 
			
		||||
    log.info("get_all_models()")
 | 
			
		||||
 | 
			
		||||
    if (
 | 
			
		||||
@ -236,6 +236,9 @@ async def get_all_models():
 | 
			
		||||
        responses = await asyncio.gather(*tasks)
 | 
			
		||||
        log.debug(f"get_all_models:responses() {responses}")
 | 
			
		||||
 | 
			
		||||
        if raw:
 | 
			
		||||
            return responses
 | 
			
		||||
 | 
			
		||||
        models = {
 | 
			
		||||
            "data": merge_models_lists(
 | 
			
		||||
                list(
 | 
			
		||||
 | 
			
		||||
@ -466,8 +466,10 @@ async def get_models(user=Depends(get_verified_user)):
 | 
			
		||||
 | 
			
		||||
@app.get("/api/pipelines/list")
 | 
			
		||||
async def get_pipelines_list(user=Depends(get_admin_user)):
 | 
			
		||||
    models = await get_all_models()
 | 
			
		||||
    urlIdxs = list(set([model["urlIdx"] for model in models if "pipeline" in model]))
 | 
			
		||||
    responses = await get_openai_models(raw=True)
 | 
			
		||||
 | 
			
		||||
    print(responses)
 | 
			
		||||
    urlIdxs = [idx for idx, response in enumerate(responses) if "pipelines" in response]
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
        "data": [
 | 
			
		||||
@ -716,9 +718,7 @@ async def update_pipeline_valves(
 | 
			
		||||
                pass
 | 
			
		||||
 | 
			
		||||
        raise HTTPException(
 | 
			
		||||
            status_code=(
 | 
			
		||||
                r.status_code if r is not None else status.HTTP_404_NOT_FOUND
 | 
			
		||||
            ),
 | 
			
		||||
            status_code=(r.status_code if r is not None else status.HTTP_404_NOT_FOUND),
 | 
			
		||||
            detail=detail,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -154,7 +154,7 @@ export const getPipelines = async (token: string, urlIdx?: string) => {
 | 
			
		||||
	let error = null;
 | 
			
		||||
 | 
			
		||||
	const searchParams = new URLSearchParams();
 | 
			
		||||
	if (urlIdx) {
 | 
			
		||||
	if (urlIdx !== undefined) {
 | 
			
		||||
		searchParams.append('urlIdx', urlIdx);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -188,7 +188,7 @@ export const getPipelineValves = async (token: string, pipeline_id: string, urlI
 | 
			
		||||
	let error = null;
 | 
			
		||||
 | 
			
		||||
	const searchParams = new URLSearchParams();
 | 
			
		||||
	if (urlIdx) {
 | 
			
		||||
	if (urlIdx !== undefined) {
 | 
			
		||||
		searchParams.append('urlIdx', urlIdx);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -224,7 +224,7 @@ export const getPipelineValvesSpec = async (token: string, pipeline_id: string,
 | 
			
		||||
	let error = null;
 | 
			
		||||
 | 
			
		||||
	const searchParams = new URLSearchParams();
 | 
			
		||||
	if (urlIdx) {
 | 
			
		||||
	if (urlIdx !== undefined) {
 | 
			
		||||
		searchParams.append('urlIdx', urlIdx);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -265,7 +265,7 @@ export const updatePipelineValves = async (
 | 
			
		||||
	let error = null;
 | 
			
		||||
 | 
			
		||||
	const searchParams = new URLSearchParams();
 | 
			
		||||
	if (urlIdx) {
 | 
			
		||||
	if (urlIdx !== undefined) {
 | 
			
		||||
		searchParams.append('urlIdx', urlIdx);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -90,6 +90,7 @@
 | 
			
		||||
		valves_spec = null;
 | 
			
		||||
 | 
			
		||||
		if (PIPELINES_LIST.length > 0) {
 | 
			
		||||
			console.log(selectedPipelinesUrlIdx);
 | 
			
		||||
			pipelines = await getPipelines(localStorage.token, selectedPipelinesUrlIdx);
 | 
			
		||||
 | 
			
		||||
			if (pipelines.length > 0) {
 | 
			
		||||
@ -143,10 +144,10 @@
 | 
			
		||||
		console.log(PIPELINES_LIST);
 | 
			
		||||
 | 
			
		||||
		if (PIPELINES_LIST.length > 0) {
 | 
			
		||||
			selectedPipelinesUrlIdx = PIPELINES_LIST[0]['idx'];
 | 
			
		||||
			selectedPipelinesUrlIdx = PIPELINES_LIST[0]['idx'].toString();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		setPipelines();
 | 
			
		||||
		await setPipelines();
 | 
			
		||||
	});
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
@ -182,7 +183,7 @@
 | 
			
		||||
								>
 | 
			
		||||
 | 
			
		||||
								{#each PIPELINES_LIST as pipelines, idx}
 | 
			
		||||
									<option value={pipelines.idx} class="bg-gray-100 dark:bg-gray-700"
 | 
			
		||||
									<option value={pipelines.idx.toString()} class="bg-gray-100 dark:bg-gray-700"
 | 
			
		||||
										>{pipelines.url}</option
 | 
			
		||||
									>
 | 
			
		||||
								{/each}
 | 
			
		||||
@ -190,187 +191,187 @@
 | 
			
		||||
						</div>
 | 
			
		||||
					</div>
 | 
			
		||||
				</div>
 | 
			
		||||
			{/if}
 | 
			
		||||
 | 
			
		||||
			<div class=" my-2">
 | 
			
		||||
				<div class=" mb-2 text-sm font-medium">
 | 
			
		||||
					{$i18n.t('Install from Github URL')}
 | 
			
		||||
				</div>
 | 
			
		||||
				<div class="flex w-full">
 | 
			
		||||
					<div class="flex-1 mr-2">
 | 
			
		||||
						<input
 | 
			
		||||
							class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
 | 
			
		||||
							placeholder={$i18n.t('Enter Github Raw URL')}
 | 
			
		||||
							bind:value={pipelineDownloadUrl}
 | 
			
		||||
						/>
 | 
			
		||||
				<div class=" my-2">
 | 
			
		||||
					<div class=" mb-2 text-sm font-medium">
 | 
			
		||||
						{$i18n.t('Install from Github URL')}
 | 
			
		||||
					</div>
 | 
			
		||||
					<button
 | 
			
		||||
						class="px-2.5 bg-gray-100 hover:bg-gray-200 text-gray-800 dark:bg-gray-850 dark:hover:bg-gray-800 dark:text-gray-100 rounded-lg transition"
 | 
			
		||||
						on:click={() => {
 | 
			
		||||
							addPipelineHandler();
 | 
			
		||||
						}}
 | 
			
		||||
						disabled={downloading}
 | 
			
		||||
						type="button"
 | 
			
		||||
					>
 | 
			
		||||
						{#if downloading}
 | 
			
		||||
							<div class="self-center">
 | 
			
		||||
								<svg
 | 
			
		||||
									class=" w-4 h-4"
 | 
			
		||||
									viewBox="0 0 24 24"
 | 
			
		||||
									fill="currentColor"
 | 
			
		||||
									xmlns="http://www.w3.org/2000/svg"
 | 
			
		||||
								>
 | 
			
		||||
									<style>
 | 
			
		||||
										.spinner_ajPY {
 | 
			
		||||
											transform-origin: center;
 | 
			
		||||
											animation: spinner_AtaB 0.75s infinite linear;
 | 
			
		||||
										}
 | 
			
		||||
 | 
			
		||||
										@keyframes spinner_AtaB {
 | 
			
		||||
											100% {
 | 
			
		||||
												transform: rotate(360deg);
 | 
			
		||||
											}
 | 
			
		||||
										}
 | 
			
		||||
									</style>
 | 
			
		||||
									<path
 | 
			
		||||
										d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,19a8,8,0,1,1,8-8A8,8,0,0,1,12,20Z"
 | 
			
		||||
										opacity=".25"
 | 
			
		||||
									/>
 | 
			
		||||
									<path
 | 
			
		||||
										d="M10.14,1.16a11,11,0,0,0-9,8.92A1.59,1.59,0,0,0,2.46,12,1.52,1.52,0,0,0,4.11,10.7a8,8,0,0,1,6.66-6.61A1.42,1.42,0,0,0,12,2.69h0A1.57,1.57,0,0,0,10.14,1.16Z"
 | 
			
		||||
										class="spinner_ajPY"
 | 
			
		||||
									/>
 | 
			
		||||
								</svg>
 | 
			
		||||
							</div>
 | 
			
		||||
						{:else}
 | 
			
		||||
							<svg
 | 
			
		||||
								xmlns="http://www.w3.org/2000/svg"
 | 
			
		||||
								viewBox="0 0 16 16"
 | 
			
		||||
								fill="currentColor"
 | 
			
		||||
								class="w-4 h-4"
 | 
			
		||||
							>
 | 
			
		||||
								<path
 | 
			
		||||
									d="M8.75 2.75a.75.75 0 0 0-1.5 0v5.69L5.03 6.22a.75.75 0 0 0-1.06 1.06l3.5 3.5a.75.75 0 0 0 1.06 0l3.5-3.5a.75.75 0 0 0-1.06-1.06L8.75 8.44V2.75Z"
 | 
			
		||||
								/>
 | 
			
		||||
								<path
 | 
			
		||||
									d="M3.5 9.75a.75.75 0 0 0-1.5 0v1.5A2.75 2.75 0 0 0 4.75 14h6.5A2.75 2.75 0 0 0 14 11.25v-1.5a.75.75 0 0 0-1.5 0v1.5c0 .69-.56 1.25-1.25 1.25h-6.5c-.69 0-1.25-.56-1.25-1.25v-1.5Z"
 | 
			
		||||
								/>
 | 
			
		||||
							</svg>
 | 
			
		||||
						{/if}
 | 
			
		||||
					</button>
 | 
			
		||||
				</div>
 | 
			
		||||
			</div>
 | 
			
		||||
 | 
			
		||||
			<hr class=" dark:border-gray-800 my-3 w-full" />
 | 
			
		||||
 | 
			
		||||
			{#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 class="flex w-full">
 | 
			
		||||
						<div class="flex-1 mr-2">
 | 
			
		||||
							<input
 | 
			
		||||
								class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
 | 
			
		||||
								placeholder={$i18n.t('Enter Github Raw URL')}
 | 
			
		||||
								bind:value={pipelineDownloadUrl}
 | 
			
		||||
							/>
 | 
			
		||||
						</div>
 | 
			
		||||
					</div>
 | 
			
		||||
					<div class="space-y-1">
 | 
			
		||||
						{#if pipelines.length > 0}
 | 
			
		||||
							<div class="flex gap-2">
 | 
			
		||||
								<div class="flex-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.type ?? 'pipe'})</option
 | 
			
		||||
											>
 | 
			
		||||
										{/each}
 | 
			
		||||
									</select>
 | 
			
		||||
								</div>
 | 
			
		||||
 | 
			
		||||
								<button
 | 
			
		||||
									class="px-2.5 bg-gray-100 hover:bg-gray-200 text-gray-800 dark:bg-gray-850 dark:hover:bg-gray-800 dark:text-gray-100 rounded-lg transition"
 | 
			
		||||
									on:click={() => {
 | 
			
		||||
										deletePipelineHandler();
 | 
			
		||||
									}}
 | 
			
		||||
									type="button"
 | 
			
		||||
								>
 | 
			
		||||
						<button
 | 
			
		||||
							class="px-2.5 bg-gray-100 hover:bg-gray-200 text-gray-800 dark:bg-gray-850 dark:hover:bg-gray-800 dark:text-gray-100 rounded-lg transition"
 | 
			
		||||
							on:click={() => {
 | 
			
		||||
								addPipelineHandler();
 | 
			
		||||
							}}
 | 
			
		||||
							disabled={downloading}
 | 
			
		||||
							type="button"
 | 
			
		||||
						>
 | 
			
		||||
							{#if downloading}
 | 
			
		||||
								<div class="self-center">
 | 
			
		||||
									<svg
 | 
			
		||||
										xmlns="http://www.w3.org/2000/svg"
 | 
			
		||||
										viewBox="0 0 16 16"
 | 
			
		||||
										class=" w-4 h-4"
 | 
			
		||||
										viewBox="0 0 24 24"
 | 
			
		||||
										fill="currentColor"
 | 
			
		||||
										class="w-4 h-4"
 | 
			
		||||
										xmlns="http://www.w3.org/2000/svg"
 | 
			
		||||
									>
 | 
			
		||||
										<style>
 | 
			
		||||
											.spinner_ajPY {
 | 
			
		||||
												transform-origin: center;
 | 
			
		||||
												animation: spinner_AtaB 0.75s infinite linear;
 | 
			
		||||
											}
 | 
			
		||||
 | 
			
		||||
											@keyframes spinner_AtaB {
 | 
			
		||||
												100% {
 | 
			
		||||
													transform: rotate(360deg);
 | 
			
		||||
												}
 | 
			
		||||
											}
 | 
			
		||||
										</style>
 | 
			
		||||
										<path
 | 
			
		||||
											fill-rule="evenodd"
 | 
			
		||||
											d="M5 3.25V4H2.75a.75.75 0 0 0 0 1.5h.3l.815 8.15A1.5 1.5 0 0 0 5.357 15h5.285a1.5 1.5 0 0 0 1.493-1.35l.815-8.15h.3a.75.75 0 0 0 0-1.5H11v-.75A2.25 2.25 0 0 0 8.75 1h-1.5A2.25 2.25 0 0 0 5 3.25Zm2.25-.75a.75.75 0 0 0-.75.75V4h3v-.75a.75.75 0 0 0-.75-.75h-1.5ZM6.05 6a.75.75 0 0 1 .787.713l.275 5.5a.75.75 0 0 1-1.498.075l-.275-5.5A.75.75 0 0 1 6.05 6Zm3.9 0a.75.75 0 0 1 .712.787l-.275 5.5a.75.75 0 0 1-1.498-.075l.275-5.5a.75.75 0 0 1 .786-.711Z"
 | 
			
		||||
											clip-rule="evenodd"
 | 
			
		||||
											d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,19a8,8,0,1,1,8-8A8,8,0,0,1,12,20Z"
 | 
			
		||||
											opacity=".25"
 | 
			
		||||
										/>
 | 
			
		||||
										<path
 | 
			
		||||
											d="M10.14,1.16a11,11,0,0,0-9,8.92A1.59,1.59,0,0,0,2.46,12,1.52,1.52,0,0,0,4.11,10.7a8,8,0,0,1,6.66-6.61A1.42,1.42,0,0,0,12,2.69h0A1.57,1.57,0,0,0,10.14,1.16Z"
 | 
			
		||||
											class="spinner_ajPY"
 | 
			
		||||
										/>
 | 
			
		||||
									</svg>
 | 
			
		||||
								</button>
 | 
			
		||||
							</div>
 | 
			
		||||
						{/if}
 | 
			
		||||
 | 
			
		||||
						<div class="space-y-1">
 | 
			
		||||
							{#if pipelines[selectedPipelineIdx].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>
 | 
			
		||||
											</div>
 | 
			
		||||
 | 
			
		||||
											{#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}
 | 
			
		||||
										</div>
 | 
			
		||||
									{/each}
 | 
			
		||||
								{:else}
 | 
			
		||||
									<Spinner className="size-5" />
 | 
			
		||||
								{/if}
 | 
			
		||||
								</div>
 | 
			
		||||
							{:else}
 | 
			
		||||
								<div>No valves</div>
 | 
			
		||||
								<svg
 | 
			
		||||
									xmlns="http://www.w3.org/2000/svg"
 | 
			
		||||
									viewBox="0 0 16 16"
 | 
			
		||||
									fill="currentColor"
 | 
			
		||||
									class="w-4 h-4"
 | 
			
		||||
								>
 | 
			
		||||
									<path
 | 
			
		||||
										d="M8.75 2.75a.75.75 0 0 0-1.5 0v5.69L5.03 6.22a.75.75 0 0 0-1.06 1.06l3.5 3.5a.75.75 0 0 0 1.06 0l3.5-3.5a.75.75 0 0 0-1.06-1.06L8.75 8.44V2.75Z"
 | 
			
		||||
									/>
 | 
			
		||||
									<path
 | 
			
		||||
										d="M3.5 9.75a.75.75 0 0 0-1.5 0v1.5A2.75 2.75 0 0 0 4.75 14h6.5A2.75 2.75 0 0 0 14 11.25v-1.5a.75.75 0 0 0-1.5 0v1.5c0 .69-.56 1.25-1.25 1.25h-6.5c-.69 0-1.25-.56-1.25-1.25v-1.5Z"
 | 
			
		||||
									/>
 | 
			
		||||
								</svg>
 | 
			
		||||
							{/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" />
 | 
			
		||||
						</button>
 | 
			
		||||
					</div>
 | 
			
		||||
				</div>
 | 
			
		||||
 | 
			
		||||
				<hr class=" dark:border-gray-800 my-3 w-full" />
 | 
			
		||||
 | 
			
		||||
				{#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">
 | 
			
		||||
										<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.type ?? 'pipe'})</option
 | 
			
		||||
												>
 | 
			
		||||
											{/each}
 | 
			
		||||
										</select>
 | 
			
		||||
									</div>
 | 
			
		||||
 | 
			
		||||
									<button
 | 
			
		||||
										class="px-2.5 bg-gray-100 hover:bg-gray-200 text-gray-800 dark:bg-gray-850 dark:hover:bg-gray-800 dark:text-gray-100 rounded-lg transition"
 | 
			
		||||
										on:click={() => {
 | 
			
		||||
											deletePipelineHandler();
 | 
			
		||||
										}}
 | 
			
		||||
										type="button"
 | 
			
		||||
									>
 | 
			
		||||
										<svg
 | 
			
		||||
											xmlns="http://www.w3.org/2000/svg"
 | 
			
		||||
											viewBox="0 0 16 16"
 | 
			
		||||
											fill="currentColor"
 | 
			
		||||
											class="w-4 h-4"
 | 
			
		||||
										>
 | 
			
		||||
											<path
 | 
			
		||||
												fill-rule="evenodd"
 | 
			
		||||
												d="M5 3.25V4H2.75a.75.75 0 0 0 0 1.5h.3l.815 8.15A1.5 1.5 0 0 0 5.357 15h5.285a1.5 1.5 0 0 0 1.493-1.35l.815-8.15h.3a.75.75 0 0 0 0-1.5H11v-.75A2.25 2.25 0 0 0 8.75 1h-1.5A2.25 2.25 0 0 0 5 3.25Zm2.25-.75a.75.75 0 0 0-.75.75V4h3v-.75a.75.75 0 0 0-.75-.75h-1.5ZM6.05 6a.75.75 0 0 1 .787.713l.275 5.5a.75.75 0 0 1-1.498.075l-.275-5.5A.75.75 0 0 1 6.05 6Zm3.9 0a.75.75 0 0 1 .712.787l-.275 5.5a.75.75 0 0 1-1.498-.075l.275-5.5a.75.75 0 0 1 .786-.711Z"
 | 
			
		||||
												clip-rule="evenodd"
 | 
			
		||||
											/>
 | 
			
		||||
										</svg>
 | 
			
		||||
									</button>
 | 
			
		||||
								</div>
 | 
			
		||||
							{/if}
 | 
			
		||||
 | 
			
		||||
							<div class="space-y-1">
 | 
			
		||||
								{#if pipelines[selectedPipelineIdx].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>
 | 
			
		||||
												</div>
 | 
			
		||||
 | 
			
		||||
												{#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}
 | 
			
		||||
											</div>
 | 
			
		||||
										{/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>
 | 
			
		||||
					</div>
 | 
			
		||||
				{/if}
 | 
			
		||||
			{/if}
 | 
			
		||||
		{:else}
 | 
			
		||||
			<div class="flex justify-center h-full">
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user