Replace htmlparser2 to simple-xml-to-json

This commit is contained in:
rasta5man 2024-04-27 14:42:30 +02:00
parent 0ecea2ef9d
commit 2ccd31d53b
5 changed files with 87 additions and 148 deletions

View file

@ -1,70 +1,9 @@
# Getting Started with Create React App
Node version used in project: v14.21.3
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
Instalation:
## Available Scripts
1. Download the repositary.
2. Go to project folder.
3. Run 'npm i' to install all necessary packages.
4. Start app with 'npm start' command.
In the project directory, you can run:
### `npm start`
Runs the app in the development mode.\
Open [http://localhost:3000](http://localhost:3000) to view it in your browser.
The page will reload when you make changes.\
You may also see any lint errors in the console.
### `npm test`
Launches the test runner in the interactive watch mode.\
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
### `npm run build`
Builds the app for production to the `build` folder.\
It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.\
Your app is ready to be deployed!
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
### `npm run eject`
**Note: this is a one-way operation. Once you `eject`, you can't go back!**
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.
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.
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.
## Learn More
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
To learn React, check out the [React documentation](https://reactjs.org/).
### Code Splitting
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)
### Analyzing the Bundle Size
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)
### Making a Progressive Web App
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)
### Advanced Configuration
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)
### Deployment
This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
### `npm run build` fails to minify
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)

View file

@ -10,10 +10,10 @@
"@testing-library/react": "^13.3.0",
"@testing-library/user-event": "^13.5.0",
"axios": "^0.27.2",
"htmlparser2": "^9.1.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"simple-xml-to-json": "^1.2.2",
"web-vitals": "^2.1.4"
},
"scripts": {

View file

@ -5,7 +5,6 @@
width:100%;
background-color:black;
overflow: hidden;
}
.containerBottom
@ -26,7 +25,7 @@
{
width: 100%;
height: 200vmax;
height: 150vmax;
/* height: 5000px; */
pointer-events: none;
border: 0;
@ -36,4 +35,8 @@
display: flex;
justify-content: center;
align-items: center;
}
}
.scrollMarginTop {
scroll-margin-top: 30px;
}

View file

