all repos — kōi @ 733b1e68ded9a74d31e7b734fc5fb0064d5c0bd2

Minimalist task manager

💄 Setup layout
Tim Izzo tim@5ika.ch
Fri, 31 Jan 2025 10:19:30 +0100
commit

733b1e68ded9a74d31e7b734fc5fb0064d5c0bd2

parent

ba5b1ae641bdb07f549e3c46c9dc3d1b4686aa45

M deno.lockdeno.lock

@@ -4,9 +4,12 @@ "specifiers": {

"npm:@inrupt/solid-client-authn-browser@^2.3.0": "2.3.0", "npm:@inrupt/solid-client@^2.1.2": "2.1.2", "npm:@sveltejs/vite-plugin-svelte@^5.0.3": "5.0.3_svelte@5.17.3__acorn@8.14.0_vite@6.0.7", + "npm:@tailwindcss/vite@^4.0.1": "4.0.1_vite@6.0.7_lightningcss@1.29.1", "npm:@tsconfig/svelte@^5.0.4": "5.0.4", + "npm:daisyui@^5.0.0-beta.6": "5.0.0-beta.6", "npm:svelte-check@^4.1.1": "4.1.3_svelte@5.17.3__acorn@8.14.0_typescript@5.6.3", "npm:svelte@^5.15.0": "5.17.3_acorn@8.14.0", + "npm:tailwindcss@^4.0.1": "4.0.1", "npm:typescript@~5.6.2": "5.6.3", "npm:vite@^6.0.5": "6.0.7" },

