modo oscuro + organización de código

This commit is contained in:
Cat /dev/Nulo 2023-12-08 21:17:25 -03:00
parent c9347b583b
commit 0ee2b5993e
11 changed files with 130 additions and 147 deletions

View file

@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Transicion Desordenada Diablo (ver dataset)</title> <title>Transicion Desordenada Diablo (ver dataset)</title>
</head> </head>
<body class="bg-gray-50"> <body class="bg-gray-50 dark:bg-gray-900 dark:text-white">
<div id="app"></div> <div id="app"></div>
<script type="module" src="/src/main.ts"></script> <script type="module" src="/src/main.ts"></script>
</body> </body>

View file

@ -10,6 +10,7 @@
"check": "svelte-check --tsconfig ./tsconfig.json" "check": "svelte-check --tsconfig ./tsconfig.json"
}, },
"devDependencies": { "devDependencies": {
"@poppanator/sveltekit-svg": "^4.1.3",
"@sveltejs/vite-plugin-svelte": "^3.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0",
"@tailwindcss/typography": "^0.5.10", "@tailwindcss/typography": "^0.5.10",
"@tsconfig/svelte": "^5.0.2", "@tsconfig/svelte": "^5.0.2",
@ -24,8 +25,7 @@
"tailwindcss": "^3.3.6", "tailwindcss": "^3.3.6",
"tslib": "^2.6.2", "tslib": "^2.6.2",
"typescript": "^5.2.2", "typescript": "^5.2.2",
"vite": "^5.0.0", "vite": "^5.0.0"
"vite-plugin-svelte-svg": "^2.3.0"
}, },
"dependencies": { "dependencies": {
"eva-icons": "^1.1.3", "eva-icons": "^1.1.3",

View file

@ -0,0 +1,5 @@
<div
class="rounded-lg border dark:border-gray-700 bg-white dark:bg-gray-800 m-2"
>
<slot />
</div>

View file

@ -0,0 +1,15 @@
<script lang="ts">
import ExternalLink from "eva-icons/outline/svg/external-link-outline.svg?component";
export let href: string;
</script>
<a
class="flex items-center leading-none text-gray-600 dark:text-gray-300 gap-1 pt-2"
{href}
target="_blank"
rel="noopener"
>
<ExternalLink fill="currentColor" class="h-4" />
<span class="underline">Fuente</span>
</a>

View file

@ -2,49 +2,40 @@
import { inject } from "regexparam"; import { inject } from "regexparam";
import ChevronRight from "eva-icons/outline/svg/chevron-right-outline.svg?component"; import ChevronRight from "eva-icons/outline/svg/chevron-right-outline.svg?component";
import { generateDumpName, routes } from "../router"; import { generateDumpName, routes } from "../router";
import Portal from "../routes/Portal.svelte"; import NavItem from "./NavItem.svelte";
export let params: export let params:
| { dumpUrl: string } | { dumpUrl: string }
| { dumpUrl: string; portal: string } | { dumpUrl: string; portal: string }
| { dumpUrl: string; portal: string; id: string }; | { dumpUrl: string; portal: string; id: string };
$: kind = "id" in params ? "dataset" : "portal" in params ? "portal" : "dump";
$: dumpName = generateDumpName(params.dumpUrl); $: dumpName = generateDumpName(params.dumpUrl);
</script> </script>
<nav class="flex justify-between m-2"> <nav class="flex justify-between m-2">
<ol <ol
class="flex items-center mb-3 text-sm text-neutral-500 [&_.active-breadcrumb]:text-neutral-600 [&_.active-breadcrumb]:font-medium sm:mb-0" class="flex items-center mb-3 text-sm text-neutral-500 dark:text-neutral-300 [&_.active-breadcrumb]:text-neutral-600 dark:[&_.active-breadcrumb]:text-neutral-200 [&_.active-breadcrumb]:font-bold sm:mb-0"
class:active-breadcrumb={kind === "dump"}
> >
<li class="flex items-center h-full"> <NavItem href={inject(routes.Dump, params)} active={kind === "dump"}
<a >{dumpName}</NavItem
href={inject(routes.Dump, params)} >
class="inline-flex items-center px-2 py-1.5 space-x-1.5 rounded-md hover:text-neutral-900 hover:bg-neutral-100"
>
<span>{dumpName}</span>
</a>
</li>
{#if "portal" in params} {#if "portal" in params}
<ChevronRight class="w-5 h-5 text-gray-400" fill="currentColor" /> <ChevronRight class="w-5 h-5 text-neutral-400" fill="currentColor" />
<li> <NavItem href={inject(routes.Portal, params)} active={kind === "portal"}>
<a {params.portal}
href={inject(routes.Portal, params)} </NavItem>
class="inline-flex items-center px-2 py-1.5 space-x-1.5 font-normal rounded-md hover:bg-neutral-100 hover:text-neutral-900"
>
<span>{params.portal}</span>
</a>
</li>
{/if} {/if}
{#if "id" in params} {#if "id" in params}
<ChevronRight class="w-5 h-5 text-gray-400" fill="currentColor" /> <ChevronRight class="w-5 h-5 text-neutral-400" fill="currentColor" />
<li> <NavItem
<a href={inject(routes.Dataset, params)}
href={inject(routes.Dataset, params)} active={kind === "dataset"}
class="inline-flex items-center px-2 py-1.5 space-x-1.5 font-normal rounded-md hover:bg-neutral-100 hover:text-neutral-900" >
> {params.id}
<span>{params.id}</span> </NavItem>
</a>
</li>
{/if} {/if}
</ol> </ol>
</nav> </nav>

View file

@ -0,0 +1,14 @@
<script lang="ts">
export let active: boolean = false;
export let href: string;
</script>
<li class="flex items-center h-full">
<a
{href}
class="inline-flex items-center px-2 py-1.5 space-x-1.5 rounded-md hover:text-neutral-900 hover:bg-neutral-100 dark:hover:text-gray-100 dark:hover:bg-gray-800"
class:active-breadcrumb={active}
>
<span><slot /></span>
</a>
</li>

View file

@ -1,11 +1,12 @@
<script lang="ts"> <script lang="ts">
import ArrowBack from "eva-icons/outline/svg/arrow-back-outline.svg?component"; import ArrowBack from "eva-icons/outline/svg/arrow-back-outline.svg?component";
import ExternalLink from "eva-icons/outline/svg/external-link-outline.svg?component";
import { downloadFile, fetchData, fetchErrors } from "../fetch"; import { downloadFile, fetchData, fetchErrors } from "../fetch";
import NotFound from "./NotFound.svelte"; import NotFound from "./NotFound.svelte";
import { inject } from "regexparam"; import { inject } from "regexparam";
import { routes } from "../router"; import { routes } from "../router";
import Nav from "../nav/Nav.svelte"; import Nav from "../nav/Nav.svelte";
import SourceLink from "../components/SourceLink.svelte";
import Container from "../components/Container.svelte";
export let params: { dumpUrl: string; portal: string; id: string }; export let params: { dumpUrl: string; portal: string; id: string };
$: url = decodeURIComponent(params.dumpUrl) + "/" + params.portal; $: url = decodeURIComponent(params.dumpUrl) + "/" + params.portal;
@ -18,7 +19,7 @@
<main class="mx-auto max-w-3xl"> <main class="mx-auto max-w-3xl">
<Nav {params} /> <Nav {params} />
<div class="rounded-lg border bg-white m-2"> <Container>
{#await data} {#await data}
<p class="p-6">Cargando dataset...</p> <p class="p-6">Cargando dataset...</p>
{:then { data, errors }} {:then { data, errors }}
@ -26,18 +27,9 @@
{#if !dataset} {#if !dataset}
<NotFound /> <NotFound />
{:else} {:else}
<header class="py-5 px-6 border-b border-b-gray-200"> <header
<small> class="py-5 px-6 border-b border-b-gray-200 dark:border-b-gray-700"
<a >
class="flex text-blue-500 leading-none gap-1 items-center"
href={inject(routes.Portal, {
dumpUrl: params.dumpUrl,
portal: params.portal,
})}
>
<ArrowBack fill="currentColor" class="h-[1.25em]" /> Viendo {data.title}
</a>
</small>
<h1 class="font-bold text-3xl">{dataset.title}</h1> <h1 class="font-bold text-3xl">{dataset.title}</h1>
<p class="text-xl">{dataset.description}</p> <p class="text-xl">{dataset.description}</p>
<!-- <!--
@ -55,7 +47,7 @@
</a> </a>
{/if} --> {/if} -->
</header> </header>
<ul class="divide-y divide-gray-100"> <ul class="divide-y divide-gray-100 dark:divide-gray-700">
{#each dataset.distribution as dist} {#each dataset.distribution as dist}
{@const error = errors.find( {@const error = errors.find(
(e) => (e) =>
@ -68,7 +60,7 @@
{dist.title} {dist.title}
{#if dist.format} {#if dist.format}
<span <span
class="border border-current text-blue-800 relative inline-flex items-center text-xs font-semibold px-2 py-1 rounded-full ml-1" class="border border-current text-blue-800 dark:text-blue-400 relative inline-flex items-center text-xs font-semibold px-2 py-1 rounded-full ml-1"
> >
<span>{dist.format}</span> <span>{dist.format}</span>
</span> </span>
@ -99,15 +91,7 @@
> >
{/if} {/if}
{#if dist.downloadURL} {#if dist.downloadURL}
<a <SourceLink href={dist.downloadURL} />
class="flex items-center leading-none text-gray-600 gap-1 pt-2"
href={dist.downloadURL}
target="_blank"
rel="noopener"
>
<ExternalLink fill="currentColor" class="h-4" />
Fuente
</a>
{/if} {/if}
</div> </div>
</li> </li>
@ -115,5 +99,5 @@
</ul> </ul>
{/if} {/if}
{/await} {/await}
</div> </Container>
</main> </main>

View file

@ -1,8 +1,9 @@
<script lang="ts"> <script lang="ts">
import { inject } from "regexparam"; import { inject } from "regexparam";
import ExternalLink from "eva-icons/outline/svg/external-link-outline.svg?component";
import { fetchDumpMetadata } from "../fetch"; import { fetchDumpMetadata } from "../fetch";
import { routes } from "../router"; import { routes } from "../router";
import SourceLink from "../components/SourceLink.svelte";
import Container from "../components/Container.svelte";
export let params: { dumpUrl: string }; export let params: { dumpUrl: string };
$: url = decodeURIComponent(params.dumpUrl); $: url = decodeURIComponent(params.dumpUrl);
@ -11,36 +12,25 @@
</script> </script>
<main class="mx-auto max-w-3xl"> <main class="mx-auto max-w-3xl">
<div class="rounded-lg border bg-white m-2"> <Container>
{#await metadataPromise} {#await metadataPromise}
<p class="p-6">Cargando..</p> <p class="p-6">Cargando..</p>
{:then metadata} {:then metadata}
<header class="py-5 px-6 border-b border-b-gray-200 leading-none"> <header
class="py-5 px-6 border-b border-b-gray-200 dark:border-b-gray-700 leading-none"
>
<small> <small>
Viendo archivo en Viendo archivo en
<a <a
class="underline text-blue-500" class="underline text-blue-500 dark:text-blue-300"
target="_blank" target="_blank"
rel="noopener" rel="noopener"
href={url}>{url}</a href={url}>{url}</a
> >
</small> </small>
<!-- <h1 class="font-bold text-3xl">{data.title}</h1>
<p class="text-xl">{data.description}</p>
{#if data.homepage}
<a
class="flex items-center leading-none text-gray-600 gap-1 pt-2"
href={arreglarHomepageUrl(data.homepage)}
target="_blank"
rel="noopener"
>
<ExternalLink fill="currentColor" class="h-4" />
Fuente
</a>
{/if} -->
</header> </header>
<ul class="divide-y divide-gray-100"> <ul class="divide-y divide-gray-100 dark:divide-gray-700">
{#each metadata.sites as site} {#each metadata.sites as site}
{@const portalLink = inject(routes.Portal, { {@const portalLink = inject(routes.Portal, {
dumpUrl: params.dumpUrl, dumpUrl: params.dumpUrl,
@ -58,15 +48,7 @@
class="inline-flex items-center justify-center px-4 py-2 text-sm font-medium tracking-wide text-white transition-colors duration-200 bg-blue-600 rounded-md hover:bg-blue-700 focus:ring-2 focus:ring-offset-2 focus:ring-blue-700 focus:shadow-outline focus:outline-none" class="inline-flex items-center justify-center px-4 py-2 text-sm font-medium tracking-wide text-white transition-colors duration-200 bg-blue-600 rounded-md hover:bg-blue-700 focus:ring-2 focus:ring-offset-2 focus:ring-blue-700 focus:shadow-outline focus:outline-none"
>Ver portal</a >Ver portal</a
> >
<a <SourceLink href={site.url} />
class="flex items-center leading-none text-gray-600 gap-1 pt-2"
href={site.url}
target="_blank"
rel="noopener"
>
<ExternalLink fill="currentColor" class="h-4" />
Fuente
</a>
</div> </div>
</div> </div>
</li> </li>
@ -75,5 +57,5 @@
{:catch error} {:catch error}
Hubo un error intenando cargar este archivo. <pre>{error}</pre> Hubo un error intenando cargar este archivo. <pre>{error}</pre>
{/await} {/await}
</div> </Container>
</main> </main>

View file

@ -1,44 +1,47 @@
<script lang="ts"> <script lang="ts">
import { inject } from "regexparam"; import { inject } from "regexparam";
import { routes } from "../router"; import { routes } from "../router";
import Container from "../components/Container.svelte";
</script> </script>
<main class="p-2"> <main class="mx-auto prose dark:prose-invert">
<div class="mx-auto rounded-lg border bg-white py-5 px-6 prose"> <Container>
<h1>Archivo de portales de datos abiertos</h1> <div class="py-5 px-6">
<p> <h1>Archivo de portales de datos abiertos</h1>
Esta herramienta permite ver datos en archivos de portales de datos <p>
abiertos de <a Esta herramienta permite ver datos en archivos de portales de datos
href="https://github.com/catdevnull/transicion-desordenada-diablo/" abiertos de <a
rel="noopener">transicion-desordenada-diablo</a href="https://github.com/catdevnull/transicion-desordenada-diablo/"
> rel="noopener">transicion-desordenada-diablo</a
(un mejor nombre sería genial), creada en el marco de >
<a href="https://bit.ly/CartaDatosAbiertos">un pedido hecho</a> al gobierno (un mejor nombre sería genial), creada en el marco de
entrante el 10 de diciembre de 2023 por garantizar el mantenimiento de las <a href="https://bit.ly/CartaDatosAbiertos">un pedido hecho</a> al gobierno
políticas de datos públicos en Argentina. entrante el 10 de diciembre de 2023 por garantizar el mantenimiento de las
</p> políticas de datos públicos en Argentina.
</p>
<div class="not-prose flex place-content-center"> <div class="not-prose flex place-content-center">
<a <a
href={inject(routes.Dump, { href={inject(routes.Dump, {
dumpUrl: encodeURIComponent( dumpUrl: encodeURIComponent(
"https://archivos.nulo.ar/dump-2023-12-08/", "https://archivos.nulo.ar/dump-2023-12-08/",
), ),
})} })}
class="flex items-center justify-center px-4 py-2 text-xl font-medium text-white transition-colors duration-200 bg-blue-600 rounded-md hover:bg-blue-700 focus:ring-2 focus:ring-offset-2 focus:ring-blue-700 focus:shadow-outline focus:outline-none text-center" class="flex items-center justify-center px-4 py-2 text-xl font-medium text-white transition-colors duration-200 bg-blue-600 rounded-md hover:bg-blue-700 focus:ring-2 focus:ring-offset-2 focus:ring-blue-700 focus:shadow-outline focus:outline-none text-center"
> >
Acceder al archivo creado el 8 de diciembre de 2023 Acceder al archivo creado el 8 de diciembre de 2023
</a> </a>
</div>
<p>
Los archivos y las herramientas fueron creados por
<a href="https://nulo.ar">Nulo</a> con ayuda de varias personas. El
código está disponible
<a
href="https://github.com/catdevnull/transicion-desordenada-diablo/"
rel="noopener">en GitHub</a
>.
</p>
</div> </div>
</Container>
<p>
Los archivos y las herramientas fueron creados por
<a href="https://nulo.ar">Nulo</a> con ayuda de varias personas. El código
está disponible
<a
href="https://github.com/catdevnull/transicion-desordenada-diablo/"
rel="noopener">en GitHub</a
>.
</p>
</div>
</main> </main>

View file

@ -1,11 +1,12 @@
<script lang="ts"> <script lang="ts">
import { inject } from "regexparam"; import { inject } from "regexparam";
import ArrowForward from "eva-icons/outline/svg/arrow-forward-outline.svg?component"; import ArrowForward from "eva-icons/outline/svg/arrow-forward-outline.svg?component";
import ExternalLink from "eva-icons/outline/svg/external-link-outline.svg?component";
import { fetchData, fetchErrors } from "../fetch"; import { fetchData, fetchErrors } from "../fetch";
import { routes } from "../router"; import { routes } from "../router";
import type { Dataset } from "common/schema"; import type { Dataset } from "common/schema";
import Nav from "../nav/Nav.svelte"; import Nav from "../nav/Nav.svelte";
import SourceLink from "../components/SourceLink.svelte";
import Container from "../components/Container.svelte";
export let params: { dumpUrl: string; portal: string }; export let params: { dumpUrl: string; portal: string };
$: url = `${decodeURIComponent(params.dumpUrl)}/${params.portal}`; $: url = `${decodeURIComponent(params.dumpUrl)}/${params.portal}`;
@ -45,15 +46,17 @@
<main class="mx-auto max-w-3xl"> <main class="mx-auto max-w-3xl">
<Nav {params} /> <Nav {params} />
<div class="rounded-lg border bg-white m-2"> <Container>
{#await data} {#await data}
<p class="p-6">Cargando..</p> <p class="p-6">Cargando..</p>
{:then { data, errors }} {:then { data, errors }}
<header class="py-5 px-6 border-b border-b-gray-200 leading-none"> <header
class="py-5 px-6 border-b border-b-gray-200 dark:border-b-gray-700 leading-none"
>
<small> <small>
Viendo portal archivado de Viendo portal archivado de
<a <a
class="underline text-blue-500" class="underline text-blue-500 dark:text-blue-300"
target="_blank" target="_blank"
rel="noopener" rel="noopener"
href={url}>{url}</a href={url}>{url}</a
@ -62,15 +65,7 @@
<h1 class="font-bold text-3xl">{data.title}</h1> <h1 class="font-bold text-3xl">{data.title}</h1>
<p class="text-xl">{data.description}</p> <p class="text-xl">{data.description}</p>
{#if data.homepage} {#if data.homepage}
<a <SourceLink href={arreglarHomepageUrl(data.homepage)} />
class="flex items-center leading-none text-gray-600 gap-1 pt-2"
href={arreglarHomepageUrl(data.homepage)}
target="_blank"
rel="noopener"
>
<ExternalLink fill="currentColor" class="h-4" />
Fuente
</a>
{/if} {/if}
</header> </header>
@ -78,12 +73,12 @@
<input <input
type="text" type="text"
placeholder="Buscar..." placeholder="Buscar..."
class="flex w-full h-10 px-3 py-2 text-sm bg-white border rounded-md border-neutral-300 ring-offset-background placeholder:text-neutral-500 focus:border-neutral-300 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-400 disabled:cursor-not-allowed disabled:opacity-50" class="flex w-full h-10 px-3 py-2 text-sm bg-white dark:bg-gray-800 border rounded-md border-neutral-300 dark:border-gray-700 ring-offset-background placeholder:text-neutral-500 dark:placeholder:text-gray-500 focus:border-neutral-300 dark:focus:border-gray-700 focus:outline-none focus:ring-2 focus:ring-neutral-400 dark:focus:ring-gray-600 disabled:cursor-not-allowed disabled:opacity-50"
bind:value={query} bind:value={query}
/> />
</div> </div>
<ul class="divide-y divide-gray-100"> <ul class="divide-y divide-gray-100 dark:divide-gray-700">
{#each filterDatasets(data.dataset, query) as dataset} {#each filterDatasets(data.dataset, query) as dataset}
{@const datasetLink = inject(routes.Dataset, { {@const datasetLink = inject(routes.Dataset, {
dumpUrl: params.dumpUrl, dumpUrl: params.dumpUrl,
@ -92,7 +87,7 @@
})} })}
<li> <li>
<a <a
class="flex px-6 py-5 hover:bg-gray-50 justify-between" class="flex px-6 py-5 hover:bg-gray-50 dark:hover:bg-gray-700 justify-between"
href={datasetLink} href={datasetLink}
> >
<div> <div>
@ -102,7 +97,7 @@
<ArrowForward <ArrowForward
fill="currentColor" fill="currentColor"
aria-hidden="true" aria-hidden="true"
class="w-6 shrink-0 text-gray-600" class="w-6 shrink-0 text-gray-600 dark:text-gray-400 "
/> />
</a> </a>
</li> </li>
@ -111,5 +106,5 @@
{:catch error} {:catch error}
Hubo un error intenando cargar este portal archivado. <pre>{error}</pre> Hubo un error intenando cargar este portal archivado. <pre>{error}</pre>
{/await} {/await}
</div> </Container>
</main> </main>

View file

@ -1,17 +1,11 @@
import { defineConfig } from "vite"; import { defineConfig } from "vite";
import { svelte } from "@sveltejs/vite-plugin-svelte"; import { svelte } from "@sveltejs/vite-plugin-svelte";
import svelteSVG from "vite-plugin-svelte-svg"; import svg from "@poppanator/sveltekit-svg";
// https://vitejs.dev/config/ // https://vitejs.dev/config/
export default defineConfig({ export default defineConfig({
build: { build: {
sourcemap: true, sourcemap: true,
}, },
plugins: [ plugins: [svelte(), svg()],
svelte(),
svelteSVG({
svgoConfig: {}, // See https://github.com/svg/svgo#configuration
requireSuffix: true, // Set false to accept '.svg' without the '?component'
}),
],
}); });