mirror of
https://seed.radicle.dev/rad:z4V1sjrXqjvFdnCUbxPFqd5p4DtH5.git
synced 2026-10-18 19:30:27 +08:00
Add explore seeds to landing page
Signed-off-by: Sebastian Martinez <sebastinez@me.com> Signed-off-by: Alexis Sellier <self@cloudhead.io>
This commit is contained in:
+47
-11
@@ -1,18 +1,30 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { Link } from 'svelte-routing';
|
||||
import Avatar from '@app/Avatar.svelte';
|
||||
import type { Profile } from '@app/profile';
|
||||
import type { Config } from '@app/config';
|
||||
import { formatName, formatAddress } from '@app/utils';
|
||||
import type { Seed } from '@app/base/seeds/Seed';
|
||||
|
||||
export let profile: Profile | {
|
||||
address: string;
|
||||
avatar?: string;
|
||||
name?: string;
|
||||
} ;
|
||||
} | null = null;
|
||||
export let seed: Seed | null = null;
|
||||
export let config: Config;
|
||||
export let path: string;
|
||||
export let members: string[] = [];
|
||||
|
||||
let numberOfProjects: number | null = null;
|
||||
|
||||
onMount(async () => {
|
||||
if (seed) {
|
||||
const projects = await seed.getProjects();
|
||||
numberOfProjects = projects.length;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@@ -55,6 +67,16 @@
|
||||
color: var(--color-foreground-faded);
|
||||
}
|
||||
|
||||
.card.seed {
|
||||
width: 14rem;
|
||||
}
|
||||
.card.seed .card-label {
|
||||
max-width: 12rem;
|
||||
}
|
||||
.card.seed .seed-emoji {
|
||||
font-size: 3rem;
|
||||
}
|
||||
|
||||
@media (max-width: 720px) {
|
||||
.card {
|
||||
margin-right: 0;
|
||||
@@ -63,22 +85,36 @@
|
||||
</style>
|
||||
|
||||
<Link to={path}>
|
||||
<div class="card">
|
||||
<div class="card" class:seed={!!seed}>
|
||||
<div class="card-avatar">
|
||||
<Avatar source={profile.avatar ?? profile.address} address={profile.address} />
|
||||
{#if profile}
|
||||
<Avatar source={profile.avatar ?? profile.address} address={profile.address} />
|
||||
{:else if seed}
|
||||
<span class="seed-emoji">
|
||||
{seed.emoji}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="card-label">
|
||||
{#if profile.name}
|
||||
{formatName(profile.name, config)}
|
||||
{:else}
|
||||
{formatAddress(profile.address)}
|
||||
{#if profile}
|
||||
{#if profile.name}
|
||||
{formatName(profile.name, config)}
|
||||
{:else}
|
||||
{formatAddress(profile.address)}
|
||||
{/if}
|
||||
{:else if seed}
|
||||
{seed.host}
|
||||
{/if}
|
||||
</div>
|
||||
<div class="card-members">
|
||||
{#if members.length > 0}
|
||||
{members.length} member(s)
|
||||
{:else}
|
||||
{formatAddress(profile.address)}
|
||||
{#if profile}
|
||||
{#if members.length > 0}
|
||||
{members.length} member(s)
|
||||
{:else}
|
||||
{formatAddress(profile.address)}
|
||||
{/if}
|
||||
{:else if numberOfProjects}
|
||||
{numberOfProjects} project(s)
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+7
-1
@@ -4,10 +4,12 @@
|
||||
import Card from '@app/Card.svelte';
|
||||
import type { Org } from '@app/base/orgs/Org';
|
||||
import type { Config } from '@app/config';
|
||||
import type { Seed } from '@app/base/seeds/Seed';
|
||||
|
||||
export let config: Config;
|
||||
export let orgs: Org[] = [];
|
||||
export let profiles: Profile[] = [];
|
||||
export let seeds: Seed[] = [];
|
||||
|
||||
const orgMembers: Record<string, string[]> = {};
|
||||
|
||||
@@ -52,7 +54,11 @@
|
||||
<Card {profile} {config} path={`/${profile.nameOrAddress}`} />
|
||||
{/each}
|
||||
|
||||
{#if !orgs.length && !profiles.length}
|
||||
{#each seeds as seed}
|
||||
<Card {seed} {config} path={`/seeds/${seed.host}`} />
|
||||
{/each}
|
||||
|
||||
{#if !orgs.length && !profiles.length && !seeds.length}
|
||||
<slot />
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
import Message from '@app/Message.svelte';
|
||||
import Cards from '@app/Cards.svelte';
|
||||
import { setOpenGraphMetaTag } from '@app/utils';
|
||||
import { Seed } from '@app/base/seeds/Seed';
|
||||
|
||||
export let config: Config;
|
||||
|
||||
@@ -24,8 +25,12 @@
|
||||
? Profile.getMulti(config.users.pinned, config)
|
||||
: Promise.resolve([]);
|
||||
|
||||
const getEntities = Promise.all([getUsers, getOrgs]).then(([users, orgs]) => {
|
||||
return { users, orgs };
|
||||
const getSeeds = Object.keys(config.seeds.pinned).length > 0
|
||||
? Seed.lookupMulti(Object.keys(config.seeds.pinned), config)
|
||||
: Promise.resolve([]);
|
||||
|
||||
const getEntities = Promise.all([getUsers, getOrgs, getSeeds]).then(([users, orgs, seeds]) => {
|
||||
return { users, orgs, seeds };
|
||||
});
|
||||
|
||||
const viewMore = () => {
|
||||
@@ -88,6 +93,14 @@
|
||||
<Loading center />
|
||||
</div>
|
||||
{:then entities}
|
||||
{#if entities.seeds.length}
|
||||
<div class="heading">
|
||||
Explore <strong>seed nodes</strong> on the Radicle network.
|
||||
</div>
|
||||
<Cards {config} seeds={entities.seeds}>
|
||||
<div class="empty">There are no seed nodes.</div>
|
||||
</Cards>
|
||||
{/if}
|
||||
{#if entities.orgs.length || entities.users.length}
|
||||
<div class="heading">
|
||||
Explore <strong>orgs</strong> and <strong>users</strong> on the Radicle network.
|
||||
|
||||
@@ -24,6 +24,7 @@ export class Seed {
|
||||
link: { host: string; id: string; port: number };
|
||||
|
||||
version?: string;
|
||||
emoji: string;
|
||||
|
||||
constructor(seed: {
|
||||
host: string;
|
||||
@@ -58,6 +59,13 @@ export class Seed {
|
||||
assert(isDomain(git), `invalid seed git host ${git}`);
|
||||
}
|
||||
|
||||
const meta = cfg.seeds.pinned[seed.host];
|
||||
if (meta) {
|
||||
this.emoji = meta.emoji;
|
||||
} else {
|
||||
this.emoji = "🌱";
|
||||
}
|
||||
|
||||
// The `git` and `api` keys being more specific take
|
||||
// precedence over the `host`, if available.
|
||||
api = api ?? seed.host;
|
||||
@@ -117,4 +125,8 @@ export class Seed {
|
||||
version: info.version,
|
||||
}, cfg);
|
||||
}
|
||||
|
||||
static async lookupMulti(hostnames: string[], cfg: Config): Promise<Seed[]> {
|
||||
return await Promise.all(hostnames.map(h => Seed.lookup(h, cfg)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
<div class="info">
|
||||
<span class="title">
|
||||
<span class="bold">
|
||||
{host} 🌱
|
||||
{host} {seed.emoji}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -26,6 +26,19 @@
|
||||
"cloudhead.radicle.eth"
|
||||
]
|
||||
},
|
||||
"seeds": {
|
||||
"pinned": {
|
||||
"willow.radicle.garden": {
|
||||
"emoji": "🪵"
|
||||
},
|
||||
"pine.radicle.garden": {
|
||||
"emoji": "🌲"
|
||||
},
|
||||
"maple.radicle.garden": {
|
||||
"emoji": "🍁"
|
||||
}
|
||||
}
|
||||
},
|
||||
"safe": {
|
||||
"api": "https://safe-transaction.gnosis.io",
|
||||
"viewer": "https://gnosis-safe.io/app/#/safes"
|
||||
|
||||
@@ -32,6 +32,7 @@ export class Config {
|
||||
reverseRegistrar: { address: string };
|
||||
orgs: { subgraph: string; contractHash: string; pinned: string[] };
|
||||
users: { pinned: string[] };
|
||||
seeds: { pinned: Record<string, { emoji: string }> };
|
||||
gasLimits: { createOrg: number };
|
||||
provider: ethers.providers.JsonRpcProvider;
|
||||
signer: ethers.Signer & TypedDataSigner | WalletConnectSigner | null;
|
||||
@@ -108,6 +109,7 @@ export class Config {
|
||||
this.reverseRegistrar = cfg.reverseRegistrar;
|
||||
this.orgs = cfg.orgs;
|
||||
this.users = cfg.users;
|
||||
this.seeds = cfg.seeds;
|
||||
this.safe = cfg.safe;
|
||||
this.safe.client = this.safe.api
|
||||
? new SafeServiceClient(this.safe.api)
|
||||
|
||||
Reference in New Issue
Block a user