Creates an embedable webpage widget

This commit is contained in:
Alicia Sykes 2021-12-13 14:03:39 +00:00
parent d9759c06b3
commit ae8179ecd7
3 changed files with 99 additions and 62 deletions

View File

@ -3,11 +3,24 @@
Dashy has support for displaying dynamic content in the form of widgets. There are several built-in widgets availible out-of-the-box (with more on the way!) as well as support for custom widgets to display stats from almost any service with an accessible API. Dashy has support for displaying dynamic content in the form of widgets. There are several built-in widgets availible out-of-the-box (with more on the way!) as well as support for custom widgets to display stats from almost any service with an accessible API.
##### Contents ##### Contents
- [Built-In Widgets](#built-in-widgets) - [General Widgets](#general-widgets)
- [Clock](#clock)
- [Weather](#weather)
- [Weather Forecast](#weather-forecast)
- [Crypto Watch List](#crypto-watch-list)
- [Crypto Price History](#crypto-token-price-history)
- [XKCD Comics](#xkcd-comics)
- [TFL Status](#tfl-status)
- [Exchange Rates](#exchange-rates)
- [Stock Price History](#stock-price-history)
- [Joke of the Day](#joke)
- [Self-Hosted Services Widgets](#dynamic-widgets)
- [Dynamic Widgets](#dynamic-widgets) - [Dynamic Widgets](#dynamic-widgets)
- [Iframe Widget](#iframe-widget)
- [HTML Widget](#html-widget)
- [Build your own Widget](#build-your-own-widget) - [Build your own Widget](#build-your-own-widget)
## Built-In Widgets ## General Widgets
### Clock ### Clock
@ -26,9 +39,7 @@ A simple, live-updating time and date widget with time-zone support. All options
##### Example ##### Example
```yaml ```yaml
- name: London Time - type: clock
icon: fas fa-clock
type: clock
options: options:
timeZone: Europe/London timeZone: Europe/London
format: en-GB format: en-GB
@ -53,9 +64,7 @@ A simple, live-updating local weather component, showing temperature, conditions
##### Example ##### Example
```yaml ```yaml
- name: Local Weather - type: weather
icon: fas fa-clouds
type: weather
options: options:
apiKey: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx apiKey: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
city: London city: London
@ -82,9 +91,7 @@ Displays the weather (temperature and conditions) for the next few days for a gi
##### Example ##### Example
```yaml ```yaml
- name: Weather Forecast - type: weather-forecast
icon: ':sunny:'
type: weather-forecast
options: options:
city: California city: California
numDays: 6 numDays: 6
@ -109,9 +116,7 @@ Keep track of price changes of your favorite crypto assets. Data is fetched from
##### Example ##### Example
```yaml ```yaml
- name: Crypto Prices - type: crypto-watch-list
icon: fas fa-rocket
type: crypto-watch-list
options: options:
currency: GBP currency: GBP
sortBy: marketCap sortBy: marketCap
@ -141,9 +146,7 @@ Shows recent price history for a given crypto asset, using price data fetched fr
##### Example ##### Example
```yaml ```yaml
- name: Bitcoin Price - type: crypto-price-chart
icon: fab fa-bitcoin
type: crypto-price-chart
options: options:
asset: bitcoin asset: bitcoin
currency: GBP currency: GBP
@ -165,9 +168,7 @@ Have a laugh with the daily comic from [XKCD](https://xkcd.com/). A classic webc
##### Example ##### Example
```yaml ```yaml
- name: XKCD of the Day - type: xkcd-comic
icon: fas fa-laugh
type: xkcd-comic
options: options:
comic: latest comic: latest
``` ```
@ -189,14 +190,11 @@ Shows real-time tube status of the London Underground. All options are optional.
##### Example ##### Example
```yaml ```yaml
- name: London Underground - type: tfl-status
type: tfl-status
``` ```
```yaml ```yaml
- name: Commute - type: tfl-status
icon: '🚋'
type: tfl-status
options: options:
showAll: true showAll: true
sortAlphabetically: true sortAlphabetically: true
@ -223,9 +221,7 @@ Display current FX rates in your native currency
##### Example ##### Example
```yaml ```yaml
- name: Exchange Rates - type: exchange-rates
icon: fas fa-money-bill-wave
type: exchange-rates
options: options:
apiKey: xxxxxxxxxxxxxxxxxxxxxxxx apiKey: xxxxxxxxxxxxxxxxxxxxxxxx
inputCurrency: GBP inputCurrency: GBP
@ -253,9 +249,7 @@ Shows recent price history for a given publicly-traded stock or share
##### Example ##### Example
```yaml ```yaml
- name: CloudFlare Stock Price - type: stock-price-chart
icon: fas fa-analytics
type: stock-price-chart
options: options:
stock: NET stock: NET
apiKey: PGUWSWD6CZTXMT8N apiKey: PGUWSWD6CZTXMT8N
@ -278,9 +272,7 @@ Renders a programming or generic joke. Data is fetched from the [JokesAPI](https
##### Example ##### Example
```yaml ```yaml
- name: Joke - type: joke
icon: fas fa-laugh
type: joke
options: options:
safeMode: true safeMode: true
language: en language: en
@ -291,6 +283,26 @@ Renders a programming or generic joke. Data is fetched from the [JokesAPI](https
## Dynamic Widgets ## Dynamic Widgets
### Iframe Widget
Embed any webpage into your dashboard as a widget.
<p align="center"><img width="400" src="https://i.ibb.co/t4VHnh3/iframe-widget.gif" /></p>
##### Options
**Field** | **Type** | **Required** | **Description**
--- | --- | --- | ---
**`url`** | `string` | Required | The URL to the webpage to embed
##### Example
```yaml
- type: iframe
options:
url: https://fiatleak.com/
```
--- ---
## Build your own Widget ## Build your own Widget

View File

@ -0,0 +1,35 @@
<template>
<div class="iframe-widget">
<iframe v-if="frameUrl" :src="frameUrl" />
</div>
</template>
<script>
import WidgetMixin from '@/mixins/WidgetMixin';
import ErrorHandler from '@/utils/ErrorHandler';
export default {
mixins: [WidgetMixin],
computed: {
frameUrl() {
const usersChoice = this.options.url;
if (!usersChoice || typeof usersChoice !== 'string') {
ErrorHandler('Iframe widget expects a URL');
return null;
}
return usersChoice;
},
},
};
</script>
<style scoped lang="scss">
.iframe-widget {
iframe {
width: 100%;
min-height: 240px;
border: 0;
}
}
</style>

View File

@ -1,30 +1,19 @@
<template> <template>
<div> <Clock v-if="widgetType === 'clock'" :options="widgetOptions" />
<Collapsable <Weather v-else-if="widgetType === 'weather'" :options="widgetOptions" />
:title="widget.name" <WeatherForecast v-else-if="widgetType === 'weather-forecast'" :options="widgetOptions" />
:icon="widget.icon" <TflStatus v-else-if="widgetType === 'tfl-status'" :options="widgetOptions" />
:uniqueKey="groupId" <CryptoPriceChart v-else-if="widgetType === 'crypto-price-chart'" :options="widgetOptions" />
:collapsed="displayData.collapsed" <CryptoWatchList v-else-if="widgetType === 'crypto-watch-list'" :options="widgetOptions" />
:cols="displayData.cols" <XkcdComic v-else-if="widgetType === 'xkcd-comic'" :options="widgetOptions" />
:rows="displayData.rows" <ExchangeRates v-else-if="widgetType === 'exchange-rates'" :options="widgetOptions" />
:color="displayData.color" <StockPriceChart v-else-if="widgetType === 'stock-price-chart'" :options="widgetOptions" />
:customStyles="displayData.customStyles" <Jokes v-else-if="widgetType === 'joke'" :options="widgetOptions" />
> <IframeWidget v-else-if="widgetType === 'iframe'" :options="widgetOptions" />
<Clock v-if="widgetType === 'clock'" :options="widgetOptions" />
<Weather v-else-if="widgetType === 'weather'" :options="widgetOptions" />
<WeatherForecast v-else-if="widgetType === 'weather-forecast'" :options="widgetOptions" />
<TflStatus v-else-if="widgetType === 'tfl-status'" :options="widgetOptions" />
<CryptoPriceChart v-else-if="widgetType === 'crypto-price-chart'" :options="widgetOptions" />
<CryptoWatchList v-else-if="widgetType === 'crypto-watch-list'" :options="widgetOptions" />
<XkcdComic v-else-if="widgetType === 'xkcd-comic'" :options="widgetOptions" />
<ExchangeRates v-else-if="widgetType === 'exchange-rates'" :options="widgetOptions" />
<StockPriceChart v-else-if="widgetType === 'stock-price-chart'" :options="widgetOptions" />
<Jokes v-else-if="widgetType === 'joke'" :options="widgetOptions" />
</Collapsable>
</div>
</template> </template>
<script> <script>
import ErrorHandler from '@/utils/ErrorHandler';
import Clock from '@/components/Widgets/Clock.vue'; import Clock from '@/components/Widgets/Clock.vue';
import Weather from '@/components/Widgets/Weather.vue'; import Weather from '@/components/Widgets/Weather.vue';
import WeatherForecast from '@/components/Widgets/WeatherForecast.vue'; import WeatherForecast from '@/components/Widgets/WeatherForecast.vue';
@ -35,12 +24,11 @@ import XkcdComic from '@/components/Widgets/XkcdComic.vue';
import ExchangeRates from '@/components/Widgets/ExchangeRates.vue'; import ExchangeRates from '@/components/Widgets/ExchangeRates.vue';
import StockPriceChart from '@/components/Widgets/StockPriceChart.vue'; import StockPriceChart from '@/components/Widgets/StockPriceChart.vue';
import Jokes from '@/components/Widgets/Jokes.vue'; import Jokes from '@/components/Widgets/Jokes.vue';
import Collapsable from '@/components/LinkItems/Collapsable.vue'; import IframeWidget from '@/components/Widgets/IframeWidget.vue';
export default { export default {
name: 'Widget', name: 'Widget',
components: { components: {
Collapsable,
Clock, Clock,
Weather, Weather,
WeatherForecast, WeatherForecast,
@ -51,19 +39,21 @@ export default {
ExchangeRates, ExchangeRates,
StockPriceChart, StockPriceChart,
Jokes, Jokes,
IframeWidget,
}, },
props: { props: {
widget: Object, widget: Object,
index: Number, index: Number,
}, },
computed: { computed: {
displayData() {
return this.widget.displayData || {};
},
groupId() { groupId() {
return `widget-${this.index}`; return `widget-${this.index}`;
}, },
widgetType() { widgetType() {
if (!this.widget.type) {
ErrorHandler('Missing type attribute for widget');
return null;
}
return this.widget.type.toLowerCase(); return this.widget.type.toLowerCase();
}, },
widgetOptions() { widgetOptions() {