Skip to content

Commit

Permalink
Add forecast, humidity, wind-speed to weather dashboard box (#961)
Browse files Browse the repository at this point in the history
* Refactoring Weather module to display more informations and forecast

* Prettier front

* Front eslint

* Front pretty

* Fix icon weather and debug mode

* Fix after atrovato review

Co-authored-by: Pierre-Gilles Leymarie <pierregilles.leymarie@gmail.com>
  • Loading branch information
callemand and Pierre-Gilles authored Nov 27, 2020
1 parent abb17b3 commit c2103b7
Show file tree
Hide file tree
Showing 19 changed files with 13,047 additions and 446 deletions.
24 changes: 24 additions & 0 deletions front/src/actions/dashboard/boxes/weather.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,19 @@ import get from 'get-value';

const BOX_KEY = 'Weather';

const WEATHER_ICONS = {
snow: 'fe-cloud-snow',
rain: 'fe-cloud-rain',
clear: 'fe-sun',
cloud: 'fe-cloud',
fog: 'fe-cloud',
sleet: 'fe-cloud-drizzle',
wind: 'fe-wind',
night: 'fe-moon'
};

const translateWeatherToFeIcon = weather => get(WEATHER_ICONS, weather, { default: 'fe-question' });

function createActions(store) {
const boxActions = createBoxActions(store);

Expand All @@ -17,6 +30,17 @@ function createActions(store) {
weather.datetime_beautiful = dayjs(weather.datetime)
.locale(state.user.language)
.format('D MMM');
weather.weather_icon = translateWeatherToFeIcon(weather.weather);

weather.hours.map(hour => {
hour.weather_icon = translateWeatherToFeIcon(hour.weather);
hour.datetime_beautiful = dayjs(hour.datetime).format('HH');
});
weather.days.map(day => {
day.weather_icon = translateWeatherToFeIcon(day.weather);
day.datetime_beautiful = dayjs(day.datetime).format('D MMM');
});

boxActions.mergeBoxData(state, BOX_KEY, x, y, {
weather
});
Expand Down
39 changes: 38 additions & 1 deletion front/src/components/boxs/weather/EditWeatherBox.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { connect } from 'unistore/preact';
import { Text } from 'preact-i18n';
import actions from '../../../actions/dashboard/edit-boxes/editWeather';
import BaseEditBox from '../baseEditBox';
import { GetWeatherModes } from '../../../utils/consts';

const EditWeatherBox = ({ children, ...props }) => (
<BaseEditBox {...props} titleKey="dashboard.boxTitle.weather">
Expand All @@ -22,6 +23,33 @@ const EditWeatherBox = ({ children, ...props }) => (
))}
</select>
</div>
<div className="form-group">
<div>
<label>
<Text id="dashboard.boxes.weather.editModeLabel" />
</label>
</div>
<div>
{Object.keys(GetWeatherModes).map(key => {
const mode = GetWeatherModes[key];
const label = 'dashboard.boxes.weather.displayModes.' + mode;
return (
<div className="form-check">
<input
type="checkbox"
className="form-check-input"
name={mode}
checked={props.box.modes !== undefined && props.box.modes[mode]}
onChange={props.updateBoxModes}
/>
<label className="form-check-label">
<Text id={label} />
</label>
</div>
);
})}
</div>
</div>
</BaseEditBox>
);

Expand All @@ -32,12 +60,21 @@ class EditWeatherBoxComponent extends Component {
house: e.target.value
});
};

updateBoxModes = e => {
const modes = this.props.box.modes || {};
modes[e.target.name] = e.target.checked;
this.props.updateBoxConfig(this.props.x, this.props.y, {
modes
});
};

componentDidMount() {
this.props.getHouses();
}

render(props, {}) {
return <EditWeatherBox {...props} updateBoxHouse={this.updateBoxHouse} />;
return <EditWeatherBox {...props} updateBoxHouse={this.updateBoxHouse} updateBoxModes={this.updateBoxModes} />;
}
}

