feat: Added top menu
This commit is contained in:
parent
b7c27ddc8a
commit
b7949c38a4
@ -37,11 +37,13 @@ const ensureDecrypted = async (dvm: NDKUser, event: NDKEvent) => {
|
|||||||
return event;
|
return event;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const NPUB_DVM_THUMBNAIL_CREATION = 'npub1q8cv87l47fql2xer2uyw509y5n5s9f53h76hvf9377efdptmsvusxf3n8s';
|
||||||
|
|
||||||
const FileEventEditor = ({ data }: { data: FileEventData }) => {
|
const FileEventEditor = ({ data }: { data: FileEventData }) => {
|
||||||
const [fileEventData, setFileEventData] = useState(data);
|
const [fileEventData, setFileEventData] = useState(data);
|
||||||
const [thumbnailRequestEventId, setThumbnailRequestEventId] = useState<string | undefined>();
|
const [thumbnailRequestEventId, setThumbnailRequestEventId] = useState<string | undefined>();
|
||||||
const { ndk, user } = useNDK();
|
const { ndk, user } = useNDK();
|
||||||
const dvm = ndk.getUser({ npub: 'npub1q8cv87l47fql2xer2uyw509y5n5s9f53h76hvf9377efdptmsvusxf3n8s' });
|
const dvm = ndk.getUser({ npub: NPUB_DVM_THUMBNAIL_CREATION });
|
||||||
|
|
||||||
const thumbnailDvmFilter = useMemo(
|
const thumbnailDvmFilter = useMemo(
|
||||||
() => ({ kinds: [6204 as NDKKind], '#e': [thumbnailRequestEventId || ''] }),
|
() => ({ kinds: [6204 as NDKKind], '#e': [thumbnailRequestEventId || ''] }),
|
||||||
|
@ -6,38 +6,11 @@
|
|||||||
@apply flex flex-col self-center md:w-10/12 w-full min-h-[80vh] px-4 md:px-0;
|
@apply flex flex-col self-center md:w-10/12 w-full min-h-[80vh] px-4 md:px-0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
|
||||||
@apply text-neutral-content text-4xl flex flex-row items-center gap-2 p-4 md:w-10/12 w-full self-center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title img {
|
|
||||||
@apply w-10;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title a.action {
|
|
||||||
@apply flex flex-col text-sm items-center opacity-50 hover:opacity-100 cursor-pointer px-2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title a.logo {
|
|
||||||
@apply flex flex-row flex-grow items-center gap-2 cursor-pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title span {
|
|
||||||
@apply flex-grow;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title svg {
|
|
||||||
@apply w-7;
|
|
||||||
}
|
|
||||||
|
|
||||||
.avatar {
|
|
||||||
@apply flex-shrink;
|
|
||||||
}
|
|
||||||
|
|
||||||
.avatar img {
|
|
||||||
@apply w-10 h-10 rounded-full;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer {
|
.footer {
|
||||||
@apply justify-center gap-1 text-base-content pt-12 pb-6;
|
@apply justify-center gap-1 text-base-content pt-12 pb-6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn svg {
|
||||||
|
@apply w-8;
|
||||||
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Outlet, useNavigate } from 'react-router-dom';
|
import { Outlet, useNavigate } from 'react-router-dom';
|
||||||
import { useNDK } from '../../utils/ndk';
|
import { useNDK } from '../../utils/ndk';
|
||||||
import './Layout.css';
|
import './Layout.css';
|
||||||
import { ArrowUpOnSquareIcon } from '@heroicons/react/24/outline';
|
import { ArrowUpOnSquareIcon, MagnifyingGlassIcon, ServerStackIcon } from '@heroicons/react/24/outline';
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import ThemeSwitcher from '../ThemeSwitcher';
|
import ThemeSwitcher from '../ThemeSwitcher';
|
||||||
|
|
||||||
@ -15,22 +15,36 @@ export const Layout = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="main">
|
<div className="main">
|
||||||
<div className="title">
|
<div className="navbar bg-base-300">
|
||||||
<a className="logo" onClick={() => navigate('/')}>
|
<div className="navbar-start">
|
||||||
<img src="/bouquet.png" /> <span>bouquet</span>
|
<button className="btn btn-ghost text-xl">
|
||||||
</a>
|
<a className="logo" onClick={() => navigate('/')}>
|
||||||
<div>
|
<img className="w-8" src="/bouquet.png" />{' '}
|
||||||
|
</a>
|
||||||
|
<span>bouquet</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="navbar-center">
|
||||||
|
<button className=" btn btn-ghost" onClick={() => navigate('/upload')}>
|
||||||
|
<ArrowUpOnSquareIcon /> Upload
|
||||||
|
</button>
|
||||||
|
<button className=" btn btn-ghost" onClick={() => navigate('/')}>
|
||||||
|
<MagnifyingGlassIcon /> Browse
|
||||||
|
</button>
|
||||||
|
<button className=" btn btn-ghost" onClick={() => navigate('/transfer')}>
|
||||||
|
<ServerStackIcon /> Sync
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="navbar-end">
|
||||||
<ThemeSwitcher />
|
<ThemeSwitcher />
|
||||||
<div className="tooltip tooltip-bottom" data-tip="Upload">
|
<div className="avatar px-4">
|
||||||
<button className=" btn btn-square btn-ghost" onClick={() => navigate('/upload')}>
|
<div className="w-12 rounded-full">
|
||||||
<ArrowUpOnSquareIcon />
|
<img src={user?.profile?.image} />
|
||||||
</button>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="avatar">
|
|
||||||
<img src={user?.profile?.image} />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="content">{<Outlet />}</div>
|
<div className="content">{<Outlet />}</div>
|
||||||
<div className="footer">
|
<div className="footer">
|
||||||
made with 💜 by{' '}
|
made with 💜 by{' '}
|
||||||
|
@ -14,8 +14,8 @@ const ThemeSwitcher = () => {
|
|||||||
<div className="tooltip tooltip-bottom" data-tip="Switch theme">
|
<div className="tooltip tooltip-bottom" data-tip="Switch theme">
|
||||||
<label className="swap swap-rotate">
|
<label className="swap swap-rotate">
|
||||||
<input onClick={toggleTheme} type="checkbox" />
|
<input onClick={toggleTheme} type="checkbox" />
|
||||||
<MoonIcon className="tooltip swap-on" />
|
<MoonIcon className="w-8 tooltip swap-on" />
|
||||||
<SunIcon className="tooltip swap-off" />
|
<SunIcon className="w-8 *:tooltip swap-off" />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -41,6 +41,7 @@ const router = createBrowserRouter(
|
|||||||
<Route element={<Layout />}>
|
<Route element={<Layout />}>
|
||||||
<Route path="/" element={<Home />} />
|
<Route path="/" element={<Home />} />
|
||||||
<Route path="/transfer/:source" element={<Transfer />} />
|
<Route path="/transfer/:source" element={<Transfer />} />
|
||||||
|
<Route path="/transfer" element={<Transfer />} />
|
||||||
<Route path="/upload" element={<Upload />} />
|
<Route path="/upload" element={<Upload />} />
|
||||||
<Route path="/check/:source" element={<Check />} />
|
<Route path="/check/:source" element={<Check />} />
|
||||||
</Route>
|
</Route>
|
||||||
|
@ -27,7 +27,8 @@ type TransferStatus = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const Transfer = () => {
|
export const Transfer = () => {
|
||||||
const { source: transferSource } = useParams();
|
const { source } = useParams();
|
||||||
|
const [transferSource, setTransferSource] = useState(source);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { serverInfo } = useServerInfo();
|
const { serverInfo } = useServerInfo();
|
||||||
const [transferTarget, setTransferTarget] = useState<string | undefined>();
|
const [transferTarget, setTransferTarget] = useState<string | undefined>();
|
||||||
@ -100,88 +101,96 @@ export const Transfer = () => {
|
|||||||
return { ...stats, fullSize: transferJobs?.reduce((acc, b) => acc + b.size, 0) || 0 };
|
return { ...stats, fullSize: transferJobs?.reduce((acc, b) => acc + b.size, 0) || 0 };
|
||||||
}, [transferLog, transferJobs]);
|
}, [transferLog, transferJobs]);
|
||||||
|
|
||||||
return (
|
return transferSource ? (
|
||||||
transferSource && (
|
<>
|
||||||
<>
|
<ServerList
|
||||||
<ServerList
|
servers={Object.values(serverInfo).filter(s => s.name == transferSource)}
|
||||||
servers={Object.values(serverInfo).filter(s => s.name == transferSource)}
|
onCancel={() => closeTransferMode()}
|
||||||
onCancel={() => closeTransferMode()}
|
title={
|
||||||
title={
|
|
||||||
<>
|
|
||||||
<ArrowUpOnSquareIcon /> Transfer Source
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
></ServerList>
|
|
||||||
<ServerList
|
|
||||||
servers={Object.values(serverInfo)
|
|
||||||
.filter(s => s.name != transferSource)
|
|
||||||
.sort()}
|
|
||||||
selectedServer={transferTarget}
|
|
||||||
setSelectedServer={setTransferTarget}
|
|
||||||
title={
|
|
||||||
<>
|
|
||||||
<ArrowDownOnSquareIcon /> Transfer Target
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
></ServerList>
|
|
||||||
{transferTarget && transferJobs && transferJobs.length > 0 ? (
|
|
||||||
<>
|
<>
|
||||||
<div className=" bg-base-200 rounded-xl p-4 text-neutral-content gap-4 flex flex-col my-4">
|
<ArrowUpOnSquareIcon /> Transfer Source
|
||||||
<div className="message">
|
</>
|
||||||
{transferJobs.length} object{transferJobs.length > 1 ? 's' : ''} to transfer{' '}
|
}
|
||||||
{!started && (
|
></ServerList>
|
||||||
<button
|
<ServerList
|
||||||
className="action-button"
|
servers={Object.values(serverInfo)
|
||||||
onClick={() => performTransfer(transferSource, transferTarget, transferJobs)}
|
.filter(s => s.name != transferSource)
|
||||||
>
|
.sort()}
|
||||||
<ArrowUpOnSquareIcon />
|
selectedServer={transferTarget}
|
||||||
Start
|
setSelectedServer={setTransferTarget}
|
||||||
</button>
|
title={
|
||||||
)}
|
<>
|
||||||
</div>
|
<ArrowDownOnSquareIcon /> Transfer Target
|
||||||
<div className="w-5/6">
|
</>
|
||||||
<ProgressBar
|
}
|
||||||
value={transferStatus.size}
|
></ServerList>
|
||||||
max={transferStatus.fullSize}
|
{transferTarget && transferJobs && transferJobs.length > 0 ? (
|
||||||
description={
|
<>
|
||||||
formatFileSize(transferStatus.size) +
|
<div className=" bg-base-200 rounded-xl p-4 text-neutral-content gap-4 flex flex-col my-4">
|
||||||
' / ' +
|
<div className="message">
|
||||||
formatFileSize(transferStatus.fullSize) +
|
{transferJobs.length} object{transferJobs.length > 1 ? 's' : ''} to transfer{' '}
|
||||||
' transferred'
|
{!started && (
|
||||||
}
|
<button
|
||||||
/>
|
className="action-button"
|
||||||
{<div className="message"></div>}
|
onClick={() => performTransfer(transferSource, transferTarget, transferJobs)}
|
||||||
<div className="error-log">
|
>
|
||||||
{Object.values(transferLog)
|
<ArrowUpOnSquareIcon />
|
||||||
.filter(b => b.status == 'error')
|
Start
|
||||||
.map(t => (
|
</button>
|
||||||
<div>
|
)}
|
||||||
<span>
|
</div>
|
||||||
<DocumentIcon />
|
<div className="w-5/6">
|
||||||
</span>
|
<ProgressBar
|
||||||
<span>{t.sha256}</span>
|
value={transferStatus.size}
|
||||||
<span>{formatFileSize(t.size)}</span>
|
max={transferStatus.fullSize}
|
||||||
<span>{t.status && (t.status == 'error' ? <ExclamationTriangleIcon /> : '')}</span>
|
description={
|
||||||
<span>{t.message}</span>
|
formatFileSize(transferStatus.size) + ' / ' + formatFileSize(transferStatus.fullSize) + ' transferred'
|
||||||
</div>
|
}
|
||||||
))}
|
/>
|
||||||
</div>
|
{<div className="message"></div>}
|
||||||
|
<div className="error-log">
|
||||||
|
{Object.values(transferLog)
|
||||||
|
.filter(b => b.status == 'error')
|
||||||
|
.map(t => (
|
||||||
|
<div>
|
||||||
|
<span>
|
||||||
|
<DocumentIcon />
|
||||||
|
</span>
|
||||||
|
<span>{t.sha256}</span>
|
||||||
|
<span>{formatFileSize(t.size)}</span>
|
||||||
|
<span>{t.status && (t.status == 'error' ? <ExclamationTriangleIcon /> : '')}</span>
|
||||||
|
<span>{t.message}</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{!started && <BlobList blobs={transferJobs}></BlobList>}
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<div className="message">
|
|
||||||
{transferTarget ? (
|
|
||||||
<>
|
|
||||||
<CheckBadgeIcon /> no missing objects to transfer
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<>choose a transfer target above</>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
{!started && <BlobList blobs={transferJobs}></BlobList>}
|
||||||
</>
|
</>
|
||||||
)
|
) : (
|
||||||
|
<div className="message">
|
||||||
|
{transferTarget ? (
|
||||||
|
<>
|
||||||
|
<CheckBadgeIcon /> no missing objects to transfer
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>choose a transfer target above</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<ServerList
|
||||||
|
title={
|
||||||
|
<>
|
||||||
|
<ArrowUpOnSquareIcon /> Transfer Source
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
servers={Object.values(serverInfo).sort()}
|
||||||
|
selectedServer={transferSource}
|
||||||
|
setSelectedServer={s => setTransferSource(s)}
|
||||||
|
></ServerList>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user