Skip to content

Commit

Permalink
feat: add space route (#10)
Browse files Browse the repository at this point in the history
adds an nextjs app route for `/space` that lets the user see all their
spaces and drill down.

aiming at making the info architecture of console more obvious so folks
dont have to think to hard about the spaces -> space -> upload item flow

the dream:

```

* My first space (active)
  did:key:z6Mkv8gU6CYtiKGjLwTjyfzTQGfrog9VaxQYSqWNWD7x8svz

  best gifs
  did:key:zOtherone

  work junk
  did:key:zOtherOtherone

(above is hidden once space is chosen an can be re-opened)

* My first space
  did:key:z6Mkv8gU6CYtiKGjLwTjyfzTQGfrog9VaxQYSqWNWD7x8svz

list | share | upload
----

show cid + type (e.g dag-pb, dag-json, dag-cbor, raw... not super helpful, but)
 - bafyx <--- click me
 - bafyy
 - bafyz

Root CID: bafyx
CAR Shards:
 - bagy1 (size in MiB)
 - bagy2 (size in MiB)

Open on http gateway | Delete | etc

```

THE MANIFESTATION:

Spaces --> Space --> Item flow is go! Sub navs are go.


![spaces](https://github.com/web3-storage/console/assets/58871/778a0734-0ee8-47a6-bfda-c409a1d71b49)

it still needs a proper navigation method for going back the spaces
list, and in general the UI needs tightening up, but the bones are in
places.

License: MIT

---------

Signed-off-by: Oli Evans <[email protected]>
  • Loading branch information
olizilla authored Oct 26, 2023
1 parent 056debe commit eeb11c6
Show file tree
Hide file tree
Showing 18 changed files with 394 additions and 135 deletions.
6 changes: 5 additions & 1 deletion src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
@tailwind utilities;

.w3ui-button {
@apply text-white bg-slate-800 hover:bg-blue-800 rounded-md py-2 px-8 text-sm font-medium transition-colors ease-in;
@apply text-white bg-slate-800 hover:bg-blue-800 rounded-sm py-2 px-8 text-sm font-medium transition-colors ease-in;
}

.w3ui-button.active {
@apply bg-transparent;
}

.authenticator {
Expand Down
5 changes: 5 additions & 0 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import SidebarLayout from '@/components/SidebarLayout'
import './globals.css'
import type { Metadata } from 'next'
import { H2 } from '@/components/Text'
import Link from 'next/link'

export const metadata: Metadata = {
title: 'w3up console',
Expand All @@ -16,6 +18,9 @@ export default function RootLayout ({
<html lang="en">
<body className='bg-gray-dark min-h-screen'>
<SidebarLayout>
<H2 explain='a decentralised bucket identified by a DID'>
<Link href='/'>Space</Link>
</H2>
{children}
</SidebarLayout>
</body>
Expand Down
42 changes: 29 additions & 13 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,39 @@
'use client'

import { useState } from 'react'
import { DIDKey } from '@ucanto/interface'
import { useKeyring } from '@w3ui/react-keyring'
import { useKeyring, Space } from '@w3ui/react-keyring'
import { DidIcon } from '@/components/DidIcon'
import Link from 'next/link'
import { SpacesNav } from './space/layout'

import { SpaceSection } from '../components/SpaceSection'
export default function SpacePage (): JSX.Element {
const [{ spaces }] = useKeyring()

export default function Home (): JSX.Element {
const [share, setShare] = useState(false)
const [, { setCurrentSpace }] = useKeyring()

function viewSpace (did: DIDKey): void {
setShare(false)
void setCurrentSpace(did)
if (spaces.length === 0) {
return <div></div>
}

return (
<SpaceSection viewSpace={viewSpace} share={share} setShare={setShare} />
<>
<SpacesNav />
<div className='max-w-lg mt-8'>
{ spaces.map(s => <Item space={s} key={s.did()} /> ) }
</div>
</>
)
}


function Item ({space}: {space: Space}) {
return (
<Link href={`/space/${space.did()}`} className='flex flex-row items-start gap-2 p-2 text-left hover:bg-gray-800'>
<DidIcon did={space.did()} />
<div className='grow overflow-hidden whitespace-nowrap text-ellipsis text-gray-500'>
<span className='text-lg font-semibold leading-5 text-white m-0'>
{space.name() ?? 'Untitled'}
</span>
<span className='font-mono text-xs block'>
{space.did()}
</span>
</div>
</Link>
)
}
66 changes: 66 additions & 0 deletions src/app/space/[did]/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
'use client'

import { PropsWithChildren } from 'react'
import { DIDKey } from '@ucanto/interface'
import { useKeyring } from '@w3ui/react-keyring'
import { DidIcon } from '@/components/DidIcon'
import Link from 'next/link'
import { Nav, NavLink } from '@/components/Nav'

interface LayoutProps extends PropsWithChildren {
params: {
did: string
}
}

export default function Layout ({children, params}: LayoutProps): JSX.Element {
const [{ space }, { setCurrentSpace }] = useKeyring()

if (!params.did) {
return <h1>NO SPACE?</h1>
}

const did = decodeDidKey(params.did)

if (space && space?.did() !== did) {
setCurrentSpace(did)
return <div></div>
}

if (!space) {
return <div></div>
}

return (
<section>
<header className='py-3'>
<div className='flex flex-row items-start gap-2'>
<DidIcon did={space.did()} />
<div className='grow overflow-hidden whitespace-nowrap text-ellipsis text-gray-500'>
<h1 className='text-lg font-semibold leading-5 text-white'>
{space.name() ?? 'Untitled'}
</h1>
<label className='font-mono text-xs'>
{space.did()}
</label>
</div>
</div>
</header>
<Nav className='mb-8'>
<NavLink href={`/space/${space.did()}`}>List</NavLink>
<NavLink href={`/space/${space.did()}/share`}>Share</NavLink>
<NavLink href={`/space/${space.did()}/upload`}>Upload</NavLink>
</Nav>
<div className='max-w-7xl'>
{children}
</div>
</section>
)
}

function decodeDidKey (str: string): DIDKey | undefined {
if (!str) return
const did = decodeURIComponent(str)
if (!did.startsWith('did:key:')) return
return did as DIDKey
}
9 changes: 9 additions & 0 deletions src/app/space/[did]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
'use client'

import { UploadsList } from '@/components/UploadsList'

export default function Home (): JSX.Element {
return (
<UploadsList />
)
}
42 changes: 42 additions & 0 deletions src/app/space/[did]/root/[cid]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
'use client'

import { H2 } from "@/components/Text"
import { useUploadsList } from "@w3ui/react-uploads-list"

interface PageProps {
params: {
cid: string
}
}

export default function ItemPage ({ params: { cid }}: PageProps): JSX.Element {
const [{ data }] = useUploadsList()
if (data.length === 0) {
return <div></div>
}
const item = data?.find(x => x.root.toString() === cid)
if (!item) {
return <h1>Not Found</h1>
}
const url = `https://${item.root.toString()}.ipfs.w3s.link`
return (
<div>
<H2>Root CID</H2>
<div className="pb-5 font-mono text-sm overflow-hidden no-wrap text-ellipsis">
{ item.root.toString() }
</div>
<H2>URL</H2>
<div className="pb-5">
<a href={url} className="font-mono text-sm text-blue-400 m-0 p-0 block">{url}</a>
</div>
<H2>Shards</H2>
<div className=''>
{ item.shards?.map(link => <Shard cid={link.toString()} key={link.toString()} />) }
</div>
</div>
)
}

function Shard ({ cid }: { cid: string}) {
return <div className="font-mono text-sm overflow-hidden no-wrap text-ellipsis">{cid}</div>
}
9 changes: 9 additions & 0 deletions src/app/space/[did]/share/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
'use client'

import { ShareSpace } from '@/share'

export default function SharePage (): JSX.Element {
return (
<ShareSpace />
)
}
11 changes: 11 additions & 0 deletions src/app/space/[did]/upload/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
'use client'

import { Uploader } from '@/components/Uploader'
import { useUploadsList } from '@w3ui/react-uploads-list'

export default function UploadPage (): JSX.Element {
const [, { reload }] = useUploadsList()
return (
<Uploader onUploadComplete={reload} />
)
}
15 changes: 15 additions & 0 deletions src/app/space/create/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
'use client'

import { SpaceCreatorForm } from '@/components/SpaceCreator'
import { SpacesNav } from '../layout'

export default function CreateSpacePage (): JSX.Element {
return (
<>
<SpacesNav />
<div className='max-w-xl'>
<SpaceCreatorForm />
</div>
</>
)
}
13 changes: 13 additions & 0 deletions src/app/space/import/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
'use client'

import { ImportSpace } from '@/share'
import { SpacesNav } from '../layout'

export default function ImportPage (): JSX.Element {
return (
<>
<SpacesNav />
<ImportSpace />
</>
)
}
39 changes: 39 additions & 0 deletions src/app/space/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { PropsWithChildren } from 'react'
import { H2 } from '@/components/Text'
import Link from 'next/link'
import { Nav, NavLink } from '@/components/Nav'

export const runtime = 'edge'

interface LayoutProps extends PropsWithChildren {
params: {
did: string
}
}

export default function Layout ({children}: LayoutProps): JSX.Element {
return (
<section>
{children}
</section>
)
}



export function SpacesNav () {
return (
<>
{/* <div style={{minHeight: 68}}>
<p className='font-normal pt-4'>
Pick a space to see what's in it, or create a new one.
</p>
</div> */}
<Nav className='mb-8'>
<NavLink href='/'>List</NavLink>
<NavLink href='/space/import'>Import</NavLink>
<NavLink href='/space/create'>Create</NavLink>
</Nav>
</>
)
}
7 changes: 7 additions & 0 deletions src/components/BackIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export default function BackIcon () {
return (
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="w-6 h-6">
<path strokeLinecap="round" strokeLinejoin="round" d="M9 15L3 9m0 0l6-6M3 9h12a6 6 0 010 12h-3" />
</svg>
)
}
26 changes: 26 additions & 0 deletions src/components/Nav.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
'use client'

import { PropsWithChildren } from "react"
import { usePathname } from "next/navigation"
import Link from "next/link"

export function Nav ({ children, ...rest}: PropsWithChildren & { className?: string }) {
return (
<nav {...rest}>
<ul className="flex max-w-lg pt-4">
{children}
</ul>
</nav>
)
}

export function NavLink ({ href, children }: PropsWithChildren & { href: string }) {
const pathname = usePathname()
const active = href === pathname ? 'active' : ''
const cls = `w3ui-button inline-block ${active}`
return (
<li className="mr-3">
<Link className={cls} href={href}>{children}</Link>
</li>
)
}
10 changes: 3 additions & 7 deletions src/components/SpaceCreator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,24 +59,20 @@ export function SpaceCreatorForm ({
)
: (
<form
className='flex flex-col space-y-2'
className=''
onSubmit={(e: React.FormEvent<HTMLFormElement>) => {
void onSubmit(e)
}}
>
<input
className='text-black py-1 px-2 rounded'
className='text-black py-1 px-2 rounded block w-full mb-4'
placeholder='Name'
value={name}
onChange={(e: ChangeEvent<HTMLInputElement>) => {
setName(e.target.value)
}}
/>
<input
type='submit'
className='w3ui-button'
value='Create'
/>
<button type='submit' className='w3ui-button'>Create</button>
</form>
)
}
Expand Down
Loading

0 comments on commit eeb11c6

Please sign in to comment.