@@ -264,7 +267,7 @@ "dependencies": [

"@sveltejs/vite-plugin-svelte", "debug", "svelte", - "vite" + "vite@6.0.7" ] }, "@sveltejs/vite-plugin-svelte@5.0.3_svelte@5.17.3__acorn@8.14.0_vite@6.0.7": {

@@ -276,10 +279,77 @@ "deepmerge",

"kleur", "magic-string", "svelte", - "vite", + "vite@6.0.7", "vitefu" ] }, + "@tailwindcss/node@4.0.1": { + "integrity": "sha512-lc+ly6PKHqgCVl7eO8D2JlV96Lks5bmL6pdtM6UasyUHLU2zmrOqU6jfgln120IVnCh3VC8GG/ca24xVTtSokw==", + "dependencies": [ + "enhanced-resolve", + "jiti", + "tailwindcss" + ] + }, + "@tailwindcss/oxide-android-arm64@4.0.1": { + "integrity": "sha512-eP/rI9WaAElpeiiHDqGtDqga9iDsOClXxIqdHayHsw93F24F03b60CwgGhrGF9Io/EuWIpz3TMRhPVOLhoXivw==" + }, + "@tailwindcss/oxide-darwin-arm64@4.0.1": { + "integrity": "sha512-jZVUo0kNd1IjxdCYwg4dwegDNsq7PoUx4LM814RmgY3gfJ63Y6GlpJXHOpd5FLv1igpeZox5LzRk2oz8MQoJwQ==" + }, + "@tailwindcss/oxide-darwin-x64@4.0.1": { + "integrity": "sha512-E31wHiIf4LB0aKRohrS4U6XfFSACCL9ifUFfPQ16FhcBIL4wU5rcBidvWvT9TQFGPkpE69n5dyXUcqiMrnF/Ig==" + }, + "@tailwindcss/oxide-freebsd-x64@4.0.1": { + "integrity": "sha512-8/3ZKLMYqgAsBzTeczOKWtT4geF02g9S7cntY5gvqQZ4E0ImX724cHcZJi9k6fkE6aLbvwxxHxaShFvRxblwKQ==" + }, + "@tailwindcss/oxide-linux-arm-gnueabihf@4.0.1": { + "integrity": "sha512-EYjbh225klQfWzy6LeIAfdjHCK+p71yLV/GjdPNW47Bfkkq05fTzIhHhCgshUvNp78EIA33iQU+ktWpW06NgHw==" + }, + "@tailwindcss/oxide-linux-arm64-gnu@4.0.1": { + "integrity": "sha512-PrX2SwIqWNP5cYeSyQfrhbk4ffOM338T6CrEwIAGvLPoUZiklt19yknlsBme6bReSw7TSAMy+8KFdLLi5fcWNQ==" + }, + "@tailwindcss/oxide-linux-arm64-musl@4.0.1": { + "integrity": "sha512-iuoFGhKDojtfloi5uj6MIk4kxEOGcsAk/kPbZItF9Dp7TnzVhxo2U/718tXhxGrg6jSL3ST3cQHIjA6yw3OeXw==" + }, + "@tailwindcss/oxide-linux-x64-gnu@4.0.1": { + "integrity": "sha512-pNUrGQYyE8RK+N9yvkPmHnlKDfFbni9A3lsi37u4RoA/6Yn+zWVoegvAQMZu3w+jqnpb2A/bYJ+LumcclUZ3yg==" + }, + "@tailwindcss/oxide-linux-x64-musl@4.0.1": { + "integrity": "sha512-xSGWaDcT6SJ75su9zWXj8GYb2jM/przXwZGH96RTS7HGDIoI1tvgpls88YajG5Sx7hXaqAWCufjw5L/dlu+lzg==" + }, + "@tailwindcss/oxide-win32-arm64-msvc@4.0.1": { + "integrity": "sha512-BUNL2isUZ2yWnbplPddggJpZxsqGHPZ1RJAYpu63W4znUnKCzI4m/jiy0WpyYqqOKL9jDM5q0QdsQ9mc3aw5YQ==" + }, + "@tailwindcss/oxide-win32-x64-msvc@4.0.1": { + "integrity": "sha512-ZtcVu+XXOddGsPlvO5nh2fnbKmwly2C07ZB1lcYCf/b8qIWF04QY9o6vy6/+6ioLRfbp3E7H/ipFio38DZX4oQ==" + }, + "@tailwindcss/oxide@4.0.1": { + "integrity": "sha512-3z1SpWoDeaA6K6jd92CRrGyDghOcRILEgyWVHRhaUm/tcpiazwJpU9BSG0xB7GGGnl9capojaC+zme/nKsZd/w==", + "dependencies": [ + "@tailwindcss/oxide-android-arm64", + "@tailwindcss/oxide-darwin-arm64", + "@tailwindcss/oxide-darwin-x64", + "@tailwindcss/oxide-freebsd-x64", + "@tailwindcss/oxide-linux-arm-gnueabihf", + "@tailwindcss/oxide-linux-arm64-gnu", + "@tailwindcss/oxide-linux-arm64-musl", + "@tailwindcss/oxide-linux-x64-gnu", + "@tailwindcss/oxide-linux-x64-musl", + "@tailwindcss/oxide-win32-arm64-msvc", + "@tailwindcss/oxide-win32-x64-msvc" + ] + }, + "@tailwindcss/vite@4.0.1_vite@6.0.7_lightningcss@1.29.1": { + "integrity": "sha512-ZkwMBA7uR+nyrafIZI8ce3PduE0dDVFVmxmInCUPTN17Jgy6RfEPXzqtL5fz658eDDxKa5xZ+gmiTt+5AMD0pw==", + "dependencies": [ + "@tailwindcss/node", + "@tailwindcss/oxide", + "lightningcss", + "tailwindcss", + "vite@6.0.7_lightningcss@1.29.1" + ] + }, "@tsconfig/svelte@5.0.4": { "integrity": "sha512-BV9NplVgLmSi4mwKzD8BD/NQ8erOY/nUE/GpgWe2ckx+wIQF5RyRirn/QsSSCPeulVpc3RA/iJt6DpfTIZps0Q==" },

@@ -363,6 +433,9 @@ },

"crypto-js@4.2.0": { "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==" }, + "daisyui@5.0.0-beta.6": { + "integrity": "sha512-gwXHv6MApRBrvUayzg83vS6bfZ+y7/1VGLu0a8/cEAMviS4rXLCd4AndEdlVxhq+25wkAp0CZRkNQ7O4wIoFnQ==" + }, "debug@4.4.0": { "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "dependencies": [

@@ -372,6 +445,16 @@ },

