diff --git a/app/dashboard/files/columns.tsx b/app/dashboard/files/columns.tsx index df0db6f..92f885e 100644 --- a/app/dashboard/files/columns.tsx +++ b/app/dashboard/files/columns.tsx @@ -73,10 +73,37 @@ export const columns: ColumnDef[] = [ variant="ghost" onClick={() => column.toggleSorting(column.getIsSorted() === "asc")} > - Modified + Modified x ago ) }, + cell: ({ row }) => { + const modified = parseFloat(row.getValue("modified")) + + let formatted: number | string = 0 + + if (modified > 365 * 24 * 60 * 60 * 1000) { // 365d + formatted = Math.round(modified / 1000 / 60 / 60 / 24 / 365) + formatted = `${formatted}y` + } else if (modified > 7 * 24 * 60 * 60 * 1000) { // 365d + formatted = Math.round(modified / 1000 / 60 / 60 / 24 / 7) + formatted = `${formatted}w` + } else if (modified > 24 * 60 * 60 * 1000) { // 24h + formatted = Math.round(modified / 1000 / 60 / 60 / 24) + formatted = `${formatted}d` + } else if (modified > 60 * 60 * 1000) { // 60min + formatted = Math.round(modified / 1000 / 60 / 60) + formatted = `${formatted}h` + } else if (modified > 60 * 1000) { // 60s + formatted = Math.round(modified / 1000 / 60) + formatted = `${formatted}m` + } else { + formatted = Math.round(modified / 1000) + formatted = `${formatted}s` + } + + return
{formatted} ago
+ }, }, ] diff --git a/app/dashboard/files/data-table.tsx b/app/dashboard/files/data-table.tsx index 827ad93..dd6c664 100644 --- a/app/dashboard/files/data-table.tsx +++ b/app/dashboard/files/data-table.tsx @@ -22,25 +22,32 @@ import { interface DataTableProps { columns: ColumnDef[] data: TData[] + cellClick: any } export function DataTable({ columns, data, + cellClick, }: DataTableProps) { const [sorting, setSorting] = React.useState([]) + const [rowSelection, setRowSelection] = React.useState({}) + const table = useReactTable({ data, columns, getCoreRowModel: getCoreRowModel(), onSortingChange: setSorting, getSortedRowModel: getSortedRowModel(), + onRowSelectionChange: setRowSelection, state: { sorting, + rowSelection, }, }) return ( +
@@ -69,7 +76,7 @@ export function DataTable({ data-state={row.getIsSelected() && "selected"} > {row.getVisibleCells().map((cell) => ( - + {cellClick(cell)}}> {flexRender(cell.column.columnDef.cell, cell.getContext())} ))} @@ -85,5 +92,18 @@ export function DataTable({
+ + + +
+ +
+ {table.getFilteredSelectedRowModel().rows.length} of{" "} + {table.getFilteredRowModel().rows.length} row(s) selected. +
+ +
+ +
) } diff --git a/app/dashboard/files/page.tsx b/app/dashboard/files/page.tsx index 8f3d718..8e28053 100644 --- a/app/dashboard/files/page.tsx +++ b/app/dashboard/files/page.tsx @@ -1,26 +1,16 @@ "use client" import { Layout } from "@/app/components/dash_lay" import React, { useRef, useEffect, useState } from 'react'; -import { - Table, - TableBody, - TableCaption, - TableCell, - TableHead, - TableHeader, - TableRow, - } from "@/components/ui/table" -import { Checkbox } from "@/components/ui/checkbox" import { Button } from "@/components/ui/button" import Icon from '@mdi/react'; -import { mdiDeleteOutline, mdiFolderMoveOutline, mdiPencilOutline } from '@mdi/js'; +import { mdiDeleteOutline, mdiChevronLeft, mdiFolderMoveOutline, mdiHomeOutline, mdiPencilOutline, mdiReload, mdiCloudDownloadOutline, mdiCloudUploadOutline, mdiContentCopy } from '@mdi/js'; import { File, columns } from "@/app/dashboard/files/columns" import { DataTable } from "@/app/dashboard/files/data-table" -async function getData(): Promise { - const res = await fetch(process.env.NEXT_PUBLIC_API_URL + '/api/files/&.', { +async function getData(path: string): Promise { + const res = await fetch(process.env.NEXT_PUBLIC_API_URL + '/api/files/' + path, { method: 'POST', headers: { 'Authorization': 'Bearer ' + localStorage.getItem('token'), @@ -39,17 +29,66 @@ async function getData(): Promise { export default function Home() { const [data, setData] = useState([]) + const [path, setPath] = useState("&.") + + const refresh = async () => { + const res = await getData(path) + setData(res) + } useEffect(() => { - getData().then(res => setData(res)) + getData(path).then(res => setData(res)) }, []) + + const goToHome = async () => { + setPath("&.") + const res = await getData("&.") + setData(res) + } + + const goUpwards = async () => { + const pathArr = path.split("&") + pathArr.pop() + const newPath = pathArr.join("&") + setPath(newPath) + const res = await getData(newPath) + setData(res) + } + + const handleClick = async (cell: any) => { + + if (cell.getContext().row.original.is_dir) { + // go in the directory + setPath(path + "&" + cell.getContext().row.original.name) + const res = await getData(path + "&" + cell.getContext().row.original.name) + setData(res) + } else { + // open the file? or download it? + } + + } + return (

Files

- + { path } + +
+ + + + + + + + + + +
+
) diff --git a/dash/src/files.rs b/dash/src/files.rs index ce7a9bf..8d0e14a 100644 --- a/dash/src/files.rs +++ b/dash/src/files.rs @@ -16,13 +16,16 @@ struct FileInfo { pub async fn get_files(path: web::Path) -> Result { let mut pathname = path.into_inner(); - if pathname.contains("..") { + /*if pathname.contains("..") || pathname.contains("~") || pathname.starts_with("-") || pathname.contains("//") || pathname.contains("\\") || pathname.contains(":") || pathname.contains("*") || pathname.contains("?") || pathname.contains("\"") || pathname.contains("<") || pathname.contains(">") || pathname.contains("|") { return Ok(HttpResponse::BadRequest().body("Invalid Pathname!")); - } - - if pathname == "&." { - pathname = ".".to_string(); - } + }*/ + // theoretically but since this only works with tokens the user can be trusted ... + + + pathname = pathname.replace("&.", "."); + pathname = pathname.replace("&", "/"); + + println!("Pathname: {}", pathname); let path = Path::new(&pathname);