add check modal window

This commit is contained in:
smanylov
2026-01-28 18:53:08 +07:00
parent a6a493fe97
commit c4ab78b89b
13 changed files with 318 additions and 67 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "no-copy-frontend", "name": "no-copy-frontend",
"version": "0.24.0", "version": "0.25.0",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "next dev -p 2999", "dev": "next dev -p 2999",
+7 -7
View File
@@ -9,7 +9,7 @@ export async function getUserData() {
const token = await getSessionData('token'); const token = await getSessionData('token');
/* для теста */ /* для теста */
if (userEmail === "test" && token === "1111") { if (userEmail === 'test' && token === '1111') {
return testUserData; return testUserData;
} }
/* для теста */ /* для теста */
@@ -18,9 +18,9 @@ export async function getUserData() {
const response = await fetch(`${API_BASE_URL}/v1/api/user?email=${userEmail}`, { const response = await fetch(`${API_BASE_URL}/v1/api/user?email=${userEmail}`, {
method: 'GET', method: 'GET',
headers: { headers: {
"Content-Type": "application/json", 'Content-Type': 'application/json',
"Accept": "application/json", 'Accept': 'application/json',
"Authorization": `Bearer ${token}`, 'Authorization': `Bearer ${token}`,
} }
}); });
@@ -42,13 +42,13 @@ export async function getUserFilesInfo() {
version: 1, version: 1,
msg_id: 20005, msg_id: 20005,
message_body: { message_body: {
action: "user_files_info", action: 'user_files_info',
token: token token: token
} }
}), }),
headers: { headers: {
"Content-Type": "application/json", 'Content-Type': 'application/json',
"Accept": "application/json" 'Accept': 'application/json'
} }
}); });
+11 -11
View File
@@ -11,9 +11,9 @@ export async function logout() {
await fetch(`${API_BASE_URL}/v1/api/auth/logout`, { await fetch(`${API_BASE_URL}/v1/api/auth/logout`, {
method: 'POST', method: 'POST',
headers: { headers: {
"Content-Type": "application/json", 'Content-Type': 'application/json',
"Accept": "application/json", 'Accept': 'application/json',
"Authorization": `Bearer ${token}`, 'Authorization': `Bearer ${token}`,
} }
}); });
} catch (error) { } catch (error) {
@@ -36,8 +36,8 @@ export async function authorization(
const password = formData.get('password'); const password = formData.get('password');
/* для теста */ /* для теста */
if (email === "test" && password === "test") { if (email === 'test' && password === 'test') {
await createSession("1111", "test"); await createSession('1111', 'test');
redirect('/pages/dashboard'); redirect('/pages/dashboard');
} }
/* для теста */ /* для теста */
@@ -81,8 +81,8 @@ export async function authorization(
} }
}), }),
headers: { headers: {
"Content-Type": "application/json", 'Content-Type': 'application/json',
"Accept": "application/json" 'Accept': 'application/json'
} }
}); });
if (response.ok) { if (response.ok) {
@@ -211,8 +211,8 @@ export async function registration(
} }
}), }),
headers: { headers: {
"Content-Type": "application/json", 'Content-Type': 'application/json',
"Accept": "application/json" 'Accept': 'application/json'
} }
}); });
@@ -302,8 +302,8 @@ export async function tokenLifeExtension() {
const response = await fetch(`${API_BASE_URL}/api/v1/data`, { const response = await fetch(`${API_BASE_URL}/api/v1/data`, {
method: 'POST', method: 'POST',
headers: { headers: {
"Content-Type": "application/json", 'Content-Type': 'application/json',
"Accept": "application/json", 'Accept': 'application/json',
}, },
body: JSON.stringify({ body: JSON.stringify({
version: 1, version: 1,
+1 -1
View File
@@ -1,5 +1,5 @@
import * as z from 'zod' import * as z from 'zod'
import { createValidationSchema } from "@/app/lib/validation-config-parser"; import { createValidationSchema } from '@/app/lib/validation-config-parser';
import validationConfig from '@/app/lib/validation-config.json'; import validationConfig from '@/app/lib/validation-config.json';
export type FormState = export type FormState =
+44 -6
View File
@@ -21,8 +21,8 @@ export async function getUserFilesData(page: number, pageSize: number) {
} }
}), }),
headers: { headers: {
"Content-Type": "application/json", 'Content-Type': 'application/json',
"Accept": "application/json" 'Accept': 'application/json'
} }
}); });
@@ -59,8 +59,8 @@ export async function removeUserFile(fileId: string, fullDelete: number) {
} }
}), }),
headers: { headers: {
"Content-Type": "application/json", 'Content-Type': 'application/json',
"Accept": "application/json" 'Accept': 'application/json'
} }
}); });
@@ -120,8 +120,46 @@ export async function searchGlobalFiles(fileId: string) {
} }
}), }),
headers: { headers: {
"Content-Type": "application/json", 'Content-Type': 'application/json',
"Accept": "application/json" 'Accept': 'application/json'
}
});
if (response.ok) {
let parsed = await response.json();
if (parsed.message_code === 0) {
return parsed.message_body;
} else {
throw parsed;
}
} else {
throw (`${response.status}`);
}
} catch (error) {
return error
}
}
export async function viewFileInfo(fileId: string) {
const token = await getSessionData('token');
try {
const response = await fetch(`${API_BASE_URL}/api/v1/data`, {
method: 'POST',
body: JSON.stringify({
version: 1,
msg_id: 20005,
message_body: {
action: 'file_info',
file_id: fileId,
token: token
}
}),
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
} }
}); });
+10 -10
View File
@@ -18,7 +18,7 @@ export async function fileUpload(messageBody: initMessageBody) {
return; return;
} }
const message = messageBody; const message = messageBody;
message.action = "init"; message.action = 'init';
message.token = token; message.token = token;
try { try {
@@ -30,8 +30,8 @@ export async function fileUpload(messageBody: initMessageBody) {
message_body: message message_body: message
}), }),
headers: { headers: {
"Content-Type": "application/json", 'Content-Type': 'application/json',
"Accept": "application/json" 'Accept': 'application/json'
} }
}); });
@@ -68,13 +68,13 @@ export async function cancelUpload(udloadId: string) {
version: 1, version: 1,
msg_id: 20004, msg_id: 20004,
message_body: { message_body: {
action: "cancel", action: 'cancel',
upload_id: udloadId, upload_id: udloadId,
} }
}), }),
headers: { headers: {
"Content-Type": "application/json", 'Content-Type': 'application/json',
"Accept": "application/json" 'Accept': 'application/json'
} }
}); });
@@ -138,8 +138,8 @@ export async function checkChunkStatus(upload_id: string) {
} }
}), }),
headers: { headers: {
"Content-Type": "application/json", 'Content-Type': 'application/json',
"Accept": "application/json" 'Accept': 'application/json'
} }
}); });
@@ -173,8 +173,8 @@ export async function getAllowedFilesExtensions(type: string) {
} }
}), }),
headers: { headers: {
"Content-Type": "application/json", 'Content-Type': 'application/json',
"Accept": "application/json" 'Accept': 'application/json'
} }
}); });
+2 -2
View File
@@ -15,8 +15,8 @@ export async function vkAuthorization(data : any, codeVerifier: string) {
const response = await fetch(`${API_BASE_URL}/api/v1/vk/authorization/${code}/${state}/${codeVerifier}/${device_id}`, { const response = await fetch(`${API_BASE_URL}/api/v1/vk/authorization/${code}/${state}/${codeVerifier}/${device_id}`, {
method: 'GET', method: 'GET',
headers: { headers: {
"Content-Type": "application/json", 'Content-Type': 'application/json',
"Accept": "application/json" 'Accept': 'application/json'
} }
}); });
if (response.ok) { if (response.ok) {
+2 -2
View File
@@ -15,8 +15,8 @@ export async function YandexAuthorization(data: any, codeVerifier: string) {
const response = await fetch(`${API_BASE_URL}/api/v1/yandex/authorization/${code}/${state}/${codeVerifier}/${device_id}`, { const response = await fetch(`${API_BASE_URL}/api/v1/yandex/authorization/${code}/${state}/${codeVerifier}/${device_id}`, {
method: 'GET', method: 'GET',
headers: { headers: {
"Content-Type": "application/json", 'Content-Type': 'application/json',
"Accept": "application/json" 'Accept': 'application/json'
} }
}); });
if (response.ok) { if (response.ok) {
+39 -21
View File
@@ -15,11 +15,12 @@ import { IconImageFile, IconVideoFile, IconAudioFile, IconEye, IconDoubleArrowRi
import { useTranslations, useLocale } from 'next-intl'; import { useTranslations, useLocale } from 'next-intl';
import DropDownList from '@/app/components/dropDownList'; import DropDownList from '@/app/components/dropDownList';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { getUserFilesData, removeUserFile } from '@/app/actions/fileEntity'; import { getUserFilesData, removeUserFile, viewFileInfo } from '@/app/actions/fileEntity';
import ModalWindow from '@/app/components/modalWindow'; import ModalWindow from '@/app/components/modalWindow';
import { toast } from 'sonner'; import { toast } from 'sonner';
import { pluralize } from '@/app/lib/pluralize'; import { pluralize } from '@/app/lib/pluralize';
import { convertBytes } from '@/app/lib/convertBytes'; import { convertBytes } from '@/app/lib/convertBytes';
import { FileInfoModalWindow } from '@/app/ui/modal-windows/file-info-modal-window';
type FileType = 'image' | 'video' | 'audio'; type FileType = 'image' | 'video' | 'audio';
@@ -423,30 +424,12 @@ export default function TanstakFilesTable({ fileType }: { fileType: string }) {
cell: ({ row }) => ( cell: ({ row }) => (
<div className="actions"> <div className="actions">
<div className="actions-group" style={{ display: "none" }}> <div className="actions-group" style={{ display: "none" }}>
<button
onClick={() => handleView(row.original)}
className="bg-blue-500 hover:bg-blue-600"
>
<IconEye />
</button>
<button <button
onClick={() => handleProtect(row.original)} onClick={() => handleProtect(row.original)}
className="bg-violet-500 hover:bg-violet-600" className="bg-violet-500 hover:bg-violet-600"
> >
<IconShieldExclamation /> <IconShieldExclamation />
</button> </button>
</div>
<div className="actions-group">
<button
onClick={() => handleDownload(row.original)}
disabled={isFileLoading}
className="table-action-download"
>
<IconFileDownload />
<span>
{t('download')}
</span>
</button>
{/* <button {/* <button
onClick={() => handleOpenWindowForRemove(row.original)} onClick={() => handleOpenWindowForRemove(row.original)}
className="table-action-delete" className="table-action-delete"
@@ -457,6 +440,31 @@ export default function TanstakFilesTable({ fileType }: { fileType: string }) {
</span> </span>
</button> */} </button> */}
</div> </div>
<div className="actions-group">
{row.original.protectStatus === 'PROTECTED' && (
<button
onClick={() => handleDownload(row.original)}
disabled={isFileLoading}
className="table-action-download"
>
<IconFileDownload />
<span>
{t('download')}
</span>
</button>
)}
<button
onClick={() => {
handleView(row.original)
}}
className="table-action-view"
>
<IconEye />
<span>
{t('make-check')}
</span>
</button>
</div>
</div> </div>
), ),
@@ -467,9 +475,19 @@ export default function TanstakFilesTable({ fileType }: { fileType: string }) {
[] []
); );
// Обработчики действий const handleView = async (file: FileItem) => {
const handleView = (file: FileItem) => {
console.log(`Просмотр файла: ${file.fileName}`); console.log(`Просмотр файла: ${file.fileName}`);
console.log(file);
const fileInfo = await viewFileInfo(file.id);
console.log(fileInfo);
setOpenWindowChildren(() => {
return (
<FileInfoModalWindow fileInfo={fileInfo} setWindowClose={setOpenWindow} setWindowChildren={setOpenWindowChildren} />
)
})
setOpenWindow(true);
}; };
const handleDownload = async (file: FileItem) => { const handleDownload = async (file: FileItem) => {
+56 -4
View File
@@ -769,10 +769,15 @@
} }
} }
.table-action-download { .table-action-download,
.table-action-delete,
.table-action-view {
display: flex; display: flex;
background-color: #3b72e0;
align-items: center; align-items: center;
}
.table-action-download {
background-color: #3b72e0;
&:hover { &:hover {
background-color: #2d56a8; background-color: #2d56a8;
@@ -780,14 +785,20 @@
} }
.table-action-delete { .table-action-delete {
display: flex;
background-color: #e80a14; background-color: #e80a14;
align-items: center;
&:hover { &:hover {
background-color: #9f0712; background-color: #9f0712;
} }
} }
.table-action-view {
background-color: #2b7fff;
&:hover {
background-color: #155dfc;
}
}
} }
} }
} }
@@ -3482,4 +3493,45 @@
} }
} }
} }
}
.file-info-modal-window {
width: 50vw;
min-width: 400px;
&-close-button {
position: absolute;
top: 15px;
right: 20px;
background: none;
border: none;
font-size: 24px;
cursor: pointer;
color: #64748b;
}
&-section {
margin-bottom: 25px;
}
&-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 15px;
}
&-item {
background: v.$bg-light;
padding: 15px;
border-radius: 8px;
}
&-title {
font-weight: 600;
color: v.$text-p;
}
&-content {
color: v.$text-s;
}
} }
@@ -0,0 +1,139 @@
export function FileInfoModalWindow({ fileInfo, setWindowClose, setWindowChildren }: any) {
const exampleTest = {
ownerName: 'string',
ownerMail: 'string',
ownerCompany: 'string',
fileName: 'string',
fileSize: 'number',
fileUploadDate: 'number',
fileFormat: 'string',
protectStatus: 'string',
checksCount: 'number'
}
function closeHandler() {
setWindowChildren(null);
setWindowClose(false);
}
return (
<div className='file-info-modal-window'>
<div
className="flex justify-between"
>
<h3 className="text-2xl mb-4">
Результат проверки
</h3>
<button
className="file-info-modal-window-close-button"
onClick={closeHandler}
>
×
</button>
</div>
<div
className="file-info-modal-window-section"
>
<h4
className="mb-2"
>
Информация о владельце
</h4>
<div className="file-info-modal-window-grid" >
<div className="file-info-modal-window-item">
<div className="file-info-modal-window-title" >
Имя
</div>
<div className="file-info-modal-window-content" >
{fileInfo.ownerName ? fileInfo.ownerName : '-'}
</div>
</div>
<div className="file-info-modal-window-item">
<div className="file-info-modal-window-title" >
Email
</div>
<div className="file-info-modal-window-content" >
{fileInfo.ownerMail ? fileInfo.ownerMail : '-'}
</div>
</div>
<div className="file-info-modal-window-item">
<div className="file-info-modal-window-title" >
Компания
</div>
<div className="file-info-modal-window-content" >
{fileInfo.ownerCompany ? fileInfo.ownerCompany : '-'}
</div>
</div>
</div>
<h4
className="mb-2"
>
Информация о файле
</h4>
<div className="file-info-modal-window-grid" >
<div className="file-info-modal-window-item">
<div className="file-info-modal-window-title" >
Имя файла
</div>
<div className="file-info-modal-window-content" >
{fileInfo.fileName ? fileInfo.fileName : '-'}
</div>
</div>
<div className="file-info-modal-window-item">
<div className="file-info-modal-window-title" >
Размер
</div>
<div className="file-info-modal-window-content" >
{fileInfo.fileSize ? fileInfo.fileSize : '-'}
</div>
</div>
<div className="file-info-modal-window-item">
<div className="file-info-modal-window-title" >
Загружен
</div>
<div className="file-info-modal-window-content" >
{fileInfo.fileUploadDate ? fileInfo.fileUploadDate : '-'}
</div>
</div>
<div className="file-info-modal-window-item">
<div className="file-info-modal-window-title" >
Формат
</div>
<div className="file-info-modal-window-content" >
{fileInfo.fileFormat ? fileInfo.fileFormat : '-'}
</div>
</div>
</div>
<h4
className="mb-2"
>
Детали защиты
</h4>
<div className="file-info-modal-window-grid" >
<div className="file-info-modal-window-item">
<div className="file-info-modal-window-title" >
Статус защиты
</div>
<div className="file-info-modal-window-content" >
{fileInfo.protectStatus ? fileInfo.protectStatus : '-'}
</div>
</div>
<div className="file-info-modal-window-item">
<div className="file-info-modal-window-title" >
Количество проверок
</div>
<div className="file-info-modal-window-content" >
{fileInfo.checksCount ? fileInfo.checksCount : '-'}
</div>
</div>
</div>
</div>
</div>
)
}
+3 -1
View File
@@ -18,6 +18,7 @@
"violations-few": "Violations", "violations-few": "Violations",
"violations": "Violations", "violations": "Violations",
"check": "Check", "check": "Check",
"make-check": "Check",
"checks": "Checks", "checks": "Checks",
"checks-few": "Checks", "checks-few": "Checks",
"documents": "Documents", "documents": "Documents",
@@ -201,7 +202,8 @@
"PROCESSING": "Processing", "PROCESSING": "Processing",
"PROTECTED": "Protected", "PROTECTED": "Protected",
"FAILED": "Failed", "FAILED": "Failed",
"FAILED_SAVE": "Failed save" "FAILED_SAVE": "Failed save",
"view": "View"
}, },
"Login-register-form": { "Login-register-form": {
"and": "and", "and": "and",
+3 -1
View File
@@ -18,6 +18,7 @@
"violations-few": "Нарушения", "violations-few": "Нарушения",
"violations": "Нарушений", "violations": "Нарушений",
"check": "Проверка", "check": "Проверка",
"make-check": "Проверить",
"checks": "Проверок", "checks": "Проверок",
"checks-few": "Проверки", "checks-few": "Проверки",
"documents": "Документы", "documents": "Документы",
@@ -201,7 +202,8 @@
"PROCESSING": "Обработка", "PROCESSING": "Обработка",
"PROTECTED": "Защищено", "PROTECTED": "Защищено",
"FAILED": "Ошибка", "FAILED": "Ошибка",
"FAILED_SAVE": "Сохранение не удалось" "FAILED_SAVE": "Сохранение не удалось",
"view": "Посмотреть"
}, },
"Login-register-form": { "Login-register-form": {
"and": "и", "and": "и",