"deepmerge@4.3.1": { "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==" }, + "detect-libc@1.0.3": { + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==" + }, + "enhanced-resolve@5.18.0": { + "integrity": "sha512-0/r0MySGYG8YqlayBZ6MuCfECmHFdJ5qyPh8s8wa5Hnm6SaFLSK1VYCbj+NKp090Nm1caZhD+QTnmxO7esYGyQ==", + "dependencies": [ + "graceful-fs", + "tapable" + ] + }, "esbuild@0.24.2": { "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==", "dependencies": [

@@ -422,6 +505,9 @@ "integrity": "sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ=="

}, "fsevents@2.3.3": { "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==" + }, + "graceful-fs@4.2.11": { + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, "http-link-header@1.1.3": { "integrity": "sha512-3cZ0SRL8fb9MUlU3mKM61FcQvPfXx2dBrZW3Vbg5CXa8jFlK8OaEpePenLe1oEXQduhz8b0QjsqfS59QP4AJDQ=="

@@ -435,6 +521,9 @@ "dependencies": [

"@types/estree" ] }, + "jiti@2.4.2": { + "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==" + }, "jose@5.9.6": { "integrity": "sha512-AMlnetc9+CV9asI19zHmrgS/WYsWUwCn2R7RzlbJWD7F9eWYUTGyBmU9o6PxngtLGOiDGPRu+Uc4fhKzbpteZQ==" },

@@ -465,6 +554,52 @@ },

"kleur@4.1.5": { "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==" }, + "lightningcss-darwin-arm64@1.29.1": { + "integrity": "sha512-HtR5XJ5A0lvCqYAoSv2QdZZyoHNttBpa5EP9aNuzBQeKGfbyH5+UipLWvVzpP4Uml5ej4BYs5I9Lco9u1fECqw==" + }, + "lightningcss-darwin-x64@1.29.1": { + "integrity": "sha512-k33G9IzKUpHy/J/3+9MCO4e+PzaFblsgBjSGlpAaFikeBFm8B/CkO3cKU9oI4g+fjS2KlkLM/Bza9K/aw8wsNA==" + }, + "lightningcss-freebsd-x64@1.29.1": { + "integrity": "sha512-0SUW22fv/8kln2LnIdOCmSuXnxgxVC276W5KLTwoehiO0hxkacBxjHOL5EtHD8BAXg2BvuhsJPmVMasvby3LiQ==" + }, + "lightningcss-linux-arm-gnueabihf@1.29.1": { + "integrity": "sha512-sD32pFvlR0kDlqsOZmYqH/68SqUMPNj+0pucGxToXZi4XZgZmqeX/NkxNKCPsswAXU3UeYgDSpGhu05eAufjDg==" + }, + "lightningcss-linux-arm64-gnu@1.29.1": { + "integrity": "sha512-0+vClRIZ6mmJl/dxGuRsE197o1HDEeeRk6nzycSy2GofC2JsY4ifCRnvUWf/CUBQmlrvMzt6SMQNMSEu22csWQ==" + }, + "lightningcss-linux-arm64-musl@1.29.1": { + "integrity": "sha512-UKMFrG4rL/uHNgelBsDwJcBqVpzNJbzsKkbI3Ja5fg00sgQnHw/VrzUTEc4jhZ+AN2BvQYz/tkHu4vt1kLuJyw==" + }, + "lightningcss-linux-x64-gnu@1.29.1": { + "integrity": "sha512-u1S+xdODy/eEtjADqirA774y3jLcm8RPtYztwReEXoZKdzgsHYPl0s5V52Tst+GKzqjebkULT86XMSxejzfISw==" + }, + "lightningcss-linux-x64-musl@1.29.1": { + "integrity": "sha512-L0Tx0DtaNUTzXv0lbGCLB/c/qEADanHbu4QdcNOXLIe1i8i22rZRpbT3gpWYsCh9aSL9zFujY/WmEXIatWvXbw==" + }, + "lightningcss-win32-arm64-msvc@1.29.1": { + "integrity": "sha512-QoOVnkIEFfbW4xPi+dpdft/zAKmgLgsRHfJalEPYuJDOWf7cLQzYg0DEh8/sn737FaeMJxHZRc1oBreiwZCjog==" + }, + "lightningcss-win32-x64-msvc@1.29.1": { + "integrity": "sha512-NygcbThNBe4JElP+olyTI/doBNGJvLs3bFCRPdvuCcxZCcCZ71B858IHpdm7L1btZex0FvCmM17FK98Y9MRy1Q==" + }, + "lightningcss@1.29.1": { + "integrity": "sha512-FmGoeD4S05ewj+AkhTY+D+myDvXI6eL27FjHIjoyUkO/uw7WZD1fBVs0QxeYWa7E17CUHJaYX/RUGISCtcrG4Q==", + "dependencies": [ + "detect-libc", + "lightningcss-darwin-arm64", + "lightningcss-darwin-x64", + "lightningcss-freebsd-x64", + "lightningcss-linux-arm-gnueabihf", + "lightningcss-linux-arm64-gnu", + "lightningcss-linux-arm64-musl", + "lightningcss-linux-x64-gnu", + "lightningcss-linux-x64-musl", + "lightningcss-win32-arm64-msvc", + "lightningcss-win32-x64-msvc" + ] + }, "locate-character@3.0.0": { "integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==" },

