From f88b20ff7a6cf5aefd9b8a94d97e69302174c742 Mon Sep 17 00:00:00 2001 From: DIYgod Date: Wed, 22 Jun 2022 19:20:30 +0100 Subject: [PATCH] feat: dashboard index page --- package.json | 2 +- pnpm-lock.yaml | 220 ++++++++++++++++++- src/components/dashboard/DashboardLayout.tsx | 22 +- src/components/dashboard/SiteSwitcher.tsx | 39 +--- src/lib/user-contents.ts | 2 +- src/models/site.model.ts | 8 +- src/pages/dashboard/index.tsx | 11 +- 7 files changed, 250 insertions(+), 54 deletions(-) diff --git a/package.json b/package.json index dba83473..37bd5230 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "remark-rehype": "^10.1.0", "sortablejs": "^1.15.0", "ua-parser-js": "^1.0.2", - "unidata.js": "^0.5.2", + "unidata.js": "^0.5.4", "unified": "^10.1.2", "unist-builder": "^3.0.0", "unist-util-visit": "^4.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index dc8678cb..bbd9575e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -80,7 +80,7 @@ specifiers: tailwindcss: ^3.0.24 typescript: ^4.5.5 ua-parser-js: ^1.0.2 - unidata.js: ^0.5.2 + unidata.js: ^0.5.4 unified: ^10.1.2 unist-builder: ^3.0.0 unist-util-visit: ^4.1.0 @@ -141,7 +141,7 @@ dependencies: remark-rehype: 10.1.0 sortablejs: 1.15.0 ua-parser-js: 1.0.2 - unidata.js: 0.5.2 + unidata.js: 0.5.4 unified: 10.1.2 unist-builder: 3.0.0 unist-util-visit: 4.1.0 @@ -1432,7 +1432,7 @@ packages: /@types/bn.js/4.11.6: resolution: {integrity: sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==} dependencies: - '@types/node': 17.0.31 + '@types/node': 17.0.45 dev: false /@types/busboy/0.3.2: @@ -1520,6 +1520,10 @@ packages: /@types/node/17.0.31: resolution: {integrity: sha512-AR0x5HbXGqkEx9CadRH3EBYx/VkiUgZIhP4wvPn/+5KIsgpNoyFaRlVe0Zlx9gRtg8fA06a9tskE2MSN7TcG4Q==} + /@types/node/17.0.45: + resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==} + dev: false + /@types/normalize-package-data/2.4.1: resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} dev: false @@ -2851,7 +2855,7 @@ packages: dependencies: ethers: 5.6.9 ts-mixer: 6.0.1 - undici: 5.3.0 + undici: 5.5.1 transitivePeerDependencies: - bufferutil - utf-8-validate @@ -4533,8 +4537,8 @@ packages: multiformats: 9.6.5 dev: false - /interface-datastore/6.1.0: - resolution: {integrity: sha512-oNHdsrWBsI/kDwUtEgt+aaZtQFKtQYN0TGZzc3SGiIA6m+plZ6malhmsygtbmDpfpIsNNC7ce9Gyaj+Tki+gVw==} + /interface-datastore/6.1.1: + resolution: {integrity: sha512-AmCS+9CT34pp2u0QQVXjKztkuq3y5T+BIciuiHDDtDZucZD8VudosnSdUyXJV6IsRkN5jc4RFDhCk1O6Q3Gxjg==} dependencies: interface-store: 2.0.2 nanoid: 3.3.4 @@ -4595,6 +4599,165 @@ packages: - supports-color dev: false + /ipfs-core-types/0.8.4: + resolution: {integrity: sha512-sbRZA1QX3xJ6ywTiVQZMOxhlhp4osAZX2SXx3azOLxAtxmGWDMkHYt722VV4nZ2GyJy8qyk5GHQIZ0uvQnpaTg==} + dependencies: + interface-datastore: 6.1.1 + multiaddr: 10.0.1 + multiformats: 9.6.5 + transitivePeerDependencies: + - node-fetch + - supports-color + dev: false + + /ipfs-core-utils/0.12.2: + resolution: {integrity: sha512-RfxP3rPhXuqKIUmTAUhmee6fmaV3A7LMnjOUikRKpSyqESz/DR7aGK7tbttMxkZdkSEr0rFXlqbyb0vVwmn0wQ==} + dependencies: + any-signal: 2.1.2 + blob-to-it: 1.0.4 + browser-readablestream-to-it: 1.0.3 + debug: 4.3.4 + err-code: 3.0.1 + ipfs-core-types: 0.8.4 + ipfs-unixfs: 6.0.9 + ipfs-utils: 9.0.6 + it-all: 1.0.6 + it-map: 1.0.6 + it-peekable: 1.0.3 + it-to-stream: 1.0.0 + merge-options: 3.0.4 + multiaddr: 10.0.1 + multiaddr-to-uri: 8.0.0 + multiformats: 9.6.5 + nanoid: 3.3.4 + parse-duration: 1.0.2 + timeout-abort-controller: 1.1.1 + uint8arrays: 3.0.0 + transitivePeerDependencies: + - node-fetch + - supports-color + dev: false + + /ipfs-unixfs-exporter/7.0.11: + resolution: {integrity: sha512-qTYa69J7HbI2EIYNUddKPg9Y3rHkYZV0bNdmzZKA5+ZbwRVoUEuBW/cguEqTp22zHygh3sMnzYZFm0naVIdMgQ==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + dependencies: + '@ipld/dag-cbor': 7.0.2 + '@ipld/dag-pb': 2.1.17 + '@multiformats/murmur3': 1.1.3 + err-code: 3.0.1 + hamt-sharding: 2.0.1 + interface-blockstore: 2.0.3 + ipfs-unixfs: 6.0.9 + it-last: 1.0.6 + multiformats: 9.6.5 + uint8arrays: 3.0.0 + dev: false + + /ipfs-unixfs-importer/9.0.10: + resolution: {integrity: sha512-W+tQTVcSmXtFh7FWYWwPBGXJ1xDgREbIyI1E5JzDcimZLIyT5gGMfxR3oKPxxWj+GKMpP5ilvMQrbsPzWcm3Fw==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + dependencies: + '@ipld/dag-pb': 2.1.17 + '@multiformats/murmur3': 1.1.3 + bl: 5.0.0 + err-code: 3.0.1 + hamt-sharding: 2.0.1 + interface-blockstore: 2.0.3 + ipfs-unixfs: 6.0.9 + it-all: 1.0.6 + it-batch: 1.0.9 + it-first: 1.0.7 + it-parallel-batch: 1.0.10 + merge-options: 3.0.4 + multiformats: 9.6.5 + rabin-wasm: 0.1.5 + uint8arrays: 3.0.0 + transitivePeerDependencies: + - encoding + - supports-color + dev: false + + /ipfs-unixfs/6.0.9: + resolution: {integrity: sha512-0DQ7p0/9dRB6XCb0mVCTli33GzIzSVx5udpJuVM47tGcD+W+Bl4LsnoLswd3ggNnNEakMv1FdoFITiEnchXDqQ==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + dependencies: + err-code: 3.0.1 + protobufjs: 6.11.3 + dev: false + + /ipfs-utils/9.0.6: + resolution: {integrity: sha512-/WfdwOIiJVb3uqfKRQ9Eo+vCEKsDgp7h4Pdc37MRwAiFciZ7xKAkEqsfXubV0VQi8x5jWTifeHn8WEPBLL451w==} + dependencies: + any-signal: 3.0.1 + buffer: 6.0.3 + electron-fetch: 1.7.4 + err-code: 3.0.1 + is-electron: 2.2.1 + iso-url: 1.2.1 + it-glob: 1.0.2 + it-to-stream: 1.0.0 + merge-options: 3.0.4 + nanoid: 3.3.4 + native-fetch: 3.0.0_hmwa7nplpltavckpkeobtw6pv4 + node-fetch: /@achingbrain/node-fetch/2.6.7 + react-native-fetch-api: 2.0.0 + stream-to-it: 0.2.4 + dev: false + + /ipns/0.16.0: + resolution: {integrity: sha512-fBYkRjN3/fc6IQujUF4WBEyOXegK715w+wx9IErV6H2B5JXsMnHOBceUKn3L90dj+wJfHs6T+hM/OZiTT6mQCw==} + dependencies: + cborg: 1.9.4 + debug: 4.3.4 + err-code: 3.0.1 + interface-datastore: 6.1.1 + libp2p-crypto: 0.21.2 + long: 4.0.0 + multiformats: 9.6.5 + peer-id: 0.16.0 + protobufjs: 6.11.3 + timestamp-nano: 1.0.0 + uint8arrays: 3.0.0 + transitivePeerDependencies: + - supports-color + dev: false + + /is-alphabetical/2.0.1: + resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==} + dev: false + + /ipfs-car/0.7.0: + resolution: {integrity: sha512-9ser6WWZ1ZMTCGbcVkRXUzOrpQ4SIiLfzIEnk+3LQsXbV09yeZg3ijhRuEXozEIYE68Go9JmOFshamsK9iKlNQ==} + hasBin: true + dependencies: + '@ipld/car': 3.2.4 + '@web-std/blob': 3.0.4 + bl: 5.0.0 + blockstore-core: 1.0.5 + browser-readablestream-to-it: 1.0.3 + idb-keyval: 6.2.0 + interface-blockstore: 2.0.3 + ipfs-core-types: 0.8.4 + ipfs-core-utils: 0.12.2 + ipfs-unixfs-exporter: 7.0.11 + ipfs-unixfs-importer: 9.0.10 + ipfs-utils: 9.0.6 + it-all: 1.0.6 + it-last: 1.0.6 + it-pipe: 1.1.0 + meow: 9.0.0 + move-file: 2.1.0 + multiformats: 9.6.5 + stream-to-it: 0.2.4 + streaming-iterables: 6.2.0 + uint8arrays: 3.0.0 + transitivePeerDependencies: + - encoding + - node-fetch + - supports-color + dev: false + /ipfs-core-types/0.8.4: resolution: {integrity: sha512-sbRZA1QX3xJ6ywTiVQZMOxhlhp4osAZX2SXx3azOLxAtxmGWDMkHYt722VV4nZ2GyJy8qyk5GHQIZ0uvQnpaTg==} dependencies: @@ -5826,6 +5989,10 @@ packages: /ms/2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + /ms/2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + dev: false + /multiaddr-to-uri/8.0.0: resolution: {integrity: sha512-dq4p/vsOOUdVEd1J1gl+R2GFrXJQH8yjLtz4hodqdVbieg39LvBOdMQRdQnfbg5LSM/q1BYNVf5CBbwZFFqBgA==} dependencies: @@ -5990,7 +6157,7 @@ packages: resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} dependencies: hosted-git-info: 2.8.9 - resolve: 1.22.0 + resolve: 1.22.1 semver: 5.7.1 validate-npm-package-license: 3.0.4 dev: false @@ -6502,7 +6669,7 @@ packages: '@protobufjs/pool': 1.1.0 '@protobufjs/utf8': 1.1.0 '@types/long': 4.0.2 - '@types/node': 17.0.31 + '@types/node': 17.0.45 long: 4.0.0 dev: false @@ -6810,7 +6977,7 @@ packages: /receptacle/1.3.2: resolution: {integrity: sha512-HrsFvqZZheusncQRiEE7GatOAETrARKV/lnfYicIm8lbvp/JQOdADOfhjBd2DajvoszEyxSM6RlAAIZgEoeu/A==} dependencies: - ms: 2.1.2 + ms: 2.1.3 dev: false /redent/3.0.0: @@ -6946,6 +7113,15 @@ packages: path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 + /resolve/1.22.1: + resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} + hasBin: true + dependencies: + is-core-module: 2.9.0 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: false + /resolve/2.0.0-next.3: resolution: {integrity: sha512-W8LucSynKUIDu9ylraa7ueVZ7hc0uAgJBxVsQSKOXOyle8a93qXhcz+XAXZ8bIq2d6i4Ehddn6Evt+0/UwKk6Q==} dependencies: @@ -7587,6 +7763,32 @@ packages: - utf-8-validate dev: false + /undici/5.5.1: + resolution: {integrity: sha512-MEvryPLf18HvlCbLSzCW0U00IMftKGI5udnjrQbC5D4P0Hodwffhv+iGfWuJwg16Y/TK11ZFK8i+BPVW2z/eAw==} + engines: {node: '>=12.18'} + dev: false + + /unidata.js/0.5.4: + resolution: {integrity: sha512-amdu7judZHIE2JC9FC27/IuU4oeCTa4sJr3WMRuo9LHCVeOkipknUlHqZ0vYWZDZfhorqHp4RnTi7Eh2tOk63Q==} + dependencies: + '@types/lodash': 4.14.182 + '@urql/core': 2.5.0_graphql@16.5.0 + axios: 0.27.2 + crossbell.js: 0.5.15 + ethers: 5.6.8 + graphql: 16.5.0 + lodash: 4.17.21 + mime: 3.0.0 + web3.storage: 4.2.0 + transitivePeerDependencies: + - bufferutil + - debug + - encoding + - node-fetch + - supports-color + - utf-8-validate + dev: false + /unified/10.1.2: resolution: {integrity: sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==} dependencies: diff --git a/src/components/dashboard/DashboardLayout.tsx b/src/components/dashboard/DashboardLayout.tsx index 25b9d454..dc98117d 100644 --- a/src/components/dashboard/DashboardLayout.tsx +++ b/src/components/dashboard/DashboardLayout.tsx @@ -1,7 +1,7 @@ import clsx from "clsx" import Link from "next/link" import { useRouter } from "next/router" -import React from "react" +import React, { useState, useEffect } from "react" import { APP_NAME } from "~/lib/env" import { getSiteLink } from "~/lib/helpers" import { trpc } from "~/lib/trpc" @@ -10,6 +10,9 @@ import { DashboardIcon } from "../icons/DashboardIcon" import { UniLink } from "../ui/UniLink" import { DashboardSidebar } from "./DashboardSidebar" import { SiteSwitcher } from "./SiteSwitcher" +import { getUserSites } from "~/models/site.model" +import { useAccount } from 'wagmi' +import type { Profile } from "unidata.js" export function DashboardLayout({ children, @@ -21,12 +24,17 @@ export function DashboardLayout({ const router = useRouter() const subdomain = router.query.subdomain as string - const { data: subscriptions } = trpc.useQuery( - ["user.getSubscriptions", { canManage: true }], - {}, - ) + const { data: viewer } = useAccount() - const { data: viewer } = trpc.useQuery(["auth.viewer"]) + let [subscriptions, setSubscriptions] = useState([]) + + useEffect(() => { + if (viewer?.address) { + getUserSites(viewer.address).then((sites) => { + setSubscriptions(sites || []) + }) + } + }, [viewer?.address]) const links: { href: string @@ -76,7 +84,7 @@ export function DashboardLayout({
diff --git a/src/components/dashboard/SiteSwitcher.tsx b/src/components/dashboard/SiteSwitcher.tsx index e53a3c51..f0bdceea 100644 --- a/src/components/dashboard/SiteSwitcher.tsx +++ b/src/components/dashboard/SiteSwitcher.tsx @@ -4,14 +4,12 @@ import { useEffect, useMemo } from "react" import { trpc } from "~/lib/trpc" import { getUserContentsUrl } from "~/lib/user-contents" import { Avatar } from "../ui/Avatar" +import type { Profile } from "unidata.js" type Props = { subdomain: string - subscriptions: { - id: string - site: { id: string; name: string; subdomain: string; icon?: string | null } - }[] - viewer?: { email: string } | null + subscriptions: Profile[] + viewer?: { address?: string } } export const SiteSwitcher: React.FC = ({ @@ -20,33 +18,20 @@ export const SiteSwitcher: React.FC = ({ viewer, }) => { const activeSubscription = subscriptions.find( - (s) => s.site.subdomain === subdomain + (s) => s.username === subdomain ) - const { mutate: updateMembership } = trpc.useMutation( - "membership.updateMembership" - ) - - useEffect(() => { - if (activeSubscription?.id) { - updateMembership({ - id: activeSubscription?.id, - lastSwitchedTo: new Date().toISOString(), - }) - } - }, [activeSubscription?.id, updateMembership]) - return (
- {activeSubscription?.site.name} + {activeSubscription?.name}
@@ -65,21 +50,21 @@ export const SiteSwitcher: React.FC = ({
{viewer && (
- {viewer.email} + {viewer.address?.slice(0, 6)}...{viewer.address?.slice(-4)}
)}
{subscriptions?.map((subscription) => { return ( - {subscription.site.name} + {subscription.name} - {activeSubscription?.id === subscription.id && ( + {activeSubscription?.username === subscription.username && ( ( ): T export function getUserContentsUrl(filename: string | undefined | null) { if (!filename) return undefined - return `${R2_URL}/${filename}` + return filename } diff --git a/src/models/site.model.ts b/src/models/site.model.ts index d13ec762..b33a196d 100644 --- a/src/models/site.model.ts +++ b/src/models/site.model.ts @@ -44,7 +44,7 @@ export const checkSubdomain = async ({ } } -export const getUserLastActiveSite = async (address: string) => { +export const getUserSites = async (address: string) => { if (unidata) { const profiles = await unidata.profiles.get({ source: 'Crossbell Profile', @@ -52,11 +52,11 @@ export const getUserLastActiveSite = async (address: string) => { platform: 'Ethereum', }); - const site = profiles.list?.sort((a: any, b: any) => a.date_updated - b.date_updated)?.[0] + const sites = profiles.list?.sort((a, b) => +new Date(b.date_updated || 0) - +new Date(a.date_updated || 0)) - if (!site) return null + if (!sites || !sites.length) return null - return site + return sites } else { return null } diff --git a/src/pages/dashboard/index.tsx b/src/pages/dashboard/index.tsx index 2e4a1ba6..954c7f80 100644 --- a/src/pages/dashboard/index.tsx +++ b/src/pages/dashboard/index.tsx @@ -1,5 +1,5 @@ import { redirect } from "~/lib/server-side-props" -import { getUserLastActiveSite } from "~/models/site.model" +import { getUserSites } from "~/models/site.model" import { useAccount } from 'wagmi' import { useEffect } from "react" import { useRouter } from 'next/router' @@ -10,16 +10,17 @@ export default function Dashboard() { useEffect(() => { if (wagmiData?.address) { - getUserLastActiveSite(wagmiData.address).then((site) => { - if (!site) { + getUserSites(wagmiData.address).then((sites) => { + if (!sites) { router.push(`/dashboard/new-site`) + } else { + router.push(`/dashboard/${sites[0].username}`) } - router.push(`/dashboard/${site.username}`) }) } else { router.push("/") } - }) + }, [wagmiData?.address, router]) return
Loading...
}