From 704276037cc6f7f56037406b3a519b268835539c Mon Sep 17 00:00:00 2001 From: cracklesparkle Date: Mon, 1 Jul 2024 17:51:50 +0900 Subject: [PATCH] upstream to API changes --- frontend_reactjs/src/components/DataTable.tsx | 1 - .../src/components/FolderViewer.tsx | 191 ++++++++++++++++++ .../components/modals/CreateCompanyModal.tsx | 128 ++++++++++++ .../modals/CreateDepartmentModal.tsx | 109 ++++++++++ frontend_reactjs/src/hooks/swrHooks.ts | 43 ++++ frontend_reactjs/src/http/axiosInstance.ts | 2 + frontend_reactjs/src/interfaces/documents.ts | 5 +- frontend_reactjs/src/pages/Documents.tsx | 83 +------- .../src/services/DocumentService.ts | 17 +- 9 files changed, 489 insertions(+), 90 deletions(-) create mode 100644 frontend_reactjs/src/components/FolderViewer.tsx create mode 100644 frontend_reactjs/src/components/modals/CreateCompanyModal.tsx create mode 100644 frontend_reactjs/src/components/modals/CreateDepartmentModal.tsx diff --git a/frontend_reactjs/src/components/DataTable.tsx b/frontend_reactjs/src/components/DataTable.tsx index b2d00ee..979c68c 100644 --- a/frontend_reactjs/src/components/DataTable.tsx +++ b/frontend_reactjs/src/components/DataTable.tsx @@ -6,7 +6,6 @@ interface Props { } export default function DataTable(props: Props) { - return ( void; +} + +function ItemFolder({ folder, handleFolderClick, ...props }: FolderProps) { + return ( + + + handleFolderClick(folder)} + {...props} + > + + {folder.name} + + + + ) +} + +interface DocumentProps { + doc: IDocument; + handleDocumentClick: (doc: IDocument) => void; +} + +function ItemDocument({ doc, handleDocumentClick, ...props }: DocumentProps) { + return ( + + + { + handleDocumentClick(doc) + }} + {...props} + > + + {doc.name} + + + + ) +} + +export default function FolderViewer() { + const [currentFolder, setCurrentFolder] = useState(null) + + const [breadcrumbs, setBreadcrumbs] = useState([]) + + const { folders, isLoading: foldersLoading } = useFolders() + + const { documents, isLoading: documentsLoading } = useDocuments(currentFolder?.id) + + const handleFolderClick = (folder: IDocumentFolder) => { + setCurrentFolder(folder) + setBreadcrumbs((prev) => [...prev, folder]) + } + + const handleDocumentClick = async (doc: IDocument) => { + try { + const response = await DocumentService.downloadDoc(doc.document_folder_id, doc.id); + const url = window.URL.createObjectURL(new Blob([response.data])); + const link = document.createElement('a'); + link.href = url; + link.setAttribute('download', doc.name); + document.body.appendChild(link); + link.click(); + link.remove(); + } catch (error) { + console.error(error); + } + } + + const handleBreadcrumbClick = (index: number) => { + const newBreadcrumbs = breadcrumbs.slice(0, index + 1); + setBreadcrumbs(newBreadcrumbs) + setCurrentFolder(newBreadcrumbs[newBreadcrumbs.length - 1]) + } + + // const handleFileUpload = (event) => { + // const file = event.target.files[0] + + // } + + if (foldersLoading || documentsLoading) { + return ( + + ) + } + + return ( + + + { + setCurrentFolder(null) + setBreadcrumbs([]) + }} + sx={{ cursor: 'pointer' }} + > + Главная + + {breadcrumbs.map((breadcrumb, index) => ( + handleBreadcrumbClick(index)} + sx={{ cursor: 'pointer' }} + > + {breadcrumb.name} + + ))} + + + + {currentFolder && + + } + + + + + {currentFolder ? ( + documents?.map((doc: IDocument) => ( + + )) + ) : ( + folders?.map((folder: IDocumentFolder) => ( + + )) + )} + + + ) +} \ No newline at end of file diff --git a/frontend_reactjs/src/components/modals/CreateCompanyModal.tsx b/frontend_reactjs/src/components/modals/CreateCompanyModal.tsx new file mode 100644 index 0000000..779f9a5 --- /dev/null +++ b/frontend_reactjs/src/components/modals/CreateCompanyModal.tsx @@ -0,0 +1,128 @@ +import { SubmitHandler, useForm } from 'react-hook-form'; +import { AxiosResponse } from 'axios'; +import { ApiResponse } from '../../interfaces/auth'; +import RoleService from '../../services/RoleService'; +import { Box, Button, MenuItem, Modal, Select, TextField, Typography } from '@mui/material'; +import { ICompany } from '../../interfaces/documents'; +import { useCompanies } from '../../hooks/swrHooks'; + +interface Props { + open: boolean; + setOpen: (state: boolean) => void; +} + +const style = { + position: 'absolute' as 'absolute', + top: '50%', + left: '50%', + transform: 'translate(-50%, -50%)', + width: 400, + bgcolor: 'background.paper', + boxShadow: 24, + borderRadius: 2, + p: 4, + display: "flex", + flexDirection: "column", + gap: "8px" +} + +export default function CreateCompanyModal({ + open, + setOpen +}: Props) { + const { companies } = useCompanies() + + const { register, handleSubmit, formState: { errors } } = useForm({ + defaultValues: { + name: '', + fullname: '', + description: '', + } + }) + + const onSubmit: SubmitHandler = async (data) => { + try { + const response: AxiosResponse = await RoleService.createRole(data) + console.log(response.data) + } catch (error) { + console.error(error) + } + } + + return ( + setOpen(false)} + aria-labelledby="modal-modal-title" + aria-describedby="modal-modal-description" + > +
+ + + + Создание компании + + + + + + + + + {companies} + + + + + + + + + +
+
+ ) +} \ No newline at end of file diff --git a/frontend_reactjs/src/components/modals/CreateDepartmentModal.tsx b/frontend_reactjs/src/components/modals/CreateDepartmentModal.tsx new file mode 100644 index 0000000..61530da --- /dev/null +++ b/frontend_reactjs/src/components/modals/CreateDepartmentModal.tsx @@ -0,0 +1,109 @@ +import { SubmitHandler, useForm } from 'react-hook-form'; +import { AxiosResponse } from 'axios'; +import { ApiResponse } from '../../interfaces/auth'; +import RoleService from '../../services/RoleService'; +import { Box, Button, Modal, TextField, Typography } from '@mui/material'; +import { ICompany } from '../../interfaces/documents'; + +interface Props { + open: boolean; + setOpen: (state: boolean) => void; +} + +const style = { + position: 'absolute' as 'absolute', + top: '50%', + left: '50%', + transform: 'translate(-50%, -50%)', + width: 400, + bgcolor: 'background.paper', + boxShadow: 24, + borderRadius: 2, + p: 4, + display: "flex", + flexDirection: "column", + gap: "8px" +} + +export default function CreateDepartmentModal({ + open, + setOpen +}: Props) { + const { register, handleSubmit, formState: { errors } } = useForm({ + defaultValues: { + name: '', + fullname: '', + description: '', + } + }) + + const onSubmit: SubmitHandler = async (data) => { + try { + const response: AxiosResponse = await RoleService.createRole(data) + console.log(response.data) + } catch (error) { + console.error(error) + } + } + + return ( + setOpen(false)} + aria-labelledby="modal-modal-title" + aria-describedby="modal-modal-description" + > +
+ + + + Создание компании + + + + + + + + + + + + + + +
+
+ ) +} \ No newline at end of file diff --git a/frontend_reactjs/src/hooks/swrHooks.ts b/frontend_reactjs/src/hooks/swrHooks.ts index c0dbb6a..92571f0 100644 --- a/frontend_reactjs/src/hooks/swrHooks.ts +++ b/frontend_reactjs/src/hooks/swrHooks.ts @@ -1,6 +1,7 @@ import useSWR from "swr"; import RoleService from "../services/RoleService"; import UserService from "../services/UserService"; +import { fetcher } from "../http/axiosInstance"; export function useRoles() { const { data, error, isLoading } = useSWR(`/auth/roles`, RoleService.getRoles) @@ -20,4 +21,46 @@ export function useUsers() { isLoading, isError: error } +} + +export function useCompanies(limit?: number, offset?: number) { + const { data, error, isLoading } = useSWR(`/info/companies?limit=${limit || 10}&offset=${offset || 0}`, fetcher) + + return { + companies: data, + isLoading, + isError: error + } +} + +export function useFolders(limit?: number, offset?: number) { + const { data, error, isLoading } = useSWR( + `/info/document_folder?limit=${limit || 10}&offset=${offset || 0}`, + fetcher, + { + revalidateOnFocus: false + } + ) + + return { + folders: data, + isLoading, + isError: error + } +} + +export function useDocuments(folder_id?: number) { + const { data, error, isLoading } = useSWR( + folder_id ? `/info/documents/${folder_id}` : null, + fetcher, + { + revalidateOnFocus: false + } + ) + + return { + documents: data, + isLoading, + isError: error + } } \ No newline at end of file diff --git a/frontend_reactjs/src/http/axiosInstance.ts b/frontend_reactjs/src/http/axiosInstance.ts index 3cc3eb6..9be269b 100644 --- a/frontend_reactjs/src/http/axiosInstance.ts +++ b/frontend_reactjs/src/http/axiosInstance.ts @@ -18,4 +18,6 @@ axiosInstance.interceptors.request.use( } ); +export const fetcher = (url: string) => axiosInstance.get(url).then(res => res.data) + export default axiosInstance; \ No newline at end of file diff --git a/frontend_reactjs/src/interfaces/documents.ts b/frontend_reactjs/src/interfaces/documents.ts index f92d42f..d8ab3b1 100644 --- a/frontend_reactjs/src/interfaces/documents.ts +++ b/frontend_reactjs/src/interfaces/documents.ts @@ -1,3 +1,4 @@ +// owner_id relates to other companies export interface ICompany { name: string; fullname: string; @@ -14,13 +15,15 @@ export interface IDepartment { } export interface IDocumentFolder { + id: number; name: string; description: string; - department_id: number; create_date: string; } export interface IDocument { + id: number; + document_folder_id: number, name: string; description: string; department_id: number; diff --git a/frontend_reactjs/src/pages/Documents.tsx b/frontend_reactjs/src/pages/Documents.tsx index c94ab33..c2cd22a 100644 --- a/frontend_reactjs/src/pages/Documents.tsx +++ b/frontend_reactjs/src/pages/Documents.tsx @@ -1,41 +1,7 @@ -import React, { useState } from 'react' -import DocumentService from '../services/DocumentService' -import { Box, Button, Typography } from '@mui/material' import { GridColDef } from '@mui/x-data-grid' -import DataTable from '../components/DataTable' +import FolderViewer from '../components/FolderViewer' export default function Documents() { - const [companies, setCompanies] = useState() - const [departments, setDepartments] = useState() - const [organizations, setOrganizations] = useState() - const [banks, setBanks] = useState() - - const [documents, setDocuments] = useState() - - const fetchData = async () => { - await DocumentService.getCompanies().then(response => { - setCompanies(response.data) - }) - - await DocumentService.getOrganizations().then(response => { - setOrganizations(response.data) - }) - - await DocumentService.getDepartments().then(response => { - setDepartments(response.data) - }) - - await DocumentService.getBanks().then(response => { - setBanks(response.data) - }) - } - - const fetchDocuments = async () => { - await DocumentService.getDocuments().then(response => { - setDocuments(response.data) - }) - } - const organizationColumns: GridColDef[] = [ { field: 'id', headerName: 'ID', type: "number", width: 90 }, { field: 'id_1c', headerName: 'ID 1C', type: "string", width: 90 }, @@ -68,52 +34,7 @@ export default function Documents() { return (
- - - - - Companies - - {JSON.stringify(companies)} - - - - - Organizations - - {organizations && - - } - - - - - Departments - - {JSON.stringify(departments)} - - - - - Get banks - - {banks && - - } - - - - - - {JSON.stringify(documents)} +
) } \ No newline at end of file diff --git a/frontend_reactjs/src/services/DocumentService.ts b/frontend_reactjs/src/services/DocumentService.ts index a1e1ba8..9f37e0c 100644 --- a/frontend_reactjs/src/services/DocumentService.ts +++ b/frontend_reactjs/src/services/DocumentService.ts @@ -1,3 +1,4 @@ +import { AxiosProgressEvent } from "axios"; import axiosInstance from "../http/axiosInstance"; import { IBank, ICompany, IDepartment, IDocument, IDocumentFolder, IOrganization, IOrganizationBank } from "../interfaces/documents"; @@ -99,17 +100,19 @@ export default class DocumentService { } // Upload Files - static async uploadFiles(folder_id: number, files: any) { - return await axiosInstance.post(`/info/documents/upload/${folder_id}`, files) + static async uploadFiles(folder_id: number, files: any, setUploadProgress?: any) { + return await axiosInstance.post(`/info/documents/upload/${folder_id}`, files, { + onUploadProgress: (progressEvent: AxiosProgressEvent) => { + const percentCompleted = progressEvent.progress + setUploadProgress?.(percentCompleted) + } + }) } // Download Doc static async downloadDoc(folder_id: number, doc_id: number) { - return await axiosInstance.get(`/info/document/`, { - params: { - folder_id: folder_id, - doc_id: doc_id - } + return await axiosInstance.get(`/info/document/${folder_id}&${doc_id}`, { + responseType: 'blob', }) }