@@ -620,6 +755,12 @@ "magic-string",

"zimmerframe" ] }, + "tailwindcss@4.0.1": { + "integrity": "sha512-UK5Biiit/e+r3i0O223bisoS5+y7ZT1PM8Ojn0MxRHzXN1VPZ2KY6Lo6fhu1dOfCfyUAlK7Lt6wSxowRabATBw==" + }, + "tapable@2.2.1": { + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==" + }, "typescript@5.6.3": { "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==" },

@@ -644,10 +785,20 @@ "postcss",

"rollup" ] }, + "vite@6.0.7_lightningcss@1.29.1": { + "integrity": "sha512-RDt8r/7qx9940f8FcOIAH9PTViRrghKaK2K1jY3RaAURrEUbm9Du1mJ72G+jlhtG3WwodnfzY8ORQZbBavZEAQ==", + "dependencies": [ + "esbuild", + "fsevents", + "lightningcss", + "postcss", + "rollup" + ] + }, "vitefu@1.0.5_vite@6.0.7": { "integrity": "sha512-h4Vflt9gxODPFNGPwp4zAMZRpZR7eslzwH2c5hn5kNZ5rhnKyRJ50U+yGCdc2IRaBs8O4haIgLNGrV5CrpMsCA==", "dependencies": [ - "vite" + "vite@6.0.7" ] }, "zimmerframe@1.1.2": {

@@ -660,9 +811,12 @@ "dependencies": [

"npm:@inrupt/solid-client-authn-browser@^2.3.0", "npm:@inrupt/solid-client@^2.1.2", "npm:@sveltejs/vite-plugin-svelte@^5.0.3", + "npm:@tailwindcss/vite@^4.0.1", "npm:@tsconfig/svelte@^5.0.4", + "npm:daisyui@^5.0.0-beta.6", "npm:svelte-check@^4.1.1", "npm:svelte@^5.15.0", + "npm:tailwindcss@^4.0.1", "npm:typescript@~5.6.2", "npm:vite@^6.0.5" ]
M index.htmlindex.html

@@ -4,7 +4,7 @@ <head>

<meta charset="UTF-8" /> <link rel="icon" type="image/svg+xml" href="/vite.svg" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> - <title>Vite + Svelte + TS</title> + <title>kōi</title> </head> <body> <div id="app"></div>
M package.jsonpackage.json

@@ -20,6 +20,9 @@ },

"packageManager": "yarn@4.6.0", "dependencies": { "@inrupt/solid-client": "^2.1.2", - "@inrupt/solid-client-authn-browser": "^2.3.0" + "@inrupt/solid-client-authn-browser": "^2.3.0", + "@tailwindcss/vite": "^4.0.1", + "daisyui": "^5.0.0-beta.6", + "tailwindcss": "^4.0.1" } }
M src/app.csssrc/app.css

@@ -1,79 +1,14 @@

