mirror of
https://seed.radicle.dev/rad:z4V1sjrXqjvFdnCUbxPFqd5p4DtH5.git
synced 2026-11-03 18:50:30 +08:00
Allow opening links in a new tab
Signed-off-by: Rūdolfs Ošiņš <rudolfs@osins.org>
This commit is contained in:
@@ -144,14 +144,6 @@ p {
|
||||
.txt-faded {
|
||||
color: var(--color-foreground-5);
|
||||
}
|
||||
.txt-title {
|
||||
font-size: var(--font-size-large);
|
||||
font-weight: var(--font-weight-normal);
|
||||
color: var(--color-secondary);
|
||||
text-align: left;
|
||||
text-overflow: ellipsis;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
.txt-link {
|
||||
color: var(--color-foreground-6);
|
||||
text-decoration: none;
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
{#each results as result}
|
||||
<li>
|
||||
<Link
|
||||
on:click={modal.hide}
|
||||
on:afterNavigate={modal.hide}
|
||||
route={{
|
||||
resource: "projects",
|
||||
params: {
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
class="item selector"
|
||||
on:click|stopPropagation={() => (showFonts = !showFonts)}>
|
||||
<div>Code font</div>
|
||||
<Icon name={`chevron-${showFonts ? "up" : "down"}`} />
|
||||
<Icon name={`chevron-${showFonts ? "down" : "right"}`} />
|
||||
</div>
|
||||
{#if showFonts}
|
||||
<div
|
||||
@@ -112,7 +112,7 @@
|
||||
style:font-family={font.fontFamily}>
|
||||
{font.displayName}
|
||||
{#if isSelectedFont}
|
||||
<Icon name="checkmark" />
|
||||
<Icon name="checkmark-small" />
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
align-items: center;
|
||||
color: var(--color-foreground-6);
|
||||
padding: 0.125rem 0;
|
||||
gap: 0.25rem;
|
||||
}
|
||||
.id {
|
||||
overflow: hidden;
|
||||
@@ -24,7 +25,6 @@
|
||||
white-space: nowrap;
|
||||
}
|
||||
.body {
|
||||
margin: 0 0.4rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
display: inline-block !important;
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
.section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
max-width: 13rem;
|
||||
max-width: 13.5rem;
|
||||
padding: 0.2rem 0.5rem;
|
||||
}
|
||||
.text {
|
||||
|
||||
@@ -1,19 +1,30 @@
|
||||
<script lang="ts" strictEvents>
|
||||
import debounce from "lodash/debounce";
|
||||
import { createEventDispatcher } from "svelte";
|
||||
|
||||
import Icon from "@app/components/Icon.svelte";
|
||||
import { toClipboard } from "@app/lib/utils";
|
||||
|
||||
const dispatch = createEventDispatcher<{ copied: never }>();
|
||||
|
||||
const copy = () => {
|
||||
toClipboard(text);
|
||||
dispatch("copied");
|
||||
};
|
||||
import Icon from "@app/components/Icon.svelte";
|
||||
|
||||
export let text: string;
|
||||
export let small = false;
|
||||
export let tooltip: string | undefined = undefined;
|
||||
|
||||
const dispatch = createEventDispatcher<{ copied: never }>();
|
||||
|
||||
let icon: "clipboard-small" | "checkmark-small" | "clipboard" | "checkmark" =
|
||||
small ? "clipboard-small" : "clipboard";
|
||||
|
||||
const restoreIcon = debounce(() => {
|
||||
icon = small ? "clipboard-small" : "clipboard";
|
||||
}, 800);
|
||||
|
||||
const copy = () => {
|
||||
toClipboard(text);
|
||||
dispatch("copied");
|
||||
icon = small ? "checkmark-small" : "checkmark";
|
||||
restoreIcon();
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@@ -24,6 +35,7 @@
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
user-select: none;
|
||||
}
|
||||
.clipboard.small {
|
||||
width: 1.5rem;
|
||||
@@ -46,9 +58,5 @@
|
||||
class="clipboard"
|
||||
class:small
|
||||
on:click|stopPropagation={copy}>
|
||||
{#if small}
|
||||
<Icon name="clipboard-small" />
|
||||
{:else}
|
||||
<Icon name="clipboard" />
|
||||
{/if}
|
||||
<Icon name={icon} />
|
||||
</span>
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
{#if stackTrace}
|
||||
<div class="stack-trace">
|
||||
<Clipboard
|
||||
small
|
||||
tooltip="Copy error to clipboard"
|
||||
text={JSON.stringify({ errorMessage: message, stackTrace }, null, 2)} />
|
||||
</div>
|
||||
|
||||
+218
-189
@@ -6,6 +6,8 @@
|
||||
| "checkmark"
|
||||
| "checkmark-small"
|
||||
| "chevron-down"
|
||||
| "chevron-left"
|
||||
| "chevron-right"
|
||||
| "chevron-up"
|
||||
| "clipboard"
|
||||
| "clipboard-small"
|
||||
@@ -36,41 +38,44 @@
|
||||
viewBox="0 0 24 24">
|
||||
{#if name === "browse"}
|
||||
<path
|
||||
d="M8.46934 7.23871C8.61151 7.10623 8.79956 7.03411 8.99386
|
||||
7.03753C9.18816 7.04096 9.37355 7.11967 9.51096 7.25709C9.64838 7.3945
|
||||
9.72709 7.57988 9.73052 7.77419C9.73394 7.96849 9.66182 8.15653 9.52934
|
||||
8.29871L5.80934 12.0187L9.52934 15.7387C9.60303 15.8074 9.66213 15.8902
|
||||
9.70312 15.9822C9.74411 16.0742 9.76615 16.1735 9.76793 16.2742C9.76971
|
||||
16.3749 9.75118 16.4749 9.71346 16.5683C9.67574 16.6617 9.6196 16.7465
|
||||
9.54838 16.8177C9.47716 16.889 9.39233 16.9451 9.29894 16.9828C9.20555
|
||||
17.0206 9.10552 17.0391 9.00482 17.0373C8.90411 17.0355 8.8048 17.0135
|
||||
8.7128 16.9725C8.6208 16.9315 8.538 16.8724 8.46934 16.7987L4.21934
|
||||
12.5487C4.07889 12.4081 4 12.2175 4 12.0187C4 11.82 4.07889 11.6293 4.21934
|
||||
11.4887L8.46934 7.23871V7.23871ZM15.0293 7.23871C14.9607 7.16502 14.8779
|
||||
7.10592 14.7859 7.06493C14.6939 7.02394 14.5946 7.00189 14.4939
|
||||
7.00012C14.3932 6.99834 14.2931 7.01686 14.1997 7.05459C14.1064 7.09231
|
||||
14.0215 7.14845 13.9503 7.21967C13.8791 7.29089 13.8229 7.37572 13.7852
|
||||
7.46911C13.7475 7.5625 13.729 7.66253 13.7307 7.76323C13.7325 7.86393
|
||||
13.7546 7.96325 13.7956 8.05525C13.8366 8.14725 13.8957 8.23005 13.9693
|
||||
8.29871L17.6893 12.0187L13.9693 15.7387C13.8957 15.8074 13.8366 15.8902
|
||||
13.7956 15.9822C13.7546 16.0742 13.7325 16.1735 13.7307 16.2742C13.729
|
||||
16.3749 13.7475 16.4749 13.7852 16.5683C13.8229 16.6617 13.8791 16.7465
|
||||
13.9503 16.8177C14.0215 16.889 14.1064 16.9451 14.1997 16.9828C14.2931
|
||||
17.0206 14.3932 17.0391 14.4939 17.0373C14.5946 17.0355 14.6939 17.0135
|
||||
14.7859 16.9725C14.8779 16.9315 14.9607 16.8724 15.0293 16.7987L19.2793
|
||||
12.5487C19.4198 12.4081 19.4987 12.2175 19.4987 12.0187C19.4987 11.82
|
||||
19.4198 11.6293 19.2793 11.4887L15.0293 7.23871V7.23871Z" />
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M9.35356 6.64645C9.54882 6.84171 9.54882 7.15829 9.35356
|
||||
7.35355L5.06066 11.6464C4.8654 11.8417 4.8654 12.1583 5.06066
|
||||
12.3536L9.35356 16.6464C9.54882 16.8417 9.54882 17.1583 9.35356
|
||||
17.3536C9.15829 17.5488 8.84171 17.5488 8.64645 17.3536L4.35355
|
||||
13.0607C3.76777 12.4749 3.76777 11.5251 4.35356 10.9393L8.64645
|
||||
6.64645C8.84171 6.45118 9.15829 6.45118 9.35356 6.64645ZM14.6464
|
||||
6.64645C14.8417 6.45118 15.1583 6.45118 15.3536 6.64645L19.6464
|
||||
10.9393C20.2322 11.5251 20.2322 12.4749 19.6464 13.0607L15.3536
|
||||
17.3536C15.1583 17.5488 14.8417 17.5488 14.6464 17.3536C14.4512 17.1583
|
||||
14.4512 16.8417 14.6464 16.6464L18.9393 12.3536C19.1346 12.1583 19.1346
|
||||
11.8417 18.9393 11.6464L14.6464 7.35355C14.4512 7.15829 14.4512 6.84171
|
||||
14.6464 6.64645Z" />
|
||||
{:else if name === "clipboard"}
|
||||
<path
|
||||
d="M9 5H14.7071L18 8.29289V17H9V5ZM10 6V16H17V9H14V6H10ZM15
|
||||
6.70711L16.2929 8H15V6.70711ZM7 8H8V18H15V19H7V8Z" />
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M8.5 6C8.5 5.17157 9.17157 4.5 10 4.5H18C18.8284 4.5 19.5 5.17157 19.5
|
||||
6V14C19.5 14.8284 18.8284 15.5 18 15.5H15.5V18C15.5 18.8284 14.8284 19.5
|
||||
14 19.5H6C5.17157 19.5 4.5 18.8284 4.5 18V10C4.5 9.17157 5.17157 8.5 6
|
||||
8.5H8.5V6ZM8.5 9.5H6C5.72386 9.5 5.5 9.72386 5.5 10V18C5.5 18.2761
|
||||
5.72386 18.5 6 18.5H14C14.2761 18.5 14.5 18.2761 14.5 18V15.5H10C9.17157
|
||||
15.5 8.5 14.8284 8.5 14V9.5ZM10 5.5C9.72386 5.5 9.5 5.72386 9.5 6V14C9.5
|
||||
14.2761 9.72386 14.5 10 14.5H18C18.2761 14.5 18.5 14.2761 18.5 14V6C18.5
|
||||
5.72386 18.2761 5.5 18 5.5H10Z" />
|
||||
{:else if name === "clipboard-small"}
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M14 7L17 10V16H10V7H14ZM13
|
||||
8H11V15H16V11H13V8ZM14 8.41421V10H15.5858L14 8.41421ZM8
|
||||
10H9V17H14V18H8V10Z" />
|
||||
d="M10 6.5C10 5.67157 10.6716 5 11.5 5H17.5C18.3284 5 19 5.67157 19
|
||||
6.5V12.5C19 13.3284 18.3284 14 17.5 14H15V16.5C15 17.3284 14.3284 18 13.5
|
||||
18H7.5C6.67157 18 6 17.3284 6 16.5V10.5C6 9.67157 6.67157 9 7.5
|
||||
9H10V6.5ZM10 10H7.5C7.22386 10 7 10.2239 7 10.5V16.5C7 16.7761 7.22386 17
|
||||
7.5 17H13.5C13.7761 17 14 16.7761 14 16.5V14H11.5C10.6716 14 10 13.3284
|
||||
10 12.5V10ZM11.5 13C11.2239 13 11 12.7761 11 12.5V6.5C11 6.22386 11.2239
|
||||
6 11.5 6H17.5C17.7761 6 18 6.22386 18 6.5V12.5C18 12.7761 17.7761 13 17.5
|
||||
13H11.5Z" />
|
||||
{:else if name === "chat"}
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
@@ -88,161 +93,161 @@
|
||||
13.5H8C7.72386 13.5 7.5 13.2761 7.5 13Z" />
|
||||
{:else if name === "ellipsis"}
|
||||
<path
|
||||
d="M7 12a2 2 0 1 1-4.001-.001A2 2 0 0 1 7 12zm12-2a2 2 0 1 0 .001
|
||||
4.001A2 2 0 0 0 19 10zm-7 0a2 2 0 1 0 .001 4.001A2 2 0 0 0 12 10z" />
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M5.5 13C6.32843 13 7 12.3284 7 11.5C7 10.6716 6.32843 10 5.5
|
||||
10C4.67157 10 4 10.6716 4 11.5C4 12.3284 4.67157 13 5.5 13ZM13.5
|
||||
11.5C13.5 12.3284 12.8284 13 12 13C11.1716 13 10.5 12.3284 10.5 11.5C10.5
|
||||
10.6716 11.1716 10 12 10C12.8284 10 13.5 10.6716 13.5 11.5ZM20 11.5C20
|
||||
12.3284 19.3284 13 18.5 13C17.6716 13 17 12.3284 17 11.5C17 10.6716
|
||||
17.6716 10 18.5 10C19.3284 10 20 10.6716 20 11.5Z" />
|
||||
{:else if name === "chevron-down"}
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="m 16.353549 9.8535548 c 0.19527 0.1952622 0.19527 0.5118432 0
|
||||
0.7071032 l -3.29289 3.2929 c -0.58579 0.58578 -1.53553 0.58578
|
||||
-2.12132 0 l -3.292894 -3.2929 c -0.195262 -0.19526 -0.195262
|
||||
-0.511841 0 -0.7071042 0.195263 -0.195262 0.511844 -0.195262
|
||||
0.707104 0 l 3.2929 3.2928942 c 0.19526 0.19526 0.51184 0.19526
|
||||
0.7071 0 l 3.2929 -3.2928932 c 0.19526 -0.195262 0.51184
|
||||
-0.195262 0.7071 0 z" />
|
||||
d="M16.3536 9.64645C16.5488 9.84171 16.5488 10.1583 16.3536
|
||||
10.3536L13.0607 13.6464C12.4749 14.2322 11.5251 14.2322 10.9393
|
||||
13.6464L7.64645 10.3536C7.45118 10.1583 7.45118 9.84171 7.64645
|
||||
9.64645C7.84171 9.45118 8.15829 9.45118 8.35355 9.64645L11.6464
|
||||
12.9393C11.8417 13.1346 12.1583 13.1346 12.3536 12.9393L15.6464
|
||||
9.64645C15.8417 9.45118 16.1583 9.45118 16.3536 9.64645Z" />
|
||||
{:else if name === "chevron-up"}
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M7.64645 14.3536C7.45118 14.1583 7.45118 13.8417 7.64645
|
||||
13.6464L10.9393 10.3536C11.5251 9.76777 12.4749 9.76777 13.0607
|
||||
10.3536L16.3536 13.6464C16.5488 13.8417 16.5488 14.1583 16.3536
|
||||
14.3536C16.1583 14.5488 15.8417 14.5488 15.6464 14.3536L12.3536
|
||||
11.0607C12.1583 10.8654 11.8417 10.8654 11.6464 11.0607L8.35355
|
||||
14.3536C8.15829 14.5488 7.84171 14.5488 7.64645 14.3536Z" />
|
||||
13.6464L10.9393 10.3536C11.5251 9.76777 12.4749 9.76777 13.0607
|
||||
10.3536L16.3536 13.6464C16.5488 13.8417 16.5488 14.1583 16.3536
|
||||
14.3536C16.1583 14.5488 15.8417 14.5488 15.6464 14.3536L12.3536
|
||||
11.0607C12.1583 10.8654 11.8417 10.8654 11.6464 11.0607L8.35355
|
||||
14.3536C8.15829 14.5488 7.84171 14.5488 7.64645 14.3536Z" />
|
||||
{:else if name === "chevron-left"}
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M14.3536 16.3536C14.1583 16.5488 13.8417 16.5488 13.6464
|
||||
16.3536L10.3536 13.0607C9.76777 12.4749 9.76777 11.5251 10.3536
|
||||
10.9393L13.6464 7.64645C13.8417 7.45119 14.1583 7.45119 14.3536
|
||||
7.64645C14.5488 7.84171 14.5488 8.15829 14.3536 8.35355L11.0607
|
||||
11.6464C10.8654 11.8417 10.8654 12.1583 11.0607 12.3536L14.3536
|
||||
15.6464C14.5488 15.8417 14.5488 16.1583 14.3536 16.3536Z" />
|
||||
{:else if name === "chevron-right"}
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M9.64645 7.64645C9.84171 7.45118 10.1583 7.45118 10.3536
|
||||
7.64645L13.6464 10.9393C14.2322 11.5251 14.2322 12.4749 13.6464
|
||||
13.0607L10.3536 16.3536C10.1583 16.5488 9.84171 16.5488 9.64645
|
||||
16.3536C9.45118 16.1583 9.45118 15.8417 9.64645 15.6464L12.9393
|
||||
12.3536C13.1346 12.1583 13.1346 11.8417 12.9393 11.6464L9.64645
|
||||
8.35355C9.45118 8.15829 9.45118 7.84171 9.64645 7.64645Z" />
|
||||
{:else if name === "gear"}
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M9.23219 2.01728C9.38084
|
||||
1.97716 9.53969 2.00775 9.66279 2.10022L11.5852 3.5442C11.8032 3.53214
|
||||
12.0218 3.53214 12.2398 3.5442L14.1622 2.10022C14.2851 2.00788 14.4437
|
||||
1.97724 14.5922 2.01712C15.4415 2.24523 16.2573 2.58349 17.0188
|
||||
3.02327C17.1517 3.10003 17.242 3.23359 17.2637 3.38554L17.5851
|
||||
5.63541L20.5219 6.58028C20.6402 6.61834 20.7401 6.69907 20.8021
|
||||
6.80675C21.2406 7.56841 21.5787 8.38367 21.8077 9.23219C21.8479 9.38084
|
||||
21.8173 9.53969 21.7248 9.66279L20.2747 11.5933C20.2763 11.6489 20.278
|
||||
11.7141 20.2792 11.7842C20.2816 11.9194 20.2827 12.0847 20.2779
|
||||
12.236L21.7248 14.1622C21.8171 14.2851 21.8478 14.4437 21.8079
|
||||
14.5922C21.5798 15.4415 21.2415 16.2573 20.8017 17.0188C20.7397 17.1262
|
||||
20.64 17.2067 20.5219 17.2447L17.5851 18.1896L17.2637 20.4395C17.242 20.5916
|
||||
17.1515 20.7253 17.0183 20.8021C16.2566 21.2406 15.4413 21.5787 14.5928
|
||||
21.8077C14.4442 21.8479 14.2853 21.8173 14.1622 21.7248L12.2398
|
||||
20.2808C12.0255 20.2927 11.8107 20.2929 11.5964 20.2814L9.72748
|
||||
21.8005C9.60295 21.9017 9.4374 21.937 9.28241 21.8954C8.41326 21.6619
|
||||
7.54437 21.228 6.8062 20.8017C6.67328 20.725 6.58299 20.5914 6.56128
|
||||
20.4395L6.22012 18.0514C6.06864 17.9052 5.91981 17.7564 5.77364
|
||||
17.6049L3.38554 17.2637C3.23337 17.242 3.09966 17.1515 3.02295
|
||||
17.0183C2.58438 16.2566 2.24635 15.4413 2.01728 14.5928C1.97716 14.4442
|
||||
2.00775 14.2853 2.10022 14.1622L3.55032 12.2317C3.54868 12.1761 3.54702
|
||||
12.1109 3.54579 12.0409C3.5434 11.9056 3.54229 11.7403 3.5471
|
||||
11.5891L2.10022 9.66279C2.00788 9.53986 1.97724 9.38129 2.01712
|
||||
9.23281C2.24523 8.38352 2.58349 7.56772 3.02327 6.8062C3.10003 6.67328
|
||||
3.23359 6.58299 3.38554 6.56128L5.77364 6.22012C5.91981 6.06864 6.06864
|
||||
5.91981 6.22012 5.77364L6.56128 3.38554C6.58302 3.23337 6.67354 3.09966
|
||||
6.80675 3.02295C7.56841 2.58438 8.38367 2.24635 9.23219 2.01728ZM4.55577
|
||||
12.3686C4.56087 12.4844 4.52562 12.5983 4.45604 12.6909L3.04873
|
||||
14.5645C3.22919 15.1693 3.47157 15.7538 3.77202 16.3088L6.08634
|
||||
16.6394C6.19815 16.6554 6.30125 16.7087 6.37886 16.7908C6.59125 17.0153
|
||||
6.8097 17.2338 7.03423 17.4461C7.11628 17.5238 7.16963 17.6269 7.1856
|
||||
17.7387L7.51653 20.0552C8.09055 20.3755 8.70317 20.6699 9.30047
|
||||
20.8589L11.119 19.3808C11.2199 19.2987 11.3489 19.2592 11.4784
|
||||
19.2707C11.7672 19.2962 12.0578 19.2962 12.3466 19.2707C12.4696 19.2598
|
||||
12.5922 19.2948 12.6909 19.369L14.5645 20.7763C15.1693 20.5958 15.7538
|
||||
20.3534 16.3088 20.053L16.6394 17.7387C16.6665 17.5493 16.7992 17.392
|
||||
16.9812 17.3334L20.0293 16.3527C20.3415 15.7851 20.5919 15.1857 20.7765
|
||||
14.5648L19.369 12.6909C19.2948 12.5922 19.2598 12.4696 19.2707
|
||||
12.3467C19.2822 12.2167 19.2829 12.0017 19.2794 11.8018C19.2777 11.7056
|
||||
19.2751 11.6187 19.273 11.5559L19.2703 11.4822L19.2695 11.4626L19.2693
|
||||
11.4577L19.2692 11.4566C19.2641 11.3409 19.2994 11.2267 19.369
|
||||
11.1341L20.7763 9.26051C20.591 8.63973 20.3405 8.04027 20.029
|
||||
7.47218L16.9812 6.4916C16.7992 6.43302 16.6665 6.27569 16.6394
|
||||
6.08634L16.3087 3.77166C15.7541 3.47068 15.1696 3.22832 14.5648
|
||||
3.04851L12.6909 4.45604C12.5922 4.53018 12.4696 4.56518 12.3466
|
||||
4.55431C12.0578 4.52877 11.7672 4.52877 11.4784 4.55431C11.3554 4.56518
|
||||
11.2328 4.53018 11.1341 4.45604L9.26051 3.04873C8.65575 3.22919 8.07123
|
||||
3.47157 7.51622 3.77202L7.1856 6.08634C7.16963 6.19815 7.11628 6.30125
|
||||
7.03423 6.37886C6.8097 6.59125 6.59125 6.8097 6.37886 7.03423C6.30125
|
||||
7.11628 6.19815 7.16963 6.08634 7.1856L3.77166 7.51627C3.47068 8.07088
|
||||
3.22832 8.65536 3.04851 9.26022L4.45604 11.1341C4.53016 11.2328 4.56517
|
||||
11.3554 4.55432 11.4783C4.54285 11.6083 4.5421 11.8233 4.54563
|
||||
12.0232C4.54733 12.1194 4.54988 12.2063 4.55201 12.2691L4.55471
|
||||
12.3429L4.55551 12.3624L4.55577 12.3686ZM11.9121 8.41248C9.97912 8.41248
|
||||
8.41211 9.97948 8.41211 11.9125C8.41211 13.8455 9.97912 15.4125 11.9121
|
||||
15.4125C13.8451 15.4125 15.4121 13.8455 15.4121 11.9125C15.4121 9.97948
|
||||
13.8451 8.41248 11.9121 8.41248ZM7.41211 11.9125C7.41211 9.4272 9.42683
|
||||
7.41248 11.9121 7.41248C14.3974 7.41248 16.4121 9.4272 16.4121
|
||||
11.9125C16.4121 14.3978 14.3974 16.4125 11.9121 16.4125C9.42683 16.4125
|
||||
7.41211 14.3978 7.41211 11.9125Z" />
|
||||
d="M12 7.5C9.51472 7.5 7.5 9.51472 7.5 12C7.5 14.4853 9.51472 16.5 12
|
||||
16.5C14.4853 16.5 16.5 14.4853 16.5 12C16.5 9.51472 14.4853 7.5 12
|
||||
7.5ZM8.5 12C8.5 10.067 10.067 8.5 12 8.5C13.933 8.5 15.5 10.067 15.5
|
||||
12C15.5 13.933 13.933 15.5 12 15.5C10.067 15.5 8.5 13.933 8.5 12Z" />
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M9.31972 2.10481C9.46836 2.06468 9.62721 2.09528 9.75032
|
||||
2.18775L11.6727 3.63172C11.8908 3.61967 12.1093 3.61967 12.3273
|
||||
3.63172L14.2497 2.18775C14.3727 2.09541 14.5312 2.06476 14.6797
|
||||
2.10464C15.529 2.33276 16.3448 2.67101 17.1063 3.1108C17.2392 3.18756
|
||||
17.3295 3.32112 17.3513 3.47307L17.692 5.85812C17.8472 6.00529 17.9972
|
||||
6.15528 18.1421 6.30811L20.527 6.6488C20.6792 6.67054 20.8129 6.76107
|
||||
20.8896 6.89428C21.1184 7.29169 21.3199 7.7037 21.4928 8.12741C21.6512
|
||||
8.51576 21.7857 8.91393 21.8952 9.31972C21.9354 9.46836 21.9048 9.62721
|
||||
21.8123 9.75032L20.2861 11.7822V12.2617L21.8123 14.2935C21.9047 14.4164
|
||||
21.9353 14.575 21.8954 14.7235C21.6673 15.5728 21.3291 16.3886 20.8893
|
||||
17.1501C20.8125 17.283 20.6789 17.3733 20.527 17.395L18.1389
|
||||
17.7362C17.9927 17.8877 17.8439 18.0365 17.6924 18.1827L17.3513
|
||||
20.5708C17.3295 20.7229 17.239 20.8566 17.1058 20.9333C16.3441 21.3719
|
||||
15.5289 21.7099 14.6803 21.939C14.5317 21.9791 14.3729 21.9485 14.2497
|
||||
21.8561L12.3273 20.4121C12.1093 20.4242 11.8908 20.4242 11.6727
|
||||
20.4121L9.75032 21.8561C9.62739 21.9484 9.46882 21.9791 9.32033
|
||||
21.9392C8.47105 21.7111 7.65525 21.3728 6.89373 20.933C6.76081 20.8563
|
||||
6.67052 20.7227 6.64881 20.5708L6.30809 18.1857C6.15289 18.0385 6.00284
|
||||
17.8885 5.85795 17.7357L3.47307 17.395C3.3209 17.3733 3.18719 17.2828
|
||||
3.11048 17.1495C2.88165 16.7521 2.68018 16.3401 2.50729 15.9164C2.34882
|
||||
15.5281 2.21436 15.1299 2.10481 14.7241C2.06469 14.5755 2.09528 14.4166
|
||||
2.18775 14.2935L3.71344 12.2623V11.7815L2.18775 9.75032C2.09541 9.62739
|
||||
2.06476 9.46881 2.10464 9.32033C2.33276 8.47104 2.67101 7.65525 3.1108
|
||||
6.89373C3.18756 6.76081 3.32112 6.67051 3.47307 6.6488L5.86116
|
||||
6.30765C6.00733 6.15616 6.15616 6.00733 6.30765 5.86116L6.6488
|
||||
3.47307C6.67054 3.3209 6.76107 3.18718 6.89428 3.11048C7.65593 2.67191
|
||||
8.4712 2.33387 9.31972 2.10481ZM19.4565 11.2216C19.3906 11.3094 19.3579
|
||||
11.4117 19.3563 11.5137H19.351V12.5316L19.3563 12.5301C19.3579 12.632
|
||||
19.3906 12.7344 19.4565 12.8222L20.864 14.6961C20.6842 15.3009 20.4419
|
||||
15.8854 20.1409 16.44L17.8262 16.7707C17.7144 16.7867 17.6113 16.84
|
||||
17.5337 16.9221C17.3213 17.1466 17.1028 17.365 16.8783 17.5774C16.7963
|
||||
17.655 16.7429 17.7582 16.7269 17.87L16.3963 20.1843C15.8413 20.4847
|
||||
15.2568 20.7271 14.652 20.9076L12.7784 19.5003C12.6797 19.4261 12.5571
|
||||
19.3911 12.4341 19.402C12.1453 19.4275 11.8548 19.4275 11.5659
|
||||
19.402C11.443 19.3911 11.3203 19.4261 11.2216 19.5003L9.34775
|
||||
20.9078C8.74289 20.728 8.15841 20.4856 7.6038 20.1846L7.27313
|
||||
17.87C7.25684 17.7559 7.20165 17.651 7.1169 17.5729C6.88932 17.3633
|
||||
6.67417 17.1481 6.47132 16.9274C6.39323 16.8424 6.28813 16.787 6.17387
|
||||
16.7707L3.85955 16.4401C3.70108 16.1473 3.55877 15.8464 3.43317
|
||||
15.5386C3.32064 15.2628 3.22154 14.9816 3.13626 14.6958L4.54357
|
||||
12.8222C4.60946 12.7345 4.64214 12.6321 4.64375 12.5302L4.64855
|
||||
12.5316V11.5137H4.64375C4.64215 11.4117 4.60947 11.3094 4.54356
|
||||
11.2216L3.13604 9.34774C3.31584 8.74288 3.5582 8.15841 3.85919
|
||||
7.6038L6.17386 7.27313C6.28567 7.25716 6.38877 7.2038 6.46639
|
||||
7.12175C6.67878 6.89723 6.89723 6.67878 7.12175 6.46639C7.2038 6.38877
|
||||
7.25716 6.28567 7.27313 6.17386L7.60374 3.85954C8.15875 3.5591 8.74328
|
||||
3.31672 9.34803 3.13625L11.2216 4.54356C11.3203 4.6177 11.443 4.65271
|
||||
11.5659 4.64184C11.8548 4.6163 12.1453 4.6163 12.4341 4.64184C12.5571
|
||||
4.65271 12.6797 4.6177 12.7784 4.54356L14.6523 3.13604C15.2572 3.31584
|
||||
15.8416 3.5582 16.3963 3.85919L16.7269 6.17386C16.7432 6.28793 16.7984
|
||||
6.39287 16.8832 6.47093C17.1107 6.68053 17.3259 6.89572 17.5287
|
||||
7.11647C17.6068 7.20145 17.7119 7.25681 17.8262 7.27313L20.1405
|
||||
7.60374C20.299 7.89648 20.4413 8.19742 20.5669 8.50522C20.6794 8.78098
|
||||
20.7785 9.06225 20.8638 9.34803L19.4565 11.2216Z" />
|
||||
{:else if name === "fork"}
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M8.34375 6.9375C7.5671
|
||||
6.9375 6.9375 7.5671 6.9375 8.34375C6.9375 9.1204 7.5671 9.75 8.34375
|
||||
9.75C9.1204 9.75 9.75 9.1204 9.75 8.34375C9.75 7.5671 9.1204 6.9375 8.34375
|
||||
6.9375ZM8.8125 10.6406C9.8823 10.4235 10.6875 9.47764 10.6875
|
||||
8.34375C10.6875 7.04933 9.63817 6 8.34375 6C7.04933 6 6 7.04933 6 8.34375C6
|
||||
9.47764 6.8052 10.4235 7.875 10.6406V11.1562C7.875 11.8999 8.18601 12.4028
|
||||
8.62101 12.7834C8.82767 12.9643 9.06032 13.1164 9.28665 13.2541C9.39277
|
||||
13.3187 9.48974 13.3756 9.5849 13.4316C9.71089 13.5056 9.83369 13.5777
|
||||
9.97031 13.6631C10.4167 13.9421 10.8179 14.2499 11.1146 14.7072C11.3641
|
||||
15.0919 11.5582 15.6119 11.6108 16.3623C10.5481 16.5849 9.75 17.5274 9.75
|
||||
18.6562C9.75 19.9507 10.7993 21 12.0938 21C13.3882 21 14.4375 19.9507
|
||||
14.4375 18.6562C14.4375 17.5274 13.6394 16.5849 12.5766 16.3623C12.6293
|
||||
15.6119 12.8234 15.0919 13.073 14.7072C13.3696 14.2499 13.7709 13.9421
|
||||
14.2172 13.6631C14.3538 13.5777 14.4766 13.5056 14.6026 13.4316C14.6978
|
||||
13.3756 14.7947 13.3187 14.9008 13.2541C15.1272 13.1164 15.3598 12.9643
|
||||
15.5665 12.7834C16.0015 12.4028 16.3125 11.8999 16.3125
|
||||
11.1562V10.6406C17.3823 10.4235 18.1875 9.47764 18.1875 8.34375C18.1875
|
||||
7.04933 17.1382 6 15.8438 6C14.5493 6 13.5 7.04933 13.5 8.34375C13.5
|
||||
9.47764 14.3052 10.4235 15.375 10.6406V11.1562C15.375 11.5845 15.2173
|
||||
11.8433 14.9491 12.0779C14.8042 12.2047 14.6267 12.3235 14.4136
|
||||
12.4532C14.3363 12.5002 14.2463 12.5532 14.1515 12.6091C14.0098 12.6926
|
||||
13.8574 12.7824 13.7203 12.8681C13.2292 13.1751 12.6929 13.5705 12.2864
|
||||
14.1971C12.2176 14.3032 12.1532 14.4147 12.0938 14.5323C12.0343 14.4147
|
||||
11.9699 14.3032 11.9011 14.1971C11.4946 13.5705 10.9583 13.1751 10.4672
|
||||
12.8681C10.3301 12.7824 10.1776 12.6926 10.036 12.6091C9.94121 12.5532
|
||||
9.85123 12.5002 9.77389 12.4532C9.56077 12.3235 9.38326 12.2047 9.23836
|
||||
12.0779C8.97024 11.8433 8.8125 11.5845 8.8125 11.1562V10.6406ZM15.8438
|
||||
9.75C16.6204 9.75 17.25 9.1204 17.25 8.34375C17.25 7.5671 16.6204 6.9375
|
||||
15.8438 6.9375C15.0671 6.9375 14.4375 7.5671 14.4375 8.34375C14.4375 9.1204
|
||||
15.0671 9.75 15.8438 9.75ZM12.0938 17.25C11.3171 17.25 10.6875 17.8796
|
||||
10.6875 18.6562C10.6875 19.4329 11.3171 20.0625 12.0938 20.0625C12.8704
|
||||
20.0625 13.5 19.4329 13.5 18.6562C13.5 17.8796 12.8704 17.25 12.0938
|
||||
17.25Z" />
|
||||
d="M3.5 6C3.5 4.61929 4.61929 3.5 6 3.5C7.38071 3.5 8.5 4.61929 8.5 6C8.5
|
||||
7.20948 7.64112 8.21836 6.5 8.44999V11C6.5 11.2761 6.72386 11.5 7
|
||||
11.5H17C17.2761 11.5 17.5 11.2761 17.5 11V8.44999C16.3589 8.21836 15.5
|
||||
7.20948 15.5 6C15.5 4.61929 16.6193 3.5 18 3.5C19.3807 3.5 20.5 4.61929
|
||||
20.5 6C20.5 7.20948 19.6411 8.21836 18.5 8.44999V11C18.5 11.8284 17.8284
|
||||
12.5 17 12.5H12.5V15.55C13.6411 15.7816 14.5 16.7905 14.5 18C14.5 19.3807
|
||||
13.3807 20.5 12 20.5C10.6193 20.5 9.5 19.3807 9.5 18C9.5 16.7905 10.3589
|
||||
15.7816 11.5 15.55V12.5H7C6.17157 12.5 5.5 11.8284 5.5 11V8.44999C4.35888
|
||||
8.21836 3.5 7.20948 3.5 6ZM6 4.5C5.17157 4.5 4.5 5.17157 4.5 6C4.5
|
||||
6.82843 5.17157 7.5 6 7.5C6.82843 7.5 7.5 6.82843 7.5 6C7.5 5.17157
|
||||
6.82843 4.5 6 4.5ZM18 4.5C17.1716 4.5 16.5 5.17157 16.5 6C16.5 6.82843
|
||||
17.1716 7.5 18 7.5C18.8284 7.5 19.5 6.82843 19.5 6C19.5 5.17157 18.8284
|
||||
4.5 18 4.5ZM12 16.5C11.1716 16.5 10.5 17.1716 10.5 18C10.5 18.8284
|
||||
11.1716 19.5 12 19.5C12.8284 19.5 13.5 18.8284 13.5 18C13.5 17.1716
|
||||
12.8284 16.5 12 16.5Z" />
|
||||
{:else if name === "moon"}
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M15.75 1.5C16.1642 1.5
|
||||
16.5 1.83579 16.5 2.25V3H17.25C17.6642 3 18 3.33579 18 3.75C18 4.16421
|
||||
17.6642 4.5 17.25 4.5H16.5V5.25C16.5 5.66421 16.1642 6 15.75 6C15.3358 6 15
|
||||
5.66421 15 5.25V4.5H14.25C13.8358 4.5 13.5 4.16421 13.5 3.75C13.5 3.33579
|
||||
13.8358 3 14.25 3H15V2.25C15 1.83579 15.3358 1.5 15.75 1.5ZM10.2246
|
||||
3.15456C10.4159 3.34623 10.489 3.62613 10.4159 3.88688C9.65641 6.59529
|
||||
10.4385 9.58344 12.4276 11.5724C14.4166 13.5615 17.4047 14.3436 20.1131
|
||||
13.5841C20.3739 13.511 20.6538 13.5841 20.8454 13.7754C21.0371 13.9667
|
||||
21.1108 14.2465 21.0382 14.5074C19.1394 21.3293 10.2649 23.5102 5.37735
|
||||
18.6226C0.393755 13.639 2.70287 4.85168 9.49264 2.96184C9.75353 2.88923
|
||||
10.0333 2.96289 10.2246 3.15456ZM8.69851 4.84862C3.95753 7.06376 2.57424
|
||||
13.6982 6.43801 17.562C10.2273 21.3512 16.9232 20.041 19.1499
|
||||
15.3017C16.3194 15.6466 13.4079 14.6741 11.3669 12.6331C9.32556 10.5918
|
||||
8.35305 7.67963 8.69851 4.84862ZM20.25 5.25C20.6642 5.25 21 5.58579 21
|
||||
6V7.5H22.5C22.9142 7.5 23.25 7.83579 23.25 8.25C23.25 8.66421 22.9142 9
|
||||
22.5 9H21V10.5C21 10.9142 20.6642 11.25 20.25 11.25C19.8358 11.25 19.5
|
||||
10.9142 19.5 10.5V9H18C17.5858 9 17.25 8.66421 17.25 8.25C17.25 7.83579
|
||||
17.5858 7.5 18 7.5H19.5V6C19.5 5.58579 19.8358 5.25 20.25 5.25Z" />
|
||||
d="M13.5 4.5C9.35786 4.5 6 7.85786 6 12C6 16.1421 9.35786 19.5 13.5
|
||||
19.5C14.8679 19.5 16.149 19.1343 17.2524 18.4954C13.7773 18.3652 11
|
||||
15.5069 11 12C11 8.49307 13.7773 5.6348 17.2524 5.50463C16.149 4.86574
|
||||
14.8679 4.5 13.5 4.5ZM5 12C5 7.30558 8.80558 3.5 13.5 3.5C15.1842 3.5
|
||||
16.7554 3.99035 18.0768 4.83625C18.5001 5.10719 18.5345 5.58051 18.3915
|
||||
5.90969C18.2548 6.22425 17.9285 6.5 17.5 6.5C14.4624 6.5 12 8.96243 12
|
||||
12C12 15.0376 14.4624 17.5 17.5 17.5C17.9285 17.5 18.2548 17.7758 18.3915
|
||||
18.0903C18.5345 18.4195 18.5001 18.8928 18.0768 19.1638C16.7554 20.0097
|
||||
15.1842 20.5 13.5 20.5C8.80558 20.5 5 16.6944 5 12Z" />
|
||||
{:else if name === "checkmark"}
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M18.2941 6.59564C18.5174 6.75806 18.5668 7.07076 18.4044 7.29409L11.781
|
||||
16.4012C10.8775 17.6436 9.07768 17.7848 7.99142 16.6985L5.64645 14.3536C5.45118
|
||||
14.1583 5.45118 13.8417 5.64645 13.6465C5.84171 13.4512 6.15829 13.4512 6.35355
|
||||
13.6465L8.69852 15.9914C9.35028 16.6432 10.4302 16.5584 10.9723 15.813L17.5956
|
||||
6.70592C17.7581 6.48259 18.0708 6.43322 18.2941 6.59564Z" />
|
||||
d="M18.2941 6.59564C18.5174 6.75806 18.5668 7.07076 18.4044
|
||||
7.29409L11.781 16.4012C10.8775 17.6436 9.07768 17.7848 7.99142
|
||||
16.6985L5.64645 14.3536C5.45118 14.1583 5.45118 13.8417 5.64645
|
||||
13.6465C5.84171 13.4512 6.15829 13.4512 6.35355 13.6465L8.69852
|
||||
15.9914C9.35028 16.6432 10.4302 16.5584 10.9723 15.813L17.5956
|
||||
6.70592C17.7581 6.48259 18.0708 6.43322 18.2941 6.59564Z" />
|
||||
{:else if name === "checkmark-small"}
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
@@ -257,36 +262,60 @@
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M12 0.75C12.4142 0.75
|
||||
12.75 1.08579 12.75 1.5V3.375C12.75 3.78921 12.4142 4.125 12 4.125C11.5858
|
||||
4.125 11.25 3.78921 11.25 3.375V1.5C11.25 1.08579 11.5858 0.75 12
|
||||
0.75ZM4.04467 4.04467C4.33756 3.75178 4.81244 3.75178 5.10533
|
||||
4.04467L6.42721 5.36655C6.7201 5.65944 6.7201 6.13431 6.42721
|
||||
6.42721C6.13431 6.7201 5.65944 6.7201 5.36655 6.42721L4.04467
|
||||
5.10533C3.75178 4.81244 3.75178 4.33756 4.04467 4.04467ZM19.9553
|
||||
4.04467C20.2482 4.33756 20.2482 4.81244 19.9553 5.10533L18.6335
|
||||
6.42721C18.3406 6.7201 17.8657 6.7201 17.5728 6.42721C17.2799 6.13431
|
||||
17.2799 5.65944 17.5728 5.36655L18.8947 4.04467C19.1876 3.75178 19.6624
|
||||
3.75178 19.9553 4.04467ZM12 7.125C9.30761 7.125 7.125 9.30761 7.125
|
||||
12C7.125 14.6924 9.30761 16.875 12 16.875C14.6924 16.875 16.875 14.6924
|
||||
16.875 12C16.875 9.30761 14.6924 7.125 12 7.125ZM5.625 12C5.625 8.47918
|
||||
8.47918 5.625 12 5.625C15.5208 5.625 18.375 8.47918 18.375 12C18.375
|
||||
15.5208 15.5208 18.375 12 18.375C8.47918 18.375 5.625 15.5208 5.625
|
||||
12ZM0.75 12C0.75 11.5858 1.08579 11.25 1.5 11.25H3.375C3.78921 11.25 4.125
|
||||
11.5858 4.125 12C4.125 12.4142 3.78921 12.75 3.375 12.75H1.5C1.08579 12.75
|
||||
0.75 12.4142 0.75 12ZM19.875 12C19.875 11.5858 20.2108 11.25 20.625
|
||||
11.25H22.5C22.9142 11.25 23.25 11.5858 23.25 12C23.25 12.4142 22.9142 12.75
|
||||
22.5 12.75H20.625C20.2108 12.75 19.875 12.4142 19.875 12ZM6.42721
|
||||
17.5728C6.7201 17.8657 6.7201 18.3406 6.42721 18.6335L5.10533
|
||||
19.9553C4.81244 20.2482 4.33756 20.2482 4.04467 19.9553C3.75178 19.6624
|
||||
3.75178 19.1876 4.04467 18.8947L5.36655 17.5728C5.65944 17.2799 6.13431
|
||||
17.2799 6.42721 17.5728ZM17.5728 17.5728C17.8657 17.2799 18.3406 17.2799
|
||||
18.6335 17.5728L19.9553 18.8947C20.2482 19.1876 20.2482 19.6624 19.9553
|
||||
19.9553C19.6624 20.2482 19.1876 20.2482 18.8947 19.9553L17.5728
|
||||
18.6335C17.2799 18.3406 17.2799 17.8657 17.5728 17.5728ZM12 19.875C12.4142
|
||||
19.875 12.75 20.2108 12.75 20.625V22.5C12.75 22.9142 12.4142 23.25 12
|
||||
23.25C11.5858 23.25 11.25 22.9142 11.25 22.5V20.625C11.25 20.2108 11.5858
|
||||
19.875 12 19.875Z" />
|
||||
d="M12 8.5C10.067 8.5 8.5 10.067 8.5 12C8.5 13.933 10.067 15.5 12
|
||||
15.5C13.933 15.5 15.5 13.933 15.5 12C15.5 10.067 13.933 8.5 12 8.5ZM7.5
|
||||
12C7.5 9.51472 9.51472 7.5 12 7.5C14.4853 7.5 16.5 9.51472 16.5 12C16.5
|
||||
14.4853 14.4853 16.5 12 16.5C9.51472 16.5 7.5 14.4853 7.5 12Z" />
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M12 18.5C12.2761 18.5 12.5 18.7239 12.5 19V21C12.5 21.2761 12.2761
|
||||
21.5 12 21.5C11.7239 21.5 11.5 21.2761 11.5 21V19C11.5 18.7239 11.7239
|
||||
18.5 12 18.5Z" />
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M7.40381 16.5962C7.59907 16.7915 7.59907 17.108 7.40381
|
||||
17.3033L5.98959 18.7175C5.79433 18.9128 5.47775 18.9128 5.28249
|
||||
18.7175C5.08722 18.5223 5.08722 18.2057 5.28249 18.0104L6.6967
|
||||
16.5962C6.89196 16.4009 7.20854 16.4009 7.40381 16.5962Z" />
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M5.5 12C5.5 12.2761 5.27614 12.5 5 12.5H3C2.72386 12.5 2.5 12.2761 2.5
|
||||
12C2.5 11.7239 2.72386 11.5 3 11.5H5C5.27614 11.5 5.5 11.7239 5.5 12Z" />
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M7.40381 7.40381C7.20854 7.59907 6.89196 7.59907 6.6967
|
||||
7.40381L5.28249 5.98959C5.08722 5.79433 5.08722 5.47775 5.28249
|
||||
5.28249C5.47775 5.08722 5.79433 5.08722 5.98959 5.28249L7.40381
|
||||
6.6967C7.59907 6.89196 7.59907 7.20854 7.40381 7.40381Z" />
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M12 2.5C12.2761 2.5 12.5 2.72386 12.5 3V5C12.5 5.27614 12.2761 5.5 12
|
||||
5.5C11.7239 5.5 11.5 5.27614 11.5 5V3C11.5 2.72386 11.7239 2.5 12 2.5Z" />
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M18.7175 5.28249C18.9128 5.47775 18.9128 5.79433 18.7175
|
||||
5.98959L17.3033 7.40381C17.108 7.59907 16.7915 7.59907 16.5962
|
||||
7.40381C16.4009 7.20854 16.4009 6.89196 16.5962 6.6967L18.0104
|
||||
5.28249C18.2057 5.08722 18.5223 5.08722 18.7175 5.28249Z" />
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M21.5 12C21.5 12.2761 21.2761 12.5 21 12.5H19C18.7239 12.5 18.5
|
||||
12.2761 18.5 12C18.5 11.7239 18.7239 11.5 19 11.5H21C21.2761 11.5 21.5
|
||||
11.7239 21.5 12Z" />
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M18.7175 18.7175C18.5223 18.9128 18.2057 18.9128 18.0104
|
||||
18.7175L16.5962 17.3033C16.4009 17.108 16.4009 16.7915 16.5962
|
||||
16.5962C16.7915 16.4009 17.108 16.4009 17.3033 16.5962L18.7175
|
||||
18.0104C18.9128 18.2057 18.9128 18.5223 18.7175 18.7175Z" />
|
||||
{:else if name === "twitter"}
|
||||
<path
|
||||
clip-rule="evenodd"
|
||||
|
||||
@@ -2,22 +2,25 @@
|
||||
import type { Route } from "@app/lib/router/definitions";
|
||||
|
||||
import { createEventDispatcher } from "svelte";
|
||||
import { push, routeToPath } from "@app/lib/router";
|
||||
import { push, routeToPath, useDefaultNavigation } from "@app/lib/router";
|
||||
|
||||
export let route: Route;
|
||||
export let title: string | null = null;
|
||||
export let id: string | null = null;
|
||||
|
||||
const dispatch = createEventDispatcher<{
|
||||
click: never;
|
||||
afterNavigate: never;
|
||||
}>();
|
||||
|
||||
function onClick(): void {
|
||||
function navigateToRoute(event: MouseEvent): void {
|
||||
if (useDefaultNavigation(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
push(route);
|
||||
dispatch("click");
|
||||
dispatch("afterNavigate");
|
||||
}
|
||||
</script>
|
||||
|
||||
<a on:click|preventDefault={onClick} {title} {id} href={routeToPath(route)}>
|
||||
<a on:click={navigateToRoute} href={routeToPath(route)}>
|
||||
<slot />
|
||||
</a>
|
||||
|
||||
@@ -97,8 +97,7 @@
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div class="project" on:click class:compact>
|
||||
<div class="project" class:compact>
|
||||
<div class="left">
|
||||
<div class="id">
|
||||
<span class="name">{name}</span>
|
||||
|
||||
@@ -1,16 +1,29 @@
|
||||
<script lang="ts">
|
||||
<script lang="ts" strictEvents>
|
||||
import type { ProjectsParams } from "@app/lib/router/definitions";
|
||||
import { updateProjectRoute, projectLinkHref } from "@app/lib/router";
|
||||
import { createEventDispatcher } from "svelte";
|
||||
|
||||
import {
|
||||
projectLinkHref,
|
||||
updateProjectRoute,
|
||||
useDefaultNavigation,
|
||||
} from "@app/lib/router";
|
||||
|
||||
export let projectParams: Partial<ProjectsParams>;
|
||||
export let id: string | undefined = undefined;
|
||||
export let title: string | undefined = undefined;
|
||||
|
||||
const dispatch = createEventDispatcher<{ click: never }>();
|
||||
|
||||
function navigateToRoute(event: MouseEvent): void {
|
||||
if (useDefaultNavigation(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
updateProjectRoute(projectParams);
|
||||
dispatch("click");
|
||||
}
|
||||
</script>
|
||||
|
||||
<a
|
||||
{id}
|
||||
on:click|preventDefault={() => {
|
||||
updateProjectRoute(projectParams);
|
||||
}}
|
||||
href={projectLinkHref(projectParams)}>
|
||||
<a {title} on:click={navigateToRoute} href={projectLinkHref(projectParams)}>
|
||||
<slot />
|
||||
</a>
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
<script lang="ts" strictEvents>
|
||||
export let active: boolean = false;
|
||||
export let hoverable: boolean = true;
|
||||
export let clickable: boolean = false;
|
||||
export let disabled: boolean = false;
|
||||
export let size: "small" | "regular" = "regular";
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.square-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 2rem;
|
||||
padding: 0 0.75rem;
|
||||
background: var(--color-foreground-1);
|
||||
border: none;
|
||||
border-radius: var(--border-radius-small);
|
||||
color: var(--color-foreground);
|
||||
font-family: var(--font-family-monospace);
|
||||
font-size: var(--font-size-tiny);
|
||||
}
|
||||
|
||||
.small {
|
||||
height: var(--button-tiny-height);
|
||||
}
|
||||
|
||||
.clickable {
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.active {
|
||||
color: var(--color-background);
|
||||
background: var(--color-foreground);
|
||||
background-color: var(--color-foreground);
|
||||
}
|
||||
|
||||
.active:hover {
|
||||
background-color: var(--color-foreground);
|
||||
}
|
||||
|
||||
.hoverable:hover {
|
||||
background-color: var(--color-foreground-2);
|
||||
}
|
||||
|
||||
.active.hoverable:hover {
|
||||
background-color: var(--color-foreground);
|
||||
}
|
||||
|
||||
.disabled {
|
||||
cursor: not-allowed;
|
||||
color: var(--color-foreground-5);
|
||||
}
|
||||
.disabled.active {
|
||||
color: var(--color-background);
|
||||
}
|
||||
.disabled:hover {
|
||||
background: var(--color-foreground-1);
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div
|
||||
on:click
|
||||
class="square-button"
|
||||
class:active
|
||||
class:hoverable
|
||||
class:disabled
|
||||
class:small={size === "small"}
|
||||
class:clickable>
|
||||
<span>
|
||||
<slot />
|
||||
</span>
|
||||
</div>
|
||||
@@ -1,68 +0,0 @@
|
||||
<script lang="ts" context="module">
|
||||
export interface Tab<T> {
|
||||
title?: string;
|
||||
disabled: boolean;
|
||||
value: T;
|
||||
}
|
||||
</script>
|
||||
|
||||
<script lang="ts" strictEvents>
|
||||
type T = $$Generic;
|
||||
|
||||
import capitalize from "lodash/capitalize";
|
||||
import { createEventDispatcher } from "svelte";
|
||||
|
||||
export let options: Tab<T>[];
|
||||
export let active: T;
|
||||
|
||||
const dispatch = createEventDispatcher<{ select: T }>();
|
||||
|
||||
function onSelect(option: Tab<T>) {
|
||||
if (!option.disabled) {
|
||||
dispatch("select", option.value);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.wrapper {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
user-select: none;
|
||||
}
|
||||
button {
|
||||
border-radius: var(--border-radius-small);
|
||||
color: var(--color-foreground-6);
|
||||
cursor: pointer;
|
||||
font-family: var(--font-family-monospace);
|
||||
font-size: var(--font-size-tiny);
|
||||
height: var(--button-tiny-height);
|
||||
padding: 0.25rem 0.5rem;
|
||||
border: none;
|
||||
min-width: 0;
|
||||
background-color: var(--color-background);
|
||||
}
|
||||
button:hover,
|
||||
button.active {
|
||||
cursor: pointer;
|
||||
color: var(--color-foreground);
|
||||
background-color: var(--color-foreground-1);
|
||||
}
|
||||
button[disabled],
|
||||
button[disabled]:hover {
|
||||
cursor: not-allowed;
|
||||
color: var(--color-foreground-6);
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="wrapper">
|
||||
{#each options as option}
|
||||
<button
|
||||
class="state-toggle"
|
||||
on:click={() => onSelect(option)}
|
||||
disabled={option.disabled}
|
||||
class:active={active === option.value}>
|
||||
{option.title ?? capitalize(`${option.value}`)}
|
||||
</button>
|
||||
{/each}
|
||||
</div>
|
||||
@@ -16,6 +16,16 @@ export const activeRouteStore: Readable<Route> = derived(
|
||||
},
|
||||
);
|
||||
|
||||
export function useDefaultNavigation(event: MouseEvent) {
|
||||
return (
|
||||
event.button !== 0 ||
|
||||
event.altKey ||
|
||||
event.ctrlKey ||
|
||||
event.metaKey ||
|
||||
event.shiftKey
|
||||
);
|
||||
}
|
||||
|
||||
export const base = import.meta.env.VITE_HASH_ROUTING ? "./" : "/";
|
||||
|
||||
// Gets triggered when clicking on an anchor hash tag e.g. <a href="#header"/>
|
||||
|
||||
+20
-24
@@ -1,28 +1,13 @@
|
||||
<script lang="ts">
|
||||
import type { BaseUrl, Project } from "@httpd-client";
|
||||
|
||||
import * as router from "@app/lib/router";
|
||||
import { config } from "@app/lib/config";
|
||||
import { getProjectsFromSeeds } from "@app/lib/search";
|
||||
import { loadProjectActivity } from "@app/lib/commit";
|
||||
import { twemoji } from "@app/lib/utils";
|
||||
|
||||
import Link from "@app/components/Link.svelte";
|
||||
import Loading from "@app/components/Loading.svelte";
|
||||
import ErrorMessage from "@app/components/ErrorMessage.svelte";
|
||||
import ProjectCard from "@app/components/ProjectCard.svelte";
|
||||
|
||||
function goToProject(project: Project, baseUrl: BaseUrl) {
|
||||
router.push({
|
||||
resource: "projects",
|
||||
params: {
|
||||
view: { resource: "tree" },
|
||||
id: project.id,
|
||||
hostnamePort: baseUrl.hostname,
|
||||
peer: undefined,
|
||||
revision: undefined,
|
||||
},
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@@ -97,14 +82,25 @@
|
||||
{#each results as result}
|
||||
{#await loadProjectActivity(result.project.id, result.baseUrl) then activity}
|
||||
<div class="project">
|
||||
<ProjectCard
|
||||
compact
|
||||
description={result.project.description}
|
||||
head={result.project.head}
|
||||
id={result.project.id}
|
||||
name={result.project.name}
|
||||
{activity}
|
||||
on:click={() => goToProject(result.project, result.baseUrl)} />
|
||||
<Link
|
||||
route={{
|
||||
resource: "projects",
|
||||
params: {
|
||||
view: { resource: "tree" },
|
||||
id: result.project.id,
|
||||
hostnamePort: result.baseUrl.hostname,
|
||||
peer: undefined,
|
||||
revision: undefined,
|
||||
},
|
||||
}}>
|
||||
<ProjectCard
|
||||
compact
|
||||
description={result.project.description}
|
||||
head={result.project.head}
|
||||
id={result.project.id}
|
||||
name={result.project.name}
|
||||
{activity} />
|
||||
</Link>
|
||||
</div>
|
||||
{/await}
|
||||
{/each}
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
import { lineNumbersGutter } from "@app/lib/syntax";
|
||||
import { updateProjectRoute } from "@app/lib/router";
|
||||
|
||||
import HeaderToggleLabel from "@app/views/projects/HeaderToggleLabel.svelte";
|
||||
import Readme from "@app/views/projects/Readme.svelte";
|
||||
import SquareButton from "@app/components/SquareButton.svelte";
|
||||
|
||||
export let activeRoute: ProjectRoute;
|
||||
export let blob: Blob;
|
||||
@@ -103,7 +103,7 @@
|
||||
}
|
||||
|
||||
.last-commit {
|
||||
padding: 0.5rem;
|
||||
padding: 0.5rem 0.75rem;
|
||||
color: var(--color-secondary);
|
||||
background-color: var(--color-secondary-2);
|
||||
font-size: var(--font-size-tiny);
|
||||
@@ -229,12 +229,12 @@
|
||||
<div class="right">
|
||||
{#if isMarkdown}
|
||||
<div class="markdown-toggle">
|
||||
<HeaderToggleLabel
|
||||
<SquareButton
|
||||
active={!showMarkdown}
|
||||
clickable
|
||||
on:click={toggleMarkdown}>
|
||||
Raw
|
||||
</HeaderToggleLabel>
|
||||
</SquareButton>
|
||||
</div>
|
||||
{/if}
|
||||
<div class="last-commit" title={lastCommit.author.name} use:twemoji>
|
||||
|
||||
@@ -1,20 +1,15 @@
|
||||
<script lang="ts" strictEvents>
|
||||
import { createEventDispatcher } from "svelte";
|
||||
|
||||
import * as utils from "@app/lib/utils";
|
||||
|
||||
import Dropdown from "@app/components/Dropdown.svelte";
|
||||
import Floating from "@app/components/Floating.svelte";
|
||||
import ProjectLink from "@app/components/ProjectLink.svelte";
|
||||
|
||||
export let branches: Record<string, string>;
|
||||
export let projectDefaultBranch: string;
|
||||
export let projectHead: string | undefined = undefined;
|
||||
export let revision: string;
|
||||
|
||||
const dispatch = createEventDispatcher<{ branchChanged: string }>();
|
||||
const switchBranch = (name: string) => {
|
||||
dispatch("branchChanged", name);
|
||||
};
|
||||
|
||||
let branchLabel: string | null = null;
|
||||
|
||||
$: branchList = Object.keys(branches)
|
||||
@@ -85,10 +80,13 @@
|
||||
{branchLabel}
|
||||
</div>
|
||||
<svelte:fragment slot="modal">
|
||||
<Dropdown
|
||||
items={branchList}
|
||||
selected={branchLabel}
|
||||
on:select={e => switchBranch(e.detail.value)} />
|
||||
<Dropdown items={branchList} selected={branchLabel}>
|
||||
<div class="branch-item" slot="item" let:item>
|
||||
<ProjectLink projectParams={{ revision: item.value }} on:click>
|
||||
{item.value}
|
||||
</ProjectLink>
|
||||
</div>
|
||||
</Dropdown>
|
||||
</svelte:fragment>
|
||||
</Floating>
|
||||
<div class="hash layout-desktop">
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
|
||||
import { onMount } from "svelte";
|
||||
|
||||
import * as router from "@app/lib/router";
|
||||
import * as utils from "@app/lib/utils";
|
||||
import { HttpdClient } from "@httpd-client";
|
||||
|
||||
@@ -48,6 +47,11 @@
|
||||
|
||||
const api = new HttpdClient(baseUrl);
|
||||
|
||||
// When a user clicks between multiple files, we want to retain the previous
|
||||
// file contents and show them while the new file is loading to prevent the
|
||||
// UI from flickering or showing a loading indicator.
|
||||
let previousBlob: Blob;
|
||||
|
||||
const loadBlob = async (path: string) => {
|
||||
if (state.status === Status.Loaded && state.path === path) {
|
||||
return state.blob;
|
||||
@@ -63,6 +67,7 @@
|
||||
}
|
||||
|
||||
state = { status: Status.Loaded, path, blob };
|
||||
previousBlob = blob;
|
||||
return blob;
|
||||
};
|
||||
|
||||
@@ -70,31 +75,6 @@
|
||||
browserErrorStore.set(undefined);
|
||||
});
|
||||
|
||||
const onSelect = async (newPath: string) => {
|
||||
browserErrorStore.set(undefined);
|
||||
// Ensure we don't spend any time in a "loading" state. This means
|
||||
// the loading spinner won't be shown, and instead the blob will be
|
||||
// displayed once loaded.
|
||||
const blob = await loadBlob(newPath).catch(() => {
|
||||
browserErrorStore.set({
|
||||
message: "Not able to load selected file",
|
||||
path: newPath,
|
||||
});
|
||||
return undefined;
|
||||
});
|
||||
if (blob) {
|
||||
getBlob = new Promise(resolve => resolve(blob));
|
||||
}
|
||||
|
||||
// Close mobile tree if user navigates to other file
|
||||
mobileFileTree = false;
|
||||
|
||||
router.updateProjectRoute({
|
||||
view: { resource: "tree" },
|
||||
path: newPath,
|
||||
});
|
||||
};
|
||||
|
||||
const fetchTree = async (path: string) => {
|
||||
return api.project.getTree(project.id, commit, path).catch(() => {
|
||||
browserErrorStore.set({
|
||||
@@ -105,10 +85,6 @@
|
||||
});
|
||||
};
|
||||
|
||||
const toggleMobileFileTree = () => {
|
||||
mobileFileTree = !mobileFileTree;
|
||||
};
|
||||
|
||||
$: getBlob = loadBlob(path).catch(() => {
|
||||
browserErrorStore.set({ message: "Not able to load file", path });
|
||||
return undefined;
|
||||
@@ -203,7 +179,9 @@
|
||||
<Button
|
||||
style="width: 100%;"
|
||||
variant="secondary"
|
||||
on:click={toggleMobileFileTree}>
|
||||
on:click={() => {
|
||||
mobileFileTree = !mobileFileTree;
|
||||
}}>
|
||||
Browse
|
||||
</Button>
|
||||
</nav>
|
||||
@@ -218,8 +196,9 @@
|
||||
{path}
|
||||
{fetchTree}
|
||||
{loadingPath}
|
||||
on:select={e => {
|
||||
onSelect(e.detail);
|
||||
on:select={() => {
|
||||
// Close mobile tree if user navigates to other file
|
||||
mobileFileTree = false;
|
||||
}} />
|
||||
</div>
|
||||
</div>
|
||||
@@ -241,7 +220,20 @@
|
||||
</Placeholder>
|
||||
{:else}
|
||||
{#await getBlob}
|
||||
<Loading small center />
|
||||
{#if previousBlob}
|
||||
<div class="layout-desktop">
|
||||
<BlobComponent
|
||||
{line}
|
||||
blob={previousBlob}
|
||||
{activeRoute}
|
||||
rawPath={utils.getRawBasePath(project.id, baseUrl, commit)} />
|
||||
</div>
|
||||
<div class="layout-mobile">
|
||||
<Loading small center />
|
||||
</div>
|
||||
{:else}
|
||||
<Loading small center />
|
||||
{/if}
|
||||
{:then blob}
|
||||
{#if blob}
|
||||
<BlobComponent
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
.metadata-section {
|
||||
margin-bottom: 4rem;
|
||||
}
|
||||
.metadata-section-header {
|
||||
.header {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
align-items: center;
|
||||
@@ -56,20 +56,27 @@
|
||||
margin-bottom: 0.75rem;
|
||||
color: var(--color-foreground-6);
|
||||
}
|
||||
.metadata-section-body {
|
||||
.body {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: row;
|
||||
gap: 0.5rem;
|
||||
margin-bottom: 1.25rem;
|
||||
}
|
||||
.metadata-section-empty {
|
||||
.empty {
|
||||
color: var(--color-foreground-5);
|
||||
}
|
||||
|
||||
.chip-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="metadata-section">
|
||||
<div class="metadata-section-header">
|
||||
<div class="header">
|
||||
<span>Assignees</span>
|
||||
{#if action === "edit"}
|
||||
{#if !edit}
|
||||
@@ -94,17 +101,19 @@
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
<div class="metadata-section-body">
|
||||
<div class="body">
|
||||
{#each updatedAssignees as assignee, key (assignee)}
|
||||
<Chip
|
||||
on:remove={removeAssignee}
|
||||
removeable={edit || action === "create"}
|
||||
{key}>
|
||||
<Avatar inline nodeId={assignee} />
|
||||
<span>{formatNodeId(assignee)}</span>
|
||||
<div class="chip-content">
|
||||
<Avatar inline nodeId={assignee} />
|
||||
<span>{formatNodeId(assignee)}</span>
|
||||
</div>
|
||||
</Chip>
|
||||
{:else}
|
||||
<div class="metadata-section-empty">No assignees</div>
|
||||
<div class="empty">No assignees</div>
|
||||
{/each}
|
||||
</div>
|
||||
{#if edit || action === "create"}
|
||||
|
||||
@@ -66,6 +66,7 @@
|
||||
.tag {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
import * as router from "@app/lib/router";
|
||||
|
||||
import Changeset from "@app/views/projects/SourceBrowser/Changeset.svelte";
|
||||
import CommitAuthorship from "@app/views/projects/Commit/CommitAuthorship.svelte";
|
||||
import Clipboard from "@app/components/Clipboard.svelte";
|
||||
import CommitAuthorship from "@app/views/projects/Commit/CommitAuthorship.svelte";
|
||||
|
||||
export let commit: Commit;
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
.commit {
|
||||
padding: 0 2rem 0 8rem;
|
||||
}
|
||||
header {
|
||||
.header {
|
||||
padding: 1rem;
|
||||
background: var(--color-background-1);
|
||||
border-radius: var(--border-radius);
|
||||
@@ -54,7 +54,7 @@
|
||||
</style>
|
||||
|
||||
<div class="commit">
|
||||
<header>
|
||||
<div class="header">
|
||||
<div class="summary">
|
||||
<div class="txt-medium txt-bold" use:twemoji>{header.summary}</div>
|
||||
<div class="layout-desktop-flex txt-monospace sha1">
|
||||
@@ -68,6 +68,6 @@
|
||||
</div>
|
||||
<pre class="description txt-small">{header.description}</pre>
|
||||
<CommitAuthorship {header} />
|
||||
</header>
|
||||
<Changeset diff={commit.diff} on:browse={onBrowse} />
|
||||
</div>
|
||||
<Changeset diff={commit.diff} revision={commit.commit.id} />
|
||||
</div>
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
color: var(--color-foreground-6);
|
||||
padding: 0.125rem 0;
|
||||
}
|
||||
.authorship .author,
|
||||
.authorship .committer {
|
||||
|
||||
@@ -1,67 +1,48 @@
|
||||
<script lang="ts" strictEvents>
|
||||
<script lang="ts">
|
||||
import type { CommitHeader } from "@httpd-client";
|
||||
|
||||
import { createEventDispatcher } from "svelte";
|
||||
|
||||
import { formatCommit, twemoji } from "@app/lib/utils";
|
||||
|
||||
import CommitAuthorship from "./CommitAuthorship.svelte";
|
||||
import Icon from "@app/components/Icon.svelte";
|
||||
import ProjectLink from "@app/components/ProjectLink.svelte";
|
||||
|
||||
export let commit: CommitHeader;
|
||||
|
||||
const dispatch = createEventDispatcher<{ browseCommit: string }>();
|
||||
|
||||
function browseCommit(commit: string) {
|
||||
dispatch("browseCommit", commit);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.teaser {
|
||||
background-color: var(--color-background-1);
|
||||
padding: 0.75rem 0rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.teaser:hover {
|
||||
background-color: var(--color-foreground-2);
|
||||
}
|
||||
.hash {
|
||||
font-family: var(--font-family-monospace);
|
||||
font-size: var(--font-size-tiny);
|
||||
padding: 0 1.5rem;
|
||||
}
|
||||
.commit-teaser {
|
||||
background-color: var(--color-background-1);
|
||||
padding: 0.75rem 0rem;
|
||||
}
|
||||
.commit-teaser:hover {
|
||||
background-color: var(--color-foreground-2);
|
||||
cursor: pointer;
|
||||
}
|
||||
.commit-teaser:first-child {
|
||||
border-top-left-radius: var(--border-radius-small);
|
||||
border-top-right-radius: var(--border-radius-small);
|
||||
}
|
||||
.commit-teaser:last-child {
|
||||
border-bottom-left-radius: var(--border-radius-small);
|
||||
border-bottom-right-radius: var(--border-radius-small);
|
||||
}
|
||||
.commit-teaser:not(:last-child) {
|
||||
border-bottom: 1px solid var(--color-background);
|
||||
}
|
||||
.commit-teaser {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.column-left {
|
||||
.left {
|
||||
padding-left: 1rem;
|
||||
flex: min-content;
|
||||
}
|
||||
.commit-teaser .column-right {
|
||||
.right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-right: 1.5rem;
|
||||
margin-left: auto;
|
||||
}
|
||||
.summary {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
padding-right: 1rem;
|
||||
margin-bottom: 0.25rem;
|
||||
font-size: var(--font-size-small);
|
||||
}
|
||||
.summary:hover {
|
||||
color: var(--color-secondary);
|
||||
}
|
||||
.browse {
|
||||
display: flex;
|
||||
@@ -74,7 +55,7 @@
|
||||
.hash {
|
||||
padding-right: 0;
|
||||
}
|
||||
.column-left {
|
||||
.left {
|
||||
overflow: hidden;
|
||||
}
|
||||
.browse {
|
||||
@@ -84,29 +65,36 @@
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div class="commit-teaser" on:click>
|
||||
<div class="column-left">
|
||||
<div class="header">
|
||||
<div class="teaser">
|
||||
<div class="left">
|
||||
<ProjectLink
|
||||
projectParams={{
|
||||
view: { resource: "commits" },
|
||||
revision: commit.id,
|
||||
search: undefined,
|
||||
}}>
|
||||
<div class="summary" use:twemoji>
|
||||
{commit.summary}
|
||||
</div>
|
||||
</div>
|
||||
</ProjectLink>
|
||||
<CommitAuthorship header={commit} />
|
||||
</div>
|
||||
<div class="column-right">
|
||||
<div class="right">
|
||||
<span class="hash txt-highlight">{formatCommit(commit.id)}</span>
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div
|
||||
class="browse"
|
||||
title="Browse the repository at this point in the history"
|
||||
on:click|stopPropagation={() => browseCommit(commit.id)}>
|
||||
<Icon name="browse" />
|
||||
title="Browse the repository at this point in the history">
|
||||
<ProjectLink
|
||||
projectParams={{
|
||||
view: { resource: "tree" },
|
||||
revision: commit.id,
|
||||
}}>
|
||||
<Icon name="browse" />
|
||||
</ProjectLink>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,16 +2,16 @@
|
||||
import type { BaseUrl, Project, Remote, Tree } from "@httpd-client";
|
||||
import type { ProjectRoute } from "@app/lib/router/definitions";
|
||||
|
||||
import * as router from "@app/lib/router";
|
||||
|
||||
import { closeFocused } from "@app/components/Floating.svelte";
|
||||
import { config } from "@app/lib/config";
|
||||
import { pluralize } from "@app/lib/pluralize";
|
||||
|
||||
import BranchSelector from "@app/views/projects/BranchSelector.svelte";
|
||||
import CloneButton from "@app/views/projects/CloneButton.svelte";
|
||||
import HeaderToggleLabel from "@app/views/projects/HeaderToggleLabel.svelte";
|
||||
import Link from "@app/components/Link.svelte";
|
||||
import PeerSelector from "@app/views/projects/PeerSelector.svelte";
|
||||
import ProjectLink from "@app/components/ProjectLink.svelte";
|
||||
import SquareButton from "@app/components/SquareButton.svelte";
|
||||
|
||||
export let project: Project;
|
||||
export let activeRoute: ProjectRoute;
|
||||
@@ -22,55 +22,10 @@
|
||||
export let baseUrl: BaseUrl;
|
||||
|
||||
$: revision = activeRoute.params.revision ?? commit;
|
||||
|
||||
// Switches between project views.
|
||||
const toggleContent = (
|
||||
input: "issues" | "patches" | "history",
|
||||
keepSourceInPath: boolean,
|
||||
) => {
|
||||
router.updateProjectRoute({
|
||||
view: {
|
||||
resource: activeRoute.params.view.resource === input ? "tree" : input,
|
||||
},
|
||||
id: project.id,
|
||||
revision: revision,
|
||||
search: undefined,
|
||||
...(keepSourceInPath ? null : { revision: undefined, path: undefined }),
|
||||
});
|
||||
};
|
||||
|
||||
const updatePeer = (peer: string) => {
|
||||
router.updateProjectRoute({
|
||||
peer,
|
||||
revision: undefined,
|
||||
});
|
||||
closeFocused();
|
||||
};
|
||||
|
||||
const updateRevision = (revision: string) => {
|
||||
router.updateProjectRoute({
|
||||
revision,
|
||||
});
|
||||
closeFocused();
|
||||
};
|
||||
|
||||
function goToSeed() {
|
||||
if (baseUrl.port !== config.seeds.defaultHttpdPort) {
|
||||
router.push({
|
||||
resource: "seeds",
|
||||
params: { hostnamePort: `${baseUrl.hostname}:${baseUrl.port}` },
|
||||
});
|
||||
} else {
|
||||
router.push({
|
||||
resource: "seeds",
|
||||
params: { hostnamePort: baseUrl.hostname },
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
header {
|
||||
.header {
|
||||
font-size: var(--font-size-tiny);
|
||||
padding: 0 2rem 0 8rem;
|
||||
margin-bottom: 2rem;
|
||||
@@ -82,21 +37,21 @@
|
||||
}
|
||||
|
||||
@media (max-width: 960px) {
|
||||
header {
|
||||
.header {
|
||||
padding-left: 2rem;
|
||||
}
|
||||
header {
|
||||
.header {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<header>
|
||||
<div class="header">
|
||||
{#if peers.length > 0}
|
||||
<PeerSelector
|
||||
{peers}
|
||||
peer={activeRoute.params.peer}
|
||||
on:peerChanged={event => updatePeer(event.detail)} />
|
||||
on:click={() => closeFocused()} />
|
||||
{/if}
|
||||
|
||||
<BranchSelector
|
||||
@@ -104,45 +59,77 @@
|
||||
projectHead={project.head}
|
||||
{branches}
|
||||
{revision}
|
||||
on:branchChanged={event => updateRevision(event.detail)} />
|
||||
on:click={() => closeFocused()} />
|
||||
|
||||
<CloneButton {baseUrl} id={project.id} name={project.name} />
|
||||
|
||||
<span>
|
||||
<HeaderToggleLabel
|
||||
clickable
|
||||
ariaLabel="Seed"
|
||||
title="Project data is fetched from this seed"
|
||||
on:click={goToSeed}>
|
||||
<span>{baseUrl.hostname}</span>
|
||||
</HeaderToggleLabel>
|
||||
</span>
|
||||
<HeaderToggleLabel
|
||||
ariaLabel="Commit count"
|
||||
clickable
|
||||
active={activeRoute.params.view.resource === "history"}
|
||||
on:click={() => toggleContent("history", true)}>
|
||||
<span class="txt-bold">{tree.stats.commits}</span>
|
||||
{pluralize("commit", tree.stats.commits)}
|
||||
</HeaderToggleLabel>
|
||||
<HeaderToggleLabel
|
||||
ariaLabel="Issue count"
|
||||
active={activeRoute.params.view.resource === "issues"}
|
||||
clickable
|
||||
on:click={() => toggleContent("issues", false)}>
|
||||
<span class="txt-bold">{project.issues.open}</span>
|
||||
{pluralize("issue", project.issues.open)}
|
||||
</HeaderToggleLabel>
|
||||
<HeaderToggleLabel
|
||||
ariaLabel="Patch count"
|
||||
active={activeRoute.params.view.resource === "patches"}
|
||||
clickable
|
||||
on:click={() => toggleContent("patches", false)}>
|
||||
<span class="txt-bold">{project.patches.open}</span>
|
||||
{pluralize("patch", project.patches.open)}
|
||||
</HeaderToggleLabel>
|
||||
<HeaderToggleLabel ariaLabel="Contributor count">
|
||||
<Link
|
||||
route={{
|
||||
resource: "seeds",
|
||||
params: {
|
||||
hostnamePort:
|
||||
baseUrl.port === config.seeds.defaultHttpdPort
|
||||
? baseUrl.hostname
|
||||
: `${baseUrl.hostname}:${baseUrl.port}`,
|
||||
},
|
||||
}}>
|
||||
<SquareButton>
|
||||
{baseUrl.hostname}
|
||||
</SquareButton>
|
||||
</Link>
|
||||
|
||||
<ProjectLink
|
||||
projectParams={{
|
||||
id: project.id,
|
||||
view: {
|
||||
resource:
|
||||
activeRoute.params.view.resource === "history" ? "tree" : "history",
|
||||
},
|
||||
revision: revision,
|
||||
search: undefined,
|
||||
}}>
|
||||
<SquareButton active={activeRoute.params.view.resource === "history"}>
|
||||
<span class="txt-bold">{tree.stats.commits}</span>
|
||||
{pluralize("commit", tree.stats.commits)}
|
||||
</SquareButton>
|
||||
</ProjectLink>
|
||||
|
||||
<ProjectLink
|
||||
projectParams={{
|
||||
id: project.id,
|
||||
view: {
|
||||
resource:
|
||||
activeRoute.params.view.resource === "issues" ? "tree" : "issues",
|
||||
},
|
||||
search: undefined,
|
||||
revision: undefined,
|
||||
path: undefined,
|
||||
}}>
|
||||
<SquareButton active={activeRoute.params.view.resource === "issues"}>
|
||||
<span class="txt-bold">{project.issues.open}</span>
|
||||
{pluralize("issue", project.issues.open)}
|
||||
</SquareButton>
|
||||
</ProjectLink>
|
||||
|
||||
<ProjectLink
|
||||
projectParams={{
|
||||
id: project.id,
|
||||
view: {
|
||||
resource:
|
||||
activeRoute.params.view.resource === "patches" ? "tree" : "patches",
|
||||
},
|
||||
search: undefined,
|
||||
revision: undefined,
|
||||
path: undefined,
|
||||
}}>
|
||||
<SquareButton active={activeRoute.params.view.resource === "patches"}>
|
||||
<span class="txt-bold">{project.patches.open}</span>
|
||||
{pluralize("patch", project.patches.open)}
|
||||
</SquareButton>
|
||||
</ProjectLink>
|
||||
|
||||
<SquareButton hoverable={false}>
|
||||
<span class="txt-bold">{tree.stats.contributors}</span>
|
||||
{pluralize("contributor", tree.stats.contributors)}
|
||||
</HeaderToggleLabel>
|
||||
</header>
|
||||
</SquareButton>
|
||||
</div>
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
<script lang="ts">
|
||||
export let title: string | undefined = undefined;
|
||||
export let ariaLabel: string | undefined = undefined;
|
||||
export let active = false;
|
||||
export let clickable = false;
|
||||
export let disabled = false;
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.stat {
|
||||
font-family: var(--font-family-monospace);
|
||||
font-size: var(--font-size-tiny);
|
||||
padding: 0.5rem 0.75rem;
|
||||
padding-bottom: 1rem; /* moving the content a tad higher to match the previous span usage */
|
||||
height: 2rem;
|
||||
background: var(--color-foreground-1);
|
||||
border: none;
|
||||
color: var(--color-foreground);
|
||||
border-radius: var(--border-radius-small);
|
||||
min-width: max-content;
|
||||
}
|
||||
.active {
|
||||
color: var(--color-background);
|
||||
background: var(--color-foreground) !important;
|
||||
background-color: var(--color-foreground);
|
||||
}
|
||||
.clickable {
|
||||
cursor: pointer;
|
||||
}
|
||||
.clickable:hover {
|
||||
background-color: var(--color-foreground-2);
|
||||
}
|
||||
.not-allowed {
|
||||
cursor: not-allowed;
|
||||
color: var(--color-foreground-5);
|
||||
}
|
||||
</style>
|
||||
|
||||
<button
|
||||
{title}
|
||||
{disabled}
|
||||
class:active
|
||||
class:clickable
|
||||
class:not-allowed={disabled}
|
||||
class="stat"
|
||||
aria-label={ariaLabel}
|
||||
on:click>
|
||||
<slot />
|
||||
</button>
|
||||
@@ -1,7 +1,6 @@
|
||||
<script lang="ts">
|
||||
import type { BaseUrl, CommitHeader } from "@httpd-client";
|
||||
|
||||
import * as router from "@app/lib/router";
|
||||
import { HttpdClient } from "@httpd-client";
|
||||
import { groupCommits } from "@app/lib/commit";
|
||||
|
||||
@@ -42,20 +41,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
function goToSourceTreeAtCommit(event: { detail: string }) {
|
||||
router.updateProjectRoute({
|
||||
view: { resource: "tree" },
|
||||
revision: event.detail,
|
||||
});
|
||||
}
|
||||
|
||||
function goToCommit(revision: string) {
|
||||
router.updateProjectRoute({
|
||||
view: { resource: "commits" },
|
||||
revision,
|
||||
});
|
||||
}
|
||||
|
||||
$: showMoreButton =
|
||||
!loading && !error && totalCommitCount && history.length < totalCommitCount;
|
||||
|
||||
@@ -67,11 +52,13 @@
|
||||
padding: 0 2rem 0 8rem;
|
||||
font-size: var(--font-size-small);
|
||||
}
|
||||
.commit-group header {
|
||||
color: var(--color-foreground-6);
|
||||
}
|
||||
.commit-group-headers {
|
||||
.group {
|
||||
margin-bottom: 2rem;
|
||||
border-radius: var(--border-radius);
|
||||
overflow: hidden;
|
||||
}
|
||||
.teaser-wrapper:not(:last-child) {
|
||||
border-bottom: 1px solid var(--color-background);
|
||||
}
|
||||
.more {
|
||||
margin-top: 2rem;
|
||||
@@ -88,18 +75,13 @@
|
||||
{#if history}
|
||||
<div class="history">
|
||||
{#each groupCommits(history) as group (group.time)}
|
||||
<div class="commit-group">
|
||||
<header class="commit-date">
|
||||
<p>{group.date}</p>
|
||||
</header>
|
||||
<div class="commit-group-headers">
|
||||
{#each group.commits as commit (commit.id)}
|
||||
<CommitTeaser
|
||||
{commit}
|
||||
on:click={() => goToCommit(commit.id)}
|
||||
on:browseCommit={goToSourceTreeAtCommit} />
|
||||
{/each}
|
||||
</div>
|
||||
<p style:color="var(--color-foreground-6)">{group.date}</p>
|
||||
<div class="group">
|
||||
{#each group.commits as commit (commit.id)}
|
||||
<div class="teaser-wrapper">
|
||||
<CommitTeaser {commit} />
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/each}
|
||||
<div class="more">
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import Authorship from "@app/components/Authorship.svelte";
|
||||
import Badge from "@app/components/Badge.svelte";
|
||||
import Icon from "@app/components/Icon.svelte";
|
||||
import ProjectLink from "@app/components/ProjectLink.svelte";
|
||||
|
||||
export let issue: Issue;
|
||||
|
||||
@@ -25,14 +26,12 @@
|
||||
|
||||
<style>
|
||||
.issue-teaser {
|
||||
display: grid;
|
||||
grid-template-columns: 3rem minmax(0, 1fr) auto;
|
||||
display: flex;
|
||||
padding: 0.75rem 0;
|
||||
background-color: var(--color-foreground-1);
|
||||
}
|
||||
.issue-teaser:hover {
|
||||
background-color: var(--color-foreground-2);
|
||||
cursor: pointer;
|
||||
}
|
||||
.subtitle {
|
||||
color: var(--color-foreground-6);
|
||||
@@ -51,6 +50,10 @@
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
}
|
||||
.issue-title:hover {
|
||||
color: var(--color-secondary);
|
||||
}
|
||||
.comment-count {
|
||||
display: flex;
|
||||
@@ -70,14 +73,15 @@
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.column-right {
|
||||
.right {
|
||||
align-self: center;
|
||||
justify-self: center;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.state {
|
||||
justify-self: center;
|
||||
align-self: center;
|
||||
margin: 0 1.25rem;
|
||||
}
|
||||
.state-icon {
|
||||
width: 0.5rem;
|
||||
@@ -105,9 +109,17 @@
|
||||
class:closed={issue.state.status === "closed"}
|
||||
class:open={issue.state.status === "open"} />
|
||||
</div>
|
||||
<div class="column-left">
|
||||
<div>
|
||||
<div class="summary">
|
||||
<span class="issue-title">{issue.title}</span>
|
||||
<ProjectLink
|
||||
projectParams={{
|
||||
view: {
|
||||
resource: "issue",
|
||||
params: { issue: issue.id },
|
||||
},
|
||||
}}>
|
||||
<span class="issue-title">{issue.title}</span>
|
||||
</ProjectLink>
|
||||
<span class="tags">
|
||||
{#each issue.tags.slice(0, 4) as tag}
|
||||
<Badge style="max-width:7rem" variant="secondary">
|
||||
@@ -129,7 +141,7 @@
|
||||
</div>
|
||||
</div>
|
||||
{#if commentCount > 0}
|
||||
<div class="column-right">
|
||||
<div class="right">
|
||||
<div class="comment-count">
|
||||
<Icon name="chat" />
|
||||
<span>{commentCount}</span>
|
||||
|
||||
@@ -6,10 +6,8 @@
|
||||
|
||||
<script lang="ts">
|
||||
import type { Issue } from "@httpd-client";
|
||||
import type { Tab } from "@app/components/TabBar.svelte";
|
||||
import type { BaseUrl } from "@httpd-client";
|
||||
|
||||
import * as router from "@app/lib/router";
|
||||
import * as utils from "@app/lib/utils";
|
||||
import capitalize from "lodash/capitalize";
|
||||
import { HttpdClient } from "@httpd-client";
|
||||
@@ -17,11 +15,11 @@
|
||||
|
||||
import Button from "@app/components/Button.svelte";
|
||||
import ErrorMessage from "@app/components/ErrorMessage.svelte";
|
||||
import HeaderToggleLabel from "@app/views/projects/HeaderToggleLabel.svelte";
|
||||
import IssueTeaser from "@app/views/projects/Issue/IssueTeaser.svelte";
|
||||
import Loading from "@app/components/Loading.svelte";
|
||||
import Placeholder from "@app/components/Placeholder.svelte";
|
||||
import TabBar from "@app/components/TabBar.svelte";
|
||||
import ProjectLink from "@app/components/ProjectLink.svelte";
|
||||
import SquareButton from "@app/components/SquareButton.svelte";
|
||||
|
||||
export let projectId: string;
|
||||
export let state: IssueStatus;
|
||||
@@ -30,9 +28,6 @@
|
||||
|
||||
const perPage = 10;
|
||||
|
||||
// Keeping it true, to avoid an initial flash
|
||||
// of EmptyState Placeholder
|
||||
let refresh = true;
|
||||
let loading = false;
|
||||
let page = 0;
|
||||
let error: any;
|
||||
@@ -40,7 +35,7 @@
|
||||
|
||||
const api = new HttpdClient(baseUrl);
|
||||
|
||||
async function loadIssues(): Promise<void> {
|
||||
async function loadIssues(state: IssueStatus): Promise<void> {
|
||||
loading = true;
|
||||
try {
|
||||
const response = await api.project.getAllIssues(projectId, {
|
||||
@@ -54,26 +49,17 @@
|
||||
error = e;
|
||||
} finally {
|
||||
loading = false;
|
||||
refresh = false;
|
||||
}
|
||||
}
|
||||
|
||||
function switchState(e: CustomEvent<IssueStatus>): void {
|
||||
refresh = true;
|
||||
// Update state to be used in the query
|
||||
state = e.detail;
|
||||
// Reset page to 0 to load the first page for a new state
|
||||
page = 0;
|
||||
// Remove all existing patches with old state
|
||||
issues = [];
|
||||
loadIssues();
|
||||
router.updateProjectRoute({
|
||||
search: `state=${state}`,
|
||||
});
|
||||
interface Tab {
|
||||
value: IssueStatus;
|
||||
title: string;
|
||||
disabled: boolean;
|
||||
}
|
||||
|
||||
const stateOptions: IssueStatus[] = ["open", "closed"];
|
||||
const options = stateOptions.map<Tab<IssueStatus>>(s => ({
|
||||
const options = stateOptions.map<Tab>(s => ({
|
||||
value: s,
|
||||
title: `${issueCounters[s]} ${s}`,
|
||||
disabled: issueCounters[s] === 0,
|
||||
@@ -85,7 +71,11 @@
|
||||
issueCounters[state] &&
|
||||
issues.length < issueCounters[state];
|
||||
|
||||
loadIssues();
|
||||
$: {
|
||||
page = 0;
|
||||
issues = [];
|
||||
loadIssues(state);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@@ -98,7 +88,7 @@
|
||||
overflow: hidden;
|
||||
}
|
||||
.teaser:not(:last-child) {
|
||||
border-bottom: 1px dashed var(--color-background);
|
||||
border-bottom: 1px solid var(--color-background);
|
||||
}
|
||||
.section-header {
|
||||
display: flex;
|
||||
@@ -106,9 +96,6 @@
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
}
|
||||
.loader {
|
||||
margin-top: 8rem;
|
||||
}
|
||||
.more {
|
||||
margin-top: 2rem;
|
||||
text-align: center;
|
||||
@@ -125,61 +112,72 @@
|
||||
<div class="issues">
|
||||
<div class="section-header">
|
||||
<div style="margin-bottom: 1rem;">
|
||||
<TabBar {options} on:select={switchState} active={state} />
|
||||
<div style="display: flex; gap: 0.5rem;">
|
||||
{#each options as option}
|
||||
{#if !option.disabled}
|
||||
<ProjectLink
|
||||
projectParams={{
|
||||
search: `state=${option.value}`,
|
||||
}}>
|
||||
<SquareButton
|
||||
size="small"
|
||||
clickable={option.disabled}
|
||||
active={option.value === state}
|
||||
disabled={option.disabled}>
|
||||
{option.title}
|
||||
</SquareButton>
|
||||
</ProjectLink>
|
||||
{:else}
|
||||
<SquareButton
|
||||
size="small"
|
||||
clickable={option.disabled}
|
||||
active={option.value === state}
|
||||
disabled={option.disabled}>
|
||||
{option.title}
|
||||
</SquareButton>
|
||||
{/if}
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
<HeaderToggleLabel
|
||||
disabled={!$sessionStore || !utils.isLocal(baseUrl.hostname)}
|
||||
on:click={() => {
|
||||
router.updateProjectRoute({
|
||||
{#if $sessionStore && utils.isLocal(baseUrl.hostname)}
|
||||
<ProjectLink
|
||||
projectParams={{
|
||||
view: {
|
||||
resource: "issues",
|
||||
params: { view: { resource: "new" } },
|
||||
},
|
||||
});
|
||||
}}
|
||||
clickable>
|
||||
New issue
|
||||
</HeaderToggleLabel>
|
||||
}}>
|
||||
<SquareButton size="small">New issue</SquareButton>
|
||||
</ProjectLink>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="issues-list">
|
||||
{#if refresh}
|
||||
<div class="loader">
|
||||
<Loading center />
|
||||
{#each issues as issue}
|
||||
<div class="teaser">
|
||||
<IssueTeaser {issue} />
|
||||
</div>
|
||||
{:else}
|
||||
{#each issues as issue}
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div
|
||||
class="teaser"
|
||||
on:click={() => {
|
||||
router.updateProjectRoute({
|
||||
view: {
|
||||
resource: "issue",
|
||||
params: { issue: issue.id },
|
||||
},
|
||||
});
|
||||
}}>
|
||||
<IssueTeaser {issue} />
|
||||
</div>
|
||||
{#if error}
|
||||
<ErrorMessage message="Couldn't load issues." stackTrace={error} />
|
||||
{:else if loading}
|
||||
<!-- We already show a loader below. -->
|
||||
{:else}
|
||||
{#if error}
|
||||
<ErrorMessage message="Couldn't load issues." stackTrace={error} />
|
||||
{:else}
|
||||
<Placeholder emoji="🍂">
|
||||
<div slot="title">{capitalize(state)} issues</div>
|
||||
<div slot="body">No issues matched the current filter</div>
|
||||
</Placeholder>
|
||||
{/if}
|
||||
{/each}
|
||||
<div class="more">
|
||||
{#if loading}
|
||||
<Loading small={page !== 0} center />
|
||||
{/if}
|
||||
<Placeholder emoji="🍂">
|
||||
<div slot="title">{capitalize(state)} issues</div>
|
||||
<div slot="body">No issues matched the current filter</div>
|
||||
</Placeholder>
|
||||
{/if}
|
||||
{/each}
|
||||
</div>
|
||||
<div class="more">
|
||||
{#if loading}
|
||||
<Loading small={page !== 0} center />
|
||||
{/if}
|
||||
|
||||
{#if showMoreButton}
|
||||
<Button variant="foreground" on:click={loadIssues}>More</Button>
|
||||
{/if}
|
||||
</div>
|
||||
{#if showMoreButton}
|
||||
<Button variant="foreground" on:click={() => loadIssues(state)}>
|
||||
More
|
||||
</Button>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -40,8 +40,8 @@
|
||||
import CommitTeaser from "./Commit/CommitTeaser.svelte";
|
||||
import Dropdown from "@app/components/Dropdown.svelte";
|
||||
import Floating from "@app/components/Floating.svelte";
|
||||
import HeaderToggleLabel from "./HeaderToggleLabel.svelte";
|
||||
import TabBar from "@app/components/TabBar.svelte";
|
||||
import ProjectLink from "@app/components/ProjectLink.svelte";
|
||||
import SquareButton from "@app/components/SquareButton.svelte";
|
||||
import TagInput from "./Cob/TagInput.svelte";
|
||||
import ThreadComponent from "@app/components/Thread.svelte";
|
||||
|
||||
@@ -54,14 +54,6 @@
|
||||
|
||||
const api = new HttpdClient(baseUrl);
|
||||
|
||||
const browseCommit = (event: { detail: string }) => {
|
||||
router.updateProjectRoute({
|
||||
view: { resource: "tree" },
|
||||
search: undefined,
|
||||
revision: event.detail,
|
||||
});
|
||||
};
|
||||
|
||||
async function createReply({
|
||||
detail: reply,
|
||||
}: CustomEvent<{ id: string; body: string }>) {
|
||||
@@ -193,6 +185,11 @@
|
||||
margin: 1rem;
|
||||
color: var(--color-foreground-5);
|
||||
}
|
||||
.commit-list {
|
||||
border-radius: var(--border-radius);
|
||||
overflow: hidden;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
@media (max-width: 1092px) {
|
||||
.patch {
|
||||
@@ -214,14 +211,13 @@
|
||||
<div>
|
||||
<CobHeader id={patch.id} title={patch.title}>
|
||||
<span slot="revision" class="txt-monospace txt-tiny">
|
||||
<Floating>
|
||||
<Floating disabled={patch.revisions.length === 1}>
|
||||
<svelte:fragment slot="toggle">
|
||||
<HeaderToggleLabel
|
||||
<SquareButton
|
||||
clickable={patch.revisions.length > 1}
|
||||
disabled={patch.revisions.length === 1}
|
||||
title="Toggle revision">
|
||||
disabled={patch.revisions.length === 1}>
|
||||
Revision {currentRevisionIndex}
|
||||
</HeaderToggleLabel>
|
||||
</SquareButton>
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="modal">
|
||||
<Dropdown
|
||||
@@ -263,13 +259,32 @@
|
||||
</div>
|
||||
</svelte:fragment>
|
||||
</CobHeader>
|
||||
<TabBar
|
||||
{options}
|
||||
active={currentTab}
|
||||
on:select={({ detail: tab }) =>
|
||||
router.updateProjectRoute({
|
||||
search: `tab=${tab}`,
|
||||
})} />
|
||||
<div style="display: flex; gap: 0.5rem;">
|
||||
{#each options as option}
|
||||
{#if !option.disabled}
|
||||
<ProjectLink
|
||||
projectParams={{
|
||||
search: `tab=${option.value}`,
|
||||
}}>
|
||||
<SquareButton
|
||||
size="small"
|
||||
clickable={option.disabled}
|
||||
active={option.value === currentTab}
|
||||
disabled={option.disabled}>
|
||||
{option.title}
|
||||
</SquareButton>
|
||||
</ProjectLink>
|
||||
{:else}
|
||||
<SquareButton
|
||||
size="small"
|
||||
clickable={option.disabled}
|
||||
active={option.value === currentTab}
|
||||
disabled={option.disabled}>
|
||||
{option.title}
|
||||
</SquareButton>
|
||||
{/if}
|
||||
{/each}
|
||||
</div>
|
||||
{#if currentTab === "activity"}
|
||||
<div style:margin-top="1rem">
|
||||
<div class="txt-tiny">
|
||||
@@ -332,34 +347,16 @@
|
||||
</div>
|
||||
{:else if currentTab === "commits"}
|
||||
{#await diffPromise then diff}
|
||||
<div style:margin-top="1rem">
|
||||
<div class="commit-list">
|
||||
{#each diff.commits as commit}
|
||||
<CommitTeaser
|
||||
{commit}
|
||||
on:click={() => {
|
||||
router.updateProjectRoute({
|
||||
view: { resource: "commits" },
|
||||
revision: commit.id,
|
||||
search: undefined,
|
||||
});
|
||||
}}
|
||||
on:browseCommit={browseCommit} />
|
||||
<CommitTeaser {commit} />
|
||||
{/each}
|
||||
</div>
|
||||
{/await}
|
||||
{:else if currentTab === "files"}
|
||||
{#await diffPromise then diff}
|
||||
<div style:margin-top="1rem">
|
||||
<Changeset
|
||||
diff={diff.diff}
|
||||
on:browse={({ detail: path }) => {
|
||||
router.updateProjectRoute({
|
||||
view: { resource: "tree" },
|
||||
search: undefined,
|
||||
revision: currentRevision.oid,
|
||||
path,
|
||||
});
|
||||
}} />
|
||||
<Changeset revision={currentRevision.oid} diff={diff.diff} />
|
||||
</div>
|
||||
{/await}
|
||||
{/if}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
import Badge from "@app/components/Badge.svelte";
|
||||
import DiffStatBadge from "@app/components/DiffStatBadge.svelte";
|
||||
import Icon from "@app/components/Icon.svelte";
|
||||
import ProjectLink from "@app/components/ProjectLink.svelte";
|
||||
|
||||
export let projectId: string;
|
||||
export let baseUrl: BaseUrl;
|
||||
@@ -27,14 +28,12 @@
|
||||
|
||||
<style>
|
||||
.patch-teaser {
|
||||
display: grid;
|
||||
grid-template-columns: 3rem minmax(0, 1fr) auto;
|
||||
display: flex;
|
||||
padding: 0.75rem 0;
|
||||
background-color: var(--color-foreground-1);
|
||||
}
|
||||
.patch-teaser:hover {
|
||||
background-color: var(--color-foreground-2);
|
||||
cursor: pointer;
|
||||
}
|
||||
.meta {
|
||||
display: flex;
|
||||
@@ -57,23 +56,25 @@
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.patch-title:hover {
|
||||
color: var(--color-secondary);
|
||||
}
|
||||
.comment-count {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding-right: 1rem;
|
||||
gap: 0.5rem;
|
||||
color: var(--color-foreground-5);
|
||||
}
|
||||
|
||||
.column-right {
|
||||
.right {
|
||||
align-self: center;
|
||||
justify-self: center;
|
||||
padding-right: 1rem;
|
||||
margin-left: auto;
|
||||
}
|
||||
.state {
|
||||
justify-self: center;
|
||||
align-self: center;
|
||||
margin: 0 1.25rem;
|
||||
}
|
||||
.tags {
|
||||
display: flex;
|
||||
@@ -117,9 +118,17 @@
|
||||
class:merged={patch.state.status === "merged"}
|
||||
class:archived={patch.state.status === "archived"} />
|
||||
</div>
|
||||
<div class="column-left">
|
||||
<div>
|
||||
<div class="summary">
|
||||
<span class="patch-title">{patch.title}</span>
|
||||
<ProjectLink
|
||||
projectParams={{
|
||||
view: {
|
||||
resource: "patch",
|
||||
params: { patch: patch.id },
|
||||
},
|
||||
}}>
|
||||
<span class="patch-title">{patch.title}</span>
|
||||
</ProjectLink>
|
||||
<span class="tags">
|
||||
{#each patch.tags.slice(0, 4) as tag}
|
||||
<Badge style="max-width:7rem" variant="secondary">
|
||||
@@ -142,7 +151,7 @@
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column-right">
|
||||
<div class="right">
|
||||
<div class="comment-count">
|
||||
{#await diffPromise then { diff }}
|
||||
<DiffStatBadge
|
||||
|
||||
@@ -5,10 +5,8 @@
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import type { Tab } from "@app/components/TabBar.svelte";
|
||||
import type { BaseUrl } from "@httpd-client";
|
||||
|
||||
import * as router from "@app/lib/router";
|
||||
import capitalize from "lodash/capitalize";
|
||||
import { HttpdClient } from "@httpd-client";
|
||||
|
||||
@@ -17,7 +15,8 @@
|
||||
import Loading from "@app/components/Loading.svelte";
|
||||
import PatchTeaser from "./Patch/PatchTeaser.svelte";
|
||||
import Placeholder from "@app/components/Placeholder.svelte";
|
||||
import TabBar from "@app/components/TabBar.svelte";
|
||||
import ProjectLink from "@app/components/ProjectLink.svelte";
|
||||
import SquareButton from "@app/components/SquareButton.svelte";
|
||||
|
||||
export let projectId: string;
|
||||
export let state: PatchStatus;
|
||||
@@ -31,9 +30,6 @@
|
||||
|
||||
const perPage = 10;
|
||||
|
||||
// Keeping it true, to avoid an initial flash
|
||||
// of EmptyState Placeholder
|
||||
let refresh = true;
|
||||
let loading = false;
|
||||
let page = 0;
|
||||
let error: any;
|
||||
@@ -41,7 +37,7 @@
|
||||
|
||||
const api = new HttpdClient(baseUrl);
|
||||
|
||||
async function loadPatches(): Promise<void> {
|
||||
async function loadPatches(state: PatchStatus): Promise<void> {
|
||||
loading = true;
|
||||
try {
|
||||
const response = await api.project.getAllPatches(projectId, {
|
||||
@@ -55,37 +51,33 @@
|
||||
error = e;
|
||||
} finally {
|
||||
loading = false;
|
||||
refresh = false;
|
||||
}
|
||||
}
|
||||
|
||||
function switchState(e: CustomEvent<PatchStatus>): void {
|
||||
refresh = true;
|
||||
// Update state to be used in the query
|
||||
state = e.detail;
|
||||
// Reset page to 0 to load the first page for a new state
|
||||
page = 0;
|
||||
// Remove all existing patches with old state
|
||||
patches = [];
|
||||
loadPatches();
|
||||
router.updateProjectRoute({
|
||||
search: `state=${state}`,
|
||||
});
|
||||
interface Tab {
|
||||
value: PatchStatus;
|
||||
title: string;
|
||||
disabled: boolean;
|
||||
}
|
||||
|
||||
const stateOptions: PatchStatus[] = ["draft", "open", "archived", "merged"];
|
||||
const options = stateOptions.map<Tab<PatchStatus>>(s => ({
|
||||
const options = stateOptions.map<Tab>(s => ({
|
||||
value: s,
|
||||
title: `${patchCounters[s]} ${s}`,
|
||||
disabled: patchCounters[s] === 0,
|
||||
}));
|
||||
|
||||
$: showMoreButton =
|
||||
!loading &&
|
||||
!error &&
|
||||
patchCounters[state] &&
|
||||
patches.length < patchCounters[state];
|
||||
|
||||
loadPatches();
|
||||
$: {
|
||||
page = 0;
|
||||
patches = [];
|
||||
loadPatches(state);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@@ -97,9 +89,6 @@
|
||||
border-radius: var(--border-radius);
|
||||
overflow: hidden;
|
||||
}
|
||||
.loader {
|
||||
margin-top: 8rem;
|
||||
}
|
||||
.more {
|
||||
margin-top: 2rem;
|
||||
text-align: center;
|
||||
@@ -118,47 +107,62 @@
|
||||
|
||||
<div class="patches">
|
||||
<div style="margin-bottom: 1rem;">
|
||||
<TabBar {options} on:select={switchState} active={state} />
|
||||
</div>
|
||||
<div class="patches-list">
|
||||
{#if refresh}
|
||||
<div class="loader">
|
||||
<Loading center />
|
||||
</div>
|
||||
{:else}
|
||||
{#each patches as patch}
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div
|
||||
class="teaser"
|
||||
on:click={() => {
|
||||
router.updateProjectRoute({
|
||||
view: {
|
||||
resource: "patch",
|
||||
params: { patch: patch.id },
|
||||
},
|
||||
});
|
||||
}}>
|
||||
<PatchTeaser {baseUrl} {projectId} {patch} />
|
||||
</div>
|
||||
{:else}
|
||||
{#if error}
|
||||
<ErrorMessage message="Couldn't load patches." stackTrace={error} />
|
||||
<div style="display: flex; gap: 0.5rem;">
|
||||
{#each options as option}
|
||||
{#if option.disabled}
|
||||
<SquareButton
|
||||
size="small"
|
||||
clickable={option.disabled}
|
||||
active={option.value === state}
|
||||
disabled={option.disabled}>
|
||||
{option.title}
|
||||
</SquareButton>
|
||||
{:else}
|
||||
<Placeholder emoji="🍂">
|
||||
<div slot="title">{capitalize(state)} patches</div>
|
||||
<div slot="body">No patches matched the current filter</div>
|
||||
</Placeholder>
|
||||
<ProjectLink
|
||||
projectParams={{
|
||||
search: `state=${option.value}`,
|
||||
}}>
|
||||
<SquareButton
|
||||
size="small"
|
||||
clickable={option.disabled}
|
||||
active={option.value === state}
|
||||
disabled={option.disabled}>
|
||||
{option.title}
|
||||
</SquareButton>
|
||||
</ProjectLink>
|
||||
{/if}
|
||||
{/each}
|
||||
<div class="more">
|
||||
{#if loading}
|
||||
<Loading small={page !== 0} center />
|
||||
{/if}
|
||||
|
||||
{#if showMoreButton}
|
||||
<Button variant="foreground" on:click={loadPatches}>More</Button>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<div class="patches-list">
|
||||
{#each patches as patch}
|
||||
<div class="teaser">
|
||||
<PatchTeaser {baseUrl} {projectId} {patch} />
|
||||
</div>
|
||||
{:else}
|
||||
{#if error}
|
||||
<ErrorMessage message="Couldn't load patches." stackTrace={error} />
|
||||
{:else if loading}
|
||||
<!-- We already show a loader below. -->
|
||||
{:else}
|
||||
<Placeholder emoji="🍂">
|
||||
<div slot="title">{capitalize(state)} patches</div>
|
||||
<div slot="body">No patches matched the current filter</div>
|
||||
</Placeholder>
|
||||
{/if}
|
||||
{/each}
|
||||
</div>
|
||||
<div class="more">
|
||||
{#if loading}
|
||||
<div style:margin-top={page === 0 ? "8rem" : ""}>
|
||||
<Loading small={page !== 0} center />
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if showMoreButton}
|
||||
<Button variant="foreground" on:click={() => loadPatches(state)}>
|
||||
More
|
||||
</Button>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import type { Item } from "@app/components/Dropdown.svelte";
|
||||
import type { Remote } from "@httpd-client";
|
||||
|
||||
import { createEventDispatcher, onMount } from "svelte";
|
||||
import { onMount } from "svelte";
|
||||
|
||||
import { formatNodeId, truncateId } from "@app/lib/utils";
|
||||
|
||||
@@ -11,8 +11,9 @@
|
||||
import Dropdown from "@app/components/Dropdown.svelte";
|
||||
import Floating from "@app/components/Floating.svelte";
|
||||
import Icon from "@app/components/Icon.svelte";
|
||||
import ProjectLink from "@app/components/ProjectLink.svelte";
|
||||
|
||||
export let peer: string | null = null;
|
||||
export let peer: string | undefined = undefined;
|
||||
export let peers: Remote[];
|
||||
|
||||
let meta: Remote | undefined;
|
||||
@@ -36,11 +37,6 @@
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
const dispatch = createEventDispatcher<{ peerChanged: string }>();
|
||||
const switchPeer = (peer: string) => {
|
||||
dispatch("peerChanged", peer);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@@ -69,7 +65,7 @@
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 0;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
.prefix {
|
||||
display: inline-block;
|
||||
@@ -83,6 +79,12 @@
|
||||
height: 2rem;
|
||||
line-height: initial;
|
||||
background: var(--color-foreground-1);
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.avatar-id {
|
||||
display: flex;
|
||||
gap: 0.25rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -93,39 +95,53 @@
|
||||
<Icon name="fork" />
|
||||
{/if}
|
||||
{#if meta}
|
||||
<span style:display="flex">
|
||||
<span class="avatar-id">
|
||||
<Avatar nodeId={meta.id} inline />
|
||||
<span style:color="var(--color-secondary-5)">did:key:</span>
|
||||
{truncateId(meta.id)}
|
||||
<!-- Ignore prettier to avoid getting a whitespace between
|
||||
did:key: and the nid due to a newline. -->
|
||||
<!-- prettier-ignore -->
|
||||
<span><span style:color="var(--color-secondary-5)">did:key:</span>{truncateId(meta.id)}</span>
|
||||
</span>
|
||||
{#if meta.delegate}
|
||||
<Badge variant="primary">delegate</Badge>
|
||||
{/if}
|
||||
{:else if peer}
|
||||
<span style:display="flex">
|
||||
<span class="avatar-id">
|
||||
<Avatar nodeId={peer} inline />
|
||||
<span style:color="var(--color-secondary-5)">did:key:</span>
|
||||
{truncateId(peer)}
|
||||
<!-- prettier-ignore -->
|
||||
<span><span style:color="var(--color-secondary-5)">did:key:</span>{truncateId(peer)}</span>
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<svelte:fragment slot="modal">
|
||||
<Dropdown
|
||||
{items}
|
||||
selected={peer}
|
||||
on:select={e => switchPeer(e.detail.value)}>
|
||||
<div class="peer-item" slot="item" let:item>
|
||||
<Avatar nodeId={item.value} inline />
|
||||
<!-- We ignore prettier here for the following line
|
||||
to avoid getting a whitespace between did:key: and the nid due to a newline -->
|
||||
<!-- prettier-ignore -->
|
||||
<span><span class="prefix">did:key:</span>{item.value}</span>
|
||||
{#if item.badge}
|
||||
<Badge variant="primary">{item.badge}</Badge>
|
||||
{/if}
|
||||
</div>
|
||||
<Dropdown {items} selected={peer}>
|
||||
<svelte:fragment slot="item" let:item>
|
||||
<ProjectLink
|
||||
on:click
|
||||
projectParams={{
|
||||
peer: item.value,
|
||||
revision: undefined,
|
||||
}}>
|
||||
<div class="peer-item">
|
||||
<span class="avatar-id">
|
||||
<Avatar nodeId={item.value} inline />
|
||||
<div class="layout-desktop">
|
||||
<!-- prettier-ignore -->
|
||||
<span><span class="prefix">did:key:</span>{item.value}</span>
|
||||
</div>
|
||||
<div class="layout-mobile">
|
||||
<!-- prettier-ignore -->
|
||||
<span><span class="prefix">did:key:</span>{truncateId(item.value)}</span>
|
||||
</div>
|
||||
</span>
|
||||
{#if item.badge}
|
||||
<Badge variant="primary">{item.badge}</Badge>
|
||||
{/if}
|
||||
</div>
|
||||
</ProjectLink>
|
||||
</svelte:fragment>
|
||||
</Dropdown>
|
||||
</svelte:fragment>
|
||||
</Floating>
|
||||
|
||||
@@ -16,22 +16,28 @@
|
||||
|
||||
<style>
|
||||
.title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: left;
|
||||
color: var(--color-secondary);
|
||||
display: flex;
|
||||
font-size: var(--font-size-x-large);
|
||||
font-weight: var(--font-weight-bold);
|
||||
justify-content: left;
|
||||
margin-bottom: 0.5rem;
|
||||
overflow-x: hidden;
|
||||
text-align: left;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.title .divider {
|
||||
.divider {
|
||||
color: var(--color-foreground-4);
|
||||
margin: 0 0.5rem;
|
||||
font-weight: var(--font-weight-normal);
|
||||
}
|
||||
.title .node-id {
|
||||
.node-id {
|
||||
color: var(--color-foreground-5);
|
||||
font-weight: var(--font-weight-normal);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.project-name:hover {
|
||||
color: inherit;
|
||||
@@ -68,11 +74,15 @@
|
||||
.content {
|
||||
padding-left: 2rem;
|
||||
}
|
||||
.title {
|
||||
font-size: var(--font-size-medium);
|
||||
font-weight: var(--font-weight-bold);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<header class="content">
|
||||
<div class="title txt-bold txt-title">
|
||||
<div class="title">
|
||||
<span class="truncate">
|
||||
<ProjectLink
|
||||
projectParams={{
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import FileDiff from "@app/views/projects/SourceBrowser/FileDiff.svelte";
|
||||
|
||||
export let diff: Diff;
|
||||
export let revision: string;
|
||||
|
||||
const diffDescription = ({ modified, added, deleted }: Diff): string => {
|
||||
const s = [];
|
||||
@@ -53,12 +54,12 @@
|
||||
</div>
|
||||
<div class="diff-listing">
|
||||
{#each diff.added as file}
|
||||
<FileDiff on:browse {file} mode="added" />
|
||||
<FileDiff on:browse {file} {revision} mode="added" />
|
||||
{/each}
|
||||
{#each diff.deleted as file}
|
||||
<FileDiff on:browse {file} mode="deleted" />
|
||||
<FileDiff on:browse {file} {revision} mode="deleted" />
|
||||
{/each}
|
||||
{#each diff.modified as file}
|
||||
<FileDiff on:browse {file} />
|
||||
<FileDiff on:browse {file} {revision} />
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
@@ -1,23 +1,17 @@
|
||||
<script lang="ts" strictEvents>
|
||||
<script lang="ts">
|
||||
import type {
|
||||
DiffAddedDeletedModifiedChangeset,
|
||||
HunkLine,
|
||||
} from "@httpd-client";
|
||||
|
||||
import { createEventDispatcher } from "svelte";
|
||||
|
||||
import Badge from "@app/components/Badge.svelte";
|
||||
import Icon from "@app/components/Icon.svelte";
|
||||
|
||||
const dispatch = createEventDispatcher<{ browse: string }>();
|
||||
import ProjectLink from "@app/components/ProjectLink.svelte";
|
||||
|
||||
export let file: DiffAddedDeletedModifiedChangeset;
|
||||
export let revision: string;
|
||||
export let mode: string | null = null;
|
||||
|
||||
function collapse() {
|
||||
collapsed = !collapsed;
|
||||
}
|
||||
|
||||
let collapsed = false;
|
||||
|
||||
function lineNumberR(line: HunkLine): string | number {
|
||||
@@ -64,19 +58,19 @@
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.changeset-file {
|
||||
.wrapper {
|
||||
border: 1px solid var(--color-foreground-4);
|
||||
border-radius: var(--border-radius-small);
|
||||
margin-bottom: 2rem;
|
||||
line-height: 1.5rem;
|
||||
}
|
||||
.changeset-file header {
|
||||
cursor: pointer;
|
||||
height: 3rem;
|
||||
display: flex;
|
||||
.header {
|
||||
align-items: center;
|
||||
background: none;
|
||||
border-radius: 0;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
height: 3rem;
|
||||
padding: 1rem;
|
||||
}
|
||||
main {
|
||||
@@ -84,15 +78,8 @@
|
||||
border-top: 1px dashed var(--color-foreground-4);
|
||||
background: var(--color-background-1);
|
||||
border-radius: 0 0 var(--border-radius-small) var(--border-radius-small);
|
||||
}
|
||||
.changeset-file main {
|
||||
overflow-x: auto;
|
||||
}
|
||||
header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.actions {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
@@ -105,69 +92,82 @@
|
||||
text-align: center;
|
||||
background-color: var(--color-foreground-2);
|
||||
}
|
||||
table.diff {
|
||||
.browse {
|
||||
margin-left: auto;
|
||||
cursor: pointer;
|
||||
}
|
||||
.expand-button {
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
.diff {
|
||||
font-family: var(--font-family-monospace);
|
||||
table-layout: fixed;
|
||||
border-collapse: collapse;
|
||||
margin: 0.5rem 0;
|
||||
}
|
||||
tr.diff-line {
|
||||
.diff-line {
|
||||
vertical-align: top;
|
||||
}
|
||||
tr.diff-line[data-type="+"] > * {
|
||||
.diff-line[data-type="+"] > * {
|
||||
color: var(--color-positive);
|
||||
}
|
||||
tr.diff-line[data-type="-"] > * {
|
||||
.diff-line[data-type="-"] > * {
|
||||
color: var(--color-negative);
|
||||
}
|
||||
td.diff-line-number {
|
||||
.diff-line-number {
|
||||
text-align: right;
|
||||
user-select: none;
|
||||
line-height: 1.5rem;
|
||||
min-width: 3rem;
|
||||
}
|
||||
td.diff-line-number[data-type="+"],
|
||||
td.diff-line-type[data-type="+"] {
|
||||
.diff-line-number[data-type="+"],
|
||||
.diff-line-type[data-type="+"] {
|
||||
background-color: var(--color-positive-2);
|
||||
color: var(--color-positive-6);
|
||||
}
|
||||
td.diff-line-number[data-type="-"],
|
||||
td.diff-line-type[data-type="-"] {
|
||||
.diff-line-number[data-type="-"],
|
||||
.diff-line-type[data-type="-"] {
|
||||
background-color: var(--color-negative-2);
|
||||
color: var(--color-negative-6);
|
||||
}
|
||||
td.diff-line-number.left {
|
||||
.diff-line-number.left {
|
||||
padding: 0 0.5rem 0 0.75rem;
|
||||
}
|
||||
td.diff-line-number.right {
|
||||
.diff-line-number.right {
|
||||
padding: 0 0.75rem 0 0.5rem;
|
||||
}
|
||||
td.diff-line-content {
|
||||
.diff-line-content {
|
||||
white-space: pre-wrap;
|
||||
overflow-wrap: anywhere;
|
||||
width: 100%;
|
||||
padding-right: 0.5rem;
|
||||
}
|
||||
td.diff-line-type {
|
||||
.diff-line-type {
|
||||
text-align: center;
|
||||
padding-left: 0.75rem;
|
||||
padding-right: 0.75rem;
|
||||
}
|
||||
td.diff-expand-header {
|
||||
.diff-expand-header {
|
||||
padding-left: 0.5rem;
|
||||
color: var(--color-foreground-5);
|
||||
}
|
||||
td.diff-line-number {
|
||||
.diff-line-number {
|
||||
color: var(--color-foreground-5);
|
||||
}
|
||||
.browse {
|
||||
display: flex;
|
||||
}
|
||||
</style>
|
||||
|
||||
<article id={file.path} class="changeset-file">
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<header class="file-header" on:click={collapse}>
|
||||
<div id={file.path} class="wrapper">
|
||||
<header class="header">
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div class="expand-button" on:click={() => (collapsed = !collapsed)}>
|
||||
{#if collapsed}
|
||||
<Icon name="chevron-right" />
|
||||
{:else}
|
||||
<Icon name="chevron-down" />
|
||||
{/if}
|
||||
</div>
|
||||
<div class="actions">
|
||||
<p class="txt-regular">{file.path}</p>
|
||||
{#if mode === "added"}
|
||||
@@ -176,12 +176,16 @@
|
||||
<Badge variant="negative">deleted</Badge>
|
||||
{/if}
|
||||
</div>
|
||||
<div
|
||||
class="browse clickable"
|
||||
on:click|stopPropagation={() => dispatch("browse", file.path)}>
|
||||
<span title="View file" style="transform: scale(1.25);">
|
||||
<div class="browse" title="View file">
|
||||
<ProjectLink
|
||||
projectParams={{
|
||||
view: { resource: "tree" },
|
||||
path: file.path,
|
||||
revision,
|
||||
search: undefined,
|
||||
}}>
|
||||
<Icon name="browse" />
|
||||
</span>
|
||||
</ProjectLink>
|
||||
</div>
|
||||
</header>
|
||||
{#if !collapsed}
|
||||
@@ -216,4 +220,4 @@
|
||||
{/if}
|
||||
</main>
|
||||
{/if}
|
||||
</article>
|
||||
</div>
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
import File from "./Tree/File.svelte";
|
||||
import Folder from "./Tree/Folder.svelte";
|
||||
import ProjectLink from "@app/components/ProjectLink.svelte";
|
||||
|
||||
export let fetchTree: (path: string) => Promise<Tree | undefined>;
|
||||
export let path: string;
|
||||
@@ -27,10 +28,16 @@
|
||||
currentPath={path}
|
||||
on:select={onSelect} />
|
||||
{:else}
|
||||
<File
|
||||
active={entry.path === path}
|
||||
loading={entry.path === loadingPath}
|
||||
name={entry.name}
|
||||
on:click={() => onSelect({ detail: entry.path })} />
|
||||
<ProjectLink
|
||||
projectParams={{
|
||||
view: { resource: "tree" },
|
||||
path: entry.path,
|
||||
}}
|
||||
on:click={() => onSelect({ detail: entry.path })}>
|
||||
<File
|
||||
active={entry.path === path}
|
||||
loading={entry.path === loadingPath}
|
||||
name={entry.name} />
|
||||
</ProjectLink>
|
||||
{/if}
|
||||
{/each}
|
||||
|
||||
@@ -46,8 +46,7 @@
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div class="file" class:active on:click>
|
||||
<div class="file" class:active>
|
||||
<span class="name">{name}</span>
|
||||
<div class="spinner">
|
||||
{#if loading}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
import { createEventDispatcher } from "svelte";
|
||||
|
||||
import Loading from "@app/components/Loading.svelte";
|
||||
import ProjectLink from "@app/components/ProjectLink.svelte";
|
||||
|
||||
import File from "./File.svelte";
|
||||
|
||||
@@ -84,13 +85,17 @@
|
||||
{loadingPath}
|
||||
{currentPath} />
|
||||
{:else}
|
||||
<File
|
||||
active={entry.path === currentPath}
|
||||
loading={entry.path === loadingPath}
|
||||
name={entry.name}
|
||||
on:click={() => {
|
||||
onSelectFile({ detail: entry.path });
|
||||
}} />
|
||||
<ProjectLink
|
||||
projectParams={{
|
||||
view: { resource: "tree" },
|
||||
path: entry.path,
|
||||
}}
|
||||
on:click={() => onSelectFile({ detail: entry.path })}>
|
||||
<File
|
||||
active={entry.path === currentPath}
|
||||
loading={entry.path === loadingPath}
|
||||
name={entry.name} />
|
||||
</ProjectLink>
|
||||
{/if}
|
||||
{/each}
|
||||
{/if}
|
||||
|
||||
+33
-31
@@ -2,7 +2,6 @@
|
||||
import type { Project, NodeStats } from "@httpd-client";
|
||||
import type { WeeklyActivity } from "@app/lib/commit";
|
||||
|
||||
import * as router from "@app/lib/router";
|
||||
import { HttpdClient } from "@httpd-client";
|
||||
import { config } from "@app/lib/config";
|
||||
import { extractBaseUrl, isLocal, truncateId } from "@app/lib/utils";
|
||||
@@ -11,6 +10,7 @@
|
||||
import Button from "@app/components/Button.svelte";
|
||||
import Clipboard from "@app/components/Clipboard.svelte";
|
||||
import ErrorMessage from "@app/components/ErrorMessage.svelte";
|
||||
import Link from "@app/components/Link.svelte";
|
||||
import Loading from "@app/components/Loading.svelte";
|
||||
import ProjectCard from "@app/components/ProjectCard.svelte";
|
||||
|
||||
@@ -58,23 +58,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
function goToProject(project: Project) {
|
||||
router.push({
|
||||
resource: "projects",
|
||||
params: {
|
||||
view: { resource: "tree" },
|
||||
id: project.id,
|
||||
hostnamePort:
|
||||
baseUrl.port === config.seeds.defaultHttpdPort
|
||||
? baseUrl.hostname
|
||||
: `${baseUrl.hostname}:${baseUrl.port}`,
|
||||
revision: undefined,
|
||||
hash: undefined,
|
||||
search: undefined,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
$: showMoreButton =
|
||||
!loadingProjects &&
|
||||
!error &&
|
||||
@@ -90,12 +73,18 @@
|
||||
margin: 5rem 0;
|
||||
}
|
||||
.header {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
color: var(--color-secondary);
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
font-size: var(--font-size-large);
|
||||
font-weight: var(--font-weight-bold);
|
||||
justify-content: space-between;
|
||||
margin-bottom: 2rem;
|
||||
overflow-x: hidden;
|
||||
text-align: left;
|
||||
text-overflow: ellipsis;
|
||||
width: 100%;
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
@@ -128,9 +117,7 @@
|
||||
|
||||
<div class="wrapper">
|
||||
<div class="header">
|
||||
<span class="txt-title txt-bold">
|
||||
{hostName}
|
||||
</span>
|
||||
{hostName}
|
||||
</div>
|
||||
|
||||
{#await api.getRoot()}
|
||||
@@ -168,13 +155,28 @@
|
||||
<div style:margin-top="1rem">
|
||||
{#each projectsWithActivity as { project, activity }}
|
||||
<div style:margin-bottom="0.5rem">
|
||||
<ProjectCard
|
||||
{activity}
|
||||
id={project.id}
|
||||
name={project.name}
|
||||
description={project.description}
|
||||
head={project.head}
|
||||
on:click={() => goToProject(project)} />
|
||||
<Link
|
||||
route={{
|
||||
resource: "projects",
|
||||
params: {
|
||||
view: { resource: "tree" },
|
||||
id: project.id,
|
||||
hostnamePort:
|
||||
baseUrl.port === config.seeds.defaultHttpdPort
|
||||
? baseUrl.hostname
|
||||
: `${baseUrl.hostname}:${baseUrl.port}`,
|
||||
revision: undefined,
|
||||
hash: undefined,
|
||||
search: undefined,
|
||||
},
|
||||
}}>
|
||||
<ProjectCard
|
||||
{activity}
|
||||
id={project.id}
|
||||
name={project.name}
|
||||
description={project.description}
|
||||
head={project.head} />
|
||||
</Link>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
@@ -34,7 +34,7 @@ test("navigation between seed and project pages", async ({ page }) => {
|
||||
await expectBackAndForwardNavigationWorks("/#/seeds/radicle.local", page);
|
||||
await expectUrlPersistsReload(page);
|
||||
|
||||
await page.locator('role=button[name="Seed"]').click();
|
||||
await page.locator('role=link[name="127.0.0.1"]').click();
|
||||
await expect(page).toHaveURL("/#/seeds/127.0.0.1");
|
||||
});
|
||||
|
||||
@@ -60,7 +60,7 @@ test.describe("project page navigation", () => {
|
||||
await page.goto(projectTreeURL);
|
||||
await expect(page).toHaveURL(projectTreeURL);
|
||||
|
||||
await page.locator('role=button[name="Commit count"]').click();
|
||||
await page.locator('role=link[name="8 commits"]').click();
|
||||
await expect(page).toHaveURL(`/#${projectFixtureUrl}/history/main`);
|
||||
|
||||
await expectBackAndForwardNavigationWorks(projectTreeURL, page);
|
||||
|
||||
@@ -34,7 +34,7 @@ test("navigation between seed and project pages", async ({ page }) => {
|
||||
await expectBackAndForwardNavigationWorks("/seeds/radicle.local", page);
|
||||
await expectUrlPersistsReload(page);
|
||||
|
||||
await page.locator('role=button[name="Seed"]').click();
|
||||
await page.locator('role=link[name="127.0.0.1"]').click();
|
||||
await expect(page).toHaveURL("/seeds/127.0.0.1");
|
||||
});
|
||||
|
||||
@@ -60,7 +60,7 @@ test.describe("project page navigation", () => {
|
||||
await page.goto(projectTreeURL);
|
||||
await expect(page).toHaveURL(projectTreeURL);
|
||||
|
||||
await page.locator('role=button[name="Commit count"]').click();
|
||||
await page.locator('role=link[name="8 commits"]').click();
|
||||
await expect(page).toHaveURL(
|
||||
`${projectFixtureUrl}/history/${aliceMainHead}`,
|
||||
);
|
||||
|
||||
+22
-17
@@ -14,16 +14,21 @@ async function expectCounts(
|
||||
params: { commits: number; contributors: number },
|
||||
page: Page,
|
||||
) {
|
||||
await expect(page.locator('role=button[name="Commit count"]')).toContainText(
|
||||
`${params.commits} ${params.commits === 1 ? "commit" : "commits"}`,
|
||||
);
|
||||
await expect(
|
||||
page.locator('role=button[name="Contributor count"]'),
|
||||
).toContainText(
|
||||
`${params.contributors} ${
|
||||
params.contributors === 1 ? "contributor" : "contributors"
|
||||
}`,
|
||||
);
|
||||
page.locator(
|
||||
`role=link[name="${params.commits} ${
|
||||
params.commits === 1 ? "commit" : "commits"
|
||||
}"]`,
|
||||
),
|
||||
).toBeVisible();
|
||||
|
||||
await expect(
|
||||
page.locator(
|
||||
`text=${params.contributors} ${
|
||||
params.contributors === 1 ? "contributor" : "contributors"
|
||||
}`,
|
||||
),
|
||||
).toBeVisible();
|
||||
}
|
||||
|
||||
test("navigate to project", async ({ page }) => {
|
||||
@@ -62,10 +67,10 @@ test("navigate to project", async ({ page }) => {
|
||||
|
||||
test("show source tree at specific revision", async ({ page }) => {
|
||||
await page.goto(projectFixtureUrl);
|
||||
await page.locator('role=button[name="Commit count"]').click();
|
||||
await page.locator('role=link[name="8 commits"]').click();
|
||||
|
||||
await page
|
||||
.locator(".commit-teaser", { hasText: "335dd6d" })
|
||||
.locator(".teaser", { hasText: "335dd6d" })
|
||||
.getByTitle("Browse the repository at this point in the history")
|
||||
.click();
|
||||
|
||||
@@ -90,7 +95,7 @@ test("source file highlighting", async ({ page }) => {
|
||||
|
||||
test("navigate line numbers", async ({ page }) => {
|
||||
await page.goto(`${projectFixtureUrl}/tree/main/markdown/cheatsheet.md`);
|
||||
await page.locator('role=button[name="Raw"]').click();
|
||||
await page.locator(".markdown-toggle").click();
|
||||
|
||||
await page.locator('[href="#L5"]').click();
|
||||
await expect(page.locator("#L5")).toHaveClass("line highlight");
|
||||
@@ -225,7 +230,7 @@ test("markdown files", async ({ page }) => {
|
||||
|
||||
// Switch between raw and rendered modes.
|
||||
{
|
||||
const rawButton = page.locator('role=button[name="Raw"]');
|
||||
const rawButton = page.locator(".markdown-toggle .square-button");
|
||||
|
||||
await rawButton.click();
|
||||
await expect(rawButton).toHaveClass(/active/);
|
||||
@@ -262,9 +267,9 @@ test("peer and branch switching", async ({ page }) => {
|
||||
await page.getByTitle("Change peer").click();
|
||||
await page.locator(`text=${aliceRemote}`).click();
|
||||
await expect(page.getByTitle("Change peer")).toHaveText(
|
||||
` did:key: ${aliceRemote
|
||||
.substring(8)
|
||||
.substring(0, 6)}…${aliceRemote.slice(-6)} `,
|
||||
` did:key:${aliceRemote.substring(8).substring(0, 6)}…${aliceRemote.slice(
|
||||
-6,
|
||||
)} `,
|
||||
);
|
||||
await expect(
|
||||
page.locator(
|
||||
@@ -327,7 +332,7 @@ test("peer and branch switching", async ({ page }) => {
|
||||
await page.getByTitle("Change peer").click();
|
||||
await page.locator(`text=${bobRemote}`).click();
|
||||
await expect(page.getByTitle("Change peer")).toHaveText(
|
||||
` did:key: ${bobRemote.substring(8).substring(0, 6)}…${bobRemote.slice(
|
||||
` did:key:${bobRemote.substring(8).substring(0, 6)}…${bobRemote.slice(
|
||||
-6,
|
||||
)} `,
|
||||
);
|
||||
|
||||
@@ -13,7 +13,7 @@ test("navigation from commit list", async ({ page }) => {
|
||||
await page.goto(projectFixtureUrl);
|
||||
await page.getByTitle("Change peer").click();
|
||||
await page.locator(`text=${bobRemote}`).click();
|
||||
await page.locator('role=button[name="Commit count"]').click();
|
||||
await page.locator('role=link[name="9 commits"]').click();
|
||||
|
||||
await page.locator("text=Update readme").click();
|
||||
await expect(page).toHaveURL(modifiedFileFixture);
|
||||
@@ -31,7 +31,7 @@ test("relative timestamps", async ({ page }) => {
|
||||
});
|
||||
await page.goto(modifiedFileFixture);
|
||||
await expect(
|
||||
page.locator(`.commit header >> text=${"Bob Belcher committed now"}`),
|
||||
page.locator(`.commit .header >> text=${"Bob Belcher committed now"}`),
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
@@ -40,7 +40,7 @@ test("modified file", async ({ page }) => {
|
||||
|
||||
// Commit header.
|
||||
{
|
||||
const header = page.locator(".commit header");
|
||||
const header = page.locator(".commit .header");
|
||||
await expect(header.locator("text=Update readme")).toBeVisible();
|
||||
await expect(
|
||||
header.locator("text=1e0bb83a89b63da815f2fc24e7ae3c5ceb30e0eb"),
|
||||
|
||||
@@ -8,30 +8,28 @@ import {
|
||||
|
||||
test("peer and branch switching", async ({ page }) => {
|
||||
await page.goto(projectFixtureUrl);
|
||||
await page.locator('role=button[name="Commit count"]').click();
|
||||
await page.locator('role=link[name="8 commits"]').click();
|
||||
|
||||
// Alice's peer.
|
||||
{
|
||||
await page.getByTitle("Change peer").click();
|
||||
await page.locator(`text=${aliceRemote}`).click();
|
||||
await expect(page.getByTitle("Change peer")).toHaveText(
|
||||
` did:key: ${aliceRemote
|
||||
.substring(8)
|
||||
.substring(0, 6)}…${aliceRemote.slice(-6)} `,
|
||||
` did:key:${aliceRemote.substring(8).substring(0, 6)}…${aliceRemote.slice(
|
||||
-6,
|
||||
)} `,
|
||||
);
|
||||
|
||||
await expect(page.getByText("Thursday, November 17, 2022")).toBeVisible();
|
||||
await expect(
|
||||
page.locator(".commit-group-headers .commit-teaser"),
|
||||
).toHaveCount(8);
|
||||
await expect(page.locator(".history .teaser")).toHaveCount(8);
|
||||
|
||||
const latestCommit = page.locator(".commit-teaser").first();
|
||||
const latestCommit = page.locator(".teaser").first();
|
||||
await expect(latestCommit).toContainText(
|
||||
"Adds a new markdown file with an image with a relative path",
|
||||
);
|
||||
await expect(latestCommit).toContainText("fcc9294");
|
||||
|
||||
const earliestCommit = page.locator(".commit-teaser").last();
|
||||
const earliestCommit = page.locator(".teaser").last();
|
||||
await expect(earliestCommit).toContainText(
|
||||
"Initialize an empty git repository",
|
||||
);
|
||||
@@ -44,9 +42,7 @@ test("peer and branch switching", async ({ page }) => {
|
||||
"feature/branch d6318f7",
|
||||
);
|
||||
await expect(page.getByText("Thursday, November 17, 2022")).toBeVisible();
|
||||
await expect(
|
||||
page.locator(".commit-group-headers .commit-teaser"),
|
||||
).toHaveCount(10);
|
||||
await expect(page.locator(".history .teaser")).toHaveCount(10);
|
||||
|
||||
await page.getByTitle("Change branch").click();
|
||||
await page.locator("text=orphaned-branch").click();
|
||||
@@ -55,9 +51,7 @@ test("peer and branch switching", async ({ page }) => {
|
||||
"orphaned-branch af3641c",
|
||||
);
|
||||
await expect(page.getByText("Thursday, November 17, 2022")).toBeVisible();
|
||||
await expect(
|
||||
page.locator(".commit-group-headers .commit-teaser"),
|
||||
).toHaveCount(1);
|
||||
await expect(page.locator(".group .teaser")).toHaveCount(1);
|
||||
}
|
||||
|
||||
// Bob's peer.
|
||||
@@ -65,27 +59,26 @@ test("peer and branch switching", async ({ page }) => {
|
||||
await page.getByTitle("Change peer").click();
|
||||
await page.locator(`text=${bobRemote}`).click();
|
||||
await expect(page.getByTitle("Change peer")).toContainText(
|
||||
` did:key: ${bobRemote.substring(8).substring(0, 6)}…${bobRemote.slice(
|
||||
` did:key:${bobRemote.substring(8).substring(0, 6)}…${bobRemote.slice(
|
||||
-6,
|
||||
)} `,
|
||||
);
|
||||
|
||||
await expect(page.getByText("Tuesday, December 20, 2022")).toBeVisible();
|
||||
await expect(
|
||||
page.locator(".commit-group-headers").first().locator(".commit-teaser"),
|
||||
).toHaveCount(1);
|
||||
await expect(page.locator(".group").first().locator(".teaser")).toHaveCount(
|
||||
1,
|
||||
);
|
||||
|
||||
await expect(page.getByText("Thursday, November 17, 2022")).toBeVisible();
|
||||
await expect(
|
||||
page.locator(".commit-group-headers").last().locator(".commit-teaser"),
|
||||
).toHaveCount(6);
|
||||
await expect(page.locator(".group").last().locator(".teaser")).toHaveCount(
|
||||
6,
|
||||
);
|
||||
|
||||
await page.pause();
|
||||
const latestCommit = page.locator(".commit-teaser").first();
|
||||
const latestCommit = page.locator(".teaser").first();
|
||||
await expect(latestCommit).toContainText("Update readme");
|
||||
await expect(latestCommit).toContainText("1e0bb83");
|
||||
|
||||
const earliestCommit = page.locator(".commit-teaser").last();
|
||||
const earliestCommit = page.locator(".teaser").last();
|
||||
await expect(earliestCommit).toContainText(
|
||||
"Initialize an empty git repository",
|
||||
);
|
||||
@@ -105,19 +98,19 @@ test("relative timestamps", async ({ page }) => {
|
||||
});
|
||||
|
||||
await page.goto(projectFixtureUrl);
|
||||
await page.locator('role=button[name="Commit count"]').click();
|
||||
await page.locator('role=link[name="8 commits"]').click();
|
||||
|
||||
await page.getByTitle("Change peer").click();
|
||||
await page.locator(`text=${bobRemote}`).click();
|
||||
await expect(page.getByTitle("Change peer")).toHaveText(
|
||||
` did:key: ${bobRemote.substring(8).substring(0, 6)}…${bobRemote.slice(
|
||||
` did:key:${bobRemote.substring(8).substring(0, 6)}…${bobRemote.slice(
|
||||
-6,
|
||||
)} `,
|
||||
);
|
||||
const latestCommit = page.locator(".commit-teaser").first();
|
||||
const latestCommit = page.locator(".teaser").first();
|
||||
await expect(latestCommit).toContainText("Bob Belcher committed now");
|
||||
await expect(latestCommit).toContainText("1e0bb83");
|
||||
const earliestCommit = page.locator(".commit-teaser").last();
|
||||
const earliestCommit = page.locator(".teaser").last();
|
||||
await expect(earliestCommit).toContainText(
|
||||
"Alice Liddell committed last month",
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user