├── README.md
├── example.env
├── package-lock.json
├── package.json
├── public
├── apple-touch-icon.png
├── favicon.ico
├── index.html
├── logo192.png
├── logo512.png
├── manifest.json
└── robots.txt
└── src
├── assets
└── congreso_logo.png
├── helpers
└── notificationMessage.js
├── index.css
├── index.js
├── routers
└── App.jsx
├── services
└── honorables.service.js
├── ui
└── components
│ ├── Footer
│ └── Footer.jsx
│ ├── Navbar
│ └── Navbar.jsx
│ └── index.js
└── views
├── Download
├── Download.jsx
└── components
│ ├── AutoTextArea.jsx
│ ├── DrawArea.jsx
│ ├── EditPosition.jsx
│ ├── ModifyPage.jsx
│ ├── Pdf
│ └── na.pdf
│ ├── PdfCreator.jsx
│ ├── SinglePage.jsx
│ └── index.js
├── Home
├── Home.jsx
└── components
│ ├── ChatGPT
│ └── ChatGPT.jsx
│ ├── WebScrapping
│ └── WebScrapping.jsx
│ └── index.js
└── index.js
/README.md:
--------------------------------------------------------------------------------
1 | # Getting Started with Create React App
2 |
3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
4 |
5 | ## Available Scripts
6 |
7 | In the project directory, you can run:
8 |
9 | ### `npm start`
10 |
11 | Runs the app in the development mode.\
12 | Open [http://localhost:3000](http://localhost:3000) to view it in your browser.
13 |
14 | The page will reload when you make changes.\
15 | You may also see any lint errors in the console.
16 |
17 | ### `npm test`
18 |
19 | Launches the test runner in the interactive watch mode.\
20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
21 |
22 | ### `npm run build`
23 |
24 | Builds the app for production to the `build` folder.\
25 | It correctly bundles React in production mode and optimizes the build for the best performance.
26 |
27 | The build is minified and the filenames include the hashes.\
28 | Your app is ready to be deployed!
29 |
30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
31 |
32 | ### `npm run eject`
33 |
34 | **Note: this is a one-way operation. Once you `eject`, you can't go back!**
35 |
36 | If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
37 |
38 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own.
39 |
40 | You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it.
41 |
42 | ## Learn More
43 |
44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
45 |
46 | To learn React, check out the [React documentation](https://reactjs.org/).
47 |
48 | ### Code Splitting
49 |
50 | This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)
51 |
52 | ### Analyzing the Bundle Size
53 |
54 | This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)
55 |
56 | ### Making a Progressive Web App
57 |
58 | This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)
59 |
60 | ### Advanced Configuration
61 |
62 | This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)
63 |
64 | ### Deployment
65 |
66 | This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
67 |
68 | ### `npm run build` fails to minify
69 |
70 | This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)
71 |
--------------------------------------------------------------------------------
/example.env:
--------------------------------------------------------------------------------
1 | REACT_APP_API_URL_DEVELOPMENT=
2 | REACT_APP_API_URL_TEST=
3 | REACT_APP_API_URL_PROD=
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "front",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@aws-sdk/client-s3": "^3.259.0",
7 | "@emotion/react": "^11.10.5",
8 | "@emotion/styled": "^11.10.5",
9 | "@fortawesome/fontawesome-svg-core": "^6.3.0",
10 | "@fortawesome/free-solid-svg-icons": "^5.15.0",
11 | "@fortawesome/react-fontawesome": "^0.2.0",
12 | "@mui/icons-material": "^5.11.0",
13 | "@mui/material": "^5.11.6",
14 | "@testing-library/jest-dom": "^5.16.5",
15 | "@testing-library/react": "^13.4.0",
16 | "@testing-library/user-event": "^13.5.0",
17 | "animate.css": "^4.1.1",
18 | "aws-sdk": "^2.1303.0",
19 | "axios": "^1.2.5",
20 | "immutable": "^4.0.0-rc.12",
21 | "jquery": "^3.5.1",
22 | "pdf-lib": "^1.9.0",
23 | "pdfjs-dist": "^2.6.347",
24 | "prop-types": "^15.7.2",
25 | "react": "^18.2.0",
26 | "react-app-rewired": "^2.2.1",
27 | "react-dom": "^18.2.0",
28 | "react-draggable": "^4.4.3",
29 | "react-pdf": "^5.3.2",
30 | "react-router-dom": "^6.8.1",
31 | "react-scripts": "^5.0.1",
32 | "sweetalert2": "^11.7.1",
33 | "use-resize-observer": "^6.1.0",
34 | "web-vitals": "^2.1.4"
35 | },
36 | "scripts": {
37 | "start": "react-scripts start",
38 | "build": "react-scripts build",
39 | "test": "react-scripts test",
40 | "eject": "react-scripts eject"
41 | },
42 | "eslintConfig": {
43 | "extends": [
44 | "react-app",
45 | "react-app/jest"
46 | ]
47 | },
48 | "browserslist": {
49 | "production": [
50 | ">0.2%",
51 | "not dead",
52 | "not op_mini all"
53 | ],
54 | "development": [
55 | "last 1 chrome version",
56 | "last 1 firefox version",
57 | "last 1 safari version"
58 | ]
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/public/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GasFeDev/ChatPDF/7a22a6183116572f76d783d80a2a1a783abf4cfa/public/apple-touch-icon.png
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GasFeDev/ChatPDF/7a22a6183116572f76d783d80a2a1a783abf4cfa/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
17 |
18 |
27 | Honorables project
28 |
29 |
30 | You need to enable JavaScript to run this app.
31 |
32 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GasFeDev/ChatPDF/7a22a6183116572f76d783d80a2a1a783abf4cfa/public/logo192.png
--------------------------------------------------------------------------------
/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GasFeDev/ChatPDF/7a22a6183116572f76d783d80a2a1a783abf4cfa/public/logo512.png
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/src/assets/congreso_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GasFeDev/ChatPDF/7a22a6183116572f76d783d80a2a1a783abf4cfa/src/assets/congreso_logo.png
--------------------------------------------------------------------------------
/src/helpers/notificationMessage.js:
--------------------------------------------------------------------------------
1 | export const configSuccess = (message) => ({
2 | position: 'bottom-end',
3 | icon: 'success',
4 | showConfirmButton: false,
5 | toast: true,
6 | timer: 3000,
7 | html: message
8 | });
9 |
10 | export const configError = (message) => ({
11 | position: 'bottom-end',
12 | icon: 'error',
13 | showConfirmButton: false,
14 | toast: true,
15 | timer: 3000,
16 | html: message
17 | });
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
5 | sans-serif;
6 | -webkit-font-smoothing: antialiased;
7 | -moz-osx-font-smoothing: grayscale;
8 | }
9 |
10 | code {
11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
12 | monospace;
13 | }
14 |
15 | * {
16 | box-sizing: border-box;
17 | padding: 0;
18 | margin: 0;
19 | scroll-behavior: smooth;
20 | }
21 |
22 | html, body{
23 | margin: 0;
24 | height: 100%;
25 | }
26 |
27 | .type {
28 | color:#0000;
29 | background:
30 | linear-gradient(-90deg,#984D0F 5px,#0000 0) 10px 0,
31 | linear-gradient(#984D0F 0 0) 0 0;
32 | background-size:calc(var(--n)*1ch) 200%;
33 | -webkit-background-clip:padding-box,text;
34 | background-clip:padding-box,text;
35 | background-repeat:no-repeat;
36 | animation:
37 | blink-caret .7s infinite steps(1),
38 | typing calc(var(--n)*.3s) steps(var(--n)) forwards;
39 | }
40 |
41 | .App {
42 | font-family: sans-serif;
43 | text-align: center;
44 | font-size:small;
45 | }
46 |
47 | .container {
48 | display: flex;
49 | flex-wrap: wrap;
50 | width: 100%;
51 | height: 100%;
52 | }
53 |
54 |
55 | h4 {
56 | text-align: left;
57 | margin-left: 40px;
58 | }
59 |
60 | hr {
61 | border-top: 2px dotted #3f51b5;
62 | }
63 |
64 | button {
65 | margin-right: 10px;
66 | font-size: 25px;
67 | background: #3f51b5;
68 | color: white;
69 | border: none;
70 | padding: 5px 10px;
71 | cursor: pointer;
72 | box-shadow: 2px 2px 2px 1px #ccc;
73 | }
74 | /* For pdf */
75 | .react-pdf__Page {
76 | z-index: 1;
77 | width: 100%;
78 | height: 100%;
79 | /*Optional*/
80 | position: absolute !important;
81 | top: 0;
82 | left: 0;
83 | display: none;
84 | /*Optional*/
85 | }
86 | .react-pdf__Page__textContent {
87 | border: 1px solid darkgrey;
88 | box-shadow: 5px 5px 5px 1px #ccc;
89 | border-radius: 5px;
90 | }
91 |
92 | /*Optional*/
93 | .react-pdf__Page__annotations.annotationLayer {
94 | padding: 20px;
95 | }
96 | /*Optional*/
97 |
98 | /*Optional*/
99 | .react-pdf__Page__canvas {
100 | margin: 0 auto;
101 | }
102 | /*Optional*/
103 |
104 | /*Optional*/
105 | /* For all pages */
106 | .all-page-container {
107 | height: 100%;
108 | max-height: 500px;
109 | overflow: auto;
110 | }
111 | /*Optional*/
112 |
113 | #drawArea {
114 | width: 612px;
115 | height: 792px;
116 | border: 1px solid black;
117 | position: relative;
118 | border:transparent;
119 | }
120 |
121 | .crosshair {
122 | cursor: crosshair;
123 | }
124 |
125 | svg {
126 | z-index: 1;
127 | position: absolute !important;
128 | top: 0;
129 | left: 0;
130 | }
131 |
132 | .path {
133 | fill: none;
134 | stroke-width: 1px;
135 | stroke: black;
136 | stroke-linejoin: round;
137 | stroke-linecap: round;
138 | }
139 |
140 | .drawing {
141 | width: 100%;
142 | height: 100%;
143 | }
144 | textarea {
145 | resize: none;
146 | }
147 |
148 | textarea:focus {
149 | outline: none;
150 | border-color: transparent;
151 | }
152 |
153 | .pdf-file{
154 | display: none;
155 | }
156 |
157 | @keyframes typing{
158 | from {background-size:0 200%}
159 | }
160 | @keyframes blink-caret {
161 | 50% {background-position:0 -100%,0 0}
162 | }
163 |
164 | :root{
165 | --color-bg: #984D0F;
166 | }
167 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import './index.css';
4 | import { App } from './routers/App';
5 |
6 |
7 | const root = ReactDOM.createRoot(document.getElementById('root'));
8 | root.render(
9 |
10 |
11 |
12 | );
--------------------------------------------------------------------------------
/src/routers/App.jsx:
--------------------------------------------------------------------------------
1 | import { createContext, useState } from "react";
2 | import { Route, BrowserRouter, Routes } from "react-router-dom";
3 | import { Footer, Navbar } from "../ui/components";
4 | import { Download, Home } from "../views";
5 |
6 | export const Context = createContext(null);
7 |
8 | export const App = () => {
9 | const [question, setQuestion] = useState("");
10 | const [message, setMessage] = useState("");
11 | const [keywords, setKeyWords] = useState([]);
12 | const [loading, setLoading] = useState(false);
13 |
14 | return (
15 |
27 |
28 |
29 |
30 |
31 | } />
32 | } />
33 |
34 |
35 |
36 |
37 |
38 | );
39 | };
40 |
--------------------------------------------------------------------------------
/src/services/honorables.service.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 |
3 | const env = process.env.REACT_APP_NODE_ENV || 'development';
4 |
5 | const API_CONFIG = {
6 | "development": {
7 | "url_api": process.env.REACT_APP_API_URL_DEVELOPMENT,
8 | },
9 | "test": {
10 | "url_api": process.env.REACT_APP_API_URL_TEST,
11 | },
12 | "production": {
13 | "url_api": process.env.REACT_APP_API_URL_PROD
14 | }
15 | };
16 |
17 | const honorablesService = axios.create({
18 | baseURL: `${API_CONFIG[env].url_api}`
19 | });
20 |
21 | export default honorablesService
--------------------------------------------------------------------------------
/src/ui/components/Footer/Footer.jsx:
--------------------------------------------------------------------------------
1 | import { Box, Container, Paper, Typography } from '@mui/material'
2 | import React from 'react'
3 |
4 | const Footer = () => {
5 | return (
6 |
15 |
16 |
24 |
25 | Copyright TitaniusTech Corp ©2023.
26 |
27 |
28 |
29 |
30 | )
31 | }
32 |
33 | export default Footer
--------------------------------------------------------------------------------
/src/ui/components/Navbar/Navbar.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react'
2 | import AppBar from '@mui/material/AppBar';
3 | import Box from '@mui/material/Box';
4 | import Toolbar from '@mui/material/Toolbar';
5 | import Typography from '@mui/material/Typography';
6 | import IconButton from '@mui/material/IconButton';
7 | import AccountCircle from '@mui/icons-material/AccountCircle';
8 | import MenuItem from '@mui/material/MenuItem';
9 | import Menu from '@mui/material/Menu';
10 |
11 | import logo from '../../../assets/congreso_logo.png'
12 |
13 | const Navbar = () => {
14 | const [auth, setAuth] = useState(true);
15 | const [anchorEl, setAnchorEl] = useState(null);
16 |
17 | const handleMenu = (event) => {
18 | setAnchorEl(event.currentTarget);
19 | };
20 |
21 | const handleClose = () => {
22 | setAnchorEl(null);
23 | };
24 |
25 | return (
26 |
27 |
28 |
29 |
35 |
36 | Motor de leyes
37 |
38 | {auth && (
39 |
69 | )}
70 |
71 |
72 |
73 | )
74 | }
75 |
76 | export default Navbar
--------------------------------------------------------------------------------
/src/ui/components/index.js:
--------------------------------------------------------------------------------
1 | export { default as Navbar } from './Navbar/Navbar';
2 | export { default as Footer } from './Footer/Footer';
--------------------------------------------------------------------------------
/src/views/Download/Download.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { PdfCreator } from "./components";
3 |
4 | const Download = () => {
5 | return (
6 |
9 | );
10 | };
11 |
12 | export default Download;
13 |
--------------------------------------------------------------------------------
/src/views/Download/components/AutoTextArea.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect, useRef } from "react";
2 |
3 | function AutoTextArea(props) {
4 | const textAreaRef = useRef(null);
5 | const divAreaRef = useRef(null);
6 | const [text, setText] = useState(props.text);
7 | const [, setTextAreaHeight] = useState("auto");
8 | const [parentHeight, setParentHeight] = useState("auto");
9 |
10 | useEffect(() => {
11 | setParentHeight(`${textAreaRef.current.scrollHeight}px`);
12 | setTextAreaHeight(`${textAreaRef.current.scrollHeight}px`);
13 | }, [text]);
14 |
15 | useEffect(() => {
16 | textAreaRef.current.focus();
17 | }, []);
18 |
19 | const onChangeHandler = (event) => {
20 | setTextAreaHeight("auto");
21 | setParentHeight(`${textAreaRef.current.scrollHeight}px`);
22 | setText(event.target.value);
23 | };
24 |
25 | const onBlurHandler = () => {
26 | props.onTextChange(props.unique_key, text, divAreaRef);
27 | };
28 |
29 | return (
30 |
60 | );
61 | }
62 |
63 | export default AutoTextArea;
64 |
--------------------------------------------------------------------------------
/src/views/Download/components/DrawArea.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect, useRef, useCallback } from "react";
2 | import Immutable from "immutable";
3 |
4 | function DrawArea(props) {
5 | const [lines, setLines] = useState([]);
6 | const [isDrawing, setIsDrawing] = useState(false);
7 | const [redoEl, setRedoEl] = useState([]);
8 | const [isCrosshair, setIsCrosshair] = useState(false);
9 | const drawAreaEl = useRef(null);
10 | const { flag, changeFlag } = props;
11 | const { buttonType, resetButtonType } = props;
12 |
13 | useEffect(() => {
14 | document
15 | .getElementById("drawArea")
16 | props.getBounds({
17 | x: drawAreaEl.current.getBoundingClientRect().left,
18 | y: drawAreaEl.current.getBoundingClientRect().bottom,
19 | });
20 | return () => {
21 | document
22 | .getElementById("drawArea")
23 | };// eslint-disable-next-line react-hooks/exhaustive-deps
24 | }, []);
25 |
26 | useEffect(() => {
27 | if (flag === "undo") {
28 | setRedoEl((arr) => [...arr, lines.pop()]);
29 | setLines(lines);
30 | }
31 | if (flag === "redo") {
32 | setLines((lines) => [...lines, redoEl.pop()]);
33 | }
34 | changeFlag();
35 | }, [flag, lines, redoEl, changeFlag]);
36 |
37 |
38 | useEffect(() => {
39 | const { getPaths } = props;
40 | if (isDrawing === false && lines.length) {
41 | getPaths(lines[lines.length - 1]);
42 | }
43 | }, [isDrawing, lines, props]);
44 |
45 | const handleMouseDown = useCallback((e) => {
46 | if (e.button !== 0) {
47 | return;
48 | }
49 | const point = relativeCoordinatesForEvent(e);
50 | let obj = {
51 | arr: [point],
52 | page: props.page,
53 | type: "freehand",
54 | };
55 | setLines((prevlines) => [...prevlines, obj]);
56 | setIsDrawing(true);
57 | },[props]);
58 |
59 | const handleMouseMove = (e) => {
60 | if (!isDrawing) {
61 | return;
62 | }
63 | const point = relativeCoordinatesForEvent(e);
64 | let last = lines.pop();
65 | last.arr.push(point);
66 | setLines((prevlines) => [...prevlines, last]);
67 | };
68 |
69 | const relativeCoordinatesForEvent = (e) => {
70 | const boundingRect = drawAreaEl.current.getBoundingClientRect();
71 | return new Immutable.Map({
72 | x: e.clientX - boundingRect.left,
73 | y: e.clientY - boundingRect.top,
74 | });
75 | };
76 |
77 | const addMouseDown = useCallback(() => {
78 | setIsCrosshair(true);
79 | document
80 | .getElementById("drawArea")
81 | .addEventListener("mousedown", handleMouseDown, { once: true });
82 | }, [handleMouseDown]);
83 |
84 | useEffect(() => {
85 | if (buttonType === "draw") {
86 | addMouseDown();
87 | resetButtonType();
88 | }
89 | }, [buttonType, resetButtonType, addMouseDown]);
90 |
91 | return (
92 | <>
93 |
99 | {props.children}
100 |
101 |
102 | >
103 | );
104 | }
105 |
106 | function Drawing({ lines, page }) {
107 | return (
108 |
109 | {lines.map((line, index) => (
110 |
111 | ))}
112 |
113 | );
114 | }
115 |
116 | function DrawingLine({ line, page }) {
117 | const pathData =
118 | "M " +
119 | line.arr
120 | .map((p) => {
121 | return `${p.get("x")},${p.get("y")}`;
122 | })
123 | .join(" L ");
124 |
125 | if (line.page === page) {
126 | return ;
127 | }
128 | return null;
129 | }
130 |
131 | export default DrawArea;
132 |
--------------------------------------------------------------------------------
/src/views/Download/components/EditPosition.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | const EditPosition = ({ x, y, addText, style }) => {
4 | return (
5 | addText(x, y)}
8 | >
9 | );
10 | };
11 |
12 | export default EditPosition;
13 |
--------------------------------------------------------------------------------
/src/views/Download/components/ModifyPage.jsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useCallback } from "react";
2 | import { PDFDocument, rgb, StandardFonts } from "pdf-lib";
3 |
4 | function ModifyPage(props) {
5 | const { buttonType, resetButtonType } = props;
6 | const memoizedModifyPdf = useCallback(modifyPdf, [modifyPdf]);
7 |
8 | useEffect(() => {
9 | if (buttonType === "download") {
10 | memoizedModifyPdf();
11 | resetButtonType();
12 | }
13 | }, [buttonType, resetButtonType, memoizedModifyPdf]);
14 |
15 | async function modifyPdf() {
16 | const existingPdfBytes = await fetch(props.pdf).then((res) => {
17 | return res.arrayBuffer();
18 | });
19 |
20 | const pdfDoc = await PDFDocument.load(existingPdfBytes);
21 | const helveticaFont = await pdfDoc.embedFont(StandardFonts.Helvetica);
22 | const pages = pdfDoc.getPages();
23 | const textSize = 12;
24 |
25 | props.result.forEach((res) => {
26 | if (res.type === "text") {
27 | if (!res.ref || !res.ref.current) {
28 | return;
29 | }
30 | console.log(
31 | res.x,
32 | res.y,
33 | res.ref.current.offsetLeft,
34 | res.ref.current.offsetTop
35 | );
36 | console.log(
37 | "Width",
38 | res.ref.current.getBoundingClientRect().width,
39 | res.ref.current.offsetWidth
40 | );
41 | pages[res.page - 1].drawText(res.text, {
42 | x: res.ref.current.offsetLeft - props.bounds.x,
43 | y: props.bounds.y - res.ref.current.offsetTop - 44,
44 | size: textSize,
45 | font: helveticaFont,
46 | color: rgb(0, 0, 0),
47 | maxWidth: res.ref.current.getBoundingClientRect().width,
48 | lineHeight: 15,
49 | });
50 | }
51 | if (res.type === "freehand") {
52 | const pathData =
53 | "M " +
54 | res.arr
55 | .map((p) => {
56 | return `${p.get("x")},${p.get("y")}`;
57 | })
58 | .join(" L ");
59 | pages[res.page - 1].moveTo(0, pages[0].getHeight());
60 | pages[res.page - 1].drawSvgPath(pathData, {
61 | borderColor: rgb(0, 0, 0),
62 | });
63 | }
64 | });
65 |
66 | const pdfBytes = await pdfDoc.save();
67 |
68 | let blob = new Blob([pdfBytes], { type: "application/pdf" });
69 | let link = document.createElement("a");
70 | link.href = window.URL.createObjectURL(blob);
71 | let fileName = "pdf-doc";
72 | link.download = fileName;
73 | link.click();
74 | }
75 |
76 | return
;
77 | }
78 |
79 | export default ModifyPage;
80 |
--------------------------------------------------------------------------------
/src/views/Download/components/Pdf/na.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GasFeDev/ChatPDF/7a22a6183116572f76d783d80a2a1a783abf4cfa/src/views/Download/components/Pdf/na.pdf
--------------------------------------------------------------------------------
/src/views/Download/components/PdfCreator.jsx:
--------------------------------------------------------------------------------
1 | import React, {
2 | useState,
3 | useEffect,
4 | useRef,
5 | useCallback,
6 | useContext,
7 | } from "react";
8 |
9 | import samplePDF from "./Pdf/na.pdf";
10 | import SinglePage from "./SinglePage";
11 | import ModifyPage from "./ModifyPage";
12 | import AutoTextArea from "./AutoTextArea";
13 | import { Context } from "../../../routers/App";
14 |
15 | const getTextAreaStyles = (pos) => {
16 | if (pos.x === 122 && pos.y === 237) {
17 | return {
18 | width: "175px",
19 | height: "12px",
20 | };
21 | } else if (pos.x === 308 && pos.y === 243) {
22 | return {
23 | width: "260px",
24 | height: "42px",
25 | };
26 | } else if (pos.x === 135 && pos.y === 253) {
27 | return {
28 | width: "160px",
29 | height: "33px",
30 | };
31 | } else if (pos.x === 200 && pos.y === 292) {
32 | return {
33 | width: "365px",
34 | height: "23px",
35 | };
36 | } else if (pos.x === 153 && pos.y === 319) {
37 | return {
38 | width: "37px",
39 | height: "22px",
40 | };
41 | } else if (pos.x === 262 && pos.y === 319) {
42 | return {
43 | width: "59px",
44 | height: "22px",
45 | };
46 | } else if (pos.x === 400 && pos.y === 319) {
47 | return {
48 | width: "49px",
49 | height: "22px",
50 | };
51 | } else if (pos.x === 507 && pos.y === 319) {
52 | return {
53 | width: "61px",
54 | height: "22px",
55 | };
56 | } else if (pos.x === 107 && pos.y === 346) {
57 | return {
58 | width: "85px",
59 | height: "38px",
60 | };
61 | } else if (pos.x === 263 && pos.y === 346) {
62 | return {
63 | width: "95px",
64 | height: "38px",
65 | };
66 | } else if (pos.x === 430 && pos.y === 346) {
67 | return {
68 | width: "139px",
69 | height: "38px",
70 | };
71 | } else if (pos.x === 128 && pos.y === 387) {
72 | return {
73 | width: "440px",
74 | height: "23px",
75 | };
76 | } else if (pos.x === 185 && pos.y === 413) {
77 | return {
78 | width: "380px",
79 | height: "48px",
80 | };
81 | } else if (pos.x === 213 && pos.y === 464) {
82 | return {
83 | width: "355px",
84 | height: "48px",
85 | };
86 | } else if (pos.x === 247 && pos.y === 516) {
87 | return {
88 | width: "323px",
89 | height: "48px",
90 | };
91 | } else if (pos.x === 70 && pos.y === 580) {
92 | return {
93 | width: "500px",
94 | height: "230px",
95 | };
96 | }
97 | };
98 |
99 | function PdfRellenado() {
100 | function NavbarButton({ changeButtonType }) {
101 | return (
102 | changeButtonType("download")}>Descargar
103 | );
104 | }
105 |
106 | const context = useContext(Context);
107 |
108 | const [result, setResult] = useState([]);
109 | const [pageNumber, setPageNumber] = useState(1);
110 | const [flag, setFlag] = useState("");
111 | const [bounds, setBounds] = useState({});
112 | const [isText, setIsText] = useState(false);
113 | const [buttonType, setButtonType] = useState("");
114 | const [positions] = useState([
115 | {
116 | x: 122,
117 | y: 227,
118 | text: "COLOMBIA",
119 | },
120 | {
121 | x: 308,
122 | y: 243,
123 | text: "Ninguna",
124 | },
125 | {
126 | x: 135,
127 | y: 253,
128 | text: "Senador",
129 | },
130 | {
131 | x: 200,
132 | y: 292,
133 | text: "Abogado",
134 | },
135 | {
136 | x: 153,
137 | y: 319,
138 | text: "130",
139 | },
140 | {
141 | x: 262,
142 | y: 319,
143 | text: "1810",
144 | },
145 | {
146 | x: 400,
147 | y: 319,
148 | text: "14900",
149 | },
150 | {
151 | x: 507,
152 | y: 319,
153 | text: "No",
154 | },
155 | {
156 | x: 107,
157 | y: 346,
158 | text: "26/01/2023",
159 | },
160 | {
161 | x: 263,
162 | y: 346,
163 | text: "20",
164 | },
165 | {
166 | x: 430,
167 | y: 346,
168 | text: "50",
169 | },
170 | {
171 | x: 128,
172 | y: 387,
173 | text: "Carlos y Juan",
174 | },
175 | {
176 | x: 185,
177 | y: 413,
178 | text: "Silvia",
179 | },
180 | {
181 | x: 213,
182 | y: 464,
183 | text: "Ley Nacional de Glaciares",
184 | },
185 | {
186 | x: 247,
187 | y: 516,
188 | text: "Control de Glaciares",
189 | },
190 | {
191 | x: 70,
192 | y: 580,
193 | text: `${context.message}`,
194 | },
195 | ]);
196 |
197 | const tempRef = useRef(null);
198 |
199 | //Keep track of current page number
200 | const pageChange = (num) => {
201 | setPageNumber(num);
202 | };
203 |
204 | //Function to add text in PDF
205 | const addText = useCallback(
206 | (x, y, text) => {
207 | setIsText(true);
208 | setResult((result) => [
209 | ...result,
210 | {
211 | id: generateKey(x),
212 | x: x,
213 | y: y,
214 | text: text,
215 | page: pageNumber,
216 | type: "text",
217 | ref: tempRef,
218 | },
219 | ]);
220 | },
221 | [pageNumber]
222 | );
223 |
224 | useEffect(() => {
225 | positions.forEach(({ x, y, text }) => {
226 | addText(x, y, text);
227 | });
228 | }, [positions, addText]);
229 |
230 | //Flag for DrawArea reference
231 | const changeFlag = () => {
232 | setFlag("");
233 | };
234 |
235 | const getPaths = (el) => {
236 | setResult((res) => [...res, el]);
237 | };
238 |
239 | const getBounds = (obj) => {
240 | setBounds(obj);
241 | };
242 |
243 | const generateKey = (pre) => {
244 | return `${pre}_${new Date().getTime()}`;
245 | };
246 | const onTextChange = (id, txt, ref) => {
247 | let indx = result.findIndex((x) => x.id === id);
248 | let item = { ...result[indx] };
249 | item.text = txt;
250 | item.ref = ref;
251 | result[indx] = item;
252 | setResult(result);
253 | };
254 |
255 | const changeButtonType = (type) => {
256 | setButtonType(type);
257 | };
258 |
259 | const resetButtonType = () => {
260 | setButtonType("");
261 | };
262 |
263 | return (
264 |
265 | {result.map((res) => {
266 | if (res.type === "text") {
267 | if (res.page === pageNumber) {
268 | }
269 | return (
270 |
271 | {positions.map((pos, index) => (
272 |
292 | ))}
293 |
294 | );
295 | } else {
296 | return null;
297 | }
298 | })}
299 |
300 |
Honorables - PDF
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
313 |
314 |
315 |
326 |
333 |
334 | );
335 | }
336 |
337 | export default PdfRellenado;
338 |
--------------------------------------------------------------------------------
/src/views/Download/components/SinglePage.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from "react";
2 | import DrawArea from "./DrawArea";
3 | import { Document, Page, pdfjs } from "react-pdf/dist/esm/entry.webpack";
4 | pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`;
5 |
6 | export default function SinglePage(props) {
7 | const [, setNumPages] = useState(null);
8 | const [pageNumber, setPageNumber] = useState(1);
9 |
10 | function onDocumentLoadSuccess({ numPages }) {
11 | setNumPages(numPages);
12 | setPageNumber(1);
13 | }
14 |
15 | useEffect(() => {
16 | props.pageChange(pageNumber);
17 | });
18 |
19 | //Load PDF
20 | const { pdf } = props;
21 |
22 | return (
23 | <>
24 |
25 |
console.log(err)}
29 | onSourceSuccess={() => console.log("SUCCESS")}
30 | onLoadSuccess={onDocumentLoadSuccess}
31 | onLoadError={() => console.log("ERR")}
32 | >
33 |
43 |
44 |
45 |
46 |
47 | >
48 | );
49 | }
50 |
--------------------------------------------------------------------------------
/src/views/Download/components/index.js:
--------------------------------------------------------------------------------
1 | export { default as AutoTextArea } from "./AutoTextArea";
2 | export { default as DrawArea } from "./DrawArea";
3 | export { default as EditPosition } from "./EditPosition";
4 | export { default as ModifyPage } from "./ModifyPage";
5 | export { default as PdfCreator } from "./PdfCreator";
6 | export { default as SinglePage } from "./SinglePage";
7 |
--------------------------------------------------------------------------------
/src/views/Home/Home.jsx:
--------------------------------------------------------------------------------
1 | import React, { useContext, useState } from 'react'
2 | import { Container } from '@mui/system'
3 | import { Box, Divider, IconButton, InputBase, Paper, Tooltip, Zoom } from '@mui/material'
4 | import SearchIcon from '@mui/icons-material/Search';
5 | import InfoIcon from '@mui/icons-material/Info';
6 | import { ChatGPT, WebScrapping } from './components';
7 | import honorablesService from '../../services/honorables.service';
8 | import Swal from 'sweetalert2';
9 | import { configError } from '../../helpers/notificationMessage';
10 | import { Context } from '../../routers/App';
11 |
12 | const Home = () => {
13 | const halfWidthContainer = "50%";
14 | const allHeightContainer = "100%";
15 | const padding = "10 px";
16 |
17 | const [search, setSearch] = useState("");
18 | const context = useContext(Context)
19 |
20 | const onChangeSearch = (e) => {
21 | setSearch(e.target.value)
22 | }
23 |
24 | const searchText = async(e) => {
25 | try{
26 | if(search.length > 0 ){
27 | context.setLoading(true);
28 | //Search text user
29 | const result = await honorablesService.post("/gpt-3",{ message: search})
30 | //Search key words
31 | const resultKeyWords = await honorablesService.post("/gpt-3",{ message: `${search}, dime las palabras clave de este texto separadas por coma`})
32 | const keywords = resultKeyWords.data?.text.replace("\n\nPalabras clave: ","").split(",");
33 | context.setKeyWords(keywords);
34 | context.setQuestion(search);
35 | context.setMessage(result.data?.text.slice(2));
36 |
37 | //Remove search
38 | setSearch("")
39 | }else{
40 | Swal.fire(configError("Escriba la ley que desea buscar"))
41 | }
42 | }catch(error){
43 | context.setLoading(false);
44 | Swal.fire(configError("Ocurrió un error de conexión"))
45 | }
46 | }
47 |
48 | return (
49 |
50 |
51 |
55 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 | )
87 | }
88 |
89 | export default Home
--------------------------------------------------------------------------------
/src/views/Home/components/ChatGPT/ChatGPT.jsx:
--------------------------------------------------------------------------------
1 | import React, { useContext, useEffect, useState } from 'react'
2 | import { Box, CircularProgress, Paper, Typography } from '@mui/material'
3 | import { Context } from '../../../../routers/App'
4 | import 'animate.css';
5 |
6 | const ChatGPT = () => {
7 | const context = useContext(Context);
8 | const [listAnswers, setListAnswers] = useState([]);
9 |
10 | useEffect(()=>{
11 | if(context.message.length > 0){
12 | const answer = {
13 | question: context.question,
14 | answer: context.message
15 | }
16 | listAnswers.unshift(answer);
17 | setListAnswers(listAnswers);
18 | context.setLoading(false);
19 | }
20 | },[context.message]);
21 |
22 | return (
23 |
24 | { context.loading ?
25 |
26 |
27 |
28 | :
29 | <>>
30 | }
31 | {
32 | listAnswers.map( (answers,index) => (
33 |
34 | Pregunta: {answers.question}
35 |
36 | {answers.answer}
37 |
38 |
39 | ))
40 | }
41 |
42 | )
43 | }
44 |
45 | export default ChatGPT
--------------------------------------------------------------------------------
/src/views/Home/components/WebScrapping/WebScrapping.jsx:
--------------------------------------------------------------------------------
1 | import React, { useContext, useEffect, useState } from 'react'
2 | import { Alert, Box, Button, Card, CardActions, CardContent, CircularProgress, Typography } from '@mui/material'
3 | import { useNavigate } from 'react-router-dom'
4 | import { Container } from '@mui/system'
5 | import { Context } from '../../../../routers/App'
6 | import honorablesService from '../../../../services/honorables.service'
7 | import 'animate.css';
8 |
9 | const WebScrapping = () => {
10 | const context = useContext(Context);
11 | const navigate = useNavigate();
12 | const fontSize = 14;
13 | const color= "text.secondary"
14 | const fullWidth = "100%"
15 | const centerElements = {
16 | display:"flex",
17 | flexDirection:"column",
18 | justifyContent:"center",
19 | alignItems:"center"
20 | }
21 | const [ listDocuments, setListDocuments ] = useState([]);
22 | const [ statusFetch, setStatusFetch ] = useState(false);
23 |
24 | useEffect(()=>{
25 | if(context.keywords.length > 0){
26 | setListDocuments([]);
27 | const fetchScrapping = async () =>{
28 | try{
29 | setStatusFetch("Buscando...");
30 | await Promise.all(context.keywords.map(async (keyword) => {
31 | const res = await honorablesService.post('/webscrapping',{ message: keyword})
32 | const documents = res.data.results.slice(0,2).map((doc)=>{
33 | return {
34 | id: doc["@id"],
35 | entity: doc.entity,
36 | date: doc.date,
37 | link: doc.link
38 | }
39 | })
40 | listDocuments.push(...documents);
41 | }));
42 | }finally{
43 | setListDocuments(listDocuments);
44 | if(listDocuments.length === 0){
45 | setStatusFetch("No se encontró información.");
46 | }else{
47 | setStatusFetch(false);
48 | }
49 | }
50 | }
51 | fetchScrapping()
52 | }
53 | },[context.keywords])
54 |
55 | const navigatePDF = () => {
56 | navigate('/download');
57 | }
58 |
59 | return (
60 |
61 |
62 | Aqui encontrarás una biblioteca de archivos que te servirán basado en tu ultima busqueda!
63 | {
64 | statusFetch ?
65 |
66 | {
67 | statusFetch === "Buscando..." ?
68 | <>
69 |
70 | {statusFetch}
71 | >
72 | :
73 | {statusFetch}
74 | }
75 |
76 | :
77 | <>>
78 | }
79 | {
80 | context.keywords.length > 0 ?
81 |
82 | Puedes descargar un resumen aqui!
83 | Descargar resumen
84 | :
85 | <>>
86 | }
87 | {
88 | listDocuments.map((document,index)=>(
89 |
90 |
91 |
92 | Documento N° {document.id}
93 |
94 |
95 | Entidad: {document.entity}
96 |
97 |
98 | Fecha: {document.date}
99 |
100 |
101 |
102 | {window.open(document.link)}}>Descargar documento
103 |
104 |
105 | ))
106 | }
107 |
108 |
109 | )
110 | }
111 |
112 | export default WebScrapping
--------------------------------------------------------------------------------
/src/views/Home/components/index.js:
--------------------------------------------------------------------------------
1 | export { default as ChatGPT} from './ChatGPT/ChatGPT';
2 | export { default as WebScrapping} from './WebScrapping/WebScrapping';
--------------------------------------------------------------------------------
/src/views/index.js:
--------------------------------------------------------------------------------
1 | export { default as Home} from './Home/Home';
2 | export { default as Download} from './Download/Download';
--------------------------------------------------------------------------------