-
Notifications
You must be signed in to change notification settings - Fork 84
Enhance note status #487
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Enhance note status #487
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
38974e5
enhance notices view
ticruz38 278959f
UI refinements
ticruz38 858194a
multiple select button
ticruz38 68ddf31
align button to the left
ticruz38 3059257
filter out undefined selected
ticruz38 7a5418c
refactor connectionstatus code
ticruz38 fbccdf5
add subscription Notices
ticruz38 2d8fe0c
track subscriptions notices and display them
ticruz38 a97f9b9
clean up and refactor
ticruz38 8764d90
- add fuzzy search
ticruz38 0b0c84a
log verbs are configurable via environment variable
ticruz38 e449ec8
have notice verb settings hardcoded
ticruz38 dfceba3
tighten the fuzzy search threshold
ticruz38 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,70 +1,22 @@ | ||
<script lang="ts"> | ||
import {pluralize, seconds} from "hurdak" | ||
import {assoc, now, remove, sortBy} from "@welshman/lib" | ||
import {LOCAL_RELAY_URL} from "@welshman/util" | ||
import {PublishStatus} from "@welshman/net" | ||
import Tile from "src/partials/Tile.svelte" | ||
import PublishesConnections from "src/app/views/PublishesConnections.svelte" | ||
import PublishesNotices from "src/app/views/PublishesNotices.svelte" | ||
import PublishesEvents from "src/app/views/PublishesEvents.svelte" | ||
import Subheading from "src/partials/Subheading.svelte" | ||
import PublishCard from "src/app/shared/PublishCard.svelte" | ||
import {thunks, type Thunk} from "@welshman/app" | ||
import {get} from "svelte/store" | ||
import Tabs from "src/partials/Tabs.svelte" | ||
|
||
const hasStatus = (thunk: Thunk, statuses: PublishStatus[]) => | ||
Object.values(get(thunk.status)).some(s => statuses.includes(s.status)) | ||
const tabs = ["events", "connections", "notices"] | ||
let activeTab = "events" | ||
|
||
$: recent = (Object.values($thunks) as Thunk[]).filter( | ||
t => | ||
remove(LOCAL_RELAY_URL, t.request.relays).length > 0 && | ||
t.event.created_at > now() - seconds(24, "hour"), | ||
) | ||
$: relays = new Set( | ||
remove( | ||
LOCAL_RELAY_URL, | ||
recent.flatMap(({request}) => request.relays), | ||
), | ||
) | ||
$: success = recent.filter(t => hasStatus(t, [PublishStatus.Success])) | ||
$: pending = recent.filter( | ||
t => hasStatus(t, [PublishStatus.Pending]) && !hasStatus(t, [PublishStatus.Success]), | ||
) | ||
|
||
// If the page gets refreshed before pending finishes, it hangs. Set stuff to failed | ||
$: { | ||
for (const t of recent) { | ||
if (t.event.created_at < now() - seconds(1, "minute")) { | ||
for (const [url, s] of Object.entries(t.status)) { | ||
if (s.status === PublishStatus.Pending) { | ||
t.status.update(assoc(url, {status: PublishStatus.Failure, message: ""})) | ||
} | ||
} | ||
} | ||
} | ||
} | ||
let selected: string | ||
</script> | ||
|
||
<Subheading>Published Events</Subheading> | ||
<div class="grid grid-cols-4 justify-between gap-2 sm:grid-cols-5"> | ||
<Tile background> | ||
<p class="text-lg sm:text-2xl">{recent.length}</p> | ||
<span class="text-sm">{pluralize(recent.length, "Event")}</span> | ||
</Tile> | ||
<Tile background> | ||
<p class="text-lg sm:text-2xl">{relays.size}</p> | ||
<span class="text-sm">{pluralize(relays.size, "Relay")}</span> | ||
</Tile> | ||
<Tile background lass="hidden sm:block"> | ||
<p class="text-lg sm:text-2xl">{pending.length}</p> | ||
<span class="text-sm">Pending</span> | ||
</Tile> | ||
<Tile background> | ||
<p class="text-lg sm:text-2xl">{success.length}</p> | ||
<span class="text-sm">Succeeded</span> | ||
</Tile> | ||
<Tile background> | ||
<p class="text-lg sm:text-2xl">{recent.length - pending.length - success.length}</p> | ||
<span class="text-sm">Failed</span> | ||
</Tile> | ||
</div> | ||
{#each sortBy(t => -t.event.created_at, recent) as thunk (thunk.event.id)} | ||
<PublishCard {thunk} /> | ||
{/each} | ||
<Tabs {tabs} {activeTab} setActiveTab={tab => (activeTab = tab)} /> | ||
{#if activeTab === "events"} | ||
<PublishesEvents /> | ||
{:else if activeTab === "connections"} | ||
<PublishesConnections bind:selected bind:activeTab /> | ||
{:else if activeTab === "notices"} | ||
<PublishesNotices search={selected} /> | ||
{/if} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
<script lang="ts"> | ||
import {relaysByUrl} from "@welshman/app" | ||
import {addToMapKey, ctx} from "@welshman/lib" | ||
import {displayRelayUrl} from "@welshman/util" | ||
import {quantify} from "hurdak" | ||
import {onMount} from "svelte" | ||
import AltColor from "src/partials/AltColor.svelte" | ||
import SelectButton from "src/partials/SelectButton.svelte" | ||
import {ConnectionType, displayConnectionType, getConnectionStatus} from "src/domain/connection" | ||
|
||
export let selected: string | ||
export let activeTab: string | ||
|
||
let selectedOptions: ConnectionType[] = [] | ||
let connectionsStatus: Map<ConnectionType, Set<string>> = new Map() | ||
|
||
const options = [ | ||
ConnectionType.Connected, | ||
ConnectionType.Logging, | ||
ConnectionType.LoginFailed, | ||
ConnectionType.ConnectFailed, | ||
ConnectionType.WaitReconnect, | ||
ConnectionType.NotConnected, | ||
ConnectionType.UnstableConnection, | ||
] | ||
|
||
$: connections = Array.from(ctx.net.pool.data.keys()).filter(url => | ||
selectedOptions.length ? selectedOptions.some(s => connectionsStatus.get(s)?.has(url)) : true, | ||
) | ||
|
||
function fetchConnectionStatus() { | ||
const newConnectionStatus: Map<ConnectionType, Set<string>> = new Map() | ||
for (const [url, cxn] of ctx.net.pool.data.entries()) { | ||
addToMapKey(newConnectionStatus, getConnectionStatus(cxn), url) | ||
} | ||
connectionsStatus = newConnectionStatus | ||
} | ||
|
||
onMount(() => { | ||
fetchConnectionStatus() | ||
const interval = setInterval(fetchConnectionStatus, 800) | ||
|
||
return () => { | ||
clearInterval(interval) | ||
} | ||
}) | ||
</script> | ||
|
||
<SelectButton {options} bind:value={selectedOptions} multiple class="text-left"> | ||
<div class="flex items-center gap-2" slot="item" let:option> | ||
{connectionsStatus.get(option)?.size || 0} | ||
{displayConnectionType(option)} | ||
</div> | ||
</SelectButton> | ||
{#each connections as url (url)} | ||
{@const relay = $relaysByUrl.get(url)} | ||
<AltColor | ||
background | ||
class="cursor-pointer justify-between rounded-md p-6 shadow" | ||
on:click={() => { | ||
selected = url | ||
activeTab = "notices" | ||
}}> | ||
<div class="flex min-w-0 shrink-0 items-start gap-3"> | ||
{#if relay?.profile?.icon} | ||
<img class="h-9 w-9 shrink-0 rounded-full border" src={relay.profile.icon} /> | ||
{:else} | ||
<div class="flex h-9 w-9 shrink-0 items-center justify-center rounded-full border"> | ||
<i class="fa fa-server text-xl text-neutral-100"></i> | ||
</div> | ||
{/if} | ||
<div class="shrink-0"> | ||
<div class="flex items-center gap-2"> | ||
<div class="text-md overflow-hidden text-ellipsis whitespace-nowrap"> | ||
{displayRelayUrl(url)} | ||
</div> | ||
</div> | ||
<div class="flex gap-4 text-xs text-neutral-400"> | ||
{#if relay?.profile?.supported_nips} | ||
<span> | ||
{relay.profile.supported_nips.length} NIPs | ||
</span> | ||
{/if} | ||
<span> | ||
Connected {quantify(relay?.stats?.open_count || 0, "time")} | ||
</span> | ||
</div> | ||
</div> | ||
<div class="flex w-full items-center justify-end gap-2 text-sm"> | ||
{#each options.filter(o => connectionsStatus.get(o)?.has(url)) as o} | ||
{@const opt = displayConnectionType(o)} | ||
<div class="flex items-center gap-2"> | ||
<span>{opt}</span> | ||
<div | ||
class:!bg-danger={opt.includes("Failed") || opt.includes("Not")} | ||
class:!bg-warning={opt == "Logging in" || | ||
o == ConnectionType.WaitReconnect || | ||
o == ConnectionType.UnstableConnection} | ||
class="h-3 w-3 rounded-full bg-success" /> | ||
</div> | ||
{/each} | ||
</div> | ||
</div> | ||
</AltColor> | ||
{/each} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
<script lang="ts"> | ||
import {thunks, type Thunk} from "@welshman/app" | ||
import {assoc, now, remove, sortBy} from "@welshman/lib" | ||
import {pluralize, seconds} from "hurdak" | ||
import Tile from "src/partials/Tile.svelte" | ||
import PublishCard from "src/app/shared/PublishCard.svelte" | ||
import {LOCAL_RELAY_URL} from "@welshman/util" | ||
import {PublishStatus} from "@welshman/net" | ||
import {get} from "svelte/store" | ||
|
||
const hasStatus = (thunk: Thunk, statuses: PublishStatus[]) => | ||
Object.values(get(thunk.status)).some(s => statuses.includes(s.status)) | ||
|
||
$: recent = (Object.values($thunks) as Thunk[]).filter( | ||
t => | ||
remove(LOCAL_RELAY_URL, t.request.relays).length > 0 && | ||
t.event.created_at > now() - seconds(24, "hour"), | ||
) | ||
$: relays = new Set( | ||
remove( | ||
LOCAL_RELAY_URL, | ||
recent.flatMap(({request}) => request.relays), | ||
), | ||
) | ||
$: success = recent.filter(t => hasStatus(t, [PublishStatus.Success])) | ||
$: pending = recent.filter( | ||
t => hasStatus(t, [PublishStatus.Pending]) && !hasStatus(t, [PublishStatus.Success]), | ||
) | ||
|
||
// If the page gets refreshed before pending finishes, it hangs. Set stuff to failed | ||
$: { | ||
for (const t of recent) { | ||
if (t.event.created_at < now() - seconds(1, "minute")) { | ||
for (const [url, s] of Object.entries(t.status)) { | ||
if (s.status === PublishStatus.Pending) { | ||
t.status.update(assoc(url, {status: PublishStatus.Failure, message: ""})) | ||
} | ||
} | ||
} | ||
} | ||
} | ||
</script> | ||
|
||
<div class="grid grid-cols-4 justify-between gap-2 sm:grid-cols-5"> | ||
<Tile background> | ||
<p class="text-lg sm:text-2xl">{recent.length}</p> | ||
<span class="text-sm">{pluralize(recent.length, "Event")}</span> | ||
</Tile> | ||
<Tile background> | ||
<p class="text-lg sm:text-2xl">{relays.size}</p> | ||
<span class="text-sm">{pluralize(relays.size, "Relay")}</span> | ||
</Tile> | ||
<Tile background lass="hidden sm:block"> | ||
<p class="text-lg sm:text-2xl">{pending.length}</p> | ||
<span class="text-sm">Pending</span> | ||
</Tile> | ||
<Tile background> | ||
<p class="text-lg sm:text-2xl">{success.length}</p> | ||
<span class="text-sm">Succeeded</span> | ||
</Tile> | ||
<Tile background> | ||
<p class="text-lg sm:text-2xl">{recent.length - pending.length - success.length}</p> | ||
<span class="text-sm">Failed</span> | ||
</Tile> | ||
</div> | ||
{#each sortBy(t => -t.event.created_at, recent) as thunk (thunk.event.id)} | ||
<PublishCard {thunk} /> | ||
{/each} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.