mirror of
https://github.com/aljazceru/hypergolic.git
synced 2025-12-20 15:04:18 +01:00
problem: can't see votes
This commit is contained in:
@@ -58,7 +58,7 @@
|
|||||||
{#each $merits as [id, merit], _ (id)}
|
{#each $merits as [id, merit], _ (id)}
|
||||||
<Table.Row
|
<Table.Row
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
console.log(merit.Request.rawEvent());
|
console.log(merit.Event.rawEvent());
|
||||||
goto(`${base}/rockets/merits/${merit.ID}`);
|
goto(`${base}/rockets/merits/${merit.ID}`);
|
||||||
}}
|
}}
|
||||||
class="cursor-pointer bg-accent"
|
class="cursor-pointer bg-accent"
|
||||||
|
|||||||
@@ -1,38 +1,49 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import * as Card from '$lib/components/ui/card/index.js';
|
import * as Card from '$lib/components/ui/card/index.js';
|
||||||
import type { MeritRequest } from '@/event_helpers/merits';
|
import { Vote, type MeritRequest } from '@/event_helpers/merits';
|
||||||
import { ndk } from '@/ndk';
|
import { ndk } from '@/ndk';
|
||||||
import type { NDKEvent } from '@nostr-dev-kit/ndk';
|
import type { NDKEvent, NDKKind } from '@nostr-dev-kit/ndk';
|
||||||
import { Avatar, Name } from '@nostr-dev-kit/ndk-svelte-components';
|
import { Avatar, Name } from '@nostr-dev-kit/ndk-svelte-components';
|
||||||
import { ExternalLink } from 'lucide-svelte';
|
import { ExternalLink } from 'lucide-svelte';
|
||||||
import { onDestroy } from 'svelte';
|
import { onDestroy } from 'svelte';
|
||||||
import VoteOnMeritRequest from './VoteOnMeritRequest.svelte';
|
import VoteOnMeritRequest from './VoteOnMeritRequest.svelte';
|
||||||
|
|
||||||
import ChevronLeft from 'lucide-svelte/icons/chevron-left';
|
|
||||||
import ChevronRight from 'lucide-svelte/icons/chevron-right';
|
|
||||||
import Copy from 'lucide-svelte/icons/copy';
|
|
||||||
import CreditCard from 'lucide-svelte/icons/credit-card';
|
|
||||||
import EllipsisVertical from 'lucide-svelte/icons/ellipsis-vertical';
|
|
||||||
import Truck from 'lucide-svelte/icons/truck';
|
|
||||||
import { Button } from '$lib/components/ui/button/index.js';
|
|
||||||
import * as DropdownMenu from '$lib/components/ui/dropdown-menu/index.js';
|
|
||||||
import * as Pagination from '$lib/components/ui/pagination/index.js';
|
|
||||||
import { Separator } from '$lib/components/ui/separator/index.js';
|
import { Separator } from '$lib/components/ui/separator/index.js';
|
||||||
|
import * as Table from '@/components/ui/table';
|
||||||
|
import { RocketATagFilter } from '@/event_helpers/rockets';
|
||||||
|
import { derived } from 'svelte/store';
|
||||||
|
import { goto } from '$app/navigation';
|
||||||
|
import { base } from '$app/paths';
|
||||||
|
import { unixToRelativeTime } from '@/helpers';
|
||||||
|
|
||||||
export let merit: MeritRequest;
|
export let merit: MeritRequest;
|
||||||
export let rocket: NDKEvent;
|
export let rocket: NDKEvent;
|
||||||
|
|
||||||
let votes = $ndk.storeSubscribe([merit.REQFilter(1410)], {
|
let _votes = $ndk.storeSubscribe(
|
||||||
|
{ '#a': [RocketATagFilter(rocket)], kinds: [1410 as NDKKind] },
|
||||||
|
{
|
||||||
subId: merit.RocketTag!.split(':')[2] + '_votes'
|
subId: merit.RocketTag!.split(':')[2] + '_votes'
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
let votes = derived(_votes, ($_votes) => {
|
||||||
|
let vMap = new Map<string, Vote>();
|
||||||
|
for (let v of $_votes) {
|
||||||
|
let vote = new Vote(v);
|
||||||
|
if (vote.BasicValidation()) {
|
||||||
|
vMap.set(vote.ID, vote);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return vMap;
|
||||||
});
|
});
|
||||||
|
|
||||||
onDestroy(() => {
|
onDestroy(() => {
|
||||||
votes.unsubscribe();
|
_votes.unsubscribe();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Card.Root class="sm:col-span-2">
|
<Card.Root class="sm:col-span-2">
|
||||||
<Card.Header class="bg-muted/50 pb-3">
|
<Card.Header class="pb-3">
|
||||||
<div class="flex flex-nowrap justify-between">
|
<div class="flex flex-nowrap justify-between">
|
||||||
<Card.Title>Problem: {merit.Problem().substring(0, 20)}</Card.Title>{#if merit.Solution()}<a
|
<Card.Title>Problem: {merit.Problem().substring(0, 20)}</Card.Title>{#if merit.Solution()}<a
|
||||||
class="flex flex-nowrap text-orange-500 underline decoration-orange-500"
|
class="flex flex-nowrap text-orange-500 underline decoration-orange-500"
|
||||||
@@ -45,7 +56,7 @@
|
|||||||
pubkey={merit.Pubkey}
|
pubkey={merit.Pubkey}
|
||||||
class="h-10 w-10 flex-none rounded-full object-cover"
|
class="h-10 w-10 flex-none rounded-full object-cover"
|
||||||
/>
|
/>
|
||||||
<Name ndk={$ndk} pubkey={merit.Pubkey} class="hidden max-w-32 truncate p-2 md:inline-block" />
|
<Name ndk={$ndk} pubkey={merit.Pubkey} class="max-w-32 truncate p-2 inline-block" />
|
||||||
</div>
|
</div>
|
||||||
<Card.Description class="max-w-lg text-balance leading-relaxed">
|
<Card.Description class="max-w-lg text-balance leading-relaxed">
|
||||||
{#if merit.Problem().length > 20}{merit.Problem()}{/if}
|
{#if merit.Problem().length > 20}{merit.Problem()}{/if}
|
||||||
@@ -76,7 +87,9 @@
|
|||||||
<div class="grid gap-3">
|
<div class="grid gap-3">
|
||||||
<div class="font-semibold">Analysis</div>
|
<div class="font-semibold">Analysis</div>
|
||||||
<span class="grid gap-0.5 not-italic text-muted-foreground">
|
<span class="grid gap-0.5 not-italic text-muted-foreground">
|
||||||
A competent freelance developer earns $70 CuckLoserBucks an hour (on average). Using this rate, the contributor is claiming to have spent about {merit.Sats/1000} hours working on this.
|
A competent freelance developer earns $70 CuckLoserBucks an hour (on average). Using
|
||||||
|
this rate, the contributor is claiming to have spent about {merit.Sats / 1000} hours working
|
||||||
|
on this.
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid auto-rows-max gap-3">
|
<div class="grid auto-rows-max gap-3">
|
||||||
@@ -84,9 +97,42 @@
|
|||||||
<div class="text-muted-foreground">{merit.Sats / 1000} hours</div>
|
<div class="text-muted-foreground">{merit.Sats / 1000} hours</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<Separator class="my-4" />
|
||||||
|
<div class="font-semibold">Votes</div>
|
||||||
</Card.Content>
|
<Table.Root>
|
||||||
|
<Table.Body>
|
||||||
|
{#each $votes as [id, vote], _ (id)}
|
||||||
|
<Table.Row
|
||||||
|
on:click={() => {
|
||||||
|
console.log(vote.Event.rawEvent());
|
||||||
|
goto(`${base}/rockets/merits/${vote.ID}`);
|
||||||
|
}}
|
||||||
|
class="cursor-pointer {vote.VoteDirection == "ratify"?"bg-lime-600":"bg-red-700"} "
|
||||||
|
>
|
||||||
|
<Table.Cell>
|
||||||
|
<div class="flex flex-nowrap">
|
||||||
|
<Avatar
|
||||||
|
ndk={$ndk}
|
||||||
|
pubkey={vote.Pubkey}
|
||||||
|
class="h-10 w-10 flex-none rounded-full object-cover"
|
||||||
|
/>
|
||||||
|
<Name
|
||||||
|
ndk={$ndk}
|
||||||
|
pubkey={vote.Pubkey}
|
||||||
|
class="max-w-32 truncate p-2 inline-block"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Table.Cell>
|
||||||
|
<Table.Cell class="hidden text-left md:table-cell">{vote.VoteDirection}</Table.Cell>
|
||||||
|
<Table.Cell class="text-right table-cell"
|
||||||
|
>{unixToRelativeTime(vote.TimeStamp * 1000)}</Table.Cell
|
||||||
|
>
|
||||||
|
</Table.Row>
|
||||||
|
{/each}
|
||||||
|
</Table.Body>
|
||||||
|
</Table.Root>
|
||||||
|
</div></Card.Content
|
||||||
|
>
|
||||||
</Card.Header>
|
</Card.Header>
|
||||||
<Card.Footer class="flex flex-row items-center border-t px-6 py-3">
|
<Card.Footer class="flex flex-row items-center border-t px-6 py-3">
|
||||||
<VoteOnMeritRequest {merit} {rocket} />
|
<VoteOnMeritRequest {merit} {rocket} />
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
import type { NDKEvent, NDKFilter } from '@nostr-dev-kit/ndk';
|
import type { NDKEvent, NDKFilter, NDKTag } from '@nostr-dev-kit/ndk';
|
||||||
import { getNumberFromTag, isValidUrl } from './rockets';
|
import { getNumberFromTag, isValidUrl } from './rockets';
|
||||||
|
|
||||||
export class MeritRequest {
|
export class MeritRequest {
|
||||||
ID: string;
|
ID: string;
|
||||||
Sats: number;
|
Sats: number;
|
||||||
Merits: number;
|
Merits: number;
|
||||||
Request: NDKEvent;
|
Event: NDKEvent;
|
||||||
Pubkey: string;
|
Pubkey: string;
|
||||||
TimeStamp: number;
|
TimeStamp: number;
|
||||||
RocketTag: string | undefined; //31108:<pubkey>:<dtag>
|
RocketTag: string | undefined; //31108:<pubkey>:<dtag>
|
||||||
Problem(): string {
|
Problem(): string {
|
||||||
let _problem = '';
|
let _problem = '';
|
||||||
//todo: handle 1971 problem tracker event tags somehow
|
//todo: handle 1971 problem tracker event tags somehow
|
||||||
for (let problem of this.Request.getMatchingTags('problem')) {
|
for (let problem of this.Event.getMatchingTags('problem')) {
|
||||||
if (problem && problem.length > 2) {
|
if (problem && problem.length > 2) {
|
||||||
_problem = problem[2];
|
_problem = problem[2];
|
||||||
}
|
}
|
||||||
@@ -21,10 +21,10 @@ export class MeritRequest {
|
|||||||
}
|
}
|
||||||
Solution(): URL | undefined {
|
Solution(): URL | undefined {
|
||||||
let _solution: URL | undefined = undefined;
|
let _solution: URL | undefined = undefined;
|
||||||
for (let solution of this.Request.getMatchingTags('solution')) {
|
for (let solution of this.Event.getMatchingTags('solution')) {
|
||||||
if (solution && solution.length > 2 && solution[1] == "url") {
|
if (solution && solution.length > 2 && solution[1] == 'url') {
|
||||||
if (isValidUrl(solution[2])) {
|
if (isValidUrl(solution[2])) {
|
||||||
_solution = new URL(solution[2])
|
_solution = new URL(solution[2]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -36,28 +36,40 @@ export class MeritRequest {
|
|||||||
BasicValidation(): boolean {
|
BasicValidation(): boolean {
|
||||||
//todo: make a ValidateAgainstRocket and check that pubkey is in WoT
|
//todo: make a ValidateAgainstRocket and check that pubkey is in WoT
|
||||||
let valid = true;
|
let valid = true;
|
||||||
if (!(this.ID.length == 64 && this.Merits > 0 && this.Pubkey.length == 64 && this.TimeStamp && this.RocketTag)) {
|
if (
|
||||||
valid = false
|
!(
|
||||||
|
this.ID.length == 64 &&
|
||||||
|
this.Merits > 0 &&
|
||||||
|
this.Pubkey.length == 64 &&
|
||||||
|
this.TimeStamp &&
|
||||||
|
this.RocketTag
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
valid = false;
|
||||||
}
|
}
|
||||||
return valid;
|
return valid;
|
||||||
}
|
}
|
||||||
REQFilter(kind?: number): NDKFilter {
|
REQFilter(kind?: number): NDKFilter {
|
||||||
if (!this.BasicValidation()) {
|
if (!this.BasicValidation()) {
|
||||||
return {}
|
return {};
|
||||||
}
|
}
|
||||||
if (!kind) {
|
if (!kind) {
|
||||||
kind = 31108
|
kind = 31108;
|
||||||
}
|
}
|
||||||
return { '#d': [this.RocketTag?.split(":")[2]!], authors: [this.RocketTag?.split(":")[1]!], kinds: [kind as number] }
|
return {
|
||||||
|
'#d': [this.RocketTag?.split(':')[2]!],
|
||||||
|
authors: [this.RocketTag?.split(':')[1]!],
|
||||||
|
kinds: [kind as number]
|
||||||
|
};
|
||||||
}
|
}
|
||||||
constructor(request: NDKEvent) {
|
constructor(request: NDKEvent) {
|
||||||
this.Request = request;
|
this.Event = request;
|
||||||
this.ID = request.id;
|
this.ID = request.id;
|
||||||
this.Pubkey = request.pubkey;
|
this.Pubkey = request.pubkey;
|
||||||
if (this.Request.created_at) {
|
if (this.Event.created_at) {
|
||||||
this.TimeStamp = this.Request.created_at;
|
this.TimeStamp = this.Event.created_at;
|
||||||
}
|
}
|
||||||
for (let tag of this.Request.getMatchingTags('a')) {
|
for (let tag of this.Event.getMatchingTags('a')) {
|
||||||
if (tag && tag.length > 1) {
|
if (tag && tag.length > 1) {
|
||||||
if (tag[1].split(':') && tag[1].split(':').length == 3) {
|
if (tag[1].split(':') && tag[1].split(':').length == 3) {
|
||||||
if ((tag[1].split(':')[0] = '31108')) {
|
if ((tag[1].split(':')[0] = '31108')) {
|
||||||
@@ -71,3 +83,75 @@ export class MeritRequest {
|
|||||||
this.Merits = getNumberFromTag('merits', request);
|
this.Merits = getNumberFromTag('merits', request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class Vote {
|
||||||
|
ID: string;
|
||||||
|
Request: string;
|
||||||
|
VoteDirection: VoteDirection | undefined;
|
||||||
|
Pubkey: string;
|
||||||
|
TimeStamp: number;
|
||||||
|
Event: NDKEvent;
|
||||||
|
BasicValidation(): boolean {
|
||||||
|
let valid = true;
|
||||||
|
if (
|
||||||
|
!(
|
||||||
|
this.ID.length == 64 &&
|
||||||
|
this.Request.length == 64 &&
|
||||||
|
this.VoteDirection &&
|
||||||
|
this.TimeStamp
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
RocketTag(): NDKTag | undefined {
|
||||||
|
let tag: NDKTag | undefined = undefined;
|
||||||
|
if (this.BasicValidation()) {
|
||||||
|
for (let t of this.Event.getMatchingTags('a')) {
|
||||||
|
if (t && t.length > 1 && t[1].split(':').length == 3 && t[1].split(':')[0] == '31108') {
|
||||||
|
tag = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
REQFilter(kind?: number): NDKFilter {
|
||||||
|
let filter = {};
|
||||||
|
if (!kind) {
|
||||||
|
kind = 31108;
|
||||||
|
}
|
||||||
|
if (this.BasicValidation()) {
|
||||||
|
let t = this.RocketTag();
|
||||||
|
if (t) {
|
||||||
|
filter = {
|
||||||
|
'#d': [t[1].split(':')[2]!],
|
||||||
|
authors: [t[1].split(':')[1]!],
|
||||||
|
kinds: [kind as number]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return filter;
|
||||||
|
}
|
||||||
|
constructor(event: NDKEvent) {
|
||||||
|
this.Event = event;
|
||||||
|
this.ID = event.id;
|
||||||
|
this.Pubkey = event.pubkey;
|
||||||
|
if (this.Event.created_at) {
|
||||||
|
this.TimeStamp = this.Event.created_at;
|
||||||
|
}
|
||||||
|
for (let t of this.Event.getMatchingTags("vote")) {
|
||||||
|
if (t && t.length == 2 && (t[1] == "blackball" || t[1] == "ratify")) {
|
||||||
|
this.VoteDirection = t[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let t of this.Event.getMatchingTags("request")) {
|
||||||
|
if (t && t.length == 2 && t[1].length == 64) {
|
||||||
|
this.Request = t[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type VoteDirection = "blackball" | "ratify"
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { NDKEvent, type NDKTag } from '@nostr-dev-kit/ndk';
|
import { NDKEvent, type NDKFilter, type NDKTag } from '@nostr-dev-kit/ndk';
|
||||||
|
|
||||||
export class RocketProduct {
|
export class RocketProduct {
|
||||||
ID: string;
|
ID: string;
|
||||||
@@ -144,3 +144,7 @@ export function isValidUrl(string:string):boolean {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function RocketATagFilter(rocket:NDKEvent):string {
|
||||||
|
return `31108:${rocket.pubkey}:${rocket.dTag}`
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user