From fad1e5ff50eb27b3ba68254dea594a4139932d42 Mon Sep 17 00:00:00 2001 From: Alicia Sykes <sykes.alicia@gmail.com> Date: Sat, 18 Dec 2021 14:57:24 +0000 Subject: [PATCH] :sparkles: Adds NASA APOD widget --- docs/widgets.md | 42 +++++++++- src/components/Widgets/Apod.vue | 112 ++++++++++++++++++++++++++ src/components/Widgets/WidgetBase.vue | 11 ++- src/utils/defaults.js | 1 + 4 files changed, 163 insertions(+), 3 deletions(-) create mode 100644 src/components/Widgets/Apod.vue diff --git a/docs/widgets.md b/docs/widgets.md index c6eef10b..4b6e3e24 100644 --- a/docs/widgets.md +++ b/docs/widgets.md @@ -18,6 +18,7 @@ Dashy has support for displaying dynamic content in the form of widgets. There a - [Stock Price History](#stock-price-history) - [Joke of the Day](#joke) - [Flight Data](#flight-data) + - [NASA APOD](#astronomy-picture-of-the-day) - [GitHub Trending](#github-trending) - [GitHub Profile Stats](#github-profile-stats) - [Public IP Address](#public-ip) @@ -29,7 +30,11 @@ Dashy has support for displaying dynamic content in the form of widgets. There a - [Dynamic Widgets](#dynamic-widgets) - [Iframe Widget](#iframe-widget) - [HTML Embed Widget](#html-embedded-widget) -- [Build your own Widget](#build-your-own-widget) + - [API Response](#api-response) + - [Data Feed](#data-feed) +- [Custom Widgets](#custom-widgets) + - [Build your own Widget](#build-your-own-widget) + - [Widget Styling](#widget-styling) ## General Widgets @@ -433,6 +438,24 @@ Displays airport departure and arrival flights, using data from [AeroDataBox](ht --- +### Astronomy Picture of the Day + +Show the NASA Astronomy Pictore of the Day. Data is fetched from [APOD](https://apod.nasa.gov/apod/) using [PawelPleskaczynski/apod_api](https://github.com/PawelPleskaczynski/apod_api). + +<p align="center"><img width="400" src="https://i.ibb.co/ZMkgLFK/apod.png" /></p> + +##### Options + +_No config options._ + +##### Example + +```yaml +- type: apod +``` + +--- + ### GitHub Trending Displays currently trending projects on GitHub. Optionally specify a language and time-frame. Data is fetched from [Lissy93/gh-trending-no-cors](https://github.com/Lissy93/gh-trending-no-cors) using the GitHub API. @@ -668,6 +691,21 @@ Or --- -## Build your own Widget +### API Response + +--- + +### Data Feed + +--- + +## Custom Widgets + +### Build your own Widget For a full tutorial on creating your own widget, you can follow [this guide](https://github.com/Lissy93/dashy/blob/master/docs/development-guides.md#building-a-widget), or take a look at [here](https://github.com/Lissy93/dashy/commit/3da76ce2999f57f76a97454c0276301e39957b8e) for a code example. + +--- + +### Widget Styling + diff --git a/src/components/Widgets/Apod.vue b/src/components/Widgets/Apod.vue new file mode 100644 index 00000000..6bd9e0c6 --- /dev/null +++ b/src/components/Widgets/Apod.vue @@ -0,0 +1,112 @@ +<template> +<div class="apod-wrapper" v-if="image"> + <a :href="link" class="title" target="__blank" title="View Article"> + {{ title }} + </a> + <a :href="hdImage" title="View HD Image" class="picture" target="__blank"> + <img :src="image" /> + </a> + <p class="copyright">{{ copyright }}</p> + <p class="description">{{ truncatedDescription }}</p> + <p @click="toggleShowFull" class="expend-details-btn"> + {{ showFullDesc ? 'Show Less' : ' Expand Details' }} + </p> +</div> +</template> + +<script> +import axios from 'axios'; +import WidgetMixin from '@/mixins/WidgetMixin'; +import { widgetApiEndpoints } from '@/utils/defaults'; + +export default { + mixins: [WidgetMixin], + data() { + return { + title: null, + image: null, + hdImage: null, + link: null, + description: null, + copyright: null, + showFullDesc: false, + }; + }, + computed: { + truncatedDescription() { + return this.showFullDesc ? this.description : `${this.description.substring(0, 100)}...`; + }, + }, + methods: { + fetchData() { + axios.get(widgetApiEndpoints.astronomyPictureOfTheDay) + .then((response) => { + this.processData(response.data); + }) + .catch((dataFetchError) => { + this.error('Unable to fetch data', dataFetchError); + }) + .finally(() => { + this.finishLoading(); + }); + }, + processData(data) { + this.title = data.title; + this.image = data.url; + this.hdImage = data.hdurl; + this.link = data.apod_site; + this.description = data.description; + this.copyright = data.copyright; + }, + toggleShowFull() { + this.showFullDesc = !this.showFullDesc; + }, + }, +}; +</script> + +<style scoped lang="scss"> +.apod-wrapper { + a.title { + font-size: 1.5rem; + margin: 0.5rem 0; + color: var(--widget-text-color); + text-decoration: none; + &:hover { text-decoration: underline; } + } + a.picture img { + width: 100%; + margin: 0.5rem auto; + border-radius: var(--curve-factor); + } + p.copyright { + font-size: 0.8rem; + margin: 0.2rem 0; + opacity: var(--dimming-factor); + color: var(--widget-text-color); + } + p.description { + color: var(--widget-text-color); + font-size: 1rem; + margin: 0.5rem 0; + } + p.expend-details-btn { + cursor: pointer; + float: right; + margin: 0; + padding: 0.1rem 0.25rem; + border: 1px solid transparent; + color: var(--widget-text-color); + opacity: var(--dimming-factor); + border-radius: var(--curve-factor); + &:hover { + border: 1px solid var(--widget-text-color); + } + &:focus, &:active { + background: var(--widget-text-color); + color: var(--widget-background-color); + } + } +} + +</style> diff --git a/src/components/Widgets/WidgetBase.vue b/src/components/Widgets/WidgetBase.vue index e1fbb019..07e5f2a7 100644 --- a/src/components/Widgets/WidgetBase.vue +++ b/src/components/Widgets/WidgetBase.vue @@ -18,8 +18,15 @@ </div> <!-- Widget --> <div v-else class="widget-wrap"> + <Apod + v-if="widgetType === 'apod'" + :options="widgetOptions" + @loading="setLoaderState" + @error="handleError" + :ref="widgetRef" + /> <Clock - v-if="widgetType === 'clock'" + v-else-if="widgetType === 'clock'" :options="widgetOptions" @loading="setLoaderState" @error="handleError" @@ -194,6 +201,7 @@ import OpenIcon from '@/assets/interface-icons/open-new-tab.svg'; import LoadingAnimation from '@/assets/interface-icons/loader.svg'; // Import available widgets (add new widgets alphabetically) +import Apod from '@/components/Widgets/Apod.vue'; import Clock from '@/components/Widgets/Clock.vue'; import CryptoPriceChart from '@/components/Widgets/CryptoPriceChart.vue'; import CryptoWatchList from '@/components/Widgets/CryptoWatchList.vue'; @@ -227,6 +235,7 @@ export default { OpenIcon, LoadingAnimation, // Register widget components + Apod, Clock, CodeStats, CryptoPriceChart, diff --git a/src/utils/defaults.js b/src/utils/defaults.js index 933ae217..9302887f 100644 --- a/src/utils/defaults.js +++ b/src/utils/defaults.js @@ -222,6 +222,7 @@ module.exports = { publicIp: 'http://ip-api.com/json', readMeStats: 'https://github-readme-stats.vercel.app/api', githubTrending: 'https://gh-trending-repos.herokuapp.com/', + astronomyPictureOfTheDay: 'https://apodapi.herokuapp.com/api', }, /* URLs for web search engines */ searchEngineUrls: {