Add Ground View screen for server edition, powered by the Windy API https://api.windy.com/
This commit is contained in:
parent
8958ef4d38
commit
598a60c7f5
11 changed files with 349 additions and 1 deletions
|
|
@ -8,6 +8,7 @@ import { registerHiddenSetting } from './modules/share.mjs';
|
|||
import settings from './modules/settings.mjs';
|
||||
import './modules/utils/theme.mjs';
|
||||
import './modules/latestobservations.mjs';
|
||||
import './modules/groundview.mjs';
|
||||
import AutoComplete from './modules/autocomplete.mjs';
|
||||
import { loadAllData } from './modules/utils/data-loader.mjs';
|
||||
import { debugFlag } from './modules/utils/debug.mjs';
|
||||
|
|
|
|||
94
server/scripts/modules/groundview.mjs
Normal file
94
server/scripts/modules/groundview.mjs
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
import STATUS from './status.mjs';
|
||||
import WeatherDisplay from './weatherdisplay.mjs';
|
||||
import { registerDisplay } from './navigation.mjs';
|
||||
import { safeJson } from './utils/fetch.mjs';
|
||||
import { withBasePath } from './utils/base-path.mjs';
|
||||
|
||||
class GroundView extends WeatherDisplay {
|
||||
constructor(navId, elemId) {
|
||||
super(navId, elemId, 'Ground View', true);
|
||||
this.refreshTime = 5 * 60 * 1000;
|
||||
this.requestToken = 0;
|
||||
}
|
||||
|
||||
async getData(weatherParameters, refresh) {
|
||||
const superResult = super.getData(weatherParameters, refresh);
|
||||
this.setAutoReload();
|
||||
const requestToken = ++this.requestToken;
|
||||
if (!this.weatherParameters?.latitude || !this.weatherParameters?.longitude || !this.weatherParameters?.city) {
|
||||
this.setStatus(STATUS.noData);
|
||||
return superResult;
|
||||
}
|
||||
|
||||
const url = new URL(withBasePath('api/ground-view'), window.location.origin);
|
||||
url.searchParams.set('lat', this.weatherParameters.latitude);
|
||||
url.searchParams.set('lon', this.weatherParameters.longitude);
|
||||
url.searchParams.set('city', this.weatherParameters.city);
|
||||
|
||||
const response = await safeJson(url.toString(), {
|
||||
retryCount: 1,
|
||||
});
|
||||
|
||||
if (requestToken !== this.requestToken) {
|
||||
return superResult;
|
||||
}
|
||||
|
||||
if (!response?.success) {
|
||||
this.data = null;
|
||||
this.setStatus(STATUS.failed);
|
||||
return superResult;
|
||||
}
|
||||
|
||||
this.data = {
|
||||
webcam: response.webcam,
|
||||
hasWebcam: Boolean(response.webcam?.imageUrl),
|
||||
};
|
||||
this.setStatus(STATUS.loaded);
|
||||
return superResult;
|
||||
}
|
||||
|
||||
resetViewState() {
|
||||
const image = this.elem.querySelector('.ground-view-image');
|
||||
const label = this.elem.querySelector('.ground-view-label');
|
||||
const empty = this.elem.querySelector('.ground-view-empty');
|
||||
const media = this.elem.querySelector('.ground-view-media');
|
||||
|
||||
image.removeAttribute('src');
|
||||
image.alt = '';
|
||||
label.textContent = '';
|
||||
empty.textContent = '';
|
||||
media.classList.add('hidden');
|
||||
label.classList.add('hidden');
|
||||
empty.classList.add('hidden');
|
||||
}
|
||||
|
||||
drawCanvas() {
|
||||
super.drawCanvas();
|
||||
const image = this.elem.querySelector('.ground-view-image');
|
||||
const label = this.elem.querySelector('.ground-view-label');
|
||||
const empty = this.elem.querySelector('.ground-view-empty');
|
||||
const media = this.elem.querySelector('.ground-view-media');
|
||||
|
||||
this.resetViewState();
|
||||
|
||||
if (this.data?.hasWebcam) {
|
||||
image.src = this.data.webcam.imageUrl;
|
||||
image.alt = this.data.webcam.label;
|
||||
label.textContent = this.data.webcam.label;
|
||||
media.classList.remove('hidden');
|
||||
label.classList.remove('hidden');
|
||||
empty.classList.add('hidden');
|
||||
} else {
|
||||
image.removeAttribute('src');
|
||||
label.textContent = '';
|
||||
media.classList.add('hidden');
|
||||
label.classList.add('hidden');
|
||||
empty.classList.remove('hidden');
|
||||
empty.textContent = 'No Ground View Available';
|
||||
}
|
||||
|
||||
this.finishDraw();
|
||||
}
|
||||
}
|
||||
|
||||
registerDisplay(new GroundView(12, 'ground-view'));
|
||||
57
server/styles/scss/_ground-view.scss
Normal file
57
server/styles/scss/_ground-view.scss
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
@use 'shared/_colors' as c;
|
||||
@use 'shared/_utils' as u;
|
||||
|
||||
.weather-display .main.ground-view {
|
||||
&.main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 12px;
|
||||
padding: 20px 24px 18px;
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ground-view-media {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex: 1 1 auto;
|
||||
min-height: 0;
|
||||
margin-right: 60px;
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.ground-view-image {
|
||||
display: block;
|
||||
max-width: 300px;
|
||||
max-height: 150px;
|
||||
object-fit: contain;
|
||||
border: 2px solid hsl(0deg 0% 100% / 35%);
|
||||
background: #000;
|
||||
}
|
||||
|
||||
.ground-view-label,
|
||||
.ground-view-empty {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
font-family: 'Star4000';
|
||||
font-size: 15pt;
|
||||
color: #ff0;
|
||||
padding: 10px;
|
||||
margin-right: 80px;
|
||||
text-shadow: 3px 3px 0 #000,-1.5px -1.5px 0 #000,0 -1.5px 0 #000,1.5px -1.5px 0 #000,1.5px 0 0 #000,1.5px 1.5px 0 #000,0 1.5px 0 #000,-1.5px 1.5px 0 #000,-1.5px 0 0 #000;
|
||||
}
|
||||
|
||||
.ground-view-empty {
|
||||
flex: 1 1 auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@
|
|||
@use 'local-forecast';
|
||||
@use 'progress';
|
||||
@use 'radar';
|
||||
@use 'ground-view';
|
||||
@use 'regional-forecast';
|
||||
@use 'almanac';
|
||||
@use 'hazards';
|
||||
|
|
|
|||
2
server/styles/ws.min.css
vendored
2
server/styles/ws.min.css
vendored
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue