Radish alpha
r
Radicle web interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
Implement org profile fallback
Alexis Sellier committed 4 years ago
commit 2928e2fe14a0a25c28e8ac7d0fdcd9d4505871f2
parent 07d2cf48ebe49ff6c6de3740f557251b64b436dc
8 files changed +82 -33
modified src/Address.svelte
@@ -66,7 +66,9 @@
    <span class="badge">contract</span>
  {:else if addressType === AddressType.EOA}
    <a href={`/users/${address}`} target="_blank">{addressLabel}</a>
-
  {:else if !noBadge}
+
  {:else if profile?.name} <!-- While we're waiting to find out what address type it is -->
+
    <a href={explorerLink(address, config)} target="_blank">{addressLabel}</a>
+
  {:else}
    <div class="loading"><Loading small /></div>
  {/if}
</div>
modified src/Icon.svelte
@@ -2,7 +2,7 @@
  export let name: string;
  export let width: number | null = null;
  export let height: number | null = null;
-
  export let inline: boolean = false;
+
  export let inline = false;

  const icons = [
    {
modified src/base/orgs/Org.ts
@@ -3,6 +3,7 @@ import type { TransactionResponse } from '@ethersproject/providers';
import type { ContractReceipt } from '@ethersproject/contracts';
import { OperationType } from "@gnosis.pm/safe-core-sdk-types";

+
import { Profile } from '@app/profile';
import { assert } from '@app/error';
import * as utils from '@app/utils';
import type { Config } from '@app/config';
@@ -141,6 +142,10 @@ export class Org {
    return projects;
  }

+
  async getProfile(config: Config): Promise<Profile> {
+
    return Org.getProfile(this.address, config);
+
  }
+

  static async getAnchor(orgAddr: string, urn: string, config: Config): Promise<string | null> {
    const org = new ethers.Contract(
      orgAddr,
@@ -207,6 +212,22 @@ export class Org {
    }
  }

+
  // Return only org profile if there is one, otherwise tries to get the profile
+
  // of its owner.
+
  static async getProfile(address: string, config: Config): Promise<Profile> {
+
    const profile = await Profile.get(address, config);
+

+
    if (profile.ens) {
+
      return profile;
+
    }
+
    const org = await Org.get(address, config);
+

+
    if (org) {
+
      return Profile.get(org.owner, config);
+
    }
+
    return profile;
+
  }
+

  // Return only Orgs that have a specific user as owner
  static async getOrgsByOwner(owner: string, config: Config): Promise<Org[]> {
    const orgsResult = await utils.querySubgraph(config.orgs.subgraph, GetOrgsByOwner, { owners: [owner] });
modified src/base/orgs/View.svelte
@@ -85,6 +85,10 @@
    width: 64px;
    height: 64px;
  }
+
  .title {
+
    display: flex;
+
    align-items: center;
+
  }
  .links {
    display: flex;
    align-items: center;
@@ -127,7 +131,7 @@
{:then org}
  {#if org}
    <main>
-
      {#await Profile.get(address, config)}
+
      {#await org.getProfile(config)}
        <div class="centered">
          <Loading center />
        </div>
@@ -139,6 +143,9 @@
          <div class="info">
            <span class="title bold">
              {parseEnsLabel(profile.name, config) ?? address}
+
              {#if profile.address === org.owner}
+
                <span class="badge">org</span>
+
              {/if}
            </span>
            <div class="links">
              {#if profile.url}
@@ -176,25 +183,28 @@
            {/if}
          </div>
          <!-- Name -->
-
          <div class="label">Name</div>
-
          <div>
-
            {#if profile.name}
-
              <Link to={`/registrations/${parseEnsLabel(profile.name, config)}`}>{profile.name}</Link>
-
            {:else}
-
              <span class="subtle">Not set</span>
-
            {/if}
-
          </div>
-
          <div>
-
            {#await isAuthorized(org)}
-
              <!-- Loading -->
-
            {:then authorized}
-
              {#if authorized}
-
                <button class="tiny secondary" on:click={setName}>
-
                  Set
-
                </button>
+
          <!-- Only show the name if we aren't already using the name of the owner -->
+
          {#if profile.address === org.address}
+
            <div class="label">Name</div>
+
            <div>
+
              {#if profile.name}
+
                <Link to={`/registrations/${parseEnsLabel(profile.name, config)}`}>{profile.name}</Link>
+
              {:else}
+
                <span class="subtle">Not set</span>
              {/if}
-
            {/await}
-
          </div>
+
            </div>
+
            <div>
+
              {#await isAuthorized(org)}
+
                <!-- Loading -->
+
              {:then authorized}
+
                {#if authorized}
+
                  <button class="tiny secondary" on:click={setName}>
+
                    Set
+
                  </button>
+
                {/if}
+
              {/await}
+
            </div>
+
          {/if}
        </div>

        {#await org.getMembers(config)}
@@ -224,7 +234,7 @@
          {:then projects}
            {#each projects as project}
              <div class="project">
-
                <Project {project} org={org.address} {config} seed={profile.seed} />
+
                <Project {project} org={org.address} config={profile.config(config)} />
              </div>
            {/each}
          {:catch err}
modified src/base/projects/View.svelte
@@ -5,7 +5,7 @@
  import Loading from '@app/Loading.svelte';
  import Modal from '@app/Modal.svelte';
  import Avatar from '@app/Avatar.svelte';
-
  import { Profile } from '@app/profile';
+
  import { Org } from '@app/base/orgs/Org';

  import Browser from './Browser.svelte';

@@ -16,13 +16,11 @@
  export let path: string;

  let projectRoot = proj.path({ urn, org, commit });
-
  let getProject = new Promise<string | undefined>(resolve => {
+
  let getProject = new Promise<string | null>(resolve => {
    if (org) {
-
      Profile.get(org, config).then((p: Profile) => {
-
        resolve(p.seed);
-
      });
+
      Org.getProfile(org, config).then(p => resolve(p?.seed || null));
    } else {
-
      resolve(undefined);
+
      resolve(null);
    }
  }).then(async (seed) => {
    const cfg = seed ? config.withSeed(seed) : config;
modified src/base/projects/Widget.svelte
@@ -16,15 +16,13 @@
  export let project: proj.Project;
  export let config: Config;
  export let org: string | undefined;
-
  export let seed: string | undefined;

  let state: State = { status: Status.Loading };
  let info: proj.Info | null = null;

  onMount(async () => {
    try {
-
      const cfg = seed ? config.withSeed(seed) : config;
-
      const result = await proj.getInfo(project.id, cfg);
+
      const result = await proj.getInfo(project.id, config);
      state = { status: Status.Loaded };
      info = result;
    } catch (err) {
modified src/base/users/View.svelte
@@ -16,6 +16,7 @@
<style>
  main {
    padding: 5rem 0;
+
    width: 36rem;
  }
  main > header {
    display: flex;
@@ -66,7 +67,7 @@
      </div>
      <div class="info">
        <span class="title bold">
-
          <Address compact noAvatar noBadge {address} {config} resolve/>
+
          <Address compact noAvatar noBadge {profile} {address} {config} resolve/>
        </span>
        <div class="links">
          {#if profile.url}
@@ -93,7 +94,7 @@
            {#await org.getProjects(config) then projects}
              {#each projects as project}
                <div class="project">
-
                  <Project {project} org={org.address} {config} seed={profile.seed} />
+
                  <Project {project} org={org.address} config={profile.config(config)} />
                </div>
              {/each}
            {:catch err}
modified src/profile.ts
@@ -20,6 +20,16 @@ export class Profile {
    this.address = address;
  }

+
  // Get the ENS profile
+
  get ens(): Registration | null {
+
    return this.profile.ens;
+
  }
+

+
  // Get the IDX profle
+
  get idx(): BasicProfile | null {
+
    return this.profile.idx;
+
  }
+

  // Using undefined as return type if nothing to be returned since it works better with <a href> links
  get github(): string | undefined {
    if (this.profile?.ens?.github) return parseUsername(this.profile.ens.github);
@@ -60,6 +70,15 @@ export class Profile {
    return this.profile?.ens?.seedApi ?? undefined;
  }

+
  // Return the profile-specific config. This sets various URLs in the config,
+
  // based on profile data.
+
  config(config: Config): Config {
+
    if (this.seed) {
+
      return config.withSeed(this.seed);
+
    }
+
    return config;
+
  }
+

  // Keeping this function private since the desired entrypoint is .get()
  private static async lookupAddress(address: string, config: Config): Promise<[IProfile, string]> {
    const profile: IProfile = { ens: null, idx: null };