@ -1,17 +1,25 @@
import React, {useState, useEffect, useRef} from 'react';
import axios from 'axios';
import {Box, Typography, Paper, Container, Link, Button} from '@mui/material';
import * as htmlparser2 from "htmlparser2";
import axios from 'axios'
import {Box, Typography, Paper, Container, Button} from '@mui/material';
import './App.css';
const mainHeaderFontSize = 50;
const {convertXML} = require("simple-xml-to-json");
const MAIN_HEADER_FONT_SIZE = 50;
const headerFontSize = 20;
const dataFontSize = 42;
const temperatureUrl = "http://10.0.0.106:3000/gettemperature";
const departuresUrl = 'http://10.0.0.106:3000/getdepartures';
const dniTyzdna = ["Neděle", "Pondělí", "Úterý", "Středa", "Čtvrtek", "Pátek", "Sobota"];
const DATA_FONT_SIZE = 42;
const TEMPERATURE_URL = "http://10.0.0.106:3000/gettemperature";
const DEPARTURES_URL = 'http://10.0.0.106:3000/getdepartures';
const SOKOLOV_RSS_URL = 'https://www.sokolov.cz/rss/';
const DAYS_OF_WEEK = ["Neděle", "Pondělí", "Úterý", "Středa", "Čtvrtek", "Pátek", "Sobota"];
let msToMidnight = null;
let updateDayOfWeek;
const OPTIONS = { hour12: false };
let sokolovFeed;
// colors in sokolov website
const LOGO_COLOR = '#82c55b' // green
const FONT_COLOR = '#00367b';
function App() {
@ -20,29 +28,37 @@ function App() {
var [temperature, setTemperature] = useState("?");
var [departures, setDepartures] = useState([]);
var [dayOfWeek, setDayOfWeek] = useState('');
var [feedData, setFeedData] = useState({updated:'', items: []});
var [feedData, setFeedData] = useState([{title: "Chyba stažení dat, kontaktujte prosím administrátora", description:"", link:"", pubDate: new Date()}]);
var [chosenArticle, setChosenArticle] = useState({clicked: false, url: ""});
// to assure, that website in iframe loads at the top
const myRef = useRef(null);
const iframeRef = useRef(null);
//to assure, that feed loads at the top
const containerRef = useRef(null);
const executeScroll = () => {
myRef.current.scrollIntoView(true);
// myRef.current.scrollTo(0,0);
iframeRef.current.scrollIntoView(true);
}
useEffect(()=> {
!chosenArticle.clicked && containerRef.current.scrollIntoView({ behavior: 'smooth' });
}, [chosenArticle])
function updateDate() {
setDate(new Date());
}
// go back to rss feed page
const resetWeb = () => {
setChosenArticle({clicked: false, url: ""});
}
function getTemperature() {
// console.log("getTemperature");
axios(temperatureUrl, {
axios(TEMPERATURE_URL, {
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Origin': '*',
}})
.then(response => {
//console.log('temp --', response);
let t = parseFloat(response.data);
//console.log(t);
if(isNaN(t)) return;
@ -55,19 +71,16 @@ function App() {
}
function getDepartures() {
// console.log("getDepartures");
axios(departuresUrl, {
axios(DEPARTURES_URL, {
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Origin': '*',
}})
.then(response => {
//console.log('----', response);
const departures = response.data;
setDepartures(departures);
})
.catch(error => {
console.log(error);
console.log(error);
});
}
@ -84,7 +97,7 @@ function App() {
function getDay() {
clearInterval(updateDayOfWeek);
const date = new Date();
setDayOfWeek(dniTyzdna[date.getDay()]);
setDayOfWeek(DAYS_OF_WEEK[date.getDay()]);
msToMidnight = milisecondsToMidnight();
console.log('setDay called, ms to midnight', msToMidnight);
@ -102,10 +115,6 @@ function App() {
var timerTemperature = setInterval(getTemperature, 60*1000);
var timerDepartures = setInterval(getDepartures, 60*1000);
//console.log(timer);
//console.log(timerTemperature);
//console.log("-----");
return function cleanup() {
clearInterval(timer);
clearInterval(timerTemperature);
@ -115,16 +124,26 @@ function App() {
}, []);
// rss feed to get articles from sokolov website
const getRssFeed = async() => {
try {
const res = await axios.get('https://www.sokolov.cz/rss/');
const feed = htmlparser2.parseFeed(res.data);
//console.log(feed);
setFeedData({updated: feed.updated, items: feed.items});
// setFeedData({updated: "feed.updated", items: dummyData});
} catch(e) {
console.log(e);
}
const getRssFeed = () => {
axios(SOKOLOV_RSS_URL).then(response => {
const myJson = convertXML(response?.data);
let data = myJson?.rss?.children[0]?.channel?.children;
if(!Array.isArray(data)) return;
// first 5 items are informational, so we skip them
const result = data.slice(5).map(item => {
const d = item?.item?.children;
const url = d[1]?.link?.content.replace('amp;','');
let pubDate = d[3]?.pubDate?.content;
pubDate ? pubDate = new Date(pubDate) : pubDate = new Date();
return {title: d[0]?.title?.content, description: d[2]?.description?.content, link: url, pubDate: pubDate}
})
console.log(result)
setFeedData(result)
}).catch(e => console.log(e))
}
useEffect(() => {
@ -135,49 +154,44 @@ function App() {
}
},[])
const resetWeb = () => {
setChosenArticle({clicked: false, url: ""});
}
const buildFeedView = () => {
return feedData.items.map((item,index) => {
return feedData.map((item,index) => {
return (
<Box sx={{padding: 2}} key={index}>
<Typography sx={{color: '#82c55b'}} variant="h4">{item.title}</Typography>
<Typography variant='body1' className='hoverOverLink' onClick={()=> setChosenArticle({clicked: true, url: item.link})}>{item.link}</Typography>
<Typography sx={{color: LOGO_COLOR}} variant="h6">{item.title}</Typography>
<Typography variant='subtitle2' className='hoverOverLink' onClick={()=> setChosenArticle({clicked: true, url: item.link})}>Přečti celý článek ...</Typography>
<Typography variant='body1'>{item.description}</Typography>
<Typography sx={{color: '#00367b'}} variant='subtitle2'>{item.pubDate.toLocaleDateString('cs-Cz')}</Typography>
<Typography sx={{color: FONT_COLOR}} variant='subtitle2'>{item.pubDate.toLocaleDateString('cs-Cz')}</Typography>
</Box>)
})
}
const sokolovFeed = buildFeedView();
const options = { hour12: false };
sokolovFeed = buildFeedView();
return (
<>
<div className='containerTop'>
<table key="dataTable" style={{width:'90%', color:'white', marginTop: '3vh'}} cellPadding="0" cellSpacing="0" align="center">
<tbody>
<tr style={{fontSize: mainHeaderFontSize}}>
<td align="center">{date.toLocaleTimeString('sk-SK', options)}</td>
<tr style={{fontSize: MAIN_HEADER_FONT_SIZE}}>
<td align="center">{date.toLocaleTimeString('sk-SK', OPTIONS)}</td>
<td align="center">{dayOfWeek} &nbsp; {date.toLocaleDateString('sk-SK')}</td>
<td align="center">{temperature} &#8451;</td>
</tr>
<tr style={{fontSize: mainHeaderFontSize}}>
<tr style={{fontSize: MAIN_HEADER_FONT_SIZE}}>
<td align="center" colSpan={3}>
<hr></hr>
</td>
</tr>
<tr style={{fontSize: mainHeaderFontSize, verticalAlign: 'top', height: 70}}>
<tr style={{fontSize: MAIN_HEADER_FONT_SIZE, verticalAlign: 'top', height: 70}}>
<td align="center">LINKA</td>
<td align="left">SMĚR</td>
<td align="center">PŘÍJEZD</td>
</tr>
{
departures.map(function(item, i){
// return <tr key={i} style={{fontSize: dataFontSize, height: 55}}><td align="center">{item.linka}</td><td align="center">{item.place}</td><td align="center">{item.time}</td></tr>;
return <tr key={i} style={{fontSize: dataFontSize}}><td align="center">{item[0]}</td><td align="left">{item[2]}</td><td align="center">{item[1]}</td></tr>;
return <tr key={i} style={{fontSize: DATA_FONT_SIZE}}><td align="center">{item[0]}</td><td align="left">{item[2]}</td><td align="center">{item[1]}</td></tr>;
})
}
</tbody>
@ -189,30 +203,23 @@ function App() {
</div>
<div key="containerBottom" className="containerBottom">
{chosenArticle.clicked ? <iframe className="iframe" ref={myRef} style={{}} onLoad={executeScroll} src={chosenArticle.url} ></iframe> :
<Container maxWidth={false}>
<Paper elevation={2} sx={{margin:'1vh 10vw 1vh'}}>
{sokolovFeed}
</Paper>
</Container>
{chosenArticle.clicked ? <iframe title="sokolovWeb" className="iframe" ref={iframeRef} onLoad={executeScroll} src={chosenArticle.url} ></iframe> :
<Container className="scrollMarginTop" ref={containerRef} maxWidth={false}>
<Paper elevation={2} sx={{margin:'1vh 10vw 1vh'}}>
{sokolovFeed}
</Paper>
</Container>
}
</div>
</>
)
}
export default App;
// helper data
const logoColor = '#82c55b' // green
const fontColor = '#00367b';
const departures = [
[ '6', '07:23', 'Sídl.Michal škola', [ 'X', '42' ] ],
[ '3', '07:27', 'Sídliště Michal', [ 'X', '32' ] ],

View file

@ -1,10 +0,0 @@
class DataContainer extends Component {
state = { }
render() {
return (
<div>Component</div>
);
}
}
export default DataContainer;