~ knotless Search/
↑↓ move↵ open⇧↵ all results

chadtmiller.com/knotless

git that lives in your Atmosphere account

knotless.dev
1 collaborator

knotless 0.13.0 Latest 2 packages, 1 image

1
10

Labels are made and changed in a dialog, under the list

Merged chadtmiller.com asked to merge into main from chadtmiller.com/knotless:web/label-dialog
harness/e2e/flows.spec.mjs+11−5
@@ -389,14 +389,20 @@ test('changing what a repository says about itself', async () => {
test('defining, changing and deleting a label', async () => {
await go(page, '/alice.test/tally/settings/labels')
await page.getByLabel('New label').fill('kind/docs')
await page.getByLabel(/^Description/).fill('Words, not code')
await page.getByRole('button', { name: 'Create label' }).click()
await page.getByRole('button', { name: 'New label' }).click()
const dialog = page.getByRole('dialog', { name: 'New label' })
await dialog.getByLabel('Name').fill('kind/docs')
await dialog.getByLabel(/^Description/).fill('Words, not code')
await dialog.getByRole('button', { name: 'Create label' }).click()
await expect(dialog).toBeHidden()
const row = page.locator('li', { hasText: 'kind/docs' })
await expect(row).toContainText('Words, not code')
await row.getByRole('button', { name: 'Edit' }).click()
await page.getByLabel(/^Description/).fill('Words about the code')
await page.getByRole('button', { name: 'Save label' }).click()
const editing = page.getByRole('dialog', { name: 'Edit label' })
await expect(editing.getByLabel('Name')).toHaveValue('kind/docs')
await editing.getByLabel(/^Description/).fill('Words about the code')
await editing.getByRole('button', { name: 'Save changes' }).click()
await expect(editing).toBeHidden()
await expect(row).toContainText('Words about the code')
await anew(page, (expect) => expect(page.locator('li', { hasText: 'kind/docs' })).toContainText('Words about the code'))
page.once('dialog', (d) => d.accept())
harness/e2e/private.spec.mjs+5−2
@@ -63,8 +63,11 @@ test('creating a private repository', async () => {
test('defining a label', async () => {
await go(page, '/alice.test/vault/settings/labels')
await page.getByLabel('New label').fill('kind/secret')
await page.getByRole('button', { name: 'Create label' }).click()
await page.getByRole('button', { name: 'New label' }).click()
const dialog = page.getByRole('dialog', { name: 'New label' })
await dialog.getByLabel('Name').fill('kind/secret')
await dialog.getByRole('button', { name: 'Create label' }).click()
await expect(dialog).toBeHidden()
await expect(page.locator('li', { hasText: 'kind/secret' })).toBeVisible()
expect(knotless('alice', 'labels', vault)).toContain('kind/secret')
await anew(page, (expect) => expect(page.locator('li', { hasText: 'kind/secret' })).toBeVisible())
web/src/lib/molecules/Dialog.sveltenew+17−0
@@ -0,0 +1,17 @@
<script lang="ts">
import type { Snippet } from 'svelte';
/**
* A dialog over the dimmed page, opened by a button whose
* `popovertarget` is its `id`, or by `showPopover`: its `title`, a
* button to close it, then `children`. `class` names it for its own
* styles; `ontoggle` hears it open and close. While `held`, it
* cannot be closed by its button, as while a write it began is under way.
*/
let { id, title, class: kind = '', held = false, ontoggle, children }: { id: string; title: string; class?: string; held?: boolean; ontoggle?: (e: ToggleEvent) => void; children: Snippet } = $props();
</script>
<div class={['dialog', kind]} {id} popover="auto" role="dialog" aria-modal="true" aria-labelledby="{id}-title" {ontoggle}>
<h2 id="{id}-title">{title}</h2>
<button class="btn close" popovertarget={id} popovertargetaction="hide" aria-label="Close" disabled={held}>×</button>
{@render children()}
</div>
web/src/lib/organisms/DangerZone.svelte+3−4
@@ -8,6 +8,7 @@
import { urlPath } from '#lib/format.ts';
import type { AtIdentifierString } from '@atproto/lex';
import HandleInput from '#lib/molecules/HandleInput.svelte';
import Dialog from '#lib/molecules/Dialog.svelte';
/**
* What cannot be taken back, or not easily: offering `repo`, owned as
* `authority` names it, to another account, or withdrawing the offer
@@ -110,13 +111,11 @@
</div>
</section>
<div class="dialog" id="delete-repo" popover="auto" role="dialog" aria-modal="true" aria-labelledby="delete-title">
<h2 id="delete-title">{`Delete ${full}`}</h2>
<button class="btn close" popovertarget="delete-repo" popovertargetaction="hide" aria-label="Close">×</button>
<Dialog id="delete-repo" title={`Delete ${full}`}>
<form onsubmit={remove}>
<label for="delete-typed">{`To confirm, type ${full}`}</label>
<input id="delete-typed" name="confirm" autocapitalize="none" autocomplete="off" spellcheck="false" bind:value={typed} />
{#if deleteProblem}<p class="problem" role="alert">{deleteProblem}</p>{/if}
<button class="btn danger solid" type="submit" disabled={!!busy || typed !== full} aria-busy={busy === 'delete'}>{busy === 'delete' ? 'Deleting…' : 'Delete this repository'}</button>
</form>
</div>
</Dialog>
web/src/lib/organisms/DeleteData.svelte+3−4
@@ -5,6 +5,7 @@
import { goto, invalidateAll } from '$app/navigation';
import { ask, call, type Answer } from '#lib/data.ts';
import { urlPath } from '#lib/format.ts';
import Dialog from '#lib/molecules/Dialog.svelte';
/**
* Deleting every knotless record from the account `did`, logged in as
* `handle`, as `knotless delete-data` does: what there is, read when the
@@ -71,9 +72,7 @@
</div>
</section>
<div class="dialog delete-data" {id} popover="auto" role="dialog" aria-modal="true" aria-labelledby="{id}-title" ontoggle={(e) => (e as ToggleEvent).newState === 'open' && !held && read()}>
<h2 id="{id}-title">Delete your knotless data</h2>
<button class="btn close" popovertarget={id} popovertargetaction="hide" aria-label="Close" disabled={busy}>×</button>
<Dialog {id} class="delete-data" title="Delete your knotless data" held={busy} ontoggle={(e) => e.newState === 'open' && !held && read()}>
{#if reading}
<p class="hint" data-loading>Reading what your account holds…</p>
{:else if held && total === 0}
@@ -113,4 +112,4 @@
</form>
{/if}
{#if problem && !held}<p class="problem" role="alert">{problem}</p>{/if}
</div>
</Dialog>
web/src/lib/organisms/LoginDialog.svelte+3−4
@@ -1,6 +1,7 @@
<script lang="ts">
import { LOGIN } from '#lib/login.ts';
import HandleInput from '#lib/molecules/HandleInput.svelte';
import Dialog from '#lib/molecules/Dialog.svelte';
/**
* Logging in with an Atmosphere account: the handle, then the account's
* own server to approve it on, which sends the browser back to this page.
@@ -44,9 +45,7 @@
}
</script>
<div class="dialog" id={LOGIN} popover="auto" role="dialog" aria-modal="true" aria-labelledby="login-title">
<h2 id="login-title">Log in with your Atmosphere account</h2>
<button class="btn close" popovertarget={LOGIN} popovertargetaction="hide" aria-label="Close">×</button>
<Dialog id={LOGIN} title="Log in with your Atmosphere account">
<div class="apps" aria-hidden="true">
<div class="apps-run">
{#each [...apps, ...apps] as app, i (i)}<img src={icon(app)} alt="" width="40" height="40" loading="lazy" />{/each}
@@ -64,4 +63,4 @@
</div>
</form>
<p class="create">Don't have an account? <button type="button" onclick={() => login(true)} disabled={!!busy}>{busy === 'create' ? 'Opening…' : 'Create one'}</button></p>
</div>
</Dialog>
web/src/lib/organisms/MergeBox.svelte+3−4
@@ -16,6 +16,7 @@
import Command from '#lib/molecules/Command.svelte';
import MergeChecks from '#lib/organisms/MergeChecks.svelte';
import Reviewers from '#lib/organisms/Reviewers.svelte';
import Dialog from '#lib/molecules/Dialog.svelte';
/**
* The open pull `pull` on `repo`, into `base` from `head`, as GitHub's
* merge box shows one: where its `reviews` stand, its `checks`, then whether it merges with its
@@ -187,9 +188,7 @@
{/if}
</div>
{#if s.may.base || s.may.head}
<div class="dialog" id={retarget} popover="auto" role="dialog" aria-modal="true" aria-labelledby="{retarget}-title">
<h2 id="{retarget}-title">Retarget this pull</h2>
<button class="btn close" popovertarget={retarget} popovertargetaction="hide" aria-label="Close">×</button>
<Dialog id={retarget} title="Retarget this pull">
<form onsubmit={point}>
{#if s.may.base}
<label for="{retarget}-base">Base branch</label>
@@ -203,7 +202,7 @@
{/if}
<button class="btn primary" type="submit" disabled={!!busy} aria-busy={busy === 'retarget'}>{busy === 'retarget' ? 'Retargeting…' : 'Retarget'}</button>
</form>
</div>
</Dialog>
{/if}
{:else if logged && !merged && !problem}
<div class="row"><Icon name="running" /><span class="mute">Checking whether it can merge…</span></div>
web/src/lib/organisms/OrgDangerZone.svelte+3−4
@@ -3,6 +3,7 @@
import { goto, invalidateAll } from '$app/navigation';
import { call } from '#lib/data.ts';
import { urlPath } from '#lib/format.ts';
import Dialog from '#lib/molecules/Dialog.svelte';
/**
* Ending the organization the account `handle` is, once its handle is
* typed, as `knotless org delete` does: every member taken out, every
@@ -46,13 +47,11 @@
</section>
</div>
<div class="dialog" id="delete-org" popover="auto" role="dialog" aria-modal="true" aria-labelledby="delete-org-title">
<h2 id="delete-org-title">Delete organization</h2>
<button class="btn close" popovertarget="delete-org" popovertargetaction="hide" aria-label="Close">×</button>
<Dialog id="delete-org" title="Delete organization">
<form onsubmit={end}>
<label for="delete-org-typed">{`To confirm, type ${handle}`}</label>
<input id="delete-org-typed" name="confirm" autocapitalize="none" autocomplete="off" spellcheck="false" bind:value={typed} />
{#if problem}<p class="problem" role="alert">{problem}</p>{/if}
<button class="btn danger solid" type="submit" disabled={busy || typed !== handle} aria-busy={busy}>{busy ? 'Deleting…' : 'Delete organization'}</button>
</form>
</div>
</Dialog>
web/src/lib/organisms/OrgMembers.svelte+3−4
@@ -13,6 +13,7 @@
import Delegate from '#lib/molecules/Delegate.svelte';
import MemberList from '#lib/organisms/MemberList.svelte';
import HandleInput from '#lib/molecules/HandleInput.svelte';
import Dialog from '#lib/molecules/Dialog.svelte';
/**
* The Members tab of the account `did`, called `handle`, as `me` sees
* it, from what `org` answers: its members and invitations, and what
@@ -194,14 +195,12 @@
<p class="feed-note">To end the organization, go to <a href="/settings/organization">its settings</a>.</p>
{/if}
<div class="dialog" id="org-confirm" popover="auto" role="dialog" aria-modal="true" aria-labelledby="org-confirm-title">
<Dialog id="org-confirm" title={asking?.title ?? ''}>
{#if asking}
<h2 id="org-confirm-title">{asking.title}</h2>
<button class="btn close" popovertarget="org-confirm" popovertargetaction="hide" aria-label="Close">×</button>
<p class="ask">{asking.body}</p>
<div class="actions">
<button class="btn" type="button" popovertarget="org-confirm" popovertargetaction="hide">Cancel</button>
<button class="btn danger solid" type="button" disabled={!!busy} aria-busy={busy === 'confirm'} onclick={confirm}>{busy === 'confirm' ? asking.busy : asking.ok}</button>
</div>
{/if}
</div>
</Dialog>
web/src/lib/organisms/ReportDialog.svelte+3−4
@@ -2,6 +2,7 @@
import type * as createReport from '#lib/lexicons/dev/knotless/createReport.ts';
import { call } from '#lib/data.ts';
import { REPORT, reporting } from '#lib/report.svelte.ts';
import Dialog from '#lib/molecules/Dialog.svelte';
/**
* Reporting what `reporting` names to the moderation service, as whoever
* is logged in: why, from atproto's reasons, and more in words.
@@ -41,9 +42,7 @@
}
</script>
<div class="dialog" id={REPORT} popover="auto" role="dialog" aria-modal="true" aria-labelledby="report-title" ontoggle={toggled}>
<h2 id="report-title">{`Report ${reporting.what || 'this'}`}</h2>
<button class="btn close" popovertarget={REPORT} popovertargetaction="hide" aria-label="Close">×</button>
<Dialog id={REPORT} title={`Report ${reporting.what || 'this'}`} ontoggle={toggled}>
{#if sent}
<p class="sent">Sent to the moderators. Thank you.</p>
{:else}
@@ -58,4 +57,4 @@
<button class="btn primary" type="submit" disabled={busy || !reporting.subject} aria-busy={busy}>{busy ? 'Sending…' : 'Send report'}</button>
</form>
{/if}
</div>
</Dialog>
web/src/lib/organisms/RunWorkflow.svelte+3−4
web/src/lib/organisms/SettingsLabels.svelte+57−35
web/src/lib/organisms/StartOrgDialog.svelte+3−4
web/src/lib/organisms/ThemeBrowser.svelte+3−4
web/src/app.css+12−2