diff --git a/.dockerignore b/.dockerignore index c77a412..5fcee18 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,2 +1,3 @@ node_modules -github \ No newline at end of file +github +public \ No newline at end of file diff --git a/.gitignore b/.gitignore index ff227fe..2955045 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ -node_modules/ -data/ \ No newline at end of file +node_modules +data +public \ No newline at end of file diff --git a/Socket.js b/Socket.js index 0ae1f56..a6a58c6 100644 --- a/Socket.js +++ b/Socket.js @@ -1,11 +1,13 @@ const WebSocket = require('ws'); +const Logger = require('./utils/Logger'); +const logger = new Logger(); class Socket { constructor(server) { this.webSocketServer = new WebSocket.Server({ server }) this.webSocketServer.on('listening', () => { - console.log('Socket: listen'); + logger.log('Socket: listen'); }) this.webSocketServer.on('connection', (webSocketClient) => { diff --git a/client/.env b/client/.env index d53bf3c..a0df532 100644 --- a/client/.env +++ b/client/.env @@ -1 +1 @@ -REACT_APP_VERSION=1.4.1 \ No newline at end of file +REACT_APP_VERSION=1.4.2 \ No newline at end of file diff --git a/client/src/components/Settings/StyleSettings/StyleSettings.tsx b/client/src/components/Settings/StyleSettings/StyleSettings.tsx index f73ac1d..9f45065 100644 --- a/client/src/components/Settings/StyleSettings/StyleSettings.tsx +++ b/client/src/components/Settings/StyleSettings/StyleSettings.tsx @@ -1,17 +1,28 @@ import { useState, useEffect, ChangeEvent, FormEvent } from 'react'; import axios from 'axios'; +// Redux +import { connect } from 'react-redux'; +import { createNotification } from '../../../store/actions'; + +// Typescript +import { ApiResponse, NewNotification } from '../../../interfaces'; + +// UI import InputGroup from '../../UI/Forms/InputGroup/InputGroup'; import Button from '../../UI/Buttons/Button/Button'; -import { ApiResponse } from '../../../interfaces'; -const StyleSettings = (): JSX.Element => { +interface ComponentProps { + createNotification: (notification: NewNotification) => void; +} + +const StyleSettings = (props: ComponentProps): JSX.Element => { const [customStyles, setCustomStyles] = useState(''); useEffect(() => { axios.get>('/api/config/0/css') .then(data => setCustomStyles(data.data.data)) - .catch(err => console.log(err)); + .catch(err => console.log(err.response)); }, []) const inputChangeHandler = (e: ChangeEvent) => { @@ -22,7 +33,14 @@ const StyleSettings = (): JSX.Element => { const formSubmitHandler = (e: FormEvent) => { e.preventDefault(); - axios.put>('/api/config/0/css', { styles: customStyles }); + axios.put>('/api/config/0/css', { styles: customStyles }) + .then(() => { + props.createNotification({ + title: 'Success', + message: 'CSS saved. Reload page to see changes' + }) + }) + .catch(err => console.log(err.response)); } return ( @@ -34,6 +52,7 @@ const StyleSettings = (): JSX.Element => { name='customStyles' value={customStyles} onChange={(e) => inputChangeHandler(e)} + spellCheck={false} > @@ -41,4 +60,4 @@ const StyleSettings = (): JSX.Element => { ) } -export default StyleSettings; \ No newline at end of file +export default connect(null, { createNotification })(StyleSettings); \ No newline at end of file diff --git a/db.js b/db.js index 7728737..94932e8 100644 --- a/db.js +++ b/db.js @@ -1,4 +1,6 @@ const { Sequelize } = require('sequelize'); +const Logger = require('./utils/Logger'); +const logger = new Logger(); const sequelize = new Sequelize({ dialect: 'sqlite', @@ -9,17 +11,18 @@ const sequelize = new Sequelize({ const connectDB = async () => { try { await sequelize.authenticate(); - console.log('Connected to database'); + logger.log('Connected to database'); + + const syncModels = false; - const syncModels = true; - if (syncModels) { - console.log('Starting model synchronization'); + logger.log('Starting model synchronization'); await sequelize.sync({ alter: true }); - console.log('All models were synchronized'); + logger.log('All models were synchronized'); } } catch (error) { - throw new Error(`Unable to connect to the database: ${error.message}`); + logger.log(`Unable to connect to the database: ${error.message}`, 'ERROR'); + process.exit(1); } } diff --git a/middleware/errorHandler.js b/middleware/errorHandler.js index 2de45a7..5db2bb2 100644 --- a/middleware/errorHandler.js +++ b/middleware/errorHandler.js @@ -1,5 +1,7 @@ const ErrorResponse = require('../utils/ErrorResponse'); const colors = require('colors'); +const Logger = require('../utils/Logger'); +const logger = new Logger(); const errorHandler = (err, req, res, next) => { let error = { ...err }; @@ -10,8 +12,7 @@ const errorHandler = (err, req, res, next) => { // error = new ErrorResponse(`Field ${msg}`, 400); // } - console.log(error); - console.log(`${err}`); + logger.log(error.message.split(',')[0], 'ERROR'); res.status(err.statusCode || 500).json({ success: false, diff --git a/server.js b/server.js index c15ebf0..6ce25d0 100644 --- a/server.js +++ b/server.js @@ -7,6 +7,8 @@ const Socket = require('./Socket'); const Sockets = require('./Sockets'); const associateModels = require('./models/associateModels'); const initConfig = require('./utils/initConfig'); +const Logger = require('./utils/Logger'); +const logger = new Logger(); const PORT = process.env.PORT || 5005; @@ -24,6 +26,6 @@ const PORT = process.env.PORT || 5005; Sockets.registerSocket('weather', weatherSocket); server.listen(PORT, () => { - console.log(`Server is running on port ${PORT} in ${process.env.NODE_ENV} mode`); + logger.log(`Server is running on port ${PORT} in ${process.env.NODE_ENV} mode`); }) })(); \ No newline at end of file diff --git a/utils/Logger.js b/utils/Logger.js index 6301dfe..6648212 100644 --- a/utils/Logger.js +++ b/utils/Logger.js @@ -1,40 +1,39 @@ -const fs = require('fs'); - class Logger { - constructor() { - this.logFileHandler(); + log(message, level = 'INFO') { + console.log(`[${this.generateTimestamp()}] [${level}] ${message}`) } - logFileHandler() { - if (!fs.existsSync('./flame.log')) { - fs.writeFileSync('./flame.log', ''); - } else { - console.log('file exists'); + generateTimestamp() { + const d = new Date(); + + // Date + const year = d.getFullYear(); + const month = this.parseDate(d.getMonth() + 1); + const day = this.parseDate(d.getDate()); + + // Time + const hour = this.parseDate(d.getHours()); + const minutes = this.parseDate(d.getMinutes()); + const seconds = this.parseDate(d.getSeconds()); + const miliseconds = this.parseDate(d.getMilliseconds(), true); + + // Timezone + const tz = -d.getTimezoneOffset() / 60; + + return `${year}-${month}-${day} ${hour}:${minutes}:${seconds}.${miliseconds} UTC${tz > 0 ? '+' + tz : tz}`; + } + + parseDate(date, ms = false) { + if (ms) { + if (date >= 10 && date < 100) { + return `0${date}`; + } else if (date < 10) { + return `00${date}`; + } } - } - writeLog(logMsg, logType) { - - } - - generateLog(logMsg, logType) { - const now = new Date(); - const date = `${this.parseNumber(now.getDate())}-${this.parseNumber(now.getMonth() + 1)}-${now.getFullYear()}`; - const time = `${this.parseNumber(now.getHours())}:${this.parseNumber(now.getMinutes())}:${this.parseNumber(now.getSeconds())}.${now.getMilliseconds()}`; - const log = `[${date} ${time}]: ${logType} ${logMsg}`; - return log; - // const timestamp = new Date().toISOString(); - } - - parseNumber(number) { - if (number > 9) { - return number; - } else { - return `0${number}`; - } + return date < 10 ? `0${date}` : date.toString(); } } -// console.log(logger.generateLog('testMsg', 'INFO')); - -module.exports = new Logger(); \ No newline at end of file +module.exports = Logger; \ No newline at end of file diff --git a/utils/clearWeatherData.js b/utils/clearWeatherData.js index d43f975..07be15b 100644 --- a/utils/clearWeatherData.js +++ b/utils/clearWeatherData.js @@ -1,5 +1,7 @@ const { Op } = require('sequelize'); const Weather = require('../models/Weather'); +const Logger = require('./Logger'); +const logger = new Logger(); const clearWeatherData = async () => { const weather = await Weather.findOne({ @@ -16,7 +18,7 @@ const clearWeatherData = async () => { }) } - console.log('Old weather data was deleted'); + logger.log('Old weather data was deleted'); } module.exports = clearWeatherData; \ No newline at end of file diff --git a/utils/initConfig.js b/utils/initConfig.js index de1cc88..1455ccb 100644 --- a/utils/initConfig.js +++ b/utils/initConfig.js @@ -1,6 +1,8 @@ const { Op } = require('sequelize'); const Config = require('../models/Config'); const { config } = require('./initialConfig.json'); +const Logger = require('./Logger'); +const logger = new Logger(); const initConfig = async () => { // Get config values @@ -26,7 +28,7 @@ const initConfig = async () => { } }) - console.log('Initial config created'); + logger.log('Initial config created'); return; } diff --git a/utils/jobs.js b/utils/jobs.js index 19dc0a8..935f497 100644 --- a/utils/jobs.js +++ b/utils/jobs.js @@ -2,15 +2,17 @@ const schedule = require('node-schedule'); const getExternalWeather = require('./getExternalWeather'); const clearWeatherData = require('./clearWeatherData'); const Sockets = require('../Sockets'); +const Logger = require('./Logger'); +const logger = new Logger(); // Update weather data every 15 minutes const weatherJob = schedule.scheduleJob('updateWeather', '0 */15 * * * *', async () => { try { const weatherData = await getExternalWeather(); - console.log('weather updated'); + logger.log('Weather updated'); Sockets.getSocket('weather').socket.send(JSON.stringify(weatherData)); } catch (err) { - console.log(err.message); + logger.log(err.message, 'ERROR'); } })