diff --git a/Dockerignore b/Dockerignore
index 72776a961..1a2648e3d 100644
--- a/Dockerignore
+++ b/Dockerignore
@@ -1,3 +1,5 @@
-prisma/migrations
+prisma
node_modules
-.next
\ No newline at end of file
+.next
+uploads
+.git
diff --git a/package.json b/package.json
index 47c1456b7..cd8fa60d0 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "zip3",
- "version": "3.2.1",
+ "version": "3.2.2",
"scripts": {
"prepare": "husky install",
"dev": "NODE_ENV=development node server",
@@ -17,10 +17,9 @@
"@emotion/styled": "^11.3.0",
"@iarna/toml": "2.2.5",
"@material-ui/core": "^5.0.0-alpha.37",
- "@material-ui/data-grid": "^4.0.0-alpha.32",
"@material-ui/icons": "^5.0.0-alpha.37",
"@material-ui/styles": "^5.0.0-alpha.35",
- "@prisma/client": "^2.30.3",
+ "@prisma/client": "^3.0.2",
"@reduxjs/toolkit": "^1.6.0",
"argon2": "^0.28.2",
"colorette": "^1.2.2",
@@ -30,7 +29,7 @@
"formik": "^2.2.9",
"multer": "^1.4.2",
"next": "11.1.1",
- "prisma": "^2.30.3",
+ "prisma": "^3.0.2",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-dropzone": "^11.3.2",
diff --git a/server/index.js b/server/index.js
index 4861a15a0..ad4e088ea 100644
--- a/server/index.js
+++ b/server/index.js
@@ -123,6 +123,7 @@ function shouldUseYarn() {
});
srv.on('listening', () => {
Logger.get('server').info(`listening on ${config.core.host}:${config.core.port}`);
+ if (process.platform === 'linux' && dev) execSync(`xdg-open ${config.core.secure ? 'https' : 'http'}://${config.core.host === '0.0.0.0' ? 'localhost' : config.core.host}:${config.core.port}`);
});
srv.listen(config.core.port, config.core.host ?? '0.0.0.0');
diff --git a/src/components/Image.tsx b/src/components/Image.tsx
index 3f3d9a3c9..acbedd0aa 100644
--- a/src/components/Image.tsx
+++ b/src/components/Image.tsx
@@ -4,64 +4,80 @@ import {
Card,
CardMedia,
CardActionArea,
- Popover,
Button,
- ButtonGroup
+ Dialog,
+ DialogTitle,
+ DialogActions,
+ DialogContent
} from '@material-ui/core';
+import AudioIcon from '@material-ui/icons/Audiotrack';
import copy from 'copy-to-clipboard';
-import useFetch from '../lib/hooks/useFetch';
+import useFetch from 'hooks/useFetch';
export default function Image({ image, updateImages }) {
- const [anchorEl, setAnchorEl] = useState(null);
+ const [open, setOpen] = useState(false);
+ const [t,] = useState(image.mimetype.split('/')[0]);
const handleDelete = async () => {
- const res = await useFetch('/api/user/images', 'DELETE', { id: image.id });
+ const res = await useFetch('/api/user/files', 'DELETE', { id: image.id });
if (!res.error) updateImages(true);
- setAnchorEl(null);
+ setOpen(false);
};
const handleCopy = () => {
copy(`${window.location.protocol}//${window.location.host}${image.url}`);
- setAnchorEl(null);
+ setOpen(false);
};
const handleFavorite = async () => {
- const data = await useFetch('/api/user/images', 'PATCH', { id: image.id, favorite: !image.favorite });
+ const data = await useFetch('/api/user/files', 'PATCH', { id: image.id, favorite: !image.favorite });
if (!data.error) updateImages(true);
};
+ const Type = (props) => {
+ return {
+ 'video': ,
+ // eslint-disable-next-line jsx-a11y/alt-text
+ 'image': ,
+ 'audio':
+ }[t];
+ };
+
return (
<>
-
+
setAnchorEl(e.currentTarget)}
+ component={t === 'audio' ? AudioIcon : t} // this is done because audio without controls is hidden
+ onClick={() => setOpen(true)}
/>
- setAnchorEl(null)}
- anchorOrigin={{
- vertical: 'center',
- horizontal: 'center',
- }}
- transformOrigin={{
- vertical: 'center',
- horizontal: 'center',
- }}
+
+
+ {image.file}
+
+
+
+
+
+
+
+
+
+
+
>
);
}
\ No newline at end of file
diff --git a/src/components/Layout.tsx b/src/components/Layout.tsx
index 2487acaca..70eedf9b7 100644
--- a/src/components/Layout.tsx
+++ b/src/components/Layout.tsx
@@ -1,6 +1,5 @@
import React, { useState } from 'react';
import Link from 'next/link';
-import useFetch from '../lib/hooks/useFetch';
import {
AppBar,
@@ -29,13 +28,13 @@ import {
Menu as MenuIcon,
Home as HomeIcon,
AccountCircle as AccountIcon,
- Image as ImageIcon,
+ Folder as FolderIcon,
Upload as UploadIcon,
ContentCopy as CopyIcon,
Autorenew as ResetIcon,
Logout as LogoutIcon,
PeopleAlt as UsersIcon,
- Brush as BrushIcon
+ Brush as BrushIcon,
} from '@material-ui/icons';
import copy from 'copy-to-clipboard';
import Backdrop from './Backdrop';
@@ -43,6 +42,7 @@ import { friendlyThemeName, themes } from './Theming';
import { useRouter } from 'next/router';
import { useStoreDispatch } from 'lib/redux/store';
import { updateUser } from 'lib/redux/reducers/user';
+import useFetch from 'hooks/useFetch';
const items = [
{
@@ -51,9 +51,9 @@ const items = [
link: '/dashboard'
},
{
- icon: ,
- text: 'Images',
- link: '/dashboard/images'
+ icon: ,
+ text: 'Files',
+ link: '/dashboard/files'
},
{
icon: ,
diff --git a/src/components/Theming.tsx b/src/components/Theming.tsx
index 7bfd501d0..cb4a8d291 100644
--- a/src/components/Theming.tsx
+++ b/src/components/Theming.tsx
@@ -1,6 +1,8 @@
import React from 'react';
import { ThemeProvider } from '@emotion/react';
import { CssBaseline } from '@material-ui/core';
+
+// themes
import dark_blue from 'lib/themes/dark_blue';
import dark from 'lib/themes/dark';
import ayu_dark from 'lib/themes/ayu_dark';
@@ -9,6 +11,7 @@ import ayu_light from 'lib/themes/ayu_light';
import nord from 'lib/themes/nord';
import polar from 'lib/themes/polar';
import dracula from 'lib/themes/dracula';
+
import { useStoreSelector } from 'lib/redux/store';
import createTheme from 'lib/themes';
diff --git a/src/components/pages/Dashboard.tsx b/src/components/pages/Dashboard.tsx
index a011dcef5..a2b4d5c18 100644
--- a/src/components/pages/Dashboard.tsx
+++ b/src/components/pages/Dashboard.tsx
@@ -16,6 +16,7 @@ import {
CardMedia,
Card as MuiCard
} from '@material-ui/core';
+import AudioIcon from '@material-ui/icons/Audiotrack';
import Link from 'components/Link';
import Card from 'components/Card';
@@ -61,18 +62,19 @@ function StatTable({ rows, columns }) {
{columns.map(col => (
- {col.name}
+ t.palette.divider }}>{col.name}
))}
- {rows.map((row, i) => (
+ {rows.map(row => (
{columns.map(col => (
-
+ t.palette.divider }}>
{col.format ? col.format(row[col.id]) : row[col.id]}
))}
@@ -94,8 +96,8 @@ export default function Dashboard() {
const [rowsPerPage, setRowsPerPage] = useState(10);
const updateImages = async () => {
- const imgs = await useFetch('/api/user/images');
- const recent = await useFetch('/api/user/recent');
+ const imgs = await useFetch('/api/user/files');
+ const recent = await useFetch('/api/user/recent?filter=media');
const stts = await useFetch('/api/stats');
setImages(imgs);
setStats(stts);
@@ -106,13 +108,13 @@ export default function Dashboard() {
setPage(newPage);
};
- const handleChangeRowsPerPage = (event) => {
+ const handleChangeRowsPerPage = event => {
setRowsPerPage(+event.target.value);
setPage(0);
};
const handleDelete = async image => {
- const res = await useFetch('/api/user/images', 'DELETE', { id: image.id });
+ const res = await useFetch('/api/user/files', 'DELETE', { id: image.id });
if (!res.error) updateImages();
};
@@ -135,6 +137,8 @@ export default function Dashboard() {
sx={{ height: 220 }}
image={image.url}
title={image.file}
+ controls
+ component={image.mimetype.split('/')[0] === 'audio' ? AudioIcon : image.mimetype.split('/')[0]} // this is done because audio without controls is hidden
/>
@@ -173,16 +177,16 @@ export default function Dashboard() {
- {columns.map((column) => (
+ {columns.map(column => (
t.palette.divider }}
>
{column.label}
))}
-
+ t.palette.divider }} align='right'>
Actions
@@ -190,18 +194,18 @@ export default function Dashboard() {
{images
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
- .map((row) => {
+ .map(row => {
return (
- {columns.map((column) => {
+ {columns.map(column => {
const value = row[column.id];
return (
-
+ t.palette.divider }}>
{column.format ? column.format(value) : value}
);
})}
-
+ t.palette.divider }}>
diff --git a/src/components/pages/Images.tsx b/src/components/pages/Files.tsx
similarity index 87%
rename from src/components/pages/Images.tsx
rename to src/components/pages/Files.tsx
index d19ce41fd..35e6c6e66 100644
--- a/src/components/pages/Images.tsx
+++ b/src/components/pages/Files.tsx
@@ -1,12 +1,12 @@
import React, { useEffect, useState } from 'react';
import { Grid, Pagination, Box, Typography, Accordion, AccordionSummary, AccordionDetails } from '@material-ui/core';
+import { ExpandMore } from '@material-ui/icons';
import Backdrop from 'components/Backdrop';
import ZiplineImage from 'components/Image';
import useFetch from 'hooks/useFetch';
-import { ExpandMore } from '@material-ui/icons';
-export default function Upload() {
+export default function Files() {
const [pages, setPages] = useState([]);
const [page, setPage] = useState(1);
const [favoritePages, setFavoritePages] = useState([]);
@@ -15,9 +15,9 @@ export default function Upload() {
const updatePages = async favorite => {
setLoading(true);
- const pages = await useFetch('/api/user/images?paged=true&filter=image');
+ const pages = await useFetch('/api/user/files?paged=true&filter=media');
if (favorite) {
- const fPages = await useFetch('/api/user/images?paged=true&favorite=true');
+ const fPages = await useFetch('/api/user/files?paged=true&favorite=media');
setFavoritePages(fPages);
}
setPages(pages);
@@ -39,13 +39,13 @@ export default function Upload() {
pt={2}
pb={3}
>
- No Images
+ No Files
- ) : Images}
+ ) : Files}
{favoritePages.length ? (
t.palette.divider }} elevation={0}>
}>
- Favorite Images
+ Favorite Files
diff --git a/src/components/pages/Manage.tsx b/src/components/pages/Manage.tsx
index d5914f2c0..d5aa8654b 100644
--- a/src/components/pages/Manage.tsx
+++ b/src/components/pages/Manage.tsx
@@ -167,7 +167,6 @@ export default function Manage() {
validationSchema: themeValidationSchema,
onSubmit: async values => {
setLoading(true);
-
const newUser = await useFetch('/api/user', 'PATCH', { customTheme: values });
if (newUser.error) {
diff --git a/src/components/pages/Upload.tsx b/src/components/pages/Upload.tsx
index 2d210e28f..8ab65a9f2 100644
--- a/src/components/pages/Upload.tsx
+++ b/src/components/pages/Upload.tsx
@@ -18,7 +18,7 @@ export default function Upload({ route }) {
const [open, setOpen] = useState(false);
const [severity, setSeverity] = useState('success');
const [message, setMessage] = useState('Saved');
- console.log(files);
+
const handleUpload = async () => {
const body = new FormData();
diff --git a/src/lib/themes/index.ts b/src/lib/themes/index.ts
index d27f24827..452bf7849 100644
--- a/src/lib/themes/index.ts
+++ b/src/lib/themes/index.ts
@@ -48,7 +48,7 @@ export default function createTheme(o: ThemeOptions) {
backgroundColor: o.border
}
}
- }
- }
+ },
+ },
});
}
\ No newline at end of file
diff --git a/src/pages/api/user/images.ts b/src/pages/api/user/files.ts
similarity index 92%
rename from src/pages/api/user/images.ts
rename to src/pages/api/user/files.ts
index 952826bc3..22aed095d 100644
--- a/src/pages/api/user/images.ts
+++ b/src/pages/api/user/files.ts
@@ -55,7 +55,7 @@ async function handler(req: NextApiReq, res: NextApiRes) {
// @ts-ignore
images.map(image => image.url = `/r/${image.file}`);
- if (req.query.filter && req.query.filter === 'image') images = images.filter(x => x.mimetype.startsWith('image'));
+ if (req.query.filter && req.query.filter === 'media') images = images.filter(x => /^(video|audio|image)/.test(x.mimetype));
return res.json(req.query.paged ? chunk(images, 16) : images);
}
diff --git a/src/pages/api/user/recent.ts b/src/pages/api/user/recent.ts
index 7eb6b7043..26187f395 100644
--- a/src/pages/api/user/recent.ts
+++ b/src/pages/api/user/recent.ts
@@ -9,7 +9,7 @@ async function handler(req: NextApiReq, res: NextApiRes) {
if (take > 50) return res.error('take can\'t be more than 50');
- const images = await prisma.image.findMany({
+ let images = await prisma.image.findMany({
take,
orderBy: {
created_at: 'desc'
@@ -23,6 +23,7 @@ async function handler(req: NextApiReq, res: NextApiRes) {
// @ts-ignore
images.map(image => image.url = `/r/${image.file}`);
+ if (req.query.filter && req.query.filter === 'media') images = images.filter(x => /^(video|audio|image)/.test(x.mimetype));
return res.json(images);
}
diff --git a/src/pages/dashboard/images.tsx b/src/pages/dashboard/files.tsx
similarity index 85%
rename from src/pages/dashboard/images.tsx
rename to src/pages/dashboard/files.tsx
index fc3dc53f0..479a29174 100644
--- a/src/pages/dashboard/images.tsx
+++ b/src/pages/dashboard/files.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import useLogin from 'hooks/useLogin';
import Layout from 'components/Layout';
-import Images from 'components/pages/Images';
+import Files from 'components/pages/Files';
export default function ImagesPage() {
const { user, loading } = useLogin();
@@ -14,7 +14,7 @@ export default function ImagesPage() {
loading={loading}
noPaper={false}
>
-
+
);
}
diff --git a/yarn.lock b/yarn.lock
index a27ca7f5f..1a0e8f91b 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -399,16 +399,6 @@
react-is "^17.0.0"
react-transition-group "^4.4.0"
-"@material-ui/data-grid@^4.0.0-alpha.32":
- version "4.0.0-alpha.32"
- resolved "https://registry.yarnpkg.com/@material-ui/data-grid/-/data-grid-4.0.0-alpha.32.tgz#72952d1dea9a9440a02827dd66996a8e94d3f28f"
- integrity sha512-yEmQ8OGGHCB9fUx6f6/ncIxAQpH/U/295EqqocCsbIjLJA1rUYF5eseo2/jnW1Wd69o3aTsXozdlKV8tQNit2Q==
- dependencies:
- "@material-ui/utils" "^5.0.0-alpha.14"
- clsx "^1.0.4"
- prop-types "^15.7.2"
- reselect "^4.0.0"
-
"@material-ui/icons@^5.0.0-alpha.37":
version "5.0.0-alpha.37"
resolved "https://registry.yarnpkg.com/@material-ui/icons/-/icons-5.0.0-alpha.37.tgz#8579986e0a3b4586dc7fbf23234d8bfe909b6c3c"
@@ -487,7 +477,7 @@
prop-types "^15.7.2"
react-is "^17.0.0"
-"@material-ui/utils@5.0.0-alpha.35", "@material-ui/utils@^5.0.0-alpha.14":
+"@material-ui/utils@5.0.0-alpha.35":
version "5.0.0-alpha.35"
resolved "https://registry.yarnpkg.com/@material-ui/utils/-/utils-5.0.0-alpha.35.tgz#89078592c42bca5db712e82e12d56cd4be737c01"
integrity sha512-Msu+zIXd7Y2JrTU9JIf0xjjjAMdWEIdlj2Tmj9bSYFF6bgStrQ1WXXZxxFz5GmdzT7FcLi5U3PqBynSNX/QDGA==
@@ -612,22 +602,22 @@
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.9.2.tgz#adea7b6953cbb34651766b0548468e743c6a2353"
integrity sha512-VZMYa7+fXHdwIq1TDhSXoVmSPEGM/aa+6Aiq3nVVJ9bXr24zScr+NlKFKC3iPljA7ho/GAZr+d2jOf5GIRC30Q==
-"@prisma/client@^2.30.3":
- version "2.30.3"
- resolved "https://registry.yarnpkg.com/@prisma/client/-/client-2.30.3.tgz#49c1015e2cec26a44b20c62eb2fd738cb0bb043b"
- integrity sha512-Ey2miZ+Hne12We3rA8XrlPoAF0iuKEhw5IK2nropaelSt0Ju3b2qSz9Qt50a/1Mx3+7yRSu/iSXt8y9TUMl/Yw==
+"@prisma/client@^3.0.2":
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/@prisma/client/-/client-3.0.2.tgz#f04d9b252f3d0c6918df43ad228eac27d03f6db1"
+ integrity sha512-6SrDYY2Yr5AmYpVB3XAXFqfzxKMdDTemXR7FmfXthnxWhQHoBwRLNZ3B3GyI/MmWa5tr+kaaGDJjp1LU0vuYvQ==
dependencies:
- "@prisma/engines-version" "2.30.1-2.b8c35d44de987a9691890b3ddf3e2e7effb9bf20"
+ "@prisma/engines-version" "2.31.0-32.2452cc6313d52b8b9a96999ac0e974d0aedf88db"
-"@prisma/engines-version@2.30.1-2.b8c35d44de987a9691890b3ddf3e2e7effb9bf20":
- version "2.30.1-2.b8c35d44de987a9691890b3ddf3e2e7effb9bf20"
- resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-2.30.1-2.b8c35d44de987a9691890b3ddf3e2e7effb9bf20.tgz#d5ef55c92beeba56e52bba12b703af0bfd30530d"
- integrity sha512-/iDRgaoSQC77WN2oDsOM8dn61fykm6tnZUAClY+6p+XJbOEgZ9gy4CKuKTBgrjSGDVjtQ/S2KGcYd3Ring8xaw==
+"@prisma/engines-version@2.31.0-32.2452cc6313d52b8b9a96999ac0e974d0aedf88db":
+ version "2.31.0-32.2452cc6313d52b8b9a96999ac0e974d0aedf88db"
+ resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-2.31.0-32.2452cc6313d52b8b9a96999ac0e974d0aedf88db.tgz#c45323e420f47dd950b22c873bdcf38f75e65779"
+ integrity sha512-iArSApZZImVmT9oC/rGOjzvpG2AOqlIeqYcVnop9poA3FxD4zfVPbNPH9DTgOWhc06OkBHujJZeAcsNddVabIQ==
-"@prisma/engines@2.30.1-2.b8c35d44de987a9691890b3ddf3e2e7effb9bf20":
- version "2.30.1-2.b8c35d44de987a9691890b3ddf3e2e7effb9bf20"
- resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-2.30.1-2.b8c35d44de987a9691890b3ddf3e2e7effb9bf20.tgz#2df768aa7c9f84acaa1f35c970417822233a9fb1"
- integrity sha512-WPnA/IUrxDihrRhdP6+8KAVSwsc0zsh8ioPYsLJjOhzVhwpRbuFH2tJDRIAbc+qFh+BbTIZbeyBYt8fpNXaYQQ==
+"@prisma/engines@2.31.0-32.2452cc6313d52b8b9a96999ac0e974d0aedf88db":
+ version "2.31.0-32.2452cc6313d52b8b9a96999ac0e974d0aedf88db"
+ resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-2.31.0-32.2452cc6313d52b8b9a96999ac0e974d0aedf88db.tgz#b6cf70bc05dd2a62168a16f3ea58a1b011074621"
+ integrity sha512-Q9CwN6e5E5Abso7J3A1fHbcF4NXGRINyMnf7WQ07fXaebxTTARY5BNUzy2Mo5uH82eRVO5v7ImNuR044KTjLJg==
"@reduxjs/toolkit@^1.6.0":
version "1.6.0"
@@ -4444,12 +4434,12 @@ prepend-http@^1.0.1:
resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc"
integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=
-prisma@^2.30.3:
- version "2.30.3"
- resolved "https://registry.yarnpkg.com/prisma/-/prisma-2.30.3.tgz#e4a770e1f52151e72c1c5be0aa2e75222a0135c4"
- integrity sha512-48qYba2BIyUmXuosBZs0g3kYGrxKvo4VkSHYOuLlDdDirmKyvoY2hCYMUYHSx3f++8ovfgs+MX5KmNlP+iAZrQ==
+prisma@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/prisma/-/prisma-3.0.2.tgz#e86cb6abf4a815c7ac97b9d0ed383f01c253ce34"
+ integrity sha512-TyOCbtWGDVdWvsM1RhUzJXoGClXGalHhyYWIc5eizSF8T1ScGiOa34asBUdTnXOUBFSErbsqMNw40DHAteBm1A==
dependencies:
- "@prisma/engines" "2.30.1-2.b8c35d44de987a9691890b3ddf3e2e7effb9bf20"
+ "@prisma/engines" "2.31.0-32.2452cc6313d52b8b9a96999ac0e974d0aedf88db"
process-nextick-args@~2.0.0:
version "2.0.1"