Show pinned orgs on the front page

Signed-off-by: Alexis Sellier <self@cloudhead.io>
This commit is contained in:
Alexis Sellier
2021-09-30 15:01:32 +02:00
parent 8493dfe52c
commit e2cc61671b
8 changed files with 89 additions and 23 deletions
+21 -1
View File
@@ -34,6 +34,22 @@
display: flex;
align-items: center;
}
header .nav {
display: inline-block;
height: 100%;
margin-left: 1.5rem;
white-space: nowrap;
}
header .nav a {
display: inline-block;
padding: 0.5rem 0.5rem;
margin-right: 1.5rem;
font-weight: 500;
color: var(--color-foreground-6);
}
header .nav a:hover {
color: var(--color-foreground);
}
.logo {
display: flex;
}
@@ -54,7 +70,7 @@
.search {
height: 42px;
width: 16rem;
margin-left: 1rem;
margin-left: 1.5rem;
display: inline-block;
}
.address {
@@ -122,6 +138,10 @@
<div class="search">
<Search />
</div>
<div class="nav">
<a use:link href="/orgs/">Orgs</a>
<a use:link href="/registrations">Register</a>
</div>
</div>
<div class="right">
+1 -1
View File
@@ -17,6 +17,6 @@
<main>
<div>
<Orgs {config} />
<Orgs {config} pinned />
</div>
</main>
+9 -5
View File
@@ -9,7 +9,11 @@
import List from './List.svelte';
export let config: Config;
export let pinned = false;
const getOrgs = pinned && (config.orgs.pinned.length > 0)
? Org.getMulti(config.orgs.pinned, config)
: Org.getAll(config);
const onCreate = () => modal = Create;
let modal: typeof SvelteComponent | null = null;
@@ -32,14 +36,14 @@
}
.padding {
padding: 0 3rem 3rem 3rem;
padding: 0 2rem 2rem 2rem;
}
.my-orgs {
margin-bottom: 3rem;
margin-bottom: 2rem;
}
.orgs-empty {
margin-left: 3rem;
margin-left: 2rem;
padding: 1rem 0 2rem 0;
font-style: italic;
color: var(--color-foreground-faded);
@@ -50,7 +54,7 @@
}
.loading {
padding: 3rem 0;
padding: 2rem 0;
}
</style>
@@ -90,7 +94,7 @@
<span><strong>Orgs</strong> of the Radicle network</span>
</header>
{#await Org.getAll(config)}
{#await getOrgs}
<div class="loading">
<Loading center />
</div>
+37 -13
View File
@@ -1,4 +1,6 @@
<script lang="ts">
import { ethers } from 'ethers';
import { onMount } from 'svelte';
import { Link } from 'svelte-routing';
import type { Org } from '@app/base/orgs/Org';
import Avatar from '@app/Avatar.svelte';
@@ -10,32 +12,43 @@
export let config: Config;
export let orgs: Org[];
const orgsAddresses = orgs.map(org => org.address);
const orgMembers: Record<string, string[]> = {};
const getProfiles = Profile.getMulti(orgs.map(o => o.name ?? o.address), config);
onMount(async () => {
const promises = orgs.map(org => org.getMembers(config).then(members => {
orgMembers[ethers.utils.getAddress(org.address)] = members;
}));
Promise.all(promises);
});
</script>
<style>
.org {
width: 8rem;
height: 8rem;
width: 10rem;
height: 10rem;
margin-left: 3rem;
margin-top: 1.5rem;
margin-bottom: 1.5rem;
padding: 1rem;
display: inline-block;
text-align: center;
border-radius: 1rem;
}
.org:hover .org-label {
color: var(--color-background);
background: var(--color-secondary);
.org:hover {
background: var(--color-foreground-background-lighter);
}
.org-avatar {
margin: 0 auto;
text-align: center;
width: 3rem;
height: 3rem;
width: 4rem;
height: 4rem;
}
.org-label {
color: var(--color-foreground-90);
display: inline-block;
font-weight: var(--font-weight-medium);
margin-top: 0.75rem;
border-radius: 0.75rem;
padding: 0rem 0.5rem;
@@ -43,6 +56,10 @@
overflow-x: hidden;
max-width: 8rem;
}
.org-members {
font-size: 0.875rem;
color: var(--color-foreground-faded);
}
.list {
display: flex;
flex-direction: row;
@@ -53,15 +70,15 @@
}
</style>
{#await Profile.getMulti(orgsAddresses, config)}
{#await getProfiles}
<div class="loading">
<Loading center />
</div>
{:then profiles}
<div class="list">
{#each profiles as profile}
<div class="org">
<Link to={`/orgs/${profile.nameOrAddress}`}>
<Link to={`/orgs/${profile.nameOrAddress}`}>
<div class="org">
<div class="org-avatar">
<Avatar source={profile.avatar ?? profile.address} />
</div>
@@ -72,8 +89,15 @@
{formatAddress(profile.address)}
{/if}
</div>
</Link>
</div>
<div class="org-members">
{#if orgMembers[profile.address]?.length}
{orgMembers[profile.address].length} members
{:else}
{formatAddress(profile.address)}
{/if}
</div>
</div>
</Link>
{:else}
<slot />
{/each}
+7
View File
@@ -172,6 +172,13 @@ export class Org {
}
}
static async getMulti(ids: string[], config: Config): Promise<Array<Org>> {
const results = await Promise.all(ids.map(addr => Org.get(addr, config)));
const orgs = results.filter((org): org is Org => org != null);
return orgs;
}
static async getAll(config: Config): Promise<Array<Org>> {
const result = await utils.querySubgraph(config.orgs.subgraph, GetOrgs, {});
const orgs: Org[] = [];
+10 -2
View File
@@ -12,7 +12,14 @@
},
"orgs": {
"subgraph": "https://gateway.thegraph.com/api/1758a78ae257ad4906f9c638e4a68c19/subgraphs/id/0x2f0963e77ca6ac0c2dad1bf4147b6b40e0dd8728-0",
"contractHash": "0x5c34bb0755876de98e801805e6685456eea739ad0abba1cc450a7ee0f2a70b74"
"contractHash": "0x5c34bb0755876de98e801805e6685456eea739ad0abba1cc450a7ee0f2a70b74",
"pinned": [
"alt-clients.radicle.eth",
"community.radicle.eth",
"upstream.radicle.eth",
"gnosisguild.radicle.eth",
"dxdao.radicle.eth"
]
},
"safe": {
"api": "https://safe-transaction.gnosis.io",
@@ -37,7 +44,8 @@
},
"orgs": {
"subgraph": "https://api.thegraph.com/subgraphs/name/radicle-dev/radicle-orgs-rinkeby",
"contractHash": "0x5c34bb0755876de98e801805e6685456eea739ad0abba1cc450a7ee0f2a70b74"
"contractHash": "0x5c34bb0755876de98e801805e6685456eea739ad0abba1cc450a7ee0f2a70b74",
"pinned": []
},
"safe": {
"api": "https://safe-transaction.rinkeby.gnosis.io",
+1 -1
View File
@@ -31,7 +31,7 @@ export class Config {
radToken: { address: string };
orgFactory: { address: string };
reverseRegistrar: { address: string };
orgs: { subgraph: string; contractHash: string };
orgs: { subgraph: string; contractHash: string; pinned: string[] };
gasLimits: { createOrg: number };
provider: ethers.providers.JsonRpcProvider;
signer: ethers.Signer & TypedDataSigner | WalletConnectSigner | null;
+3
View File
@@ -264,6 +264,9 @@ export async function resolveEnsProfile(addressOrName: string, profileType: Prof
if (name) {
const resolver = await config.provider.getResolver(name);
if (! resolver) {
return null;
}
if (profileType === ProfileType.Full) {
const registration = await getRegistration(name, config, resolver);