[simple-example][m] - remove unused components

This commit is contained in:
Luccas Mateus de Medeiros Gomes 2023-04-22 14:28:13 -03:00
parent a9940a41fe
commit a89dfaae38
9 changed files with 1 additions and 459 deletions

View File

@ -22,7 +22,7 @@ PROJECT_NAME=<app-name>
- This project uses the github api, which for anonymous users will cap at 50 requests per hour, so you might want to get a [Personal Access Token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token) and add it to your .env file like so
```
PAT_TOKEN=<github token>
GITHUB_PAT=<github token>
```
- Edit the file `datasets.json` to your liking, some examples can be found inside this [repo](https://github.com/datasets)

View File

@ -1,85 +0,0 @@
import FrictionlessViewFactory from "./drd/FrictionlessView";
import Table from "./drd/Table";
/* eslint import/no-default-export: off */
function DatapackageLayout({ children, project, excerpt }) {
const { metadata } = project;
const title = metadata.title;
const resources = metadata.resources;
const views = metadata.views;
const FrictionlessView = FrictionlessViewFactory({ views, resources });
return (
<article className="docs prose text-primary dark:text-primary-dark dark:prose-invert prose-headings:font-headings prose-a:break-words mx-auto p-6">
<header>
{title && <h1 className="mb-4">{title}</h1>}
<a
className="font-semibold mb-4"
target="_blank"
href={project.github_repo}
>
@{project.owner} / {project.name}
</a>
{excerpt && <p className="text-md">{excerpt}</p>}
</header>
<section className="mt-10">
{views.map((view, i) => {
return (
<div key={`visualization-${i}`}>
<FrictionlessView viewId={i} />
</div>
);
})}
</section>
<section className="mt-10">
<h2>Data files</h2>
<table className="table-auto">
<thead>
<tr>
<th>File</th>
<th>Title</th>
<th>Format</th>
</tr>
</thead>
<tbody>
{resources.map((r) => {
return (
<tr key={`resources-list-${r.name}`}>
<td>
<a
target="_blank"
href={`https://github.com/${project.owner}/${project.name}/blob/main/${r.path}`}
>
{r.path}
</a>
</td>
<td>{r.title}</td>
<td>{r.format.toUpperCase()}</td>
</tr>
);
})}
</tbody>
</table>
{resources.slice(0, 5).map((resource) => {
return (
<div key={`resource-preview-${resource.name}`} className="mt-10">
<h3>{resource.title || resource.name || resource.path}</h3>
<Table url={resource.path} />
</div>
);
})}
</section>
<hr />
<section>
<h2>Read me</h2>
{children}
</section>
</article>
);
}
export default function MDLayout({ children, layout, ...props }) {
return <DatapackageLayout project={props.project} excerpt={props.excerpt}>{children}</DatapackageLayout>;
}

View File

@ -1,40 +0,0 @@
import { MDXRemote } from "next-mdx-remote";
import dynamic from "next/dynamic";
import { Mermaid } from "@flowershow/core";
import FrictionlessViewFactory from "./FrictionlessView";
// Custom components/renderers to pass to MDX.
// Since the MDX files aren't loaded by webpack, they have no knowledge of how
// to handle import statements. Instead, you must include components in scope
// here.
const components = {
Table: dynamic(() => import("./Table")),
mermaid: Mermaid,
// Excel: dynamic(() => import('../components/Excel')),
// TODO: try and make these dynamic ...
Vega: dynamic(() => import("./Vega")),
VegaLite: dynamic(() => import("./VegaLite")),
LineChart: dynamic(() => import("./LineChart")),
} as any;
export default function DRD({
source,
frictionless = {
views: [],
resources: [],
},
}: {
source: any;
frictionless?: any;
}) {
// dynamic() can't be used inside of React rendering
// as it needs to be marked in the top level of the
// module for preloading to work
components.FrictionlessView = FrictionlessViewFactory({
views: frictionless.views,
resources: frictionless.resources,
});
return <MDXRemote {...source} components={components} />;
}

View File

@ -1,33 +0,0 @@
import { useEffect, useState } from "react";
const DebouncedInput = ({
value: initialValue,
onChange,
debounce = 500,
...props
}) => {
const [value, setValue] = useState(initialValue);
useEffect(() => {
setValue(initialValue);
}, [initialValue]);
useEffect(() => {
const timeout = setTimeout(() => {
onChange(value);
}, debounce);
return () => clearTimeout(timeout);
}, [value]);
return (
<input
{...props}
value={value}
onChange={(e) => setValue(e.target.value)}
/>
);
};
export default DebouncedInput;

View File

@ -1,55 +0,0 @@
// FrictionlessView is a factory because we have to
// set the views and resources lists before using it
import { convertSimpleToVegaLite } from "../../lib/viewSpecConversion";
import VegaLite from "./VegaLite";
export default function FrictionlessViewFactory({
views = [],
resources = [],
}): ({
viewId,
fullWidth,
}: {
viewId: number;
fullWidth?: boolean;
}) => JSX.Element {
return ({ viewId, fullWidth = false }) => {
if (!(viewId in views)) {
console.error(`View ${viewId} not found`);
return <></>;
}
const view = views[viewId];
let resource;
if (resources.length > 1) {
resource = resources.find((r) => r.name === view.resourceName);
} else {
resource = resources[0];
}
if (!resource) {
console.error(`Resource not found for view id ${viewId}`);
return <></>;
}
let vegaSpec;
switch (view.specType) {
case "simple":
vegaSpec = convertSimpleToVegaLite(view, resource);
break;
// ... other conversions
}
vegaSpec.data = { url: resource.path };
return (
<VegaLite
fullWidth={fullWidth}
spec={vegaSpec}
actions={{ editor: false }}
downloadFileName={resource.name}
/>
);
};
}

View File

@ -1,49 +0,0 @@
import { VegaLite } from "react-vega";
export default function LineChart({
data = [],
fullWidth = false,
title = "",
}) {
var tmp = data;
if (Array.isArray(data)) {
tmp = data.map((r, i) => {
return { x: r[0], y: r[1] };
});
}
const vegaData = { table: tmp };
const spec = {
$schema: "https://vega.github.io/schema/vega-lite/v5.json",
title,
width: "container" as "container",
height: 300,
mark: {
type: "line" as "line",
color: "black",
strokeWidth: 1,
tooltip: true,
},
data: {
name: "table",
},
selection: {
grid: {
type: "interval" as "interval",
bind: "scales",
},
},
encoding: {
x: {
field: "x",
timeUnit: "year",
type: "temporal" as "temporal",
},
y: {
field: "y",
type: "quantitative" as "temporal",
},
},
};
return <VegaLite data={vegaData} spec={spec} />;
}

View File

@ -1,188 +0,0 @@
import {
createColumnHelper,
FilterFn,
flexRender,
getCoreRowModel,
getFilteredRowModel,
getPaginationRowModel,
getSortedRowModel,
useReactTable,
} from "@tanstack/react-table";
import {
ArrowDownIcon,
ArrowUpIcon,
ChevronDoubleLeftIcon,
ChevronDoubleRightIcon,
ChevronLeftIcon,
ChevronRightIcon,
} from "@heroicons/react/24/solid";
import React, { useEffect, useMemo, useState } from "react";
import loadUrlProxied from "../../lib/loadUrlProxied";
import parseCsv from "../../lib/parseCsv";
import DebouncedInput from "./DebouncedInput";
const Table = ({
data: ogData = [],
cols: ogCols = [],
csv = "",
url = "",
}) => {
if (csv) {
const out = parseCsv(csv);
ogData = out.rows;
ogCols = out.fields;
}
const [data, setData] = React.useState(ogData);
const [cols, setCols] = React.useState(ogCols);
const [error, setError] = React.useState(""); // TODO: add error handling
const tableCols = useMemo(() => {
const columnHelper = createColumnHelper();
return cols.map((c) =>
columnHelper.accessor(c.key, {
header: () => c.name,
cell: (info) => info.getValue(),
})
);
}, [data, cols]);
const [globalFilter, setGlobalFilter] = useState("");
const table = useReactTable({
data,
columns: tableCols,
getCoreRowModel: getCoreRowModel(),
state: {
globalFilter,
},
globalFilterFn: globalFilterFn,
onGlobalFilterChange: setGlobalFilter,
getFilteredRowModel: getFilteredRowModel(),
getPaginationRowModel: getPaginationRowModel(),
getSortedRowModel: getSortedRowModel(),
});
useEffect(() => {
if (url) {
loadUrlProxied(url).then((data) => {
const { rows, fields } = parseCsv(data);
setData(rows);
setCols(fields);
});
}
}, [url]);
return (
<div>
<DebouncedInput
value={globalFilter ?? ""}
onChange={(value) => setGlobalFilter(String(value))}
className="p-2 text-sm shadow border border-block"
placeholder="Search all columns..."
/>
<table>
<thead>
{table.getHeaderGroups().map((hg) => (
<tr key={hg.id}>
{hg.headers.map((h) => (
<th key={h.id}>
<div
{...{
className: h.column.getCanSort()
? "cursor-pointer select-none"
: "",
onClick: h.column.getToggleSortingHandler(),
}}
>
{flexRender(h.column.columnDef.header, h.getContext())}
{{
asc: (
<ArrowUpIcon className="inline-block ml-2 h-4 w-4" />
),
desc: (
<ArrowDownIcon className="inline-block ml-2 h-4 w-4" />
),
}[h.column.getIsSorted() as string] ?? (
<div className="inline-block ml-2 h-4 w-4" />
)}
</div>
</th>
))}
</tr>
))}
</thead>
<tbody>
{table.getRowModel().rows.map((r) => (
<tr key={r.id}>
{r.getVisibleCells().map((c) => (
<td key={c.id}>
{flexRender(c.column.columnDef.cell, c.getContext())}
</td>
))}
</tr>
))}
</tbody>
</table>
<div className="flex gap-2 items-center justify-center">
<button
className={`w-6 h-6 ${
!table.getCanPreviousPage() ? "opacity-25" : "opacity-100"
}`}
onClick={() => table.setPageIndex(0)}
disabled={!table.getCanPreviousPage()}
>
<ChevronDoubleLeftIcon />
</button>
<button
className={`w-6 h-6 ${
!table.getCanPreviousPage() ? "opacity-25" : "opacity-100"
}`}
onClick={() => table.previousPage()}
disabled={!table.getCanPreviousPage()}
>
<ChevronLeftIcon />
</button>
<span className="flex items-center gap-1">
<div>Page</div>
<strong>
{table.getState().pagination.pageIndex + 1} of{" "}
{table.getPageCount()}
</strong>
</span>
<button
className={`w-6 h-6 ${
!table.getCanNextPage() ? "opacity-25" : "opacity-100"
}`}
onClick={() => table.nextPage()}
disabled={!table.getCanNextPage()}
>
<ChevronRightIcon />
</button>
<button
className={`w-6 h-6 ${
!table.getCanNextPage() ? "opacity-25" : "opacity-100"
}`}
onClick={() => table.setPageIndex(table.getPageCount() - 1)}
disabled={!table.getCanNextPage()}
>
<ChevronDoubleRightIcon />
</button>
</div>
</div>
);
};
const globalFilterFn: FilterFn<any> = (row, columnId, filterValue: string) => {
const search = filterValue.toLowerCase();
let value = row.getValue(columnId) as string;
if (typeof value === "number") value = String(value);
return value?.toLowerCase().includes(search);
};
export default Table;

View File

@ -1,4 +0,0 @@
import { Vega as VegaOg } from "react-vega";
export default function Vega(props) {
return <VegaOg className="w-full" {...props} />;
}

View File

@ -1,4 +0,0 @@
import { VegaLite as VegaOg } from "react-vega";
export default function Vega(props) {
return <VegaOg className="w-full" {...props} />;
}