From 1804bdbb997204205b1b05868f1f0a6ba9df25b9 Mon Sep 17 00:00:00 2001 From: Dimitar765 <112801140+Dimitar765@users.noreply.github.com> Date: Mon, 28 Oct 2024 23:52:47 +0100 Subject: [PATCH] admin panel redisign --- backend/imk-backend/prisma/schema.prisma | 4 +- .../imk-backend/src/admin/admin.service.ts | 94 ++++- frontend/imk/package-lock.json | 92 ++--- frontend/imk/package.json | 6 +- .../src/components/adminPanel/AdminPanel.jsx | 360 +++++++++++------- .../documentUpload/DocumentUpload.jsx | 108 ++++++ frontend/imk/src/services/api.js | 22 +- 7 files changed, 476 insertions(+), 210 deletions(-) create mode 100644 frontend/imk/src/components/documentUpload/DocumentUpload.jsx diff --git a/backend/imk-backend/prisma/schema.prisma b/backend/imk-backend/prisma/schema.prisma index b96a29f..400e208 100644 --- a/backend/imk-backend/prisma/schema.prisma +++ b/backend/imk-backend/prisma/schema.prisma @@ -46,4 +46,6 @@ model Notification { userId Int user User @relation(fields: [userId], references: [id]) createdAt DateTime @default(now()) -} \ No newline at end of file +} + + diff --git a/backend/imk-backend/src/admin/admin.service.ts b/backend/imk-backend/src/admin/admin.service.ts index 76b82e2..b33a3bd 100644 --- a/backend/imk-backend/src/admin/admin.service.ts +++ b/backend/imk-backend/src/admin/admin.service.ts @@ -1,4 +1,4 @@ -import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common'; +import { Injectable, NotFoundException } from '@nestjs/common'; import { PrismaService } from '../prisma/prisma.service'; import { S3Service } from '../s3/s3.service'; import { CreateDocumentDto } from '../dto/create-document.dto'; @@ -85,7 +85,6 @@ export class AdminService { }); } - async getAllDocuments() { return this.prisma.document.findMany(); } @@ -172,22 +171,91 @@ export class AdminService { }); } + // async uploadDocument( + // file: Express.Multer.File, + // title: string, + // userId: number, + // ) { + // try { + // // First create document with pending status + // const document = await this.prisma.document.create({ + // data: { + // title, + // authorId: userId, + // status: 'pending', + // s3Key: '', // Temporary empty key + // }, + // }); + + // // Update status to uploading + // await this.prisma.document.update({ + // where: { id: document.id }, + // data: { status: 'uploading' }, + // }); + + // // Upload to S3 + // const s3Key = await this.s3Service.uploadFile(file, 'documents'); + + // // Update document with s3Key and completed status + // return this.prisma.document.update({ + // where: { id: document.id }, + // data: { + // s3Key, + // status: 'completed', + // }, + // }); + // } catch (error) { + // // If anything fails, update status to failed + // const document = await this.prisma.document.findFirst({ + // where: { title, authorId: userId }, + // }); + // if (document) { + // await this.prisma.document.update({ + // where: { id: document.id }, + // data: { status: 'failed' }, + // }); + // } + // throw error; + // } + // } + + // problem whith upload status writing to db, i will fix it later + async uploadDocument( file: Express.Multer.File, title: string, - authorId: number, + userId: number, ) { - const key = `documents/${Date.now()}-${file.originalname}`; - const s3Key = await this.s3Service.uploadFile(file, key); + let s3Key; + try { + // First upload to S3 + s3Key = await this.s3Service.uploadFile(file, 'documents'); - return this.prisma.document.create({ - data: { - title, - s3Key, - authorId, - status: 'completed', - }, - }); + // Then create document with completed status and s3Key + const document = await this.prisma.document.create({ + data: { + title, + authorId: userId, + s3Key, + status: 'completed', // Set status to completed immediately after successful upload + }, + }); + + return document; + } catch (error) { + // Create document with failed status if upload fails + if (title && userId) { + await this.prisma.document.create({ + data: { + title, + authorId: userId, + s3Key: s3Key || '', + status: 'failed', + }, + }); + } + throw error; + } } async getDocumentUrl(documentId: number) { diff --git a/frontend/imk/package-lock.json b/frontend/imk/package-lock.json index 1b6954d..8a75bc6 100644 --- a/frontend/imk/package-lock.json +++ b/frontend/imk/package-lock.json @@ -20,13 +20,13 @@ "@types/react": "^18.2.15", "@types/react-dom": "^18.2.7", "@vitejs/plugin-react": "^4.0.3", - "autoprefixer": "^10.4.15", + "autoprefixer": "^10.4.20", "eslint": "^8.45.0", "eslint-plugin-react": "^7.32.2", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.3", - "postcss": "^8.4.28", - "tailwindcss": "^3.3.3", + "postcss": "^8.4.47", + "tailwindcss": "^3.4.14", "vite": "^4.4.5" } }, @@ -1166,9 +1166,9 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/autoprefixer": { - "version": "10.4.15", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.15.tgz", - "integrity": "sha512-KCuPB8ZCIqFdA4HwKXsvz7j6gvSDNhDP7WnUjBleRkKjPdvCmHFuQ77ocavI8FT6NdvlBnE2UFr2H4Mycn8Vew==", + "version": "10.4.20", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", + "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", "dev": true, "funding": [ { @@ -1185,11 +1185,11 @@ } ], "dependencies": { - "browserslist": "^4.21.10", - "caniuse-lite": "^1.0.30001520", - "fraction.js": "^4.2.0", + "browserslist": "^4.23.3", + "caniuse-lite": "^1.0.30001646", + "fraction.js": "^4.3.7", "normalize-range": "^0.1.2", - "picocolors": "^1.0.0", + "picocolors": "^1.0.1", "postcss-value-parser": "^4.2.0" }, "bin": { @@ -1262,9 +1262,9 @@ } }, "node_modules/browserslist": { - "version": "4.21.10", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz", - "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==", + "version": "4.24.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", + "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", "dev": true, "funding": [ { @@ -1281,10 +1281,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001517", - "electron-to-chromium": "^1.4.477", - "node-releases": "^2.0.13", - "update-browserslist-db": "^1.0.11" + "caniuse-lite": "^1.0.30001669", + "electron-to-chromium": "^1.5.41", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" @@ -1325,9 +1325,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001523", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001523.tgz", - "integrity": "sha512-I5q5cisATTPZ1mc588Z//pj/Ox80ERYDfR71YnvY7raS/NOk8xXlZcB0sF7JdqaV//kOaa6aus7lRfpdnt1eBA==", + "version": "1.0.30001673", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001673.tgz", + "integrity": "sha512-WTrjUCSMp3LYX0nE12ECkV0a+e6LC85E0Auz75555/qr78Oc8YWhEPNfDd6SHdtlCMSzqtuXY0uyEMNRcsKpKw==", "dev": true, "funding": [ { @@ -1524,9 +1524,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.503", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.503.tgz", - "integrity": "sha512-LF2IQit4B0VrUHFeQkWhZm97KuJSGF2WJqq1InpY+ECpFRkXd8yTIaTtJxsO0OKDmiBYwWqcrNaXOurn2T2wiA==", + "version": "1.5.48", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.48.tgz", + "integrity": "sha512-FXULnNK7ACNI9MTMOVAzUGiz/YrK9Kcb0s/JT4aJgsam7Eh6XYe7Y6q95lPq+VdBe1DpT2eTnfXFtnuPGCks4w==", "dev": true }, "node_modules/es-abstract": { @@ -1682,9 +1682,9 @@ } }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, "engines": { "node": ">=6" @@ -2148,16 +2148,16 @@ } }, "node_modules/fraction.js": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.1.tgz", - "integrity": "sha512-/KxoyCnPM0GwYI4NN0Iag38Tqt+od3/mLuguepLgCAKPn0ZhC544nssAW0tG2/00zXEYl9W+7hwAIpLHo6Oc7Q==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", "dev": true, "engines": { "node": "*" }, "funding": { "type": "patreon", - "url": "https://www.patreon.com/infusion" + "url": "https://github.com/sponsors/rawify" } }, "node_modules/fs.realpath": { @@ -2815,9 +2815,9 @@ } }, "node_modules/jiti": { - "version": "1.19.3", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.19.3.tgz", - "integrity": "sha512-5eEbBDQT/jF1xg6l36P+mWGGoH9Spuy0PCdSr2dtWRDGC6ph/w9ZCL4lmESW8f8F7MwT3XKescfP0wnZWAKL9w==", + "version": "1.21.6", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", + "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", "dev": true, "bin": { "jiti": "bin/jiti.js" @@ -3078,9 +3078,9 @@ "dev": true }, "node_modules/node-releases": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", - "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", "dev": true }, "node_modules/normalize-path": { @@ -4007,9 +4007,9 @@ } }, "node_modules/tailwindcss": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.3.tgz", - "integrity": "sha512-A0KgSkef7eE4Mf+nKJ83i75TMyq8HqY3qmFIJSWy8bNt0v1lG7jUcpGpoTFxAwYcWOphcTBLPPJg+bDfhDf52w==", + "version": "3.4.14", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.14.tgz", + "integrity": "sha512-IcSvOcTRcUtQQ7ILQL5quRDg7Xs93PdJEk1ZLbhhvJc7uj/OAhYOnruEiwnGgBvUtaUAJ8/mhSw1o8L2jCiENA==", "dev": true, "dependencies": { "@alloc/quick-lru": "^5.2.0", @@ -4017,10 +4017,10 @@ "chokidar": "^3.5.3", "didyoumean": "^1.2.2", "dlv": "^1.1.3", - "fast-glob": "^3.2.12", + "fast-glob": "^3.3.0", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", - "jiti": "^1.18.2", + "jiti": "^1.21.0", "lilconfig": "^2.1.0", "micromatch": "^4.0.5", "normalize-path": "^3.0.0", @@ -4210,9 +4210,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", - "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", "dev": true, "funding": [ { @@ -4229,8 +4229,8 @@ } ], "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.2.0", + "picocolors": "^1.1.0" }, "bin": { "update-browserslist-db": "cli.js" diff --git a/frontend/imk/package.json b/frontend/imk/package.json index db89e52..30c07aa 100644 --- a/frontend/imk/package.json +++ b/frontend/imk/package.json @@ -22,13 +22,13 @@ "@types/react": "^18.2.15", "@types/react-dom": "^18.2.7", "@vitejs/plugin-react": "^4.0.3", - "autoprefixer": "^10.4.15", + "autoprefixer": "^10.4.20", "eslint": "^8.45.0", "eslint-plugin-react": "^7.32.2", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.3", - "postcss": "^8.4.28", - "tailwindcss": "^3.3.3", + "postcss": "^8.4.47", + "tailwindcss": "^3.4.14", "vite": "^4.4.5" } } diff --git a/frontend/imk/src/components/adminPanel/AdminPanel.jsx b/frontend/imk/src/components/adminPanel/AdminPanel.jsx index 4745ae3..2a29ab5 100644 --- a/frontend/imk/src/components/adminPanel/AdminPanel.jsx +++ b/frontend/imk/src/components/adminPanel/AdminPanel.jsx @@ -1,164 +1,238 @@ -import { useState, useEffect } from 'react'; -import { getAllUsers, uploadDocument } from '../../services/api'; - -function AdminPanel() { - const [users, setUsers] = useState([]); - const [file, setFile] = useState(null); - const [title, setTitle] = useState(''); - - useEffect(() => { - fetchUsers(); - }, []); - - const fetchUsers = async () => { - try { - const response = await getAllUsers(); - setUsers(response.data); - } catch (error) { - console.error('Failed to fetch users:', error); - } - }; - - const handleFileUpload = async (e) => { - e.preventDefault(); - if (!file) return; - - const formData = new FormData(); - formData.append('file', file); - formData.append('title', title); - - try { - await uploadDocument(formData); - alert('Document uploaded successfully'); - } catch (error) { - console.error('Failed to upload document:', error); - } - }; - - return ( -