add action buttons to file listing, close #50

This commit is contained in:
spencerwooo 2021-08-29 17:14:17 +01:00
parent 8a5f4482cd
commit a3644b50e5
No known key found for this signature in database
GPG key ID: 24CD550268849CA0
2 changed files with 67 additions and 26 deletions

View file

@ -65,8 +65,8 @@ const FileListItem: FunctionComponent<{
const renderEmoji = emojiIcon && !emojiIcon.index const renderEmoji = emojiIcon && !emojiIcon.index
return ( return (
<div className="p-3 grid grid-cols-10 items-center space-x-2 cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-800"> <div className="p-3 grid grid-cols-11 items-center space-x-2 cursor-pointer">
<div className="flex space-x-2 items-center col-span-10 md:col-span-7 truncate"> <div className="flex space-x-2 items-center col-span-11 md:col-span-7 truncate">
{/* <div>{c.file ? c.file.mimeType : 'folder'}</div> */} {/* <div>{c.file ? c.file.mimeType : 'folder'}</div> */}
<div className="w-5 text-center flex-shrink-0"> <div className="w-5 text-center flex-shrink-0">
{renderEmoji ? ( {renderEmoji ? (
@ -79,7 +79,7 @@ const FileListItem: FunctionComponent<{
{renderEmoji ? c.name.replace(emojiIcon ? emojiIcon[0] : '', '').trim() : c.name} {renderEmoji ? c.name.replace(emojiIcon ? emojiIcon[0] : '', '').trim() : c.name}
</div> </div>
</div> </div>
<div className="hidden md:block font-mono text-sm col-span-2 text-gray-700 dark:text-gray-500 flex-shrink-0"> <div className="hidden md:block text-sm font-mono col-span-3 text-gray-700 dark:text-gray-500 flex-shrink-0">
{new Date(c.lastModifiedDateTime).toLocaleString('en-US', { {new Date(c.lastModifiedDateTime).toLocaleString('en-US', {
year: 'numeric', year: 'numeric',
month: '2-digit', month: '2-digit',
@ -89,7 +89,7 @@ const FileListItem: FunctionComponent<{
hour12: false, hour12: false,
})} })}
</div> </div>
<div className="hidden md:block font-mono text-sm text-gray-700 dark:text-gray-500 flex-shrink-0"> <div className="hidden md:block text-sm font-mono col-span-1 truncate text-gray-700 dark:text-gray-500 flex-shrink-0">
{humanFileSize(c.size)} {humanFileSize(c.size)}
</div> </div>
</div> </div>
@ -164,10 +164,11 @@ const FileListing: FunctionComponent<{ query?: ParsedUrlQuery }> = ({ query }) =
return ( return (
<div className="bg-white dark:bg-gray-900 dark:text-gray-100 shadow rounded"> <div className="bg-white dark:bg-gray-900 dark:text-gray-100 shadow rounded">
<div className="p-3 grid grid-cols-10 items-center space-x-2 border-b border-gray-200 dark:border-gray-700"> <div className="p-3 grid grid-cols-12 items-center space-x-2 border-b border-gray-200 dark:border-gray-700">
<div className="col-span-10 md:col-span-7 font-bold">Name</div> <div className="col-span-12 md:col-span-7 font-bold">Name</div>
<div className="hidden md:block font-bold col-span-2">Last Modified</div> <div className="hidden md:block font-bold col-span-3">Last Modified</div>
<div className="hidden md:block font-bold">Size</div> <div className="hidden md:block font-bold">Size</div>
<div className="hidden md:block font-bold">Actions</div>
</div> </div>
<Toaster /> <Toaster />
@ -197,7 +198,7 @@ const FileListing: FunctionComponent<{ query?: ParsedUrlQuery }> = ({ query }) =
return toolbars.concat([ return toolbars.concat([
{ {
key: 'copy', key: 'copy',
render: <FontAwesomeIcon icon="copy" />, render: <FontAwesomeIcon icon={['fas', 'copy']} />,
onClick: i => { onClick: i => {
clipboard.copy(i.alt ? `${getBaseUrl()}/api?path=${path + '/' + i.alt}&raw=true` : '') clipboard.copy(i.alt ? `${getBaseUrl()}/api?path=${path + '/' + i.alt}&raw=true` : '')
toast.success('Copied image permanent link to clipboard.') toast.success('Copied image permanent link to clipboard.')
@ -209,20 +210,56 @@ const FileListing: FunctionComponent<{ query?: ParsedUrlQuery }> = ({ query }) =
)} )}
{children.map((c: any) => ( {children.map((c: any) => (
<div <div className="grid grid-cols-12 hover:bg-gray-100 dark:hover:bg-gray-800" key={c.id}>
key={c.id} <div
onClick={e => { className="col-span-11"
e.preventDefault() onClick={e => {
e.preventDefault()
if (!c.folder && fileIsImage(c.name)) { if (!c.folder && fileIsImage(c.name)) {
setActiveImageIdx(imageIndexDict[c.id]) setActiveImageIdx(imageIndexDict[c.id])
setImageViewerVisibility(true) setImageViewerVisibility(true)
} else { } else {
router.push(`${path === '/' ? '' : path}/${encodeURIComponent(c.name)}`) router.push(`${path === '/' ? '' : path}/${encodeURIComponent(c.name)}`)
} }
}} }}
> >
<FileListItem fileContent={c} /> <FileListItem fileContent={c} />
</div>
{c.folder ? (
<div className="hidden md:block col-span-1 space-x-2 p-3 text-gray-700 dark:text-gray-500">
<span
title="Copy folder permalink"
className="cursor-pointer hover:opacity-80"
onClick={() => {
clipboard.copy(`${getBaseUrl()}${path === '/' ? '' : path}/${encodeURIComponent(c.name)}`)
toast.success('Copied folder permanent link to clipboard.')
}}
>
<FontAwesomeIcon icon={['far', 'copy']} />
</span>
</div>
) : (
<div className="hidden md:block col-span-1 space-x-2 p-3 text-gray-700 dark:text-gray-500">
<span
title="Copy raw file permalink"
className="cursor-pointer hover:opacity-80"
onClick={() => {
clipboard.copy(`${getBaseUrl()}/api?path=${path === '/' ? '' : path}/${c.name}&raw=true`)
toast.success('Copied permanent raw file link to clipboard.')
}}
>
<FontAwesomeIcon icon={['far', 'copy']} />
</span>
<a
title="Download file"
className="cursor-pointer hover:opacity-80"
href={c['@microsoft.graph.downloadUrl']}
>
<FontAwesomeIcon icon={['far', 'arrow-alt-circle-down']} />
</a>
</div>
)}
</div> </div>
))} ))}
@ -272,13 +309,13 @@ const FileListing: FunctionComponent<{ query?: ParsedUrlQuery }> = ({ query }) =
return <OfficePreview file={resp} /> return <OfficePreview file={resp} />
default: default:
return <div className="bg-white shadow rounded">{fileName}</div> return <div className="bg-white dark:bg-gray-900 shadow rounded">{fileName}</div>
} }
} }
return ( return (
<> <>
<div className="shadow bg-white rounded p-3"> <div className="shadow bg-white dark:bg-gray-900 rounded p-3">
<FourOhFour <FourOhFour
errorMsg={`Preview for file ${resp.name} is not available, download directly with the button below.`} errorMsg={`Preview for file ${resp.name} is not available, download directly with the button below.`}
/> />
@ -291,7 +328,7 @@ const FileListing: FunctionComponent<{ query?: ParsedUrlQuery }> = ({ query }) =
} }
return ( return (
<div className="shadow bg-white rounded p-3"> <div className="shadow bg-white dark:bg-gray-900 rounded p-3">
<FourOhFour errorMsg={`Cannot preview ${resp.name}.`} /> <FourOhFour errorMsg={`Cannot preview ${resp.name}.`} />
</div> </div>
) )

View file

@ -16,16 +16,18 @@ import {
faFileAlt, faFileAlt,
faFile, faFile,
faFolder, faFolder,
faCopy,
faArrowAltCircleDown,
} from '@fortawesome/free-regular-svg-icons' } from '@fortawesome/free-regular-svg-icons'
import { import {
faPlus, faPlus,
faMinus, faMinus,
faCopy as faCopySolid,
faDownload, faDownload,
faMusic, faMusic,
faArrowLeft, faArrowLeft,
faArrowRight, faArrowRight,
faFileDownload, faFileDownload,
faCopy,
faUndo, faUndo,
faBook, faBook,
} from '@fortawesome/free-solid-svg-icons' } from '@fortawesome/free-solid-svg-icons'
@ -53,11 +55,13 @@ library.add(
faArrowRight, faArrowRight,
faFileDownload, faFileDownload,
faCopy, faCopy,
faCopySolid,
faPlus, faPlus,
faMinus, faMinus,
faDownload, faDownload,
faUndo, faUndo,
faBook faBook,
faArrowAltCircleDown
) )
function MyApp({ Component, pageProps }: AppProps) { function MyApp({ Component, pageProps }: AppProps) {