add file info fro document view
This commit is contained in:
@@ -4,65 +4,124 @@ import Link from 'next/link';
|
|||||||
import PdfViewer from '@/app/components/PdfViewer';
|
import PdfViewer from '@/app/components/PdfViewer';
|
||||||
import { DownloadButton } from '@/app/components/document-viewer/DownloadButton';
|
import { DownloadButton } from '@/app/components/document-viewer/DownloadButton';
|
||||||
import { CopyLinkButton } from '@/app/components/document-viewer/CopyLinkButton';
|
import { CopyLinkButton } from '@/app/components/document-viewer/CopyLinkButton';
|
||||||
|
import { fetchDocumentInfo } from '@/app/actions/trackingActions';
|
||||||
|
import { LoginUserBage } from '@/app/components/document-viewer/LoginUserBage';
|
||||||
|
|
||||||
interface PageProps {
|
interface PageProps {
|
||||||
searchParams: Promise<{ docid: string; title?: string }>;
|
searchParams: Promise<{ docid: string; title?: string }>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface DocumentInfo {
|
||||||
|
checksCount?: number;
|
||||||
|
checksum?: string;
|
||||||
|
createdAt?: string;
|
||||||
|
downloadUrl?: string;
|
||||||
|
existsOnDisk?: boolean;
|
||||||
|
fileExtension?: string;
|
||||||
|
fileFormat?: string | null;
|
||||||
|
fileName?: string;
|
||||||
|
filePath?: string;
|
||||||
|
fileSize?: number;
|
||||||
|
fileUploadDate?: string;
|
||||||
|
formattedSize?: string;
|
||||||
|
id: string;
|
||||||
|
mimeType?: string;
|
||||||
|
monitoring?: string;
|
||||||
|
originalFileName?: string;
|
||||||
|
ownerCompany?: string | null;
|
||||||
|
ownerEmail?: string;
|
||||||
|
ownerName?: string;
|
||||||
|
permissions?: {
|
||||||
|
DOWNLOAD?: boolean;
|
||||||
|
};
|
||||||
|
protectStatus?: string;
|
||||||
|
protectedFilePath?: string;
|
||||||
|
status?: string;
|
||||||
|
storedFileName?: string;
|
||||||
|
supportId?: number;
|
||||||
|
thumbnailFileUrl?: string;
|
||||||
|
updatedAt?: string;
|
||||||
|
uploadSessionId?: string;
|
||||||
|
userId?: number;
|
||||||
|
}
|
||||||
|
|
||||||
export default async function Page({ searchParams }: PageProps) {
|
export default async function Page({ searchParams }: PageProps) {
|
||||||
const { docid, title } = await searchParams;
|
const { docid, title } = await searchParams;
|
||||||
|
|
||||||
|
let response: DocumentInfo | null = null;
|
||||||
|
let error: string | null = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
response = await fetchDocumentInfo(docid);
|
||||||
|
} catch (err) {
|
||||||
|
error = 'Не удалось загрузить информацию о документе';
|
||||||
|
}
|
||||||
|
|
||||||
const documentTitle = title || 'FileName';
|
const documentTitle = title || 'FileName';
|
||||||
const ownerName = "Name Name Name";
|
|
||||||
const companyName = "companyName";
|
if (error || !response) {
|
||||||
|
return (
|
||||||
|
<div className="watch-doc-wrapper">
|
||||||
|
<div className="watch-doc-page">
|
||||||
|
<header className="watch-doc-header">
|
||||||
|
<Link href="#" className="header-logo">NoCopy</Link>
|
||||||
|
<LoginUserBage />
|
||||||
|
</header>
|
||||||
|
<div className="error-container">
|
||||||
|
<h2>Ошибка загрузки документа</h2>
|
||||||
|
<p>{error || 'Документ не найден'}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="watch-doc-wrapper">
|
<div className="watch-doc-wrapper">
|
||||||
<div className="watch-doc-page">
|
<div className="watch-doc-page">
|
||||||
<header className="watch-doc-header">
|
<header className="watch-doc-header">
|
||||||
<Link href="#" className="header-logo">NoCopy</Link>
|
<Link href="#" className="header-logo">NoCopy</Link>
|
||||||
<Link href="#" className="header-user">Name</Link>
|
<LoginUserBage />
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div className="watch-doc-status">
|
<div className="watch-doc-status">
|
||||||
<div className="st-title">Защита подтверждена</div>
|
<div className="st-title">Защита подтверждена</div>
|
||||||
<div className="st-sub">
|
<div className="st-sub">
|
||||||
Документ <strong>{documentTitle}</strong> зарегистрирован и защищён платформой NoCopy.
|
Документ <strong>{response?.fileName ? response?.fileName : '#'}</strong> зарегистрирован и защищён платформой NoCopy.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="watch-doc-grid">
|
<div className="watch-doc-grid">
|
||||||
<div>
|
<div
|
||||||
|
className="flex flex-col justify-between"
|
||||||
|
>
|
||||||
<div className="watch-doc-card">
|
<div className="watch-doc-card">
|
||||||
<div className="card-head">Правообладатель</div>
|
<div className="card-head">Правообладатель</div>
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
<div className="owner-row">
|
<div className="owner-row">
|
||||||
<div className="owner-av">Н</div>
|
<div className="owner-av">
|
||||||
|
{response?.fileName ? response?.fileName[0] : ''}
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div className="owner-name">{ownerName}</div>
|
{response?.ownerName && (
|
||||||
{/* <div className="owner-meta">{companyName}</div> */}
|
<div className="owner-name">{response?.ownerName}</div>
|
||||||
<div className="owner-meta">Зарегистрирован в NoCopy</div>
|
)}
|
||||||
|
{response?.ownerCompany && (
|
||||||
|
<div className="owner-name">{response?.ownerCompany}</div>
|
||||||
|
)}
|
||||||
|
{response?.ownerName && (
|
||||||
|
<div className="owner-meta">Зарегистрирован в NoCopy</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* <div className="watch-doc-card">
|
|
||||||
<div className="card-head">Скачать документ</div>
|
|
||||||
<div className="card-body">
|
|
||||||
<DownloadButton />
|
|
||||||
<div className="download-description">
|
|
||||||
Вы вошли как <strong>{ownerName}</strong>.
|
|
||||||
<br />
|
|
||||||
Скачивание будет зарегистрировано.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div> */}
|
|
||||||
|
|
||||||
<div className="watch-doc-actions">
|
<div className="watch-doc-actions">
|
||||||
<DownloadButton />
|
{response?.permissions?.DOWNLOAD && (
|
||||||
|
<DownloadButton />
|
||||||
|
)}
|
||||||
<CopyLinkButton />
|
<CopyLinkButton />
|
||||||
<Link href="#" className="btn btn-out" target="_blank">О NoCopy</Link>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -81,8 +140,8 @@ export default async function Page({ searchParams }: PageProps) {
|
|||||||
|
|
||||||
<div className="watch-doc-footer">
|
<div className="watch-doc-footer">
|
||||||
<Link href="#">NoCopy</Link>
|
<Link href="#">NoCopy</Link>
|
||||||
<Link href="#">Условия</Link>
|
<Link href="/terms-of-use">Условия</Link>
|
||||||
<Link href="#">Конфиденциальность</Link>
|
<Link href="/privacy-policy">Конфиденциальность</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,86 +5,123 @@ import { API_BASE_URL } from '@/app/actions/definitions';
|
|||||||
import { headers } from 'next/headers';
|
import { headers } from 'next/headers';
|
||||||
|
|
||||||
export async function requestFileWithTracking(fileId: string) {
|
export async function requestFileWithTracking(fileId: string) {
|
||||||
const token = await getSessionData('token');
|
const token = await getSessionData('token');
|
||||||
const headersList = await headers();
|
const headersList = await headers();
|
||||||
const forwardedFor = headersList.get('x-forwarded-for');
|
const forwardedFor = headersList.get('x-forwarded-for');
|
||||||
const realIp = headersList.get('x-real-ip');
|
const realIp = headersList.get('x-real-ip');
|
||||||
const ip = forwardedFor?.split(',')[0] || realIp || 'unknown';
|
const ip = forwardedFor?.split(',')[0] || realIp || 'unknown';
|
||||||
const userAgent = headersList.get('user-agent') || 'unknown';
|
const userAgent = headersList.get('user-agent') || 'unknown';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/file/link`, {
|
const response = await fetch(`${API_BASE_URL}/api/file/link`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
file_id: fileId,
|
file_id: fileId,
|
||||||
token: token,
|
token: token,
|
||||||
ip: ip,
|
ip: ip,
|
||||||
user_agent: userAgent
|
user_agent: userAgent
|
||||||
}),
|
}),
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
const contentType = response.headers.get('content-type');
|
const contentType = response.headers.get('content-type');
|
||||||
|
|
||||||
if (contentType?.includes('application/json')) {
|
if (contentType?.includes('application/json')) {
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
return data.message_body;
|
return data.message_body;
|
||||||
} else {
|
} else {
|
||||||
const blob = await response.blob();
|
const blob = await response.blob();
|
||||||
return URL.createObjectURL(blob);
|
return URL.createObjectURL(blob);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Error(`${response.status}`);
|
throw new Error(`${response.status}`);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function requestFileAsBuffer(fileId: string): Promise<ArrayBuffer | null> {
|
export async function requestFileAsBuffer(fileId: string): Promise<ArrayBuffer | null> {
|
||||||
const token = await getSessionData('token');
|
const token = await getSessionData('token');
|
||||||
const headersList = await headers();
|
const headersList = await headers();
|
||||||
const forwardedFor = headersList.get('x-forwarded-for');
|
const forwardedFor = headersList.get('x-forwarded-for');
|
||||||
const realIp = headersList.get('x-real-ip');
|
const realIp = headersList.get('x-real-ip');
|
||||||
const ip = forwardedFor?.split(',')[0] || realIp || 'unknown';
|
const ip = forwardedFor?.split(',')[0] || realIp || 'unknown';
|
||||||
const userAgent = headersList.get('user-agent') || 'unknown';
|
const userAgent = headersList.get('user-agent') || 'unknown';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/file/link`, {
|
const response = await fetch(`${API_BASE_URL}/api/file/link`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
file_id: fileId,
|
file_id: fileId,
|
||||||
token: token,
|
token: token,
|
||||||
ip: ip,
|
ip: ip,
|
||||||
user_agent: userAgent
|
user_agent: userAgent
|
||||||
}),
|
}),
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`${response.status}`);
|
throw new Error(`${response.status}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const contentType = response.headers.get('content-type');
|
const contentType = response.headers.get('content-type');
|
||||||
if (contentType?.includes('application/json')) {
|
if (contentType?.includes('application/json')) {
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
const fileUrl = data.message_body;
|
const fileUrl = data.message_body;
|
||||||
const fileResponse = await fetch(fileUrl);
|
const fileResponse = await fetch(fileUrl);
|
||||||
if (!fileResponse.ok) {
|
if (!fileResponse.ok) {
|
||||||
throw new Error(`Failed to fetch file: ${fileResponse.status}`);
|
throw new Error(`Failed to fetch file: ${fileResponse.status}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return await fileResponse.arrayBuffer();
|
return await fileResponse.arrayBuffer();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return await response.arrayBuffer();
|
return await response.arrayBuffer();
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function fetchDocumentInfo(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: {
|
||||||
|
file_id: fileId,
|
||||||
|
token: token,
|
||||||
|
action: 'file_info'
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
const parsed = await response.json();
|
||||||
|
|
||||||
|
if (parsed.message_code === 0) {
|
||||||
|
return parsed.message_body;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
throw new Error(`${response.status}`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import Link from 'next/link';
|
||||||
|
import { useUserProfile } from '@/app/hooks/react-query/useUserDataInfo';
|
||||||
|
|
||||||
|
export function LoginUserBage() {
|
||||||
|
const { data: userData, isLoading, isError, error } = useUserProfile();
|
||||||
|
|
||||||
|
if (!userData?.fullName) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Link href="#" className="header-user">
|
||||||
|
{userData?.fullName}
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -164,6 +164,10 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.error-container {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-page {
|
&-page {
|
||||||
@@ -247,7 +251,7 @@
|
|||||||
background: var(--card);
|
background: var(--card);
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
border-radius: 14px;
|
border-radius: 14px;
|
||||||
margin-bottom: 14px;
|
/* margin-bottom: 14px; */
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
box-shadow: var(--shadow);
|
box-shadow: var(--shadow);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user