wsb-daemon 0.275.7622

wsb's daemon: the workbench, the GitHub mirror's schedule and peer continuity, for every workspace on the machine
<!--
  A project on GitHub: the repositories across its worktrees, and the boards it
  works from (`boards` in its committed `.wsb/project.json`).

  A board opens at its own address; a repository opens on GitHub.
-->
<script lang="ts">
  import { levels } from "../../stores/levels.svelte.js";
  import { router } from "../../stores/router.svelte.js";
  import { workbench } from "../../stores/workbench.svelte.js";
  import { opensInWorkbench } from "../../utils/open-link.js";

  interface Props {
    project: string;
  }

  let { project }: Props = $props();

  const detail = $derived(levels.details[project] ?? null);
  const failure = $derived(levels.detailErrors[project] ?? null);
  $effect(() => {
    if (!levels.details[project]) void levels.loadProject(project);
  });

  /** A board as the project names it, `owner/number`, at its address. */
  function boardPlace(ref: string) {
    const at = ref.lastIndexOf("/");
    return { level: "board" as const, owner: ref.slice(0, at), number: Number(ref.slice(at + 1)) };
  }

  function openBoard(event: MouseEvent, ref: string) {
    const place = boardPlace(ref);
    opensInWorkbench((beside) => workbench.openBoard(place.owner, place.number, { beside }))(event);
  }
</script>

<div class="project-github">
  {#if failure}
    <p class="project-github-error" role="alert">{failure}</p>
  {/if}
  {#if !detail && !failure}
    <p class="empty">Reading {project}…</p>
  {:else if detail}
    <div class="section-title">Repositories</div>
    {#if detail.repositories.length === 0}
      <p class="empty">No repository of {project} is on GitHub.</p>
    {:else}
      <ul>
        {#each detail.repositories as repository (repository)}
          <li>
            <a href="https://github.com/{repository}" target="_blank" rel="noreferrer">{repository}</a>
          </li>
        {/each}
      </ul>
    {/if}

    <div class="section-title">Boards</div>
    {#if detail.boards.length === 0}
      <p class="empty">{project} works from no board.</p>
    {:else}
      <ul>
        {#each detail.boards as board (board)}
          <li>
            <a href={router.href(boardPlace(board))} onclick={(event) => openBoard(event, board)}>{board}</a>
          </li>
        {/each}
      </ul>
    {/if}
  {/if}
</div>

<style>
  ul {
    list-style: none;
    margin: 0 0 var(--wb-spacing-8);
    padding: 0;
  }

  li {
    padding: var(--wb-spacing-2) 0;
    font-size: var(--wb-font-size-12);
    font-family: var(--vscode-editor-font-family, monospace);
  }

  a {
    color: var(--vscode-textLink-foreground);
    text-decoration: none;
  }

  a:hover {
    text-decoration: underline;
  }

  .project-github-error {
    color: var(--wb-error);
    font-size: var(--wb-font-size-12);
  }
</style>