<script lang="ts"> import { upsertComics } from '$gql/Mutations'; import { comicScrapersQuery, scrapeComic } from '$gql/Queries'; import { isError } from '$gql/Utils'; import { OnMissing, type FullComicFragment } from '$gql/graphql'; import { ScrapedComicSelector, getScraperContext } from '$lib/Scraper'; import { toastError, toastFinally } from '$lib/Toasts'; import Select from '$lib/components/Select.svelte'; import Spinner from '$lib/components/Spinner.svelte'; import { getContextClient } from '@urql/svelte'; import SelectorGroup from './components/SelectorGroup.svelte'; import SelectorItem from './components/SelectorItem.svelte'; let client = getContextClient(); const context = getScraperContext(); export let comic: FullComicFragment; let createMissing = false; let loading = false; $: scrapersResult = comicScrapersQuery(client, { id: comic.id }); $: scrapers = $scrapersResult.data?.comicScrapers; function scrape() { loading = true; scrapeComic(client, { id: comic.id, scraper: $context.scraper }) .then((result) => { if (result.error) { toastError(result.error.message); return; } if (result.data) { if (isError(result.data.scrapeComic)) { toastError(result.data.scrapeComic.message); return; } if (result.data.scrapeComic.__typename === 'ScrapeComicResult') { $context.selector = new ScrapedComicSelector(result.data.scrapeComic.data, comic); $context.warnings = result.data.scrapeComic.warnings; } } }) .catch(toastFinally) .finally(() => (loading = false)); } function updateFromScrape(createMissing: boolean) { if (!$context.selector) return; upsertComics(client, { ids: comic.id, input: $context.selector.toInput(createMissing ? OnMissing.Create : OnMissing.Ignore) }) .then(() => { $context.selector = undefined; $context.warnings = []; }) .catch(toastFinally); } </script> <div class="flex flex-col gap-4 text-sm"> {#if scrapers && scrapers.length === 0} <h2 class="text-base">No scrapers available.</h2> {:else} <form on:submit|preventDefault={scrape}> <div class="grid grid-cols-6 gap-2"> <div class="col-span-5"> <Select id="scrapers" options={scrapers} placeholder={'Select scraper...'} bind:value={$context.scraper} /> </div> <button type="submit" disabled={!$context.scraper} class="btn-blue">Scrape</button> </div> </form> {/if} {#if loading} <Spinner /> {:else if $context.selector} {#if $context.warnings.length > 0} <div class="flex flex-col gap-2"> <h2 class="flex gap-1 border-b border-slate-700 text-base font-medium">Warnings</h2> <ul class="ml-2 list-inside list-disc"> {#each $context.warnings as warning} <li>{warning}</li> {/each} </ul> </div> {/if} {#if !$context.selector.hasData()} <h2 class="text-base">No data to merge.</h2> {:else} <div class="flex flex-col gap-2"> <h2 class="border-b border-slate-700 text-base font-medium">Results</h2> <form on:submit|preventDefault={() => updateFromScrape(createMissing)}> <div class="grid grid-cols-6 gap-4 pb-2"> <SelectorItem title="Title" selector={$context.selector.title} /> <SelectorItem title="Original Title" selector={$context.selector.originalTitle} /> <SelectorItem title="URL" selector={$context.selector.url} /> <SelectorItem title="Date" selector={$context.selector.date} --span="2" /> <SelectorItem title="Category" selector={$context.selector.category} --span="2" /> <SelectorItem title="Language" selector={$context.selector.language} --span="2" /> <SelectorItem title="Rating" selector={$context.selector.rating} --span="2" /> <SelectorItem title="Censorship" selector={$context.selector.censorship} --span="2" /> <SelectorItem title="Direction" selector={$context.selector.direction} --span="2" /> <SelectorItem title="Layout" selector={$context.selector.layout} --span="2" /> <SelectorGroup title="Artists" selectors={$context.selector.artists} /> <SelectorGroup title="Circles" selectors={$context.selector.circles} /> <SelectorGroup title="Characters" selectors={$context.selector.characters} /> <SelectorGroup title="Worlds" selectors={$context.selector.worlds} /> <SelectorGroup title="Tags" selectors={$context.selector.tags} /> </div> <div class="flex flex-col gap-2"> <h2 class="border-b border-slate-700 text-base font-medium">Options</h2> <div class="flex items-center gap-1"> <input class="h-4 w-4" type="checkbox" id="create-missing" bind:checked={createMissing} /> <label class="shrink-0" for="create-missing">Create missing items</label> </div> </div> <div class="flex gap-4"> <button type="submit" class="btn-blue">Merge</button> </div> </form> </div> {/if} {/if} </div>