mirror of
https://git.v0l.io/florian/bouquet.git
synced 2025-03-18 01:13:00 +01:00
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;
|
||||
};
|
||||
|
||||
const NPUB_DVM_THUMBNAIL_CREATION = 'npub1q8cv87l47fql2xer2uyw509y5n5s9f53h76hvf9377efdptmsvusxf3n8s';
|
||||
|
||||
const FileEventEditor = ({ data }: { data: FileEventData }) => {
|
||||
const [fileEventData, setFileEventData] = useState(data);
|
||||
const [thumbnailRequestEventId, setThumbnailRequestEventId] = useState<string | undefined>();
|
||||
const { ndk, user } = useNDK();
|
||||
const dvm = ndk.getUser({ npub: 'npub1q8cv87l47fql2xer2uyw509y5n5s9f53h76hvf9377efdptmsvusxf3n8s' });
|
||||
const dvm = ndk.getUser({ npub: NPUB_DVM_THUMBNAIL_CREATION });
|
||||
|
||||
const thumbnailDvmFilter = useMemo(
|
||||
() => ({ 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;
|
||||
}
|
||||
|
||||
.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 {
|
||||
@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 { useNDK } from '../../utils/ndk';
|
||||
import './Layout.css';
|
||||
import { ArrowUpOnSquareIcon } from '@heroicons/react/24/outline';
|
||||
import { ArrowUpOnSquareIcon, MagnifyingGlassIcon, ServerStackIcon } from '@heroicons/react/24/outline';
|
||||
import { useEffect } from 'react';
|
||||
import ThemeSwitcher from '../ThemeSwitcher';
|
||||
|
||||
@ -15,22 +15,36 @@ export const Layout = () => {
|
||||
|
||||
return (
|
||||
<div className="main">
|
||||
<div className="title">
|
||||
<a className="logo" onClick={() => navigate('/')}>
|
||||
<img src="/bouquet.png" /> <span>bouquet</span>
|
||||
</a>
|
||||
<div>
|
||||
<div className="navbar bg-base-300">
|
||||
<div className="navbar-start">
|
||||
<button className="btn btn-ghost text-xl">
|
||||
<a className="logo" onClick={() => navigate('/')}>
|
||||
<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 />
|
||||
<div className="tooltip tooltip-bottom" data-tip="Upload">
|
||||
<button className=" btn btn-square btn-ghost" onClick={() => navigate('/upload')}>
|
||||
<ArrowUpOnSquareIcon />
|
||||
</button>
|
||||
<div className="avatar px-4">
|
||||
<div className="w-12 rounded-full">
|
||||
<img src={user?.profile?.image} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="avatar">
|
||||
<img src={user?.profile?.image} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="content">{<Outlet />}</div>
|
||||
<div className="footer">
|
||||
made with 💜 by{' '}
|
||||
|
@ -14,8 +14,8 @@ const ThemeSwitcher = () => {
|
||||
<div className="tooltip tooltip-bottom" data-tip="Switch theme">
|
||||
<label className="swap swap-rotate">
|
||||
<input onClick={toggleTheme} type="checkbox" />
|
||||
<MoonIcon className="tooltip swap-on" />
|
||||
<SunIcon className="tooltip swap-off" />
|
||||
<MoonIcon className="w-8 tooltip swap-on" />
|
||||
<SunIcon className="w-8 *:tooltip swap-off" />
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
|
@ -41,6 +41,7 @@ const router = createBrowserRouter(
|
||||
<Route element={<Layout />}>
|
||||
<Route path="/" element={<Home />} />
|
||||
<Route path="/transfer/:source" element={<Transfer />} />
|
||||
<Route path="/transfer" element={<Transfer />} />
|
||||
<Route path="/upload" element={<Upload />} />
|
||||
<Route path="/check/:source" element={<Check />} />
|
||||
</Route>
|
||||
|
@ -27,7 +27,8 @@ type TransferStatus = {
|
||||
};
|
||||
|
||||
export const Transfer = () => {
|
||||
const { source: transferSource } = useParams();
|
||||
const { source } = useParams();
|
||||
const [transferSource, setTransferSource] = useState(source);
|
||||
const navigate = useNavigate();
|
||||
const { serverInfo } = useServerInfo();
|
||||
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 };
|
||||
}, [transferLog, transferJobs]);
|
||||
|
||||
return (
|
||||
transferSource && (
|
||||
<>
|
||||
<ServerList
|
||||
servers={Object.values(serverInfo).filter(s => s.name == transferSource)}
|
||||
onCancel={() => closeTransferMode()}
|
||||
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 ? (
|
||||
return transferSource ? (
|
||||
<>
|
||||
<ServerList
|
||||
servers={Object.values(serverInfo).filter(s => s.name == transferSource)}
|
||||
onCancel={() => closeTransferMode()}
|
||||
title={
|
||||
<>
|
||||
<div className=" bg-base-200 rounded-xl p-4 text-neutral-content gap-4 flex flex-col my-4">
|
||||
<div className="message">
|
||||
{transferJobs.length} object{transferJobs.length > 1 ? 's' : ''} to transfer{' '}
|
||||
{!started && (
|
||||
<button
|
||||
className="action-button"
|
||||
onClick={() => performTransfer(transferSource, transferTarget, transferJobs)}
|
||||
>
|
||||
<ArrowUpOnSquareIcon />
|
||||
Start
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
<div className="w-5/6">
|
||||
<ProgressBar
|
||||
value={transferStatus.size}
|
||||
max={transferStatus.fullSize}
|
||||
description={
|
||||
formatFileSize(transferStatus.size) +
|
||||
' / ' +
|
||||
formatFileSize(transferStatus.fullSize) +
|
||||
' transferred'
|
||||
}
|
||||
/>
|
||||
{<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>
|
||||
<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">
|
||||
<div className="message">
|
||||
{transferJobs.length} object{transferJobs.length > 1 ? 's' : ''} to transfer{' '}
|
||||
{!started && (
|
||||
<button
|
||||
className="action-button"
|
||||
onClick={() => performTransfer(transferSource, transferTarget, transferJobs)}
|
||||
>
|
||||
<ArrowUpOnSquareIcon />
|
||||
Start
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
<div className="w-5/6">
|
||||
<ProgressBar
|
||||
value={transferStatus.size}
|
||||
max={transferStatus.fullSize}
|
||||
description={
|
||||
formatFileSize(transferStatus.size) + ' / ' + formatFileSize(transferStatus.fullSize) + ' transferred'
|
||||
}
|
||||
/>
|
||||
{<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>
|
||||
{!started && <BlobList blobs={transferJobs}></BlobList>}
|
||||
</>
|
||||
) : (
|
||||
<div className="message">
|
||||
{transferTarget ? (
|
||||
<>
|
||||
<CheckBadgeIcon /> no missing objects to transfer
|
||||
</>
|
||||
) : (
|
||||
<>choose a transfer target above</>
|
||||
)}
|
||||
</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…
x
Reference in New Issue
Block a user