Переглянути джерело

updated edit & save PDF form

master
kelvinsuen 1 місяць тому
джерело
коміт
990bab5751
8 змінених файлів з 818 додано та 63 видалено
  1. +4
    -4
      README.md
  2. +3
    -3
      src/pages/client/ClientSearchPage/ClientTable.js
  3. +124
    -45
      src/pages/pdf/PdfMaintainPage/index.js
  4. +312
    -0
      src/pages/pdf/PdfSearchPage/PdfSearchForm.js
  5. +220
    -0
      src/pages/pdf/PdfSearchPage/PdfTable.js
  6. +132
    -0
      src/pages/pdf/PdfSearchPage/index.js
  7. +22
    -0
      src/routes/ClientRoutes.js
  8. +1
    -11
      src/routes/MainRoutes.js

+ 4
- 4
README.md Переглянути файл

@@ -7,10 +7,10 @@
```

## 2. Config the library
- Navigate to "LIONER-frontend\node_modules\pspdfkit\dist"
- Copy the folder "pspdfkit-lib"
- Create a new folder "sdk" in "LIONER-frontend\public"
- Paste the "pspdfkit-lib" inside "sdk" folder
- Navigate to **"LIONER-frontend\node_modules\pspdfkit\dist"**
- Copy the folder **"pspdfkit-lib"**
- Create a new folder **"sdk"** in **"LIONER-frontend\public"**
- Paste the **"pspdfkit-lib"** inside **"sdk"** folder

## 3. Run the application
- Start the application by the following command:


+ 3
- 3
src/pages/client/ClientSearchPage/ClientTable.js Переглянути файл

@@ -35,8 +35,8 @@ export default function ClientTable({recordList}) {
navigate('/client/maintain/'+ id);
};

const handlePDFClick = () => () => {
navigate('/pdf');
const handlePdfClick = (id) => () => {
navigate(`/pdf/${id}`);
};

const columns = [
@@ -63,7 +63,7 @@ export default function ClientTable({recordList}) {
icon={<PictureAsPdfIcon sx={{fontSize: 25}}/>}
label="Edit PDF"
className="textPrimary"
onClick={handlePDFClick()}
onClick={handlePdfClick(id)}
color="edit"
// disabled={'true'}
// disabled={!ability.can('VIEW','DASHBOARD')}


src/pages/pdf/index.js → src/pages/pdf/PdfMaintainPage/index.js Переглянути файл

@@ -1,61 +1,107 @@
import React, { useEffect, useRef, useState } from 'react';
import { Button, Grid } from '@mui/material';
import { GeneralConfirmWindow } from "../../utils/CommonFunction";
import { GeneralConfirmWindow, notifySaveSuccess } from "../../../utils/CommonFunction";
import axios from 'axios';
import {apiPath} from "../../auth/utils";
import {apiPath} from "../../../auth/utils";
import {
GET_PDF_TEMPLATE_PATH,
GET_PDF_PATH,
POST_PDF_PATH
} from "../../utils/ApiPathConst";
import {LIONER_BUTTON_THEME} from "../../themes/colorConst";
} from "../../../utils/ApiPathConst";
import {LIONER_BUTTON_THEME} from "../../../themes/colorConst";
import {ThemeProvider} from "@emotion/react";
import {useNavigate} from "react-router-dom";
import {useForm} from "react-hook-form";
import {useLocation, useParams} from "react-router-dom";

// Import your chosen commercial PDF SDK (e.g., PSPDFKit)
import PSPDFKit from 'pspdfkit';
import { CollectionsBookmarkRounded } from '../../../../node_modules/@mui/icons-material/index';

function PDF() {
const viewerRef = useRef(null); // Ref for the DOM element where PDF will render
const instanceRef = useRef(null); // Ref for the PSPDFKit instance
const [pdfLoaded, setPdfLoaded] = useState(false);
const [viewerLoaded, setViewerLoaded] = useState(false);
const [template,setTemplate] = useState();
const [viewInstance,setViewInstance] = useState();
const [pdfBytes, setPdfBytes] = useState();
const [record, setRecord] = useState();
const navigate = useNavigate()
const params = useParams();
const location = useLocation();
const queryParams = new URLSearchParams(location.search);
const refId = queryParams.get("refId");

const loadPdfTemplate = async () => {
// if (!pdfLoaded) {
axios.get(`${apiPath}${GET_PDF_PATH}`, {
responseType: 'arraybuffer', // Essential for binary data
})
.then((response) => {
if (response.status === 200) {
setTemplate(response.data);
setPdfLoaded(true);
}
})
.catch(error => {
console.log(error);
return false;
});
// }
const loadPdfForm = async (id, templateId = 0) => {
if (!pdfLoaded) {
if (id > 0) {
// axios.get(`${apiPath}${GET_PDF_TEMPLATE_PATH}`, {
axios.get(`${apiPath}${GET_PDF_PATH}/${id}`, {
// responseType: 'arraybuffer', // Essential for binary data
})
.then((response) => {
if (response.status === 200) {
// setRecord(rec => {
// const { ["blobValue"]: _, ...newData } = response.data; // Destructure to remove blobValue
// return newData;
// });
const res = response.data;
setRecord({ // WIP - allow to update all record
id : res.id,
clientId: res.clientId,
templateId: res.templateId
})

//Convert Base64 to binary data
const byteChar = atob(response.data.blobValue);
const byteNum = new Uint8Array(byteChar.length);
for (let i = 0; i < byteChar.length; i++) {
byteNum[i] = byteChar.charCodeAt(i);
}

setPdfBytes(byteNum);
setPdfLoaded(true);
}
})
.catch(error => {
console.log(error);
return false;
});

} else {
axios.get(`${apiPath}${GET_PDF_TEMPLATE_PATH}`, {
responseType: 'arraybuffer', // Essential for binary data
})
.then((response) => {
if (response.status === 200) {
setPdfBytes(response.data);
setPdfLoaded(true);
}
})
.catch(error => {
console.log(error);
return false;
});
}
}
};

const loadPdfViewer = async () => {console.log(`PDF loaded = ${pdfLoaded}`);
if (pdfLoaded && viewerRef.current) {
const loadPdfViewer = async () => {
if (pdfLoaded && viewerRef.current && !viewerLoaded) {
try {
//New try
console.log(typeof(template));
const pdfBlob = new Blob([template], { type: 'application/pdf' });
const pdfBlob = new Blob([pdfBytes], { type: 'application/pdf' });
console.log(pdfBlob);
const pdfUrl = URL.createObjectURL(pdfBlob);
console.log('Template: ');
console.log(template.data);
console.log('URL: ');
console.log(pdfUrl);
console.log('Viewer: ');
console.log(viewerRef.current);
PSPDFKit.unload(viewerRef.current);
// console.log('Template: ');
// console.log(record);
// console.log('URL: ');
// console.log(pdfUrl);
// console.log('Viewer: ');
// console.log(viewerRef.current);
// await PSPDFKit.unload(viewerRef.current);
await PSPDFKit.load({//click into load
container: viewerRef.current,
// container: '#viewer',
@@ -76,6 +122,13 @@ function PDF() {
console.log('instance: ');
console.log(instance);
setViewerLoaded(true);
// instance.addEventListener("formFields.load", (loadedFormFields) => {
// console.log("loaded fields:", loadedFormFields);
// });
const formFieldValues = instance.getFormFieldValues();
// console.log(formFieldValues); // => { textField: 'Text Value', checkBoxField: ['A', 'B'], buttonField: null }e.log(getFormFieldValues);
});

// instanceRef.current = instance;
@@ -95,32 +148,55 @@ function PDF() {
};

useEffect(() => {
loadPdfTemplate();
}, []);
if (params.id !== null) {
const pdfData = (params.id).split("T");
if (pdfData[0] > 0) { // Existing Record
loadPdfForm(pdfData[0]);
} else { // New Record
setRecord({
id: -1,
clientId: pdfData[0] * -1, //If PDF ID is negative, convert it to client ID
templateId: pdfData[1],});
loadPdfForm(-1, pdfData[1]); // Load new Template
}
}
}, [params.id]);

// useEffect(() => {
// if (record) {
// console.log(record);
// loadPdfForm();
// }
// }, [record]);
useEffect(() => {
loadPdfViewer();
}, [viewerRef, pdfLoaded]);
}, [viewerRef.current, pdfLoaded]);

const handleSavePdf = async () => {
if (viewInstance.current) {console.log("tetes");
if (viewInstance) {
try {
// Export the filled PDF from the SDK as an ArrayBuffer
const arrayBuffer = await viewInstance.current.exportPDF();
const arrayBuffer = await viewInstance.exportPDF();
const filledPdfBlob = new Blob([arrayBuffer], { type: 'application/pdf' });

// Create FormData to send the file to Spring Boot
const formData = new FormData();
formData.append('file', filledPdfBlob, 'filled_form.pdf');

formData.append('record', JSON.stringify(record));
// Send the filled PDF to your Spring Boot backend's save endpoint
const response = await axios.post(`${apiPath}${POST_PDF_PATH}`, formData, {
headers: {
'Content-Type': 'multipart/form-data' // Important for file uploads
}
},
});
console.log('PDF saved on server:', response.data);
alert('PDF saved successfully on server!');
notifySaveSuccess();

if (viewerLoaded) {
await PSPDFKit.unload(viewerRef.current);
}
navigate(`/pdf/${record.clientId}`);
} catch (error) {
console.error('Error saving PDF:', error);
alert('Failed to save PDF.');
@@ -146,8 +222,11 @@ function PDF() {
setIsWindowOpen(true);
};

const handleBack = () => {
navigate('/client');
const handleBack = async () => {
if (viewerLoaded) {
await PSPDFKit.unload(viewerRef.current);
}
navigate(`/pdf/${record.clientId}`);
};

return (
@@ -162,7 +241,7 @@ function PDF() {
type="submit"
color="save"
disabled={!viewerLoaded}
// onClick={handleSavePdf}
onClick={handleSavePdf}
>
Save
</Button>

+ 312
- 0
src/pages/pdf/PdfSearchPage/PdfSearchForm.js Переглянути файл

@@ -0,0 +1,312 @@
// material-ui
import {
Button,
Typography,
Grid, TextField, InputLabel, CardActions
} from '@mui/material';
import MainCard from "../../../components/MainCard";
import {useForm} from "react-hook-form";
import {useContext, useState} from "react";
// import {useContext, useEffect, useState} from "react";
import Autocomplete from '@mui/material/Autocomplete';
import * as React from "react";
// import axios from "axios";
// import {apiPath, getUserData} from "../../../auth/utils";
// import {
// GET_CONSULTANT_COMBO_LIST, GET_EVENT_EXPORT,
// GET_SUB_CONSULTANT_COMBO_LIST, POST_SEARCH_TEMPLATE_PATH, VALIDATE_TEMPLATE_NAME_PATH,
// } from "../../../utils/ApiPathConst";
import {LIONER_BUTTON_THEME} from "../../../themes/colorConst";
// import {
// GeneralCreateTemplateWindow,
// getComboValueByIdList, getComboValueByLabel,
// getIdList, isOptionEqualToValue, notifySaveSuccess,
// } from "../../../utils/CommonFunction";
// import Qs from 'qs';
import {useNavigate} from "react-router";
import {ThemeProvider} from "@emotion/react";
// import UploadContext from "../../../components/UploadProvider";
// import {EVENT_REGION_COMBO, EVENT_TYPE_COMBO} from "../../../utils/ComboConst";
import {LocalizationProvider} from "@mui/x-date-pickers/LocalizationProvider";
import {AdapterDayjs} from "@mui/x-date-pickers/AdapterDayjs";
import {DemoItem} from "@mui/x-date-pickers/internals/demo";
import {DatePicker} from "@mui/x-date-pickers/DatePicker";
import dayjs from "dayjs";
// import {isObjEmpty} from "../../../utils/Utils";
// import {useLocation} from "react-router-dom";
import AbilityContext from "../../../components/AbilityProvider";
import {LIONER_FORM_THEME, CARD_MAX_WIDTH} from "../../../themes/themeConst";
import Collapse from '@mui/material/Collapse';
import {ExpandMore} from "@mui/icons-material";
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import { isNull } from 'lodash';

// ==============================|| DASHBOARD - DEFAULT ||============================== //

// const EventSearchForm = ({applySearch, refTemplateData, isUpdating,
// setIsUpdating, getTemplateList,setExpanded,expanded,userConsultant}) => {
const PdfSearchForm = ({applySearch, setExpanded,expanded, clientId}) => {

const navigate = useNavigate()
const ability = useContext(AbilityContext);

const [createDateFrom, setCreateDateFrom] = useState(null);
const [createDateTo, setCreateDateTo] = useState(null);

const { setValue, reset, register, handleSubmit, getValues } = useForm()
const handleExpandClick = () => {
setExpanded(!expanded);
};

const [createDateFromError, setCreateDateFromError] = React.useState(null);
const [createDateToError, setCreateDateToError] = React.useState(null);

const createDateFromErrorMessage = React.useMemo(() => {
switch (createDateFromError) {
case 'invalidDate': {
return "Invalid date";
}
}
}, [createDateFromError]);

const createDateToErrorMessage = React.useMemo(() => {
switch (createDateToError) {
case 'invalidDate': {
return "Invalid date";
}
}
}, [createDateToError]);

const createNewForm = () => {
navigate(`/pdf/maintain/-${clientId}T${1}`);
};

const onSubmit = (data) => {
const criteria = {
...data,
createDateFrom: createDateFrom === null ? null : dayjs(createDateFrom).format('YYYY-MM-DD'),
createDateTo: createDateTo === null ? null : dayjs(createDateTo).format('YYYY-MM-DD'),
};
applySearch(criteria);
};

// function onExport(){
// const data = getValues();
// const temp = {
// ...data,
// fromDate: fromDate === null ? null : dayjs(fromDate).format('YYYY-MM-DD'),
// createDateTo: createDateTo === null ? null : dayjs(createDateTo).format('YYYY-MM-DD'),
// region: selectedRegion === null ? null : selectedRegion.label,
// type: selectedType === null ? null :selectedType.label,
// consultantIdList: getIdList(selectedConsultants),
// caseManagerIdList: getIdList(selectedCaseManager),
// };
// setIsUploading(true);
// axios.get(`${apiPath}${GET_EVENT_EXPORT}`,{
// responseType: 'blob',
// params: temp,
// paramsSerializer: function (params) {
// return Qs.stringify(params, { arrayFormat: 'repeat' });
// },
// })
// .then((response) => {
// if (response.status === 200) {
// setIsUploading(false);
// const url = URL.createObjectURL(new Blob([response.data]));
// const link = document.createElement("a");
// link.href = url;
// link.setAttribute("download", "event_export_"+ Date.now() + ".xlsx");
// link.click();
// }
// })
// .catch(error => {
// setIsUploading(false);
// console.log(error);
// return false;
// });
// }

function resetForm(){
setCreateDateFrom(null);
setCreateDateTo(null);
reset();
}

const handleBack = () => {
navigate('/client');
};

return (
<MainCard xs={12} md={12} lg={12}
content={false}
sx={{width:CARD_MAX_WIDTH}}
>
<Grid item onClick={handleExpandClick}>
<CardActions disableSpacing>
{/*row 1*/}
<Grid item justifyContent="space-between" alignItems="center" sx={{mt:1,ml:2,mb:1}}>
<Typography variant="lionerSubLabel" >
Search Criteria(s)
</Typography>
</Grid>

<ExpandMore
expand={expanded.toString()}
onClick={handleExpandClick}
aria-expanded={expanded}
aria-label="show more"
style={{ marginLeft: 'auto' }} // Align the button to the right
>
<ExpandMoreIcon />
</ExpandMore>
</CardActions>
</Grid>

<Collapse in={expanded} timeout="auto" unmountOnExit>
<form onSubmit={handleSubmit(onSubmit)}>
<ThemeProvider theme={LIONER_FORM_THEME}>
{/*row 2*/}
<Grid container alignItems={"flex-start"} >
<Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:0.5}}>
<InputLabel htmlFor="template">Form</InputLabel>
<TextField
fullWidth
{...register("templateId")}
id='templateId'
inputProps={{maxLength: 255}}
// label="Client Name"
autoComplete="off"
/>
</Grid>

<Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:0.5}}>
<InputLabel htmlFor="createDateFrom">Form Create Date</InputLabel>

<Grid container>
<Grid item xs={5.25} s={5.25} md={5.25} lg={5.5}>
<LocalizationProvider dateAdapter={AdapterDayjs}>
<DemoItem>
<DatePicker
id="createDateFrom"
onError={(newError) => setCreateDateFromError(newError)}
slotProps={{
field: { clearable: true },
textField: {
helperText: createDateFromErrorMessage,
},
}}
format="DD/MM/YYYY"
value={createDateFrom === null ? null : dayjs(createDateFrom)}
onChange={(newValue) => setCreateDateFrom(newValue)}
// label="From"
/>
</DemoItem >
</LocalizationProvider>
</Grid>

<Grid item xs={1.5} s={1.5} md={1.5} lg={1} sx={{mt:1.3, display: 'flex', justifyContent:"center", alignItems: 'flex-start'}}>
To
</Grid>

<Grid item xs={5.25} s={5.25} md={5.25} lg={5.5}>
<LocalizationProvider dateAdapter={AdapterDayjs}>
<DemoItem components={['DatePicker']}>
<DatePicker
format="DD/MM/YYYY"
onError={(newError) => setCreateDateToError(newError)}
slotProps={{
field: { clearable: true },
textField: {
helperText: createDateToErrorMessage,
},
}}
id="createDateTo"
//label="To Date"
value={createDateTo === null ? null : dayjs(createDateTo)}
onChange={(newValue) => setCreateDateTo(newValue)}
/>
</DemoItem >
</LocalizationProvider>
</Grid>
</Grid>
</Grid>

<Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:0.5}}>
<InputLabel htmlFor="remarks">Remarks</InputLabel>
<TextField
fullWidth
{...register("remarks")}
inputProps={{maxLength: 500}}
id="remarks"
autoComplete="off"
/>
</Grid>

</Grid>


{/*last row*/}
<Grid container maxWidth justifyContent="space-between" sx={{mt:1.5}}>
<ThemeProvider theme={LIONER_BUTTON_THEME}>
<Grid item>
<Grid container>
<Grid item sx={{ml:3, mr:1.5, mb:2}}>
<Button
variant="contained"
type="submit"
color="save"
disabled={createDateFromError || createDateToError}
onClick={applySearch}
>
Search
</Button>
</Grid>

<Grid item sx={{ml:{xs:1.5, md:1.5, lg:1.5}, mr:1.5, mb:2}}>
<Button
variant="contained"
color="cancel"
onClick={resetForm}
>
Reset
</Button>
</Grid>
<Grid item sx={{ml:{xs:1.5, md:1.5, lg:1.5}, mr:1.5, mb:2}}>
<Button
variant="contained"
color="cancel"
onClick={handleBack}
>
Back
</Button>
</Grid>
</Grid>
</Grid>

<Grid item>
<Grid container>
{ability.can('EDIT','EVENT') ?
<Grid item sx={{ml:3, mr:3, mb:0.5}}>
<Button
variant="contained"
color="create"
onClick={createNewForm}
>
New Form
</Button>
</Grid>
:
<Grid/>
}
</Grid>
</Grid>
</ThemeProvider>
</Grid>
</ThemeProvider>
</form>
</Collapse>
</MainCard>
);
};

export default PdfSearchForm;

+ 220
- 0
src/pages/pdf/PdfSearchPage/PdfTable.js Переглянути файл

@@ -0,0 +1,220 @@
// material-ui
import * as React from 'react';
import {
DataGrid,
GridActionsCellItem,
} from "@mui/x-data-grid";
import EditIcon from '@mui/icons-material/Edit';
import PictureAsPdfIcon from '@mui/icons-material/PictureAsPdf';
import {useContext, useEffect} from "react";
import {useNavigate} from "react-router-dom";
import {CustomNoRowsOverlay, dateComparator, getDateString} from "../../../utils/CommonFunction";
import AbilityContext from "../../../components/AbilityProvider";
import {LIONER_BUTTON_THEME} from "../../../themes/colorConst";
import {ThemeProvider} from "@emotion/react";

// ==============================|| PDF TABLE ||============================== //

export default function PdfTable({recordList}) {
const [rows, setRows] = React.useState(recordList);
const [rowModesModel] = React.useState({});

const navigate = useNavigate()
const ability = useContext(AbilityContext);

const [paginationModel, setPaginationModel] = React.useState({
page: 0,
pageSize:10
});

useEffect(() => {
setPaginationModel({page:0,pageSize:10});
setRows(recordList);
}, [recordList]);

const handleEditClick = (id) => () => {
navigate(`/pdf/maintain/${id}`);
};

const columns = [
{
field: 'actions',
type: 'actions',
headerName: 'Actions',
// flex: 0.5,
width: 100,
cellClassName: 'actions',
getActions: ({id}) => {
return [
<ThemeProvider key="OutSave" theme={LIONER_BUTTON_THEME}>
<GridActionsCellItem
icon={<EditIcon sx={{fontSize: 25}}/>}
label="Edit"
className="textPrimary"
onClick={handleEditClick(id)}
color="edit"
// disabled={'true'}
// disabled={!ability.can('VIEW','DASHBOARD')}
/>
</ThemeProvider>
]
},
},
// {
// id: 'title',
// field: 'title',
// headerName: 'Title',
// // sortComparator: dateComparator,
// flex: 0.75,
// renderCell: (params) => (
// <div style={{display: 'flex', alignItems: 'center', justifyContent: 'center', whiteSpace: 'normal', wordBreak: 'break-word'}}>
// {params.value}
// </div>
// // <div>
// // {getDateString(params.row.pdfFrom,false)}
// // </div>
// ),
// },
{
id: 'templateId',
field: 'templateId',
headerName: 'Form Name',
flex: 2,
renderCell: (params) => {
return (
<div style={{display: 'flex', alignItems: 'center', justifyContent: 'center', whiteSpace: 'normal', wordBreak: 'break-word'}}>
{params.value}
</div>
);
}
},
{
id: 'createDate',
field: 'createDate',
headerName: 'Create Date',
flex: 1,
sortComparator: dateComparator,
renderCell: (params) => (
<div>
{getDateString(params.row.created, 'dd/MM/yyyy')}
</div>
),
},
{
id: 'modified',
field: 'modified',
headerName: 'Modified Date',
flex: 1,
sortComparator: dateComparator,
renderCell: (params) => (
<div>
{getDateString(params.row.modified, 'dd/MM/yyyy')}
</div>
),
},
// {
// id: 'lastname',
// field: 'lastname',
// headerName: 'Last Name',
// flex: 1.5,
// sortComparator: dateComparator,
// renderCell: (params) => (
// <div style={{display: 'flex', alignItems: 'center', justifyContent: 'center', whiteSpace: 'normal', wordBreak: 'break-word'}}>
// {params.value}
// </div>
// // <div>
// // {getDateString(params.row.startDate,false)}
// // </div>
// ),
// },
// {
// id: 'firstname',
// field: 'firstname',
// headerName: 'First Name',
// // sortComparator: dateComparator,
// flex: 2,
// renderCell: (params) => (
// <div style={{display: 'flex', alignItems: 'center', justifyContent: 'center', whiteSpace: 'normal', wordBreak: 'break-word'}}>
// {params.value}
// </div>
// // <div>
// // {getDateString(params.row.applicationDeadline,false)}
// // </div>
// ),
// },
// {
// id: 'email',
// field: 'email',
// headerName: 'Email',
// flex: 1.5,
// renderCell: (params) => {
// return (
// <div style={{display: 'flex', alignItems: 'center', justifyContent: 'center', whiteSpace: 'normal', wordBreak: 'break-word'}}>
// {params.value}
// </div>
// );
// }
// },
// {
// id: 'phone1',
// field: 'phone1',
// headerName: 'Phone No.',
// flex: 1,
// renderCell: (params) => {
// return (
// <div style={{display: 'flex', alignItems: 'center', justifyContent: 'center', whiteSpace: 'normal', wordBreak: 'break-word'}}>
// {params.value}
// </div>
// );
// }
// },
// {
// id: 'phone2',
// field: 'phone2',
// headerName: '2nd Phone No.',
// flex: 1,
// renderCell: (params) => {
// return (
// <div style={{display: 'flex', alignItems: 'center', justifyContent: 'center', whiteSpace: 'normal', wordBreak: 'break-word'}}>
// {params.value}
// </div>
// );
// }
// },
{
id: 'remarks',
field: 'remarks',
headerName: 'Remarks',
flex: 2,
renderCell: (params) => {
return (
<div style={{display: 'flex', alignItems: 'center', justifyContent: 'center', whiteSpace: 'normal', wordBreak: 'break-word'}}>
{params.value}
</div>
);
}
},

];

return (
<DataGrid
rows={rows}
columns={columns}
columnHeaderHeight={45}
editMode="row"
//autoPageSize
rowModesModel={rowModesModel}
getRowHeight={() => 'auto'}
paginationModel={paginationModel}
onPaginationModelChange={setPaginationModel}
slots={{
noRowsOverlay: () => (
CustomNoRowsOverlay()
)
}}
pageSizeOptions={[10]}
autoHeight
/>
);
}

+ 132
- 0
src/pages/pdf/PdfSearchPage/index.js Переглянути файл

@@ -0,0 +1,132 @@
// material-ui
import {
Grid, Typography
} from '@mui/material';
import MainCard from "../../../components/MainCard";
import {useEffect, useState} from "react";
import axios from "axios";
import {apiPath} from "../../../auth/utils";
import {
// GET_DIVISION_FROM_SUB_DIVISION,
GET_PDF_PATH,
// GET_SEARCH_TEMPLATE_COMBO_PATH,
// GET_SEARCH_TEMPLATE_PATH
} from "../../../utils/ApiPathConst";
import * as React from "react";
import LoadingComponent from "../../extra-pages/LoadingComponent";
import PdfTable from "./PdfTable";
import PdfSearchForm from "./PdfSearchForm";
import Qs from "qs";
// import Autocomplete from "@mui/material/Autocomplete";
import {isObjEmpty} from "../../../utils/Utils";
import {isFormEmpty} from "../../../utils/CommonFunction";
// import UploadContext from "../../components/UploadProvider";
// import {useLocation} from "react-router-dom";
// import dayjs from "dayjs";

import {LIONER_FORM_THEME, CARD_MAX_WIDTH} from "../../../themes/themeConst";
import {ThemeProvider} from "@emotion/react";
import {useParams} from "react-router-dom";

// ==============================|| DASHBOARD - DEFAULT ||============================== //

const PdfSearchPage = () => {
const [onReady, setOnReady] = useState(false);
const [expanded, setExpanded] = React.useState(true);
const [record,setRecord] = useState([]);
const [searchCriteria, setSearchCriteria] = useState({});
const params = useParams();

function getPdfList() {
axios.get(`${apiPath}${GET_PDF_PATH}`, {
params: searchCriteria,
// params: isInit? temp : searchCriteria,
paramsSerializer: function (params) {
return Qs.stringify(params, { arrayFormat: 'repeat' });
},
}
)
.then((response) => {
if (response.status === 200) {
// if (!isFormEmpty(searchCriteria) && !isObjEmpty(response.data.records)) {
// setExpanded(false);
// }
setRecord(response.data.records);
setOnReady(true);
}
})
.catch(error => {
console.log(error);
return false;
});
}

useEffect(() => {
setSearchCriteria({clientId: params.id,
...searchCriteria});
}, [params.id]);

useEffect(() => {
if (!isObjEmpty(searchCriteria)) {
getPdfList();
}
}, [searchCriteria]);

function applySearch(input) {
setSearchCriteria({clientId: params.id,
...input});
}

return (
<Grid container rowSpacing={3} columnSpacing={2.75} >
<ThemeProvider theme={LIONER_FORM_THEME}>
<Grid item xs={12} md={12} lg={12} >
<Grid container maxWidth justifyContent="space-between" sx={{mt:-2, width:CARD_MAX_WIDTH}} >
<Grid item xs={4} s={4} md={4} lg={4}
sx={{ mb: -2.25, display: 'flex', alignItems: 'center'}}>
<Typography variant="h4">Search PDF Form</Typography>
</Grid>
</Grid>
</Grid>

{/* Search Form */}
<Grid item xs={12} md={12} lg={12}>
<PdfSearchForm
// isUpdating={isUpdating}
// setIsUpdating={setIsUpdating}
applySearch={applySearch}
// refTemplateData={refTemplateData}
// getTemplateList={getTemplateList}
setExpanded={setExpanded}
expanded={expanded}
clientId={params.id}
// userDivision={userDivision}
/>
</Grid>

{!onReady? <LoadingComponent/> :
// PDF Table
<Grid item xs={12} md={12} lg={12}>
<MainCard elevation={0}
content={false}
sx={{mt:{lg:-1.5}, width: CARD_MAX_WIDTH}}

>
<div style={{/*height: expanded? '46vh' : '75vh',*/ width: '100%'}}>
<PdfTable
recordList={record}
pageSize={10}
expanded={expanded}
clientId={params.id}
/>
</div>
</MainCard>
</Grid>
}
</ThemeProvider>
</Grid>

);
};

export default PdfSearchPage;

+ 22
- 0
src/routes/ClientRoutes.js Переглянути файл

@@ -10,6 +10,8 @@ import AbilityContext from "../components/AbilityProvider";
// render - login
const ClientSearchPage = Loadable(lazy( () => import('pages/client/ClientSearchPage')));
const ClientMaintainPage = Loadable(lazy( () => import('pages/client/ClientMaintainPage')));
const PdfMaintainPage = Loadable(lazy(() => import('pages/pdf/PdfMaintainPage')));
const PdfSearchPage = Loadable(lazy(() => import('pages/pdf/PdfSearchPage')));

// ==============================|| AUTH ROUTING ||============================== //

@@ -40,6 +42,26 @@ const ClientRoutes =() => {
)
),
},
{
path: '/pdf/:id',
element: (
handleRouteAbility(
ability.can('VIEW', 'DASHBOARD'),
<PdfSearchPage />,
<Navigate to="/" />
)
),
},
{
path: '/pdf/maintain/:id',
element: (
handleRouteAbility(
ability.can('VIEW', 'DASHBOARD'),
<PdfMaintainPage />,
<Navigate to="/" />
)
),
},
]
};
};


+ 1
- 11
src/routes/MainRoutes.js Переглянути файл

@@ -10,7 +10,6 @@ import {Navigate} from "react-router";
// render - dashboard
//const DashboardDefault = Loadable(lazy(() => import('pages/dashboard')));
const LIONERDashboard = Loadable(lazy(() => import('pages/lionerdashboard')));
const PDF = Loadable(lazy(() => import('pages/pdf')));
const ReminderPage = Loadable(lazy(() => import('pages/lionerReminderPage')));
const TemplateSearchPage = Loadable(lazy(() => import('pages/lionerSearchPanel')));
const TemplateMaintainPage = Loadable(lazy(() => import('pages/lionerMaintainSearchTemplatePage')));
@@ -53,16 +52,7 @@ const MainRoutes = () => {
)
),
},
{
path: '/pdf',
element: (
handleRouteAbility(
ability.can('VIEW', 'DASHBOARD'),
<PDF />,
<Navigate to="/pdf" />
)
),
},
// {
// path: '/reminder',
// element: (


Завантаження…
Відмінити
Зберегти