Expand Down
195 changes: 136 additions & 59 deletions front/src/components/boxs/weather/WeatherBox.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Link } from 'preact-router/match';
import actions from '../../../actions/dashboard/boxes/weather';
import {
RequestStatus,
GetWeatherModes,
GetWeatherStatus,
DASHBOARD_BOX_STATUS_KEY,
DASHBOARD_BOX_DATA_KEY
Expand Down Expand Up @@ -97,19 +98,20 @@ const WeatherBox = ({ children, ...props }) => (
)}
{props.weather && (
<div style={padding} class="card-block px-30 py-10">
<div
style={{
fontSize: '14px',
color: '#76838f'
}}
>
{props.datetimeBeautiful + ' - ' + props.houseName}
</div>
<div class="row">
<div class="col-6">
<div class="col-9">
<div
style={{
fontSize: '14px',
color: '#76838f'
}}
>
{props.datetimeBeautiful}
</div>
<div
style={{
fontSize: '40px'
fontSize: '40px',
lineHeight: '1.2'
}}
class="font-size-40 blue-grey-700"
>
Expand All @@ -124,69 +126,78 @@ const WeatherBox = ({ children, ...props }) => (
</div>
</div>
<div
class="col-6 text-right"
class="col-3 text-right"
style={{
padding: '10px'
paddingRight: '10px',
paddingLeft: '10px',
marginTop: '-0.75rem'
}}
>
{props.weather === 'rain' && (
<i
class="fe fe-cloud-rain"
style={{
fontSize: '60px'
}}
/>
)}
{props.weather === 'clear' && (
<i
class="fe fe-sun"
style={{
fontSize: '60px'
}}
/>
)}
{props.weather === 'cloud' && (
<i
class="fe fe-cloud"
style={{
fontSize: '60px'
}}
/>
)}
{props.weather === 'snow' && (
<i
className={'fe ' + props.weather_icon}
style={{
fontSize: '50px'
}}
/>
</div>
</div>
{props.display_mode[GetWeatherModes.AdvancedWeather] && (
<div className="col-9" style={{ padding: '0' }}>
<span>
<i
class="fe fe-cloud-snow"
class="fe fe-droplet"
style={{
fontSize: '60px'
fpaddingRight: '5px'
}}
/>
)}
{props.weather === 'fog' && (
<i
class="fe fe-cloud"
{props.humidity}
<span
style={{
fontSize: '60px'
fontSize: '12px',
color: 'grey'
}}
/>
)}
{props.weather === 'drizzle' && (
>
<Text id="global.percent" />
</span>
</span>
<span className="float-right">
<i
class="fe fe-cloud-drizzle"
class="fe fe-wind"
style={{
fontSize: '60px'
paddingRight: '5px'
}}
/>
)}
{props.weather === 'thunderstorm' && (
<i
class="fe fe-cloud-lightning"
{props.wind}
<span
style={{
fontSize: '60px'
fontSize: '12px',
color: 'grey'
}}
/>
)}
>
{props.units === 'si' ? 'km/h' : 'm/h'}
</span>
</span>
</div>
</div>
)}
{props.display_mode[GetWeatherModes.HourlyForecast] && (
<div>
<div
class="row"
style={{
marginTop: '0.5em'
}}
>
{props.hours_display}
</div>
</div>
)}
{props.display_mode[GetWeatherModes.DailyForecast] && (
<div>
<div class="row">
<div className="container">{props.days_display}</div>
</div>
</div>
)}
</div>
)}
</div>
Expand All @@ -205,20 +216,86 @@ class WeatherBoxComponent extends Component {
const boxData = get(props, `${DASHBOARD_BOX_DATA_KEY}Weather.${props.x}_${props.y}`);
const boxStatus = get(props, `${DASHBOARD_BOX_STATUS_KEY}Weather.${props.x}_${props.y}`);
const weatherObject = get(boxData, 'weather');
const weather = get(weatherObject, 'weather');
const displayMode = this.props.box.modes || {};
const datetimeBeautiful = get(weatherObject, 'datetime_beautiful');
const temperature = Math.round(get(weatherObject, 'temperature'));
const units = get(weatherObject, 'units');
const datetimeBeautiful = get(weatherObject, 'datetime_beautiful');

const houseName = get(weatherObject, 'house.name');

const weather = get(weatherObject, 'weather');
const weather_icon = get(weatherObject, 'weather_icon');

let humidity, wind, hoursDisplay, daysDisplay;
if (displayMode[GetWeatherModes.AdvancedWeather]) {
humidity = get(weatherObject, 'humidity');
wind = get(weatherObject, 'wind_speed');
if (units === 'si') {
wind = wind * 3.6;
wind = wind.toFixed(2);
}
}

if (displayMode[GetWeatherModes.HourlyForecast]) {
const hours = get(weatherObject, 'hours');
if (typeof hours !== 'undefined') {
let i = 0;
hoursDisplay = hours.map(hour => {
return (
<div style={Object.assign({ width: '10%', margin: '0.25em 1.25%' })}>
<p style={{ margin: 'auto', textAlign: 'center', fontSize: '10px', color: 'grey' }}>
{hour.datetime_beautiful + 'h'}
</p>
<p style={{ margin: 'auto', textAlign: 'center' }}>
<i className={'fe ' + hour.weather_icon} style={{ fontSize: '20px' }} />
</p>
<p style={{ margin: 'auto', textAlign: 'center', fontSize: '12px' }}>
<Text id="global.degreeValue" fields={{ value: hour.temperature }} />
</p>
</div>
);
});
}
}

if (displayMode[GetWeatherModes.DailyForecast]) {
const days = get(weatherObject, 'days');
if (typeof days !== 'undefined') {
let i = 0;
daysDisplay = days.map(day => {
return (
<div className="row" style={{ marginTop: '0.5em' }}>
<div className="col-5">{day.datetime_beautiful}</div>
<div className="col-3">
<i className={'fe ' + day.weather_icon} style={{ fontSize: '20px' }} />
</div>
<div className="col-4" style={{ textAlign: 'right' }}>
<Text
id="dashboard.boxes.weather.minMaxDegreeValue"
fields={{ min: day.temperature_min, max: day.temperature_max }}
/>
</div>
</div>
);
});
}
}

return (
<WeatherBox
{...props}
weather={weather}
weather_icon={weather_icon}
temperature={temperature}
units={units}
boxStatus={boxStatus}
datetimeBeautiful={datetimeBeautiful}
houseName={houseName}
hours_display={hoursDisplay}
days_display={daysDisplay}
humidity={humidity}
wind={wind}
display_mode={displayMode}
/>
);
}
Expand Down
27 changes: 26 additions & 1 deletion front/src/config/demo.json
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,32 @@
"latitude": 12,
"longitude": 12,
"language": "en"
}
},
"hours": [
{
"temperature": 27.9,
"humidity": 0.99,
"pressure": 1005.09,
"datetime": "2019-05-09T04:27:57.000Z",
"units": "metric",
"wind_speed": 1.96,
"wind_direction": 1.96,
"weather": "rain"
}
],
"days": [
{
"temperature_min": 20.9,
"temperature_max": 27.9,
"humidity": 0.99,
"pressure": 1005.09,
"datetime": "2019-05-09T04:27:57.000Z",
"units": "metric",
"wind_speed": 1.96,
"wind_direction": 1.96,
"weather": "rain"
}
]
},
"get /api/v1/room/living-room?expand=temperature": {
"id": "1c634ff4-0476-4733-a084-b4a43d649c84",
Expand Down
Loading

0 comments on commit c2103b7

Please sign in to comment.