feat: update deps & fix stuff
This commit is contained in:
parent
d8b308a18c
commit
5d115afa71
12 changed files with 474 additions and 493 deletions
|
@ -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: |
|
||||||
|
|
||||||
|
|
62
package.json
62
package.json
|
@ -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",
|
||||||
|
|
5
src/components/icons/DatabaseIcon.tsx
Normal file
5
src/components/icons/DatabaseIcon.tsx
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import { Database } from 'react-feather';
|
||||||
|
|
||||||
|
export default function DatabaseIcon({ ...props }) {
|
||||||
|
return <Database size={15} {...props} />;
|
||||||
|
}
|
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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 && (
|
||||||
|
|
|
@ -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>
|
||||||
);
|
);
|
||||||
|
|
|
@ -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]);
|
||||||
|
|
||||||
|
|
|
@ -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];
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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';
|
||||||
|
|
Loading…
Reference in a new issue