Update bookmark. Changes to CSS. Changes to WeatherJob

This commit is contained in:
unknown 2021-06-01 14:54:47 +02:00
parent 519b6d0746
commit 96aa1f7d69
11 changed files with 165 additions and 36 deletions

View File

@ -17,7 +17,7 @@ interface ComponentProps {
addCategory: (formData: NewCategory) => void; addCategory: (formData: NewCategory) => void;
addBookmark: (formData: NewBookmark) => void; addBookmark: (formData: NewBookmark) => void;
updateCategory: (id: number, formData: NewCategory) => void; updateCategory: (id: number, formData: NewCategory) => void;
updateBookmark: (id: number, formData: NewBookmark) => void; updateBookmark: (id: number, formData: NewBookmark, categoryWasChanged: boolean) => void;
createNotification: (notification: NewNotification) => void; createNotification: (notification: NewNotification) => void;
} }
@ -90,7 +90,7 @@ const BookmarkForm = (props: ComponentProps): JSX.Element => {
setCategoryName({ name: '' }); setCategoryName({ name: '' });
} else if (props.contentType === ContentType.bookmark && props.bookmark) { } else if (props.contentType === ContentType.bookmark && props.bookmark) {
// Update bookmark // Update bookmark
props.updateBookmark(props.bookmark.id, formData); props.updateBookmark(props.bookmark.id, formData, props.bookmark.categoryId !== formData.categoryId);
setFormData({ setFormData({
name: '', name: '',
url: '', url: '',

View File

@ -1,9 +1,11 @@
import { useState, ChangeEvent, Fragment, useEffect, FormEvent } from 'react'; import { useState, ChangeEvent, useEffect, FormEvent } from 'react';
import { connect } from 'react-redux';
import axios from 'axios'; import axios from 'axios';
import { ApiResponse, Config } from '../../../interfaces'; import { ApiResponse, Config, NewNotification } from '../../../interfaces';
import InputGroup from '../../UI/Forms/InputGroup/InputGroup'; import InputGroup from '../../UI/Forms/InputGroup/InputGroup';
import Button from '../../UI/Buttons/Button/Button'; import Button from '../../UI/Buttons/Button/Button';
import { createNotification } from '../../../store/actions';
interface FormState { interface FormState {
WEATHER_API_KEY: string; WEATHER_API_KEY: string;
@ -12,7 +14,11 @@ interface FormState {
isCelsius: number; isCelsius: number;
} }
const WeatherSettings = (): JSX.Element => { interface ComponentProps {
createNotification: (notification: NewNotification) => void;
}
const WeatherSettings = (props: ComponentProps): JSX.Element => {
const [formData, setFormData] = useState<FormState>({ const [formData, setFormData] = useState<FormState>({
WEATHER_API_KEY: '', WEATHER_API_KEY: '',
lat: 0, lat: 0,
@ -59,7 +65,12 @@ const WeatherSettings = (): JSX.Element => {
e.preventDefault(); e.preventDefault();
axios.put<ApiResponse<{}>>('/api/config', formData) axios.put<ApiResponse<{}>>('/api/config', formData)
.then(data => console.log(data.data.success)) .then(data => {
props.createNotification({
title: 'Success',
message: 'Settings updated'
})
})
.catch(err => console.log(err)); .catch(err => console.log(err));
} }
@ -131,4 +142,4 @@ const WeatherSettings = (): JSX.Element => {
) )
} }
export default WeatherSettings; export default connect(null, { createNotification })(WeatherSettings);

View File

@ -1,8 +1,16 @@
.Container { .Container {
width: 100%; width: 100%;
padding: 20px; padding: 20px;
margin: 0 auto;
} }
/* .Container {
width: 60%;
margin: 0 auto;
padding: 20px;
padding-top: 20px;
} */
/* 320px 480px: Mobile devices. /* 320px 480px: Mobile devices.
481px 768px: iPads, Tablets. 481px 768px: iPads, Tablets.
769px 1024px: Small screens, laptops. 769px 1024px: Small screens, laptops.
@ -11,7 +19,8 @@
@media (min-width: 769px) { @media (min-width: 769px) {
.Container { .Container {
padding: 25px 40px; /* padding: 25px 40px; */
width: 90%;
} }
} }

View File

@ -1,5 +1,6 @@
.WeatherWidget { .WeatherWidget {
display: flex; display: flex;
visibility: hidden;
} }
.WeatherDetails { .WeatherDetails {
@ -20,3 +21,9 @@
.WeatherDetails span:last-child { .WeatherDetails span:last-child {
padding-top: 5px; padding-top: 5px;
} }
@media (min-width: 600px) {
.WeatherWidget {
visibility: visible;
}
}

View File

@ -14,27 +14,54 @@ const WeatherWidget = (): JSX.Element => {
isDay: 1, isDay: 1,
conditionText: '', conditionText: '',
conditionCode: 1000, conditionCode: 1000,
id: 0, id: -1,
createdAt: new Date(), createdAt: new Date(),
updatedAt: new Date() updatedAt: new Date()
}); });
const [isLoading, setIsLoading] = useState(true); const [isLoading, setIsLoading] = useState(true);
// Initial request to get data
useEffect(() => { useEffect(() => {
axios.get<ApiResponse<Weather[]>>('/api/weather') axios.get<ApiResponse<Weather[]>>('/api/weather')
.then(data => { .then(data => {
setWeather(data.data.data[0]); const weatherData = data.data.data[0];
if (weatherData) {
setWeather(weatherData);
}
setIsLoading(false); setIsLoading(false);
}) })
.catch(err => console.log(err)); .catch(err => console.log(err));
}, []); }, []);
// Open socket for data updates
useEffect(() => {
const webSocketClient = new WebSocket('ws://localhost:5005');
webSocketClient.onopen = () => {
console.log('WebSocket opened');
}
webSocketClient.onclose = () => {
console.log('WebSocket closed')
}
webSocketClient.onmessage = (e) => {
const data = JSON.parse(e.data);
setWeather({
...weather,
...data
})
}
return () => webSocketClient.close();
}, []);
return ( return (
<div className={classes.WeatherWidget}> <div className={classes.WeatherWidget}>
{isLoading {isLoading
? 'loading' ? 'loading'
: ( : (weather.id > 0 &&
<Fragment> (<Fragment>
<div className={classes.WeatherIcon}> <div className={classes.WeatherIcon}>
<WeatherIcon <WeatherIcon
weatherStatusCode={weather.conditionCode} weatherStatusCode={weather.conditionCode}
@ -45,7 +72,7 @@ const WeatherWidget = (): JSX.Element => {
<span>{weather.tempC}°C</span> <span>{weather.tempC}°C</span>
<span>{weather.conditionCode}</span> <span>{weather.conditionCode}</span>
</div> </div>
</Fragment> </Fragment>)
) )
} }
</div> </div>

View File

@ -2,7 +2,7 @@
margin: 0; margin: 0;
padding: 0; padding: 0;
box-sizing: border-box; box-sizing: border-box;
user-select: none; /* user-select: none; */
} }
body { body {

View File

@ -218,10 +218,13 @@ export const deleteBookmark = (bookmarkId: number, categoryId: number) => async
*/ */
export interface UpdateBookmarkAction { export interface UpdateBookmarkAction {
type: ActionTypes.updateBookmark, type: ActionTypes.updateBookmark,
payload: Bookmark payload: {
bookmark: Bookmark,
categoryWasChanged: boolean
}
} }
export const updateBookmark = (bookmarkId: number, formData: NewBookmark) => async (dispatch: Dispatch) => { export const updateBookmark = (bookmarkId: number, formData: NewBookmark, categoryWasChanged: boolean) => async (dispatch: Dispatch) => {
try { try {
const res = await axios.put<ApiResponse<Bookmark>>(`/api/bookmarks/${bookmarkId}`, formData); const res = await axios.put<ApiResponse<Bookmark>>(`/api/bookmarks/${bookmarkId}`, formData);
@ -235,7 +238,10 @@ export const updateBookmark = (bookmarkId: number, formData: NewBookmark) => asy
dispatch<UpdateBookmarkAction>({ dispatch<UpdateBookmarkAction>({
type: ActionTypes.updateBookmark, type: ActionTypes.updateBookmark,
payload: res.data.data payload: {
bookmark: res.data.data,
categoryWasChanged
}
}) })
} catch (err) { } catch (err) {
console.log(err); console.log(err);

View File

@ -107,8 +107,38 @@ const deleteBookmark = (state: State, action: Action): State => {
} }
const updateBookmark = (state: State, action: Action): State => { const updateBookmark = (state: State, action: Action): State => {
const { bookmark, categoryWasChanged } = action.payload;
const tmpCategories = [...state.categories];
let categoryIndex = state.categories.findIndex((category: Category) => category.id === bookmark.categoryId);
let bookmarkIndex = state.categories[categoryIndex].bookmarks.findIndex((bookmark: Bookmark) => bookmark.id === bookmark.id);
// if (categoryWasChanged) {
// const categoryInUpdate = tmpCategories.find((category: Category) => category.id === bookmark.categoryId);
// if (categoryInUpdate) {
// categoryInUpdate.bookmarks = categoryInUpdate.bookmarks.filter((_bookmark: Bookmark) => _bookmark.id === bookmark.id);
// }
// console.log(categoryInUpdate);
// }
return { return {
...state ...state,
categories: [
...state.categories.slice(0, categoryIndex),
{
...state.categories[categoryIndex],
bookmarks: [
...state.categories[categoryIndex].bookmarks.slice(0, bookmarkIndex),
{
...bookmark
},
...state.categories[categoryIndex].bookmarks.slice(bookmarkIndex + 1)
]
},
...state.categories.slice(categoryIndex + 1)
]
} }
} }

40
utils/Logger.js Normal file
View File

@ -0,0 +1,40 @@
const fs = require('fs');
class Logger {
constructor() {
this.logFileHandler();
}
logFileHandler() {
if (!fs.existsSync('./flame.log')) {
fs.writeFileSync('./flame.log', '');
} else {
console.log('file exists');
}
}
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}`;
}
}
}
// console.log(logger.generateLog('testMsg', 'INFO'));
module.exports = new Logger();

View File

@ -30,7 +30,7 @@ const getExternalWeather = async () => {
// Save weather data // Save weather data
const cursor = res.data.current; const cursor = res.data.current;
await Weather.create({ const weatherData = await Weather.create({
externalLastUpdate: cursor.last_updated, externalLastUpdate: cursor.last_updated,
tempC: cursor.temp_c, tempC: cursor.temp_c,
tempF: cursor.temp_f, tempF: cursor.temp_f,
@ -38,10 +38,9 @@ const getExternalWeather = async () => {
conditionText: cursor.condition.text, conditionText: cursor.condition.text,
conditionCode: cursor.condition.code conditionCode: cursor.condition.code
}); });
return weatherData;
} catch (err) { } catch (err) {
console.log(err); throw new Error('External API request failed');
console.log('External API request failed');
return;
} }
} }

View File

@ -4,10 +4,10 @@ const Sockets = require('../Sockets');
const weatherJob = schedule.scheduleJob('updateWeather', '0 */15 * * * *', async () => { const weatherJob = schedule.scheduleJob('updateWeather', '0 */15 * * * *', async () => {
try { try {
await getExternalWeather(); const weatherData = await getExternalWeather();
console.log('weather updated'); console.log('weather updated');
Sockets.getSocket('weather').socket.send('weather updated'); Sockets.getSocket('weather').socket.send(JSON.stringify(weatherData));
} catch (err) { } catch (err) {
console.log(err); console.log(err.message);
} }
}) })