feat: update deps & fix stuff

This commit is contained in:
diced 2022-12-10 14:19:53 -08:00
parent d8b308a18c
commit 5d115afa71
No known key found for this signature in database
GPG key ID: 370BD1BA142842D1
12 changed files with 474 additions and 493 deletions

View file

@ -4,7 +4,7 @@
| Version | Supported | | Version | Supported |
| ------- | ------------------ | | ------- | ------------------ |
| 3.4.8 | :white_check_mark: | | 3.6.x | :white_check_mark: |
| < 3 | :x: | | < 3 | :x: |
| < 2 | :x: | | < 2 | :x: |

View file

@ -26,27 +26,25 @@
"@dicedtomato/mantine-data-grid": "0.0.23", "@dicedtomato/mantine-data-grid": "0.0.23",
"@emotion/react": "^11.10.5", "@emotion/react": "^11.10.5",
"@emotion/server": "^11.10.0", "@emotion/server": "^11.10.0",
"@mantine/core": "^5.6.3", "@mantine/core": "^5.9.2",
"@mantine/dropzone": "^5.6.3", "@mantine/dropzone": "^5.9.2",
"@mantine/form": "^5.6.3", "@mantine/form": "^5.9.2",
"@mantine/hooks": "^5.6.3", "@mantine/hooks": "^5.9.2",
"@mantine/modals": "^5.6.3", "@mantine/modals": "^5.9.2",
"@mantine/next": "^5.6.3", "@mantine/next": "^5.9.2",
"@mantine/notifications": "^5.6.3", "@mantine/notifications": "^5.9.2",
"@mantine/nprogress": "^5.6.3", "@mantine/nprogress": "^5.9.2",
"@mantine/prism": "^5.6.3", "@mantine/prism": "^5.9.2",
"@prisma/client": "^4.5.0", "@prisma/client": "^4.7.1",
"@prisma/internals": "^4.5.0", "@prisma/internals": "^4.7.1",
"@prisma/migrate": "^4.5.0", "@prisma/migrate": "^4.7.1",
"@sapphire/shapeshift": "^3.7.0", "@sapphire/shapeshift": "^3.7.1",
"@tanstack/react-query": "^4.13.0", "@tanstack/react-query": "^4.19.1",
"argon2": "^0.30.1", "argon2": "^0.30.2",
"chart.js": "^3.9.1", "chart.js": "^4.0.1",
"chartjs-plugin-datalabels": "^2.1.0",
"color-hash": "^2.0.1",
"colorette": "^2.0.19", "colorette": "^2.0.19",
"cookie": "^0.5.0", "cookie": "^0.5.0",
"dayjs": "^1.11.6", "dayjs": "^1.11.7",
"dotenv": "^16.0.3", "dotenv": "^16.0.3",
"dotenv-expand": "^9.0.0", "dotenv-expand": "^9.0.0",
"exiftool-vendored": "^18.6.0", "exiftool-vendored": "^18.6.0",
@ -54,42 +52,42 @@
"fastify-plugin": "^4.4.0", "fastify-plugin": "^4.4.0",
"fflate": "^0.7.4", "fflate": "^0.7.4",
"find-my-way": "^7.3.1", "find-my-way": "^7.3.1",
"katex": "^0.16.3", "katex": "^0.16.4",
"minio": "^7.0.32", "minio": "^7.0.32",
"ms": "canary", "ms": "canary",
"multer": "^1.4.5-lts.1", "multer": "^1.4.5-lts.1",
"next": "^13.0.0", "next": "^13.0.6",
"otplib": "^12.0.1", "otplib": "^12.0.1",
"prisma": "^4.5.0", "prisma": "^4.7.1",
"prismjs": "^1.29.0", "prismjs": "^1.29.0",
"qrcode": "^1.5.1", "qrcode": "^1.5.1",
"react": "^18.2.0", "react": "^18.2.0",
"react-chartjs-2": "^4.3.1", "react-chartjs-2": "^5.0.1",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-feather": "^2.0.10", "react-feather": "^2.0.10",
"react-markdown": "^8.0.4", "react-markdown": "^8.0.4",
"recoil": "^0.7.6", "recoil": "^0.7.6",
"remark-gfm": "^3.0.1", "remark-gfm": "^3.0.1",
"sharp": "^0.31.1" "sharp": "^0.31.2"
}, },
"devDependencies": { "devDependencies": {
"@types/cookie": "^0.5.1", "@types/cookie": "^0.5.1",
"@types/katex": "^0.14.0", "@types/katex": "^0.14.0",
"@types/minio": "^7.0.14", "@types/minio": "^7.0.15",
"@types/multer": "^1.4.7", "@types/multer": "^1.4.7",
"@types/node": "^18.11.7", "@types/node": "^18.11.12",
"@types/qrcode": "^1.5.0", "@types/qrcode": "^1.5.0",
"@types/react": "^18.0.24", "@types/react": "^18.0.26",
"@types/sharp": "^0.31.0", "@types/sharp": "^0.31.0",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"esbuild": "^0.15.12", "esbuild": "^0.16.4",
"eslint": "^8.26.0", "eslint": "^8.29.0",
"eslint-config-next": "^13.0.0", "eslint-config-next": "^13.0.6",
"eslint-config-prettier": "^8.5.0", "eslint-config-prettier": "^8.5.0",
"eslint-plugin-prettier": "^4.2.1", "eslint-plugin-prettier": "^4.2.1",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"prettier": "^2.7.1", "prettier": "^2.8.1",
"typescript": "^4.8.4" "typescript": "^4.9.4"
}, },
"repository": { "repository": {
"type": "git", "type": "git",

View file

@ -0,0 +1,5 @@
import { Database } from 'react-feather';
export default function DatabaseIcon({ ...props }) {
return <Database size={15} {...props} />;
}

View file

@ -33,6 +33,7 @@ import GoogleIcon from './GoogleIcon';
import EyeIcon from './EyeIcon'; import EyeIcon from './EyeIcon';
import RefreshIcon from './RefreshIcon'; import RefreshIcon from './RefreshIcon';
import KeyIcon from './KeyIcon'; import KeyIcon from './KeyIcon';
import DatabaseIcon from './DatabaseIcon';
export { export {
ActivityIcon, ActivityIcon,
@ -70,4 +71,5 @@ export {
EyeIcon, EyeIcon,
RefreshIcon, RefreshIcon,
KeyIcon, KeyIcon,
DatabaseIcon,
}; };

View file

@ -1,9 +1,8 @@
import { SimpleGrid } from '@mantine/core'; import { SimpleGrid } from '@mantine/core';
import { FileIcon } from 'components/icons';
import StatCard from 'components/StatCard'; import StatCard from 'components/StatCard';
import { useStats } from 'lib/queries/stats'; import { useStats } from 'lib/queries/stats';
import { percentChange } from 'lib/utils/client'; import { percentChange } from 'lib/utils/client';
import { Database, Eye, Users } from 'react-feather'; import { EyeIcon, DatabaseIcon, UserIcon, FileIcon } from 'components/icons';
export function StatCards() { export function StatCards() {
const stats = useStats(); const stats = useStats();
@ -35,7 +34,7 @@ export function StatCards() {
title: 'STORAGE', title: 'STORAGE',
value: stats.isSuccess ? latest.data.size : '...', value: stats.isSuccess ? latest.data.size : '...',
desc: 'of storage used', desc: 'of storage used',
icon: <Database size={15} />, icon: <DatabaseIcon />,
diff: diff:
stats.isSuccess && before?.data stats.isSuccess && before?.data
? percentChange(before.data.size_num, latest.data.size_num) ? percentChange(before.data.size_num, latest.data.size_num)
@ -48,7 +47,7 @@ export function StatCards() {
title: 'VIEWS', title: 'VIEWS',
value: stats.isSuccess ? latest.data.views_count.toLocaleString() : '...', value: stats.isSuccess ? latest.data.views_count.toLocaleString() : '...',
desc: 'total page views', desc: 'total page views',
icon: <Eye size={15} />, icon: <EyeIcon />,
diff: diff:
stats.isSuccess && before?.data stats.isSuccess && before?.data
? percentChange(before.data.views_count, latest.data.views_count) ? percentChange(before.data.views_count, latest.data.views_count)
@ -61,7 +60,7 @@ export function StatCards() {
title: 'USERS', title: 'USERS',
value: stats.isSuccess ? latest.data.count_users.toLocaleString() : '...', value: stats.isSuccess ? latest.data.count_users.toLocaleString() : '...',
desc: 'total registered users', desc: 'total registered users',
icon: <Users size={15} />, icon: <UserIcon />,
}} }}
/> />
</SimpleGrid> </SimpleGrid>

View file

@ -11,18 +11,12 @@ import {
PointElement, PointElement,
Tooltip, Tooltip,
} from 'chart.js'; } from 'chart.js';
import ChartDataLabels from 'chartjs-plugin-datalabels';
import ColorHash from 'color-hash';
import { useStats } from 'lib/queries/stats'; import { useStats } from 'lib/queries/stats';
import { bytesToHuman } from 'lib/utils/bytes'; import { bytesToHuman } from 'lib/utils/bytes';
import { useMemo } from 'react'; import { useMemo } from 'react';
import { Chart, Pie } from 'react-chartjs-2'; import { Chart } from 'react-chartjs-2';
const hash = new ColorHash(); ChartJS.register(ArcElement, LinearScale, CategoryScale, PointElement, LineController, LineElement, Tooltip);
ChartJS.register(ArcElement);
ChartJS.register(ChartDataLabels);
ChartJS.register(LinearScale);
ChartJS.register(CategoryScale, PointElement, LineController, LineElement, Tooltip);
const CHART_OPTIONS = (theme: MantineTheme): ChartOptions => ({ const CHART_OPTIONS = (theme: MantineTheme): ChartOptions => ({
plugins: { plugins: {
@ -30,10 +24,6 @@ const CHART_OPTIONS = (theme: MantineTheme): ChartOptions => ({
enabled: true, enabled: true,
intersect: false, intersect: false,
}, },
datalabels: {
display: false,
},
}, },
scales: { scales: {
@ -60,17 +50,15 @@ const CHART_OPTIONS = (theme: MantineTheme): ChartOptions => ({
}, },
}); });
type LineChartData = ChartData<'line', number[], string>; export type LineChartData = ChartData<'line', number[], string>;
type ChartDataMemo = { export type ChartDataMemo = {
views: LineChartData; views: LineChartData;
uploads: LineChartData; uploads: LineChartData;
uploadTypes: ChartData<'pie', number[], string>;
storage: LineChartData; storage: LineChartData;
} | void; } | void;
export default function Graphs() { export default function Graphs() {
const historicalStats = useStats(10); const historicalStats = useStats(10);
const latest = historicalStats.data?.[0];
const theme = useMantineTheme(); const theme = useMantineTheme();
const chartOptions = useMemo(() => CHART_OPTIONS(theme), [theme]); const chartOptions = useMemo(() => CHART_OPTIONS(theme), [theme]);
@ -109,17 +97,6 @@ export default function Graphs() {
], ],
}, },
uploadTypes: {
labels: latest?.data.types_count.map((x) => x.mimetype),
datasets: [
{
data: latest?.data.types_count.map((x) => x.count),
label: 'Upload Types',
backgroundColor: latest?.data.types_count.map((x) => hash.hex(x.mimetype)),
},
],
},
storage: { storage: {
labels, labels,
datasets: [ datasets: [
@ -139,37 +116,8 @@ export default function Graphs() {
<LoadingOverlay visible={historicalStats.isLoading} /> <LoadingOverlay visible={historicalStats.isLoading} />
<Grid> <Grid>
{/* 1/4 - upload types */}
<Grid.Col md={12} lg={4}>
<Card>
<Title size='h4'>Upload Types</Title>
{chartData && (
<Pie
data={chartData.uploadTypes}
options={{
plugins: {
datalabels: {
formatter: (_, ctx) => {
// mime: count
const mime = ctx.chart.data.labels[ctx.dataIndex];
const count = ctx.chart.data.datasets[0].data[ctx.dataIndex];
return `${mime}: ${count}`;
},
color: 'white',
textShadowBlur: 7,
textShadowColor: 'black',
},
},
}}
style={{ maxHeight: '20vh' }}
/>
)}
</Card>
</Grid.Col>
{/* 3/4 - views */} {/* 3/4 - views */}
<Grid.Col md={12} lg={8}> <Grid.Col md={12}>
<Card> <Card>
<Title size='h4'>Total Views</Title> <Title size='h4'>Total Views</Title>
{chartData && ( {chartData && (

View file

@ -1,6 +1,10 @@
import { Box, Card, LoadingOverlay } from '@mantine/core'; import { Box, Card, Center, Grid, LoadingOverlay, Title } from '@mantine/core';
import { ChartData } from 'chart.js';
import { SmallTable } from 'components/SmallTable'; import { SmallTable } from 'components/SmallTable';
import { useStats } from 'lib/queries/stats'; import { useStats } from 'lib/queries/stats';
import { colorHash } from 'lib/utils/client';
import { useMemo } from 'react';
import { Pie } from 'react-chartjs-2';
export default function Types() { export default function Types() {
const stats = useStats(); const stats = useStats();
@ -9,6 +13,23 @@ export default function Types() {
const latest = stats.data[0]; const latest = stats.data[0];
const chartData = useMemo<{
uploadTypes: ChartData<'pie', number[], string>;
}>(() => {
return {
uploadTypes: {
labels: latest?.data.types_count.map((x) => x.mimetype),
datasets: [
{
data: latest?.data.types_count.map((x) => x.count),
label: ' Count',
backgroundColor: latest?.data.types_count.map((x) => colorHash(x.mimetype)),
},
],
},
};
}, [latest]);
return ( return (
<Box mt='md'> <Box mt='md'>
{latest.data.count_by_user.length ? ( {latest.data.count_by_user.length ? (
@ -23,6 +44,9 @@ export default function Types() {
</Card> </Card>
) : null} ) : null}
<Card> <Card>
<Title size='h4'>Upload Types</Title>
<Grid>
<Grid.Col md={12} lg={8}>
<SmallTable <SmallTable
columns={[ columns={[
{ id: 'mimetype', name: 'Type' }, { id: 'mimetype', name: 'Type' },
@ -30,6 +54,12 @@ export default function Types() {
]} ]}
rows={latest.data.types_count} rows={latest.data.types_count}
/> />
</Grid.Col>
<Grid.Col md={12} lg={4}>
<Center>{chartData && <Pie data={chartData.uploadTypes} style={{ maxHeight: '20vh' }} />}</Center>
</Grid.Col>
</Grid>
</Card> </Card>
</Box> </Box>
); );

View file

@ -8,7 +8,8 @@ import { useEffect } from 'react';
export default function PrismCode({ code, ext, ...props }) { export default function PrismCode({ code, ext, ...props }) {
useEffect(() => { useEffect(() => {
(async () => { (async () => {
if (ext !== 'txt') await import(`prismjs/components/prism-${extToPrismComponent(ext)}`); const component = extToPrismComponent[ext];
if (component && ext !== 'txt') await import(`prismjs/components/prism-${component}`);
})(); })();
}, [ext]); }, [ext]);

View file

@ -35,6 +35,7 @@ export default {
json: 'JSON', json: 'JSON',
vim: 'Vim Script', vim: 'Vim Script',
txt: 'Plain Text', txt: 'Plain Text',
html: 'HTML',
}; };
export const extToPrismComponent = (ext: string) => { export const extToPrismComponent = (ext: string) => {
@ -75,5 +76,6 @@ export const extToPrismComponent = (ext: string) => {
vb: 'visual-basic', vb: 'visual-basic',
json: 'json', json: 'json',
vim: 'vim', vim: 'vim',
html: 'html',
}[ext]; }[ext];
}; };

View file

@ -138,3 +138,18 @@ export function expireReadToDate(expires: string): Date {
}[expires] }[expires]
); );
} }
export function colorHash(str: string) {
let hash = 0;
for (let i = 0; i < str.length; i++) {
hash = str.charCodeAt(i) + ((hash << 5) - hash);
}
let color = '#';
for (let i = 0; i < 3; i++) {
let value = (hash >> (i * 8)) & 0xff;
color += ('00' + value.toString(16)).substr(-2);
}
return color;
}

View file

@ -1,7 +1,6 @@
import { PrismaClient } from '@prisma/client'; import { PrismaClient } from '@prisma/client';
import { Migrate } from '@prisma/migrate/dist/Migrate'; import { Migrate } from '@prisma/migrate/dist/Migrate';
import { ensureDatabaseExists } from '@prisma/migrate/dist/utils/ensureDatabaseExists'; import { ensureDatabaseExists } from '@prisma/migrate/dist/utils/ensureDatabaseExists';
import { FastifyInstance } from 'fastify';
import { ServerResponse } from 'http'; import { ServerResponse } from 'http';
import { Datasource } from '../lib/datasources'; import { Datasource } from '../lib/datasources';
import Logger from '../lib/logger'; import Logger from '../lib/logger';

752
yarn.lock

File diff suppressed because it is too large Load diff