-:root { - font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; - line-height: 1.5; - font-weight: 400; - - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: #242424; - - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} -a:hover { - color: #535bf2; +@import "tailwindcss"; +@plugin "daisyui" { + themes: + light --default, + dark --prefersdark; } -body { - margin: 0; - display: flex; - place-items: center; - min-width: 320px; - min-height: 100vh; +.hashtag { + @apply text-secondary; } -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -.card { - padding: 2em; -} - -#app { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; -} - -button { - border-radius: 8px; - border: 1px solid transparent; - padding: 0.6em 1.2em; - font-size: 1em; - font-weight: 500; - font-family: inherit; - background-color: #1a1a1a; - cursor: pointer; - transition: border-color 0.25s; -} -button:hover { - border-color: #646cff; -} -button:focus, -button:focus-visible { - outline: 4px auto -webkit-focus-ring-color; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - a:hover { - color: #747bff; - } - button { - background-color: #f9f9f9; - } +a { + @apply text-primary; }
A src/lib/components/Profile.svelte

@@ -0,0 +1,16 @@

+<script lang="ts"> + import { getProfile } from "../solid"; +</script> + +<div> + {#await getProfile()} + Chargement... + {:then profile} + <div class="flex items-center gap-2"> + <a href={profile?.webId} target="_blank">{profile?.name}</a> + {#if profile?.image} + <img class="w-8 rounded-full" src={profile.image} alt={profile.webId} /> + {/if} + </div> + {/await} +</div>
M src/lib/components/Tasks.sveltesrc/lib/components/Tasks.svelte

@@ -4,6 +4,8 @@

let { tasks = [] }: { tasks: Task[] } = $props(); </script> -{#each tasks as task} - <TaskItem {task} /> -{/each} +<div class="flex flex-col gap-4 py-4"> + {#each tasks as task} + <TaskItem {task} /> + {/each} +</div>
M src/lib/solid.tssrc/lib/solid.ts

@@ -1,5 +1,11 @@

-import { getSolidDataset, getThingAll } from "@inrupt/solid-client"; -import { fetch } from "@inrupt/solid-client-authn-browser"; +import { + getSolidDataset, + getStringNoLocale, + getThingAll, + getUrl, +} from "@inrupt/solid-client"; +import { fetch, getDefaultSession } from "@inrupt/solid-client-authn-browser"; +import { FOAF, VCARD } from "@inrupt/vocab-common-rdf"; import { thingToTask } from "./models/task"; export const getPodTasks = async (podUrl: string) => {

@@ -10,20 +16,25 @@ const things = getThingAll(tasksDataset);

return things.map(thingToTask); }; -// export const getProfile = async (webId: string) => { -// const subjects = getAllSubjects(webId); +export const getProfile = async () => { + const session = getDefaultSession(); + const webId = session.info.webId; + if (!webId) return null; + const profileDataset = await getSolidDataset(webId, { fetch: fetch }); + const subjects = getThingAll(profileDataset); -// const findValue = (predicate: string) => -// subjects -// .map( -// subject => -// getStringNoLocale(subject, predicate) || getUrl(subject, predicate) -// ) -// ?.filter(i => !!i)[0]; + const findValue = (predicate: string) => + subjects + .map( + subject => + getStringNoLocale(subject, predicate) || getUrl(subject, predicate) + ) + ?.filter(i => !!i)[0]; -// return { -// name: findValue(FOAF.name), -// organization: findValue(VCARD.organization_name), -// image: findValue(VCARD.hasPhoto), -// }; -// }; + return { + name: findValue(FOAF.name), + organization: findValue(VCARD.organization_name), + image: findValue(VCARD.hasPhoto), + webId, + }; +};
M src/pages/Home.sveltesrc/pages/Home.svelte

@@ -11,6 +11,7 @@ import { getPodTasks } from "../lib/solid";

import tasks from "../lib/store/tasksStore"; import podInfo from "../lib/store/podInfoStore"; import { getPodUrlAll } from "@inrupt/solid-client"; + import Profile from "../lib/components/Profile.svelte"; let { navigate }: PageProps = $props(); let sessionInfo = $state(getDefaultSession()?.info);

@@ -37,12 +38,15 @@ }

}); </script> -{#if sessionInfo.isLoggedIn} - <div> - Hey {sessionInfo?.webId} ! +<main class="w-xl max-w-full mx-auto p-4"> + {#if sessionInfo.isLoggedIn} + <div class="flex justify-between"> + <h1 class="text-2xl mb-4">kōi</h1> + <Profile /> + </div> <Tasks tasks={$tasks} /> <NewTask /> - </div> -{:else} - Authentification... -{/if} + {:else} + <span class="loading loading-spinner loading-xl"></span> + {/if} +</main>
M vite.config.tsvite.config.ts

@@ -1,7 +1,8 @@

-import { defineConfig } from 'vite' -import { svelte } from '@sveltejs/vite-plugin-svelte' +import { defineConfig } from "vite"; +import { svelte } from "@sveltejs/vite-plugin-svelte"; +import tailwindcss from "@tailwindcss/vite"; // https://vite.dev/config/ export default defineConfig({ - plugins: [svelte()], -}) + plugins: [svelte(), tailwindcss()], +});