diff --git a/apps/weather_status/appinfo/routes.php b/apps/weather_status/appinfo/routes.php index 6218595a3813c7f1c2f471a8f8d8ee98f0cede8f..8737bfd2dc6c05a1d4079a9fff1e442230460883 100644 --- a/apps/weather_status/appinfo/routes.php +++ b/apps/weather_status/appinfo/routes.php @@ -30,5 +30,7 @@ return [ ['name' => 'WeatherStatus#getLocation', 'url' => '/api/v1/location', 'verb' => 'GET'], ['name' => 'WeatherStatus#setLocation', 'url' => '/api/v1/location', 'verb' => 'PUT'], ['name' => 'WeatherStatus#getForecast', 'url' => '/api/v1/forecast', 'verb' => 'GET'], + ['name' => 'WeatherStatus#getFavorites', 'url' => '/api/v1/favorites', 'verb' => 'GET'], + ['name' => 'WeatherStatus#setFavorites', 'url' => '/api/v1/favorites', 'verb' => 'PUT'], ], ]; diff --git a/apps/weather_status/js/weather-status.js b/apps/weather_status/js/weather-status.js index 79699909614a3207e0f5bd062d9e0e927fe5db60..228fd92262f2b310bd0143f370b19bbac211ed75 100644 Binary files a/apps/weather_status/js/weather-status.js and b/apps/weather_status/js/weather-status.js differ diff --git a/apps/weather_status/js/weather-status.js.map b/apps/weather_status/js/weather-status.js.map index 104bb806b6d5020a24fe512e3cf217808bcded06..e8fd067b525d3cd07ca5a746dd1c23914f63ceec 100644 Binary files a/apps/weather_status/js/weather-status.js.map and b/apps/weather_status/js/weather-status.js.map differ diff --git a/apps/weather_status/lib/Controller/WeatherStatusController.php b/apps/weather_status/lib/Controller/WeatherStatusController.php index 3813bbf9b41f1fe0f8af29613bb592b77229e0a7..7ec6c71493e6e088592175ef1c06b718e0278a41 100644 --- a/apps/weather_status/lib/Controller/WeatherStatusController.php +++ b/apps/weather_status/lib/Controller/WeatherStatusController.php @@ -121,4 +121,27 @@ class WeatherStatusController extends OCSController { return new DataResponse($forecast); } } + + /** + * @NoAdminRequired + * + * Get favorites list + * + * @return DataResponse which contains the favorite list + */ + public function getFavorites(): DataResponse { + return new DataResponse($this->service->getFavorites()); + } + + /** + * @NoAdminRequired + * + * Set favorites list + * + * @param array $favorites + * @return DataResponse success state + */ + public function setFavorites(array $favorites): DataResponse { + return new DataResponse($this->service->setFavorites($favorites)); + } } diff --git a/apps/weather_status/lib/Service/WeatherStatusService.php b/apps/weather_status/lib/Service/WeatherStatusService.php index 2d9140c321826bab7e1e3228c64d3d1578856da5..0d7b31f90429df0b8a98df1a2cc9beae9dcb283d 100644 --- a/apps/weather_status/lib/Service/WeatherStatusService.php +++ b/apps/weather_status/lib/Service/WeatherStatusService.php @@ -133,6 +133,26 @@ class WeatherStatusService { return ['success' => true]; } + /** + * Get favorites list + * @param array $favorites + * @return array success state + */ + public function getFavorites(): array { + $favoritesJson = $this->config->getUserValue($this->userId, Application::APP_ID, 'favorites', ''); + return json_decode($favoritesJson, true) ?: []; + } + + /** + * Set favorites list + * @param array $favorites + * @return array success state + */ + public function setFavorites(array $favorites): array { + $this->config->setUserValue($this->userId, Application::APP_ID, 'favorites', json_encode($favorites)); + return ['success' => true]; + } + /** * Try to use the address set in user personal settings as weather location * diff --git a/apps/weather_status/src/App.vue b/apps/weather_status/src/App.vue index e574bed1fb7a368dd5ba908b76c4bcd367129992..81edc28eaf458dc1bfd3ad9cf43ebf7ffc8812e9 100644 --- a/apps/weather_status/src/App.vue +++ b/apps/weather_status/src/App.vue @@ -26,13 +26,18 @@ class="weather-status-menu-item__subheader" :default-icon="weatherIcon" :menu-title="visibleMessage"> - <ActionLink v-if="address && !errorMessage" + <ActionLink v-if="gotWeather" icon="icon-address" target="_blank" :href="weatherLinkTarget" :close-after-click="true"> {{ locationText }} </ActionLink> + <ActionButton v-if="gotWeather" + :icon="addRemoveFavoriteIcon" + @click="onAddRemoveFavoriteClick"> + {{ addRemoveFavoriteText }} + </ActionButton> <ActionSeparator v-if="address && !errorMessage" /> <ActionButton icon="icon-crosshair" @@ -49,6 +54,18 @@ @submit="onAddressSubmit"> {{ t('weather_status', 'Set custom address') }} </ActionInput> + <ActionButton + v-show="favorites.length > 0" + :icon="toggleFavoritesIcon" + @click="showFavorites = !showFavorites"> + {{ t('weather_status', 'Favorites') }} + </ActionButton> + <ActionButton v-for="f in displayedFavorites" + :key="f" + icon="icon-starred" + @click="onFavoriteClick(f)"> + {{ f }} + </ActionButton> </Actions> </div> </li> @@ -160,6 +177,8 @@ export default { lon: null, forecasts: [], loop: null, + favorites: [], + showFavorites: false, } }, computed: { @@ -217,6 +236,34 @@ export default { weatherLinkTarget() { return 'https://www.windy.com/-Rain-thunder-rain?rain,' + this.lat + ',' + this.lon + ',11' }, + gotWeather() { + return this.address && !this.errorMessage + }, + addRemoveFavoriteIcon() { + return this.currentAddressIsFavorite + ? 'icon-starred' + : 'icon-star' + }, + addRemoveFavoriteText() { + return this.currentAddressIsFavorite + ? t('weather_status', 'Remove from favorites') + : t('weather_status', 'Add as favorite') + }, + currentAddressIsFavorite() { + return this.favorites.find((f) => { + return f === this.address + }) + }, + toggleFavoritesIcon() { + return this.showFavorites + ? 'icon-triangle-s' + : 'icon-triangle-e' + }, + displayedFavorites() { + return this.showFavorites + ? this.favorites + : [] + }, }, mounted() { this.initWeatherStatus() @@ -235,6 +282,8 @@ export default { } else if (this.mode === MODE_MANUAL_LOCATION) { this.startLoop() } + const favs = await network.getFavorites() + this.favorites = favs } catch (err) { if (err?.code === 'ECONNABORTED') { console.info('The weather status request was cancelled because the user navigates.') @@ -378,6 +427,23 @@ export default { ? ((celcius * (9 / 5)) + 32).toFixed(1) : celcius }, + onAddRemoveFavoriteClick() { + const currentIsFavorite = this.currentAddressIsFavorite + if (currentIsFavorite) { + const i = this.favorites.indexOf(currentIsFavorite) + if (i !== -1) { + this.favorites.splice(i, 1) + } + } else { + this.favorites.push(this.address) + } + network.saveFavorites(this.favorites) + }, + onFavoriteClick(favAddress) { + if (favAddress !== this.address) { + this.setAddress(favAddress) + } + }, }, } </script> diff --git a/apps/weather_status/src/services/weatherStatusService.js b/apps/weather_status/src/services/weatherStatusService.js index 54ea13259ae0c616c5695ea4c3a77d9d6540bbd7..32a81bd61087d0ca452141ab7c6bb6f2e85bd455 100644 --- a/apps/weather_status/src/services/weatherStatusService.js +++ b/apps/weather_status/src/services/weatherStatusService.js @@ -106,6 +106,33 @@ const fetchForecast = async() => { return response.data.ocs.data } +/** + * Fetches the location favorites + * + * @param {String} address The location + * @returns {Promise<Object>} + */ +const getFavorites = async() => { + const url = generateOcsUrl('apps/weather_status/api/v1', 2) + 'favorites' + const response = await HttpClient.get(url) + + return response.data.ocs.data +} + +/** + * + * @param {Array} favorites List of favorite addresses + * @returns {Promise<Object>} + */ +const saveFavorites = async(favorites) => { + const url = generateOcsUrl('apps/weather_status/api/v1', 2) + 'favorites' + const response = await HttpClient.put(url, { + favorites, + }) + + return response.data.ocs.data +} + export { usePersonalAddress, setMode, @@ -113,4 +140,6 @@ export { setLocation, setAddress, fetchForecast, + getFavorites, + saveFavorites, }