feat(weather): improve weather locations list
This commit is contained in:
@@ -50,13 +50,7 @@ def build_weather_response(request: AppRequest, response: WeatherResponse):
|
||||
router = APIRouter(prefix="/weather")
|
||||
|
||||
|
||||
@router.get("/", response_class=RedirectResponse)
|
||||
async def get_weather(request: AppRequest):
|
||||
default_provider = request.app.state.api.get_api_providers(WeatherApi.TYPE)[0]
|
||||
return RedirectResponse(default_provider)
|
||||
|
||||
|
||||
@router.get("/{provider}", response_class=HTMLResponse)
|
||||
@router.get("/", response_class=HTMLResponse)
|
||||
async def get_weather_index(request: AppRequest, weather_api: WeatherApiDepends, query: str | None = None):
|
||||
locations = (await weather_api.find_locations(query)) if query else []
|
||||
return templates.TemplateResponse(
|
||||
@@ -69,7 +63,7 @@ async def get_weather_index(request: AppRequest, weather_api: WeatherApiDepends,
|
||||
|
||||
|
||||
@router.get("/{provider}/{location}", response_class=RedirectResponse)
|
||||
async def get_weather_default(location: str):
|
||||
async def get_weather(location: str):
|
||||
return RedirectResponse(f"{location}/tag/today")
|
||||
|
||||
|
||||
|
||||
@@ -1,23 +1,6 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}{{_("Weather")}}{% endblock %}
|
||||
|
||||
{# {% block header %}
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-secondary dropdown-toggle"
|
||||
type="button"
|
||||
data-bs-toggle="dropdown"
|
||||
aria-expanded="false">
|
||||
{{provider or providers[0]}}
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
{% for provider in providers %}
|
||||
<li><a class="dropdown-item"
|
||||
href="{{ url_for('get_weather_index').include_query_params(provider=provider) }}">{{provider}}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endblock %} #}
|
||||
|
||||
{% block content %}
|
||||
<h1>{{_("Weather")}}</h1>
|
||||
<form action=""
|
||||
@@ -29,70 +12,51 @@
|
||||
id="query"
|
||||
name="query"
|
||||
placeholder="{{_('Enter the city name')}}">
|
||||
<input type="hidden"
|
||||
class="form-control"
|
||||
id="provider"
|
||||
name="provider"
|
||||
value="{{provider or providers[0]}}">
|
||||
<button id="providerBtn"
|
||||
class="btn btn-secondary dropdown-toggle"
|
||||
type="text"
|
||||
data-bs-toggle="dropdown"
|
||||
aria-expanded="false">{{provider or providers[0]}}</button>
|
||||
<ul class="dropdown-menu dropdown-menu-end">
|
||||
{% for provider in providers %}
|
||||
<li>
|
||||
<a class="dropdown-item"
|
||||
onclick="provider.value='{{provider}}'; providerBtn.innerText='{{provider}}'">{{provider}}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<button class="btn btn-primary"
|
||||
type="submit">{{_("Search")}}</button>
|
||||
</div>
|
||||
</form>
|
||||
{% if locations %}
|
||||
<ul id="locations"
|
||||
class="list-group mb-5">
|
||||
{% for location in locations %}
|
||||
<a href="{{ url_for('get_weather_default', provider=request.path_params.provider, location=location.id) }}"
|
||||
class="list-group-item list-group-item-action px-4"
|
||||
onclick="saveLocation({id:'{{location.id}}', name:'{{location.name}}'});">
|
||||
<span class="fi fi-{{location.country_code}} me-1"></span>
|
||||
<span class="text-primary">{{location.name}}</span>
|
||||
<span class="small ms-1 text-secondary">
|
||||
{{location.country}}, {{location.district}}, {{location.subdistrict}}
|
||||
</span>
|
||||
<span></span>
|
||||
</a>
|
||||
<weather-location location="{{location.model_dump() | tojson | forceescape}}"></weather-location>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<hr>
|
||||
{% endif %}
|
||||
<ul id="storedLocations"
|
||||
class="list-group mb-5">
|
||||
</ul>
|
||||
<script>
|
||||
(function () {
|
||||
const getStorageKey = () => {
|
||||
const provider = window.location.pathname.split('/').pop();
|
||||
return `locations:${provider}`;
|
||||
}
|
||||
|
||||
document.loadLocations = () => {
|
||||
const provider = window.location.pathname.split('/').pop();
|
||||
console.log('!', provider);
|
||||
const locations = JSON.parse(window.localStorage.getItem(getStorageKey()) || '{}');
|
||||
const container = document.querySelector('#locations');
|
||||
container.innerHTML = '';
|
||||
for (const [id, name] of Object.entries(locations)) {
|
||||
const element = document.createElement('a');
|
||||
element.href = `${window.location.pathname}/${id}`;
|
||||
element.className = 'list-group-item list-group-item-action px-4 d-flex justify-content-between align-items-start';
|
||||
element.innerHTML = `
|
||||
<span class="text-primary me-auto">${name}</span>
|
||||
<span class="text-danger" onclick="removeLocation('${id}'); event.preventDefault();">✕</span>
|
||||
`;
|
||||
container.appendChild(element);
|
||||
}
|
||||
}
|
||||
|
||||
document.saveLocation = (location) => {
|
||||
const locations = JSON.parse(window.localStorage.getItem(getStorageKey()) || '{}');
|
||||
locations[location.id] = location.name;
|
||||
window.localStorage.setItem(getStorageKey(), JSON.stringify(locations));
|
||||
}
|
||||
|
||||
document.removeLocation = (id) => {
|
||||
const locations = JSON.parse(window.localStorage.getItem(getStorageKey()) || '{}');
|
||||
delete locations[id];
|
||||
window.localStorage.setItem(getStorageKey(), JSON.stringify(locations));
|
||||
document.loadLocations();
|
||||
}
|
||||
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const searchQuery = params.get('query');
|
||||
if (searchQuery) {
|
||||
document.querySelector('#query').value = searchQuery;
|
||||
} else {
|
||||
document.loadLocations();
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", (event) => {
|
||||
weatherLocationManager.loadLocations('#storedLocations');
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
{% endblock %}
|
||||
@@ -137,7 +137,7 @@
|
||||
{% for value in response.values %}
|
||||
<td class="precipitation"
|
||||
style="background-color: rgba(0, 128, 255, {{value.precipitation * 0.1}});">
|
||||
<span class="value">{{value.precipitation or ' '}}</span>
|
||||
<span class="value">{{(value.precipitation | round(2)) if value.precipitation else ' '}}</span>
|
||||
</td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
|
||||
Reference in New Issue
Block a user