mirror of
https://github.com/diced/zipline.git
synced 2026-04-28 10:43:06 -07:00
fix: a bunch of small fixes & bug squashing
This commit is contained in:
@@ -17,6 +17,7 @@ import {
|
||||
Pill,
|
||||
PillsInput,
|
||||
SimpleGrid,
|
||||
Stack,
|
||||
Title,
|
||||
Tooltip,
|
||||
useCombobox,
|
||||
@@ -179,9 +180,16 @@ export default function FileModal({
|
||||
opened={open}
|
||||
onClose={() => setOpen(false)}
|
||||
title={
|
||||
<Title order={3} fw={700}>
|
||||
{file?.name ?? ''}
|
||||
</Title>
|
||||
<Stack gap={1}>
|
||||
<Title order={3} fw={700}>
|
||||
{file?.name ?? ''}
|
||||
</Title>
|
||||
{!reduce && (
|
||||
<Title fw='normal' order={4} c='dimmed' size={14}>
|
||||
{file?.id}
|
||||
</Title>
|
||||
)}
|
||||
</Stack>
|
||||
}
|
||||
size='auto'
|
||||
centered
|
||||
@@ -225,60 +233,62 @@ export default function FileModal({
|
||||
)}
|
||||
</SimpleGrid>
|
||||
|
||||
<>
|
||||
<Title order={4} mt='lg' mb='xs'>
|
||||
Tags
|
||||
</Title>
|
||||
<Combobox store={tagsCombobox} onOptionSubmit={handleValueSelect} withinPortal={false}>
|
||||
<Combobox.DropdownTarget>
|
||||
<PillsInput
|
||||
onBlur={() => triggerSave()}
|
||||
pointer
|
||||
onClick={() => tagsCombobox.toggleDropdown()}
|
||||
>
|
||||
<Pill.Group>
|
||||
{values.length > 0 ? (
|
||||
values
|
||||
) : (
|
||||
<Input.Placeholder>Pick one or more tags</Input.Placeholder>
|
||||
)}
|
||||
{!reduce && (
|
||||
<>
|
||||
<Title order={4} mt='lg' mb='xs'>
|
||||
Tags
|
||||
</Title>
|
||||
<Combobox store={tagsCombobox} onOptionSubmit={handleValueSelect} withinPortal={false}>
|
||||
<Combobox.DropdownTarget>
|
||||
<PillsInput
|
||||
onBlur={() => triggerSave()}
|
||||
pointer
|
||||
onClick={() => tagsCombobox.toggleDropdown()}
|
||||
>
|
||||
<Pill.Group>
|
||||
{values.length > 0 ? (
|
||||
values
|
||||
) : (
|
||||
<Input.Placeholder>Pick one or more tags</Input.Placeholder>
|
||||
)}
|
||||
|
||||
<Combobox.EventsTarget>
|
||||
<PillsInput.Field
|
||||
type='hidden'
|
||||
onBlur={() => tagsCombobox.closeDropdown()}
|
||||
onKeyDown={(event) => {
|
||||
if (event.key === 'Backspace') {
|
||||
event.preventDefault();
|
||||
handleValueRemove(value[value.length - 1]);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</Combobox.EventsTarget>
|
||||
</Pill.Group>
|
||||
</PillsInput>
|
||||
</Combobox.DropdownTarget>
|
||||
|
||||
<Combobox.Dropdown>
|
||||
<Combobox.Options>
|
||||
{tags?.map((tag) => (
|
||||
<Combobox.Option value={tag.id} key={tag.id} active={value.includes(tag.id)}>
|
||||
<Group gap='sm'>
|
||||
<Checkbox
|
||||
checked={value.includes(tag.id)}
|
||||
onChange={() => {}}
|
||||
aria-hidden
|
||||
tabIndex={-1}
|
||||
style={{ pointerEvents: 'none' }}
|
||||
<Combobox.EventsTarget>
|
||||
<PillsInput.Field
|
||||
type='hidden'
|
||||
onBlur={() => tagsCombobox.closeDropdown()}
|
||||
onKeyDown={(event) => {
|
||||
if (event.key === 'Backspace') {
|
||||
event.preventDefault();
|
||||
handleValueRemove(value[value.length - 1]);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<TagPill tag={tag} />
|
||||
</Group>
|
||||
</Combobox.Option>
|
||||
))}
|
||||
</Combobox.Options>
|
||||
</Combobox.Dropdown>
|
||||
</Combobox>
|
||||
</>
|
||||
</Combobox.EventsTarget>
|
||||
</Pill.Group>
|
||||
</PillsInput>
|
||||
</Combobox.DropdownTarget>
|
||||
|
||||
<Combobox.Dropdown>
|
||||
<Combobox.Options>
|
||||
{tags?.map((tag) => (
|
||||
<Combobox.Option value={tag.id} key={tag.id} active={value.includes(tag.id)}>
|
||||
<Group gap='sm'>
|
||||
<Checkbox
|
||||
checked={value.includes(tag.id)}
|
||||
onChange={() => {}}
|
||||
aria-hidden
|
||||
tabIndex={-1}
|
||||
style={{ pointerEvents: 'none' }}
|
||||
/>
|
||||
<TagPill tag={tag} />
|
||||
</Group>
|
||||
</Combobox.Option>
|
||||
))}
|
||||
</Combobox.Options>
|
||||
</Combobox.Dropdown>
|
||||
</Combobox>
|
||||
</>
|
||||
)}
|
||||
|
||||
<Group justify='space-between' mt='lg'>
|
||||
<Group>
|
||||
|
||||
@@ -62,6 +62,7 @@ export async function bulkDelete(ids: string[], setSelectedFiles: (files: File[]
|
||||
icon: <IconTrashFilled size='1rem' />,
|
||||
id: 'bulk-delete',
|
||||
autoClose: true,
|
||||
loading: false,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import GridTableSwitcher from '@/components/GridTableSwitcher';
|
||||
import { useViewStore } from '@/lib/store/view';
|
||||
import { Group, Title } from '@mantine/core';
|
||||
import { ActionIcon, Group, Title, Tooltip } from '@mantine/core';
|
||||
import FavoriteFiles from './views/FavoriteFiles';
|
||||
import FileTable from './views/FileTable';
|
||||
import Files from './views/Files';
|
||||
import TagsButton from './tags/TagsButton';
|
||||
import PendingFilesButton from './PendingFilesButton';
|
||||
import Link from 'next/link';
|
||||
import { IconFileUpload } from '@tabler/icons-react';
|
||||
|
||||
export default function DashbaordFiles() {
|
||||
const view = useViewStore((state) => state.files);
|
||||
@@ -15,6 +17,14 @@ export default function DashbaordFiles() {
|
||||
<Group>
|
||||
<Title>Files</Title>
|
||||
|
||||
<Tooltip label='Upload a file'>
|
||||
<Link href='/dashboard/upload/file'>
|
||||
<ActionIcon variant='outline'>
|
||||
<IconFileUpload size='1rem' />
|
||||
</ActionIcon>
|
||||
</Link>
|
||||
</Tooltip>
|
||||
|
||||
<TagsButton />
|
||||
<PendingFilesButton />
|
||||
|
||||
|
||||
@@ -431,7 +431,7 @@ export default function FileTable({ id }: { id?: string }) {
|
||||
{
|
||||
accessor: 'favorite',
|
||||
sortable: true,
|
||||
render: (file) => (file.favorite ? 'Yes' : 'No'),
|
||||
render: (file) => (file.favorite ? <Text c='yellow'>Yes</Text> : 'No'),
|
||||
},
|
||||
{
|
||||
accessor: 'actions',
|
||||
|
||||
@@ -16,7 +16,7 @@ export default function FolderTableView() {
|
||||
const { data, isLoading } = useSWR<Extract<Response['/api/user/folders'], Folder[]>>('/api/user/folders');
|
||||
|
||||
const [sortStatus, setSortStatus] = useState<DataTableSortStatus>({
|
||||
columnAccessor: 'createdAt',
|
||||
columnAccessor: 'updatedAt',
|
||||
direction: 'desc',
|
||||
});
|
||||
const [sorted, setSorted] = useState<Folder[]>(data ?? []);
|
||||
@@ -97,6 +97,7 @@ export default function FolderTableView() {
|
||||
e.stopPropagation();
|
||||
copyFolderUrl(folder, clipboard);
|
||||
}}
|
||||
disabled={!folder.public}
|
||||
>
|
||||
<IconCopy size='1rem' />
|
||||
</ActionIcon>
|
||||
|
||||
@@ -103,6 +103,8 @@ export default function SettingsFileView() {
|
||||
description='Change the content within view-routes. Most HTML is valid, while the use of JavaScript is unavailable.'
|
||||
disabled={!form.values.enabled}
|
||||
mb='xs'
|
||||
minRows={5}
|
||||
autosize
|
||||
{...form.getInputProps('content')}
|
||||
/>
|
||||
|
||||
|
||||
@@ -11,9 +11,9 @@ export function flameshot(token: string, type: 'file' | 'url', options: Generato
|
||||
|
||||
if (type === 'file') {
|
||||
curl.push('-F', 'file=@/tmp/screenshot.png');
|
||||
curl.push('-H', 'content-type: multipart/form-data');
|
||||
curl.push('-H', "'content-type: multipart/form-data'");
|
||||
} else {
|
||||
curl.push('-H', 'content-type: application/json');
|
||||
curl.push('-H', "'content-type: application/json'");
|
||||
}
|
||||
|
||||
const toAddHeaders: UploadHeaders = {};
|
||||
|
||||
@@ -11,9 +11,9 @@ export function shell(token: string, type: 'file' | 'url', options: GeneratorOpt
|
||||
|
||||
if (type === 'file') {
|
||||
curl.push('-F', 'file=@/tmp/screenshot.png');
|
||||
curl.push('-H', 'content-type: multipart/form-data');
|
||||
curl.push('-H', "'content-type: multipart/form-data'");
|
||||
} else {
|
||||
curl.push('-H', 'content-type: application/json');
|
||||
curl.push('-H', "'content-type: application/json'");
|
||||
}
|
||||
|
||||
const toAddHeaders: UploadHeaders = {};
|
||||
|
||||
@@ -1,9 +1,30 @@
|
||||
import DashboardFileType from '@/components/file/DashboardFileType';
|
||||
import { bytes } from '@/lib/bytes';
|
||||
import { Button, Center, Group, HoverCard, Paper, Stack, Text } from '@mantine/core';
|
||||
import { Button, Center, Group, HoverCard, Overlay, Paper, Stack, Text } from '@mantine/core';
|
||||
import { IconFileUpload, IconTrashFilled } from '@tabler/icons-react';
|
||||
|
||||
export default function ToUploadFile({ file, onDelete }: { file: File; onDelete: () => void }) {
|
||||
export default function ToUploadFile({
|
||||
file,
|
||||
onDelete,
|
||||
loading,
|
||||
}: {
|
||||
loading: boolean;
|
||||
file: File;
|
||||
onDelete: () => void;
|
||||
}) {
|
||||
if (loading)
|
||||
return (
|
||||
<Paper withBorder p='md' radius='md' pos='relative'>
|
||||
<Overlay radius='md' backgroundOpacity={0.2} />
|
||||
<Center h='100%'>
|
||||
<Group justify='center' gap='xl'>
|
||||
<IconFileUpload size={48} />
|
||||
<Text size='md'>{file.name}</Text>
|
||||
</Group>
|
||||
</Center>
|
||||
</Paper>
|
||||
);
|
||||
|
||||
return (
|
||||
<HoverCard shadow='md' position='top'>
|
||||
<HoverCard.Target>
|
||||
@@ -17,7 +38,7 @@ export default function ToUploadFile({ file, onDelete }: { file: File; onDelete:
|
||||
</Paper>
|
||||
</HoverCard.Target>
|
||||
<HoverCard.Dropdown>
|
||||
<Group>
|
||||
<Group maw={400}>
|
||||
<DashboardFileType file={file} show />
|
||||
<Stack justify='xs'>
|
||||
<Text size='sm' c='dimmed'>
|
||||
|
||||
@@ -179,7 +179,7 @@ export default function UploadFile() {
|
||||
|
||||
<Collapse in={progress === 100}>
|
||||
<Paper withBorder p='xs' radius='sm'>
|
||||
<Text ta='center' size='sm' color='yellow'>
|
||||
<Text ta='center' size='sm' c='yellow'>
|
||||
Finalizing upload(s)...
|
||||
</Text>
|
||||
</Paper>
|
||||
@@ -188,7 +188,11 @@ export default function UploadFile() {
|
||||
<Grid grow my='sm'>
|
||||
{files.map((file, i) => (
|
||||
<Grid.Col span={3} key={i}>
|
||||
<ToUploadFile file={file} onDelete={() => setFiles(files.filter((_, j) => i !== j))} />
|
||||
<ToUploadFile
|
||||
loading={dropLoading}
|
||||
file={file}
|
||||
onDelete={() => setFiles(files.filter((_, j) => i !== j))}
|
||||
/>
|
||||
</Grid.Col>
|
||||
))}
|
||||
</Grid>
|
||||
|
||||
@@ -191,7 +191,7 @@ export default function UrlTableView() {
|
||||
{
|
||||
accessor: 'vanity',
|
||||
sortable: true,
|
||||
render: (url) => url.vanity ?? <b>None</b>,
|
||||
render: (url) => url.vanity ?? '',
|
||||
filter: (
|
||||
<SearchFilter
|
||||
setSearchField={setSearchField}
|
||||
@@ -227,7 +227,7 @@ export default function UrlTableView() {
|
||||
{
|
||||
accessor: 'maxViews',
|
||||
sortable: true,
|
||||
render: (url) => (url.maxViews ? url.maxViews : <b>None</b>),
|
||||
render: (url) => (url.maxViews ? url.maxViews : ''),
|
||||
},
|
||||
{
|
||||
accessor: 'createdAt',
|
||||
|
||||
@@ -34,7 +34,7 @@ export async function handlePartialUpload({
|
||||
const extension = options.overrides?.extension ?? extname(options.partial.filename);
|
||||
if (config.files.disabledExtensions.includes(extension)) throw `File extension ${extension} is not allowed`;
|
||||
|
||||
let fileName = formatFileName(options.format || config.files.defaultFormat, file.filename);
|
||||
let fileName = formatFileName(options.format || config.files.defaultFormat, options.partial.filename);
|
||||
if (options.overrides?.filename) {
|
||||
fileName = options.overrides!.filename!;
|
||||
const existing = await prisma.file.findFirst({
|
||||
|
||||
@@ -45,6 +45,7 @@ export const getServerSideProps = withSafeConfig<{
|
||||
select: {
|
||||
...fileSelect,
|
||||
password: true,
|
||||
tags: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -30,7 +30,7 @@ import { GetServerSideProps, InferGetServerSidePropsType } from 'next';
|
||||
import Head from 'next/head';
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useState } from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
export default function ViewFile({
|
||||
file,
|
||||
@@ -162,6 +162,9 @@ export default function ViewFile({
|
||||
</Head>
|
||||
);
|
||||
|
||||
const [mounted, setMounted] = useState(false);
|
||||
useEffect(() => setMounted(true), []);
|
||||
|
||||
return password && !pw ? (
|
||||
<Modal
|
||||
onClose={() => {}}
|
||||
@@ -204,7 +207,7 @@ export default function ViewFile({
|
||||
|
||||
<Collapse in={detailsOpen}>
|
||||
<Paper m='md' p='md' withBorder>
|
||||
{user?.view.content && (
|
||||
{mounted && user?.view.content && (
|
||||
<TypographyStylesProvider>
|
||||
<Text
|
||||
ta={user?.view.align ?? 'left'}
|
||||
@@ -240,15 +243,16 @@ export default function ViewFile({
|
||||
<Center h='100%'>
|
||||
<Paper m='md' p='md' shadow='md' radius='md' withBorder>
|
||||
<Group justify='space-between' mb='sm'>
|
||||
<Text size='lg' fw={700} display='flex'>
|
||||
{file.name}
|
||||
|
||||
<Group>
|
||||
<Text size='lg' fw={700} display='flex'>
|
||||
{file.name}
|
||||
</Text>
|
||||
{user?.view.showMimetype && (
|
||||
<Text size='sm' c='dimmed' ml='sm' style={{ alignSelf: 'center' }}>
|
||||
{file.type}
|
||||
</Text>
|
||||
)}
|
||||
</Text>
|
||||
</Group>
|
||||
|
||||
<Button
|
||||
ml='sm'
|
||||
@@ -265,7 +269,7 @@ export default function ViewFile({
|
||||
|
||||
<DashboardFileType file={file} password={pw} show />
|
||||
|
||||
{user?.view.content && (
|
||||
{mounted && user?.view.content && (
|
||||
<TypographyStylesProvider>
|
||||
<Text
|
||||
mt='sm'
|
||||
|
||||
@@ -51,9 +51,13 @@ export default fastifyPlugin(
|
||||
.type(file?.type || 'application/octet-stream')
|
||||
.headers({
|
||||
'Content-Length': size,
|
||||
...(file?.originalName && {
|
||||
'Content-Disposition': `${download ? 'attachment; ' : ''}filename="${file.originalName}"`,
|
||||
}),
|
||||
...(file?.originalName
|
||||
? {
|
||||
'Content-Disposition': `${download ? 'attachment; ' : ''}filename="${file.originalName}"`,
|
||||
}
|
||||
: download && {
|
||||
'Content-Disposition': 'attachment;',
|
||||
}),
|
||||
})
|
||||
.status(416)
|
||||
.send(buf);
|
||||
@@ -68,9 +72,13 @@ export default fastifyPlugin(
|
||||
'Content-Range': `bytes ${start}-${end}/${size}`,
|
||||
'Accept-Ranges': 'bytes',
|
||||
'Content-Length': end - start + 1,
|
||||
...(file?.originalName && {
|
||||
'Content-Disposition': `${download ? 'attachment; ' : ''}filename="${file.originalName}"`,
|
||||
}),
|
||||
...(file?.originalName
|
||||
? {
|
||||
'Content-Disposition': `${download ? 'attachment; ' : ''}filename="${file.originalName}"`,
|
||||
}
|
||||
: download && {
|
||||
'Content-Disposition': 'attachment;',
|
||||
}),
|
||||
})
|
||||
.status(206)
|
||||
.send(buf);
|
||||
@@ -84,9 +92,13 @@ export default fastifyPlugin(
|
||||
.headers({
|
||||
'Content-Length': size,
|
||||
'Accept-Ranges': 'bytes',
|
||||
...(file?.originalName && {
|
||||
'Content-Disposition': `${download ? 'attachment; ' : ''}filename="${file.originalName}"`,
|
||||
}),
|
||||
...(file?.originalName
|
||||
? {
|
||||
'Content-Disposition': `${download ? 'attachment; ' : ''}filename="${file.originalName}"`,
|
||||
}
|
||||
: download && {
|
||||
'Content-Disposition': 'attachment;',
|
||||
}),
|
||||
})
|
||||
.status(200)
|
||||
.send(buf);
|
||||
|
||||
Reference in New Issue
Block a user