Merge pull request #1826 from SkynetLabs/dashboard-v2-recent-activity
feat(dashboard-v2): live data for recent activity panel
This commit is contained in:
commit
db0fcab94a
|
@ -1,18 +1,36 @@
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
|
import useSWR from "swr";
|
||||||
|
|
||||||
import { Table, TableBody, TableCell, TableRow } from "../Table";
|
import { Table, TableBody, TableCell, TableRow } from "../Table";
|
||||||
|
|
||||||
export default function ActivityTable({ data }) {
|
import useFormattedActivityData from "./useFormattedActivityData";
|
||||||
|
|
||||||
|
export default function ActivityTable({ type }) {
|
||||||
|
const { data, error } = useSWR(`user/${type}?pageSize=3`);
|
||||||
|
const items = useFormattedActivityData(data?.items || []);
|
||||||
|
|
||||||
|
if (!items.length) {
|
||||||
|
return (
|
||||||
|
<div className="flex w-full h-full justify-center items-center text-palette-400">
|
||||||
|
{/* TODO: proper loading indicator / error message */}
|
||||||
|
{!data && !error && <p>Loading...</p>}
|
||||||
|
{!data && error && <p>An error occurred while loading this data.</p>}
|
||||||
|
{data && <p>No files found.</p>}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Table style={{ tableLayout: "fixed" }}>
|
<Table style={{ tableLayout: "fixed" }}>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{data.map(({ name, type, size, uploaded, skylink }) => (
|
{items.map(({ id, name, type, size, date, skylink }) => (
|
||||||
<TableRow key={skylink}>
|
<TableRow key={id}>
|
||||||
<TableCell>{name}</TableCell>
|
<TableCell>{name}</TableCell>
|
||||||
<TableCell className="w-[80px]">{type}</TableCell>
|
<TableCell className="w-[80px]">{type}</TableCell>
|
||||||
<TableCell className="w-[80px]" align="right">
|
<TableCell className="w-[80px]" align="right">
|
||||||
{size}
|
{size}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="w-[180px]">{uploaded}</TableCell>
|
<TableCell className="w-[180px]">{date}</TableCell>
|
||||||
<TableCell>{skylink}</TableCell>
|
<TableCell>{skylink}</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
))}
|
))}
|
||||||
|
|
|
@ -1,22 +1,34 @@
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
|
import { Link } from "gatsby";
|
||||||
|
|
||||||
import { Panel } from "../Panel";
|
import { Panel } from "../Panel";
|
||||||
import { Tab, TabPanel, Tabs } from "../Tabs";
|
import { Tab, TabPanel, Tabs } from "../Tabs";
|
||||||
|
import { ArrowRightIcon } from "../Icons";
|
||||||
|
|
||||||
import ActivityTable from "./ActivityTable";
|
import ActivityTable from "./ActivityTable";
|
||||||
import useRecentActivityData from "./useActivityData";
|
|
||||||
|
const ViewAllLink = (props) => (
|
||||||
|
<Link className="inline-flex mt-6 items-center gap-3 ease-in-out hover:brightness-90" {...props}>
|
||||||
|
<span className="bg-primary rounded-full w-[32px] h-[32px] inline-flex justify-center items-center">
|
||||||
|
<ArrowRightIcon />
|
||||||
|
</span>
|
||||||
|
<span className="font-sans text-xs uppercase text-palette-400">View all</span>
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
|
||||||
export default function LatestActivity() {
|
export default function LatestActivity() {
|
||||||
const { downloads, uploads } = useRecentActivityData();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Panel title="Latest activity">
|
<Panel title="Latest activity">
|
||||||
<Tabs>
|
<Tabs>
|
||||||
<Tab id="uploads" title="Uploads" />
|
<Tab id="uploads" title="Uploads" />
|
||||||
<Tab id="downloads" title="Downloads" />
|
<Tab id="downloads" title="Downloads" />
|
||||||
<TabPanel tabId="uploads" className="pt-4">
|
<TabPanel tabId="uploads" className="pt-4">
|
||||||
<ActivityTable data={uploads} />
|
<ActivityTable type="uplodads" />
|
||||||
|
<ViewAllLink to="/files?tab=uploads" />
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel tabId="downloads" className="pt-4">
|
<TabPanel tabId="downloads" className="pt-4">
|
||||||
<ActivityTable data={downloads} />
|
<ActivityTable type="downloads" />
|
||||||
|
<ViewAllLink to="/files?tab=downloads" />
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</Panel>
|
</Panel>
|
||||||
|
|
|
@ -1,54 +0,0 @@
|
||||||
const UPLOADS_DATA = [
|
|
||||||
{
|
|
||||||
name: "At_vereo_eos_censes",
|
|
||||||
type: ".mp4",
|
|
||||||
size: "2.45 MB",
|
|
||||||
uploaded: "a few seconds ago",
|
|
||||||
skylink: "_HyFqH632Rmy99c93idTtBVXeRDgaDAAWg6Bmm5P1izriu",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Miriam Klein IV",
|
|
||||||
type: ".pdf",
|
|
||||||
size: "7.52 MB",
|
|
||||||
uploaded: "01/04/2021; 17:11",
|
|
||||||
skylink: "_izriuHyFqH632Rmy99c93idTtBVXeRDgaDAAWg6Bmm5P1",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "tmp/QmWR6eVDVkwhAYq7X99w4xT9KNKBzwK39Fj1PDmr4ZnzMm/QmWR6eVDVkwhAYq7X99w4xT9KNKBzwK39Fj1PDmr4ZnzMm",
|
|
||||||
type: ".doc",
|
|
||||||
size: "8.15 MB",
|
|
||||||
uploaded: "10/26/2020; 7:21",
|
|
||||||
skylink: "_VXeRDgaDAAWg6Bmm5P1izriuHyFqH632Rmy99c93idTtB",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Perm_London",
|
|
||||||
type: ".avi",
|
|
||||||
size: "225.6 MB",
|
|
||||||
uploaded: "09/12/2020; 19:28",
|
|
||||||
skylink: "_eRDgaDAAWg6Bmm5P1izriuHyFqH632Rmy99c93idTtBVX",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Santa_Clara",
|
|
||||||
type: ".pdf",
|
|
||||||
size: "7.52 MB",
|
|
||||||
uploaded: "09/12/2020; 19:23",
|
|
||||||
skylink: "_AWg6Bmm5P1izriuHyFqH632Rmy99c93idTtBVXeRDgaDA",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Marysa_Labrone",
|
|
||||||
type: ".doc",
|
|
||||||
size: "8.15 MB",
|
|
||||||
uploaded: "09/12/2020; 19:21",
|
|
||||||
skylink: "_P1izriuHyFqH632Rmy99c93idTtBVXeRDgaDAAWg6Bmm5",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const DOWNLOADS_DATA = UPLOADS_DATA.slice().reverse();
|
|
||||||
|
|
||||||
// TODO: get real data
|
|
||||||
export default function useRecentActivityData() {
|
|
||||||
return {
|
|
||||||
uploads: UPLOADS_DATA,
|
|
||||||
downloads: DOWNLOADS_DATA,
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
import { useMemo } from "react";
|
||||||
|
import prettyBytes from "pretty-bytes";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
|
const parseFileName = (fileName) => {
|
||||||
|
const lastDotIndex = Math.max(0, fileName.lastIndexOf(".")) || Infinity;
|
||||||
|
|
||||||
|
return [fileName.substr(0, lastDotIndex), fileName.substr(lastDotIndex)];
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatItem = ({ size, name: rawFileName, uploadedOn, downloadedOn, ...rest }) => {
|
||||||
|
const [name, type] = parseFileName(rawFileName);
|
||||||
|
const date = dayjs(uploadedOn || downloadedOn).format("MM/DD/YYYY; HH:MM");
|
||||||
|
|
||||||
|
return {
|
||||||
|
...rest,
|
||||||
|
date,
|
||||||
|
size: prettyBytes(size),
|
||||||
|
type,
|
||||||
|
name,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const useFormattedActivityData = (items) => useMemo(() => items.map(formatItem), [items]);
|
||||||
|
|
||||||
|
export default useFormattedActivityData;
|
Reference in New Issue