mirror of https://github.com/Lissy93/dashy.git
✨ Builds a content embed widget
This commit is contained in:
parent
642cfc655b
commit
f61366ca48
|
@ -14,10 +14,11 @@ Dashy has support for displaying dynamic content in the form of widgets. There a
|
|||
- [Exchange Rates](#exchange-rates)
|
||||
- [Stock Price History](#stock-price-history)
|
||||
- [Joke of the Day](#joke)
|
||||
- [Flight Data](#flight-data)
|
||||
- [Self-Hosted Services Widgets](#dynamic-widgets)
|
||||
- [Dynamic Widgets](#dynamic-widgets)
|
||||
- [Iframe Widget](#iframe-widget)
|
||||
- [HTML Widget](#html-widget)
|
||||
- [HTML Embed Widget](#html-embedded-widget)
|
||||
- [Build your own Widget](#build-your-own-widget)
|
||||
|
||||
## General Widgets
|
||||
|
@ -330,12 +331,31 @@ Embed any webpage into your dashboard as a widget.
|
|||
--- | --- | --- | ---
|
||||
**`url`** | `string` | Required | The URL to the webpage to embed
|
||||
|
||||
### HTML Embedded Widget
|
||||
|
||||
Many websites and apps provide their own embeddable widgets. These can be used with Dashy using the Embed widget, which lets you dynamically embed and HTML, CSS or JavaScript contents.
|
||||
|
||||
⚠️ **NOTE:** Use with extreme caution. Embedding a script from an untrustworthy source may have serious unintended consequences.
|
||||
|
||||
<p align="center"><img width="400" src="https://i.ibb.co/yn0SGtL/embed-widget.png" /></p>
|
||||
|
||||
##### Options
|
||||
|
||||
**Field** | **Type** | **Required** | **Description**
|
||||
--- | --- | --- | ---
|
||||
**`html`** | `string` | _Optional_ | HTML contents to render in the widget
|
||||
**`script`** | `string` | _Optional_ | Raw JavaScript code to execute (caution)
|
||||
**`scriptSrc`** | `string` | _Optional_ | A URL to JavaScript content (caution)
|
||||
**`css`** | `string` | _Optional_ | Any stylings for widget contents
|
||||
|
||||
##### Example
|
||||
|
||||
```yaml
|
||||
- type: iframe
|
||||
options:
|
||||
url: https://fiatleak.com/
|
||||
- type: embed
|
||||
options:
|
||||
css: '.coinmarketcap-currency-widget { color: var(--widget-text-color); }'
|
||||
html: '<div class="coinmarketcap-currency-widget" data-currencyid="1" data-base="USD" data-secondary="" data-ticker="true" data-rank="true" data-marketcap="true" data-volume="true" data-statsticker="true" data-stats="USD"></div>'
|
||||
scriptSrc: 'https://files.coinmarketcap.com/static/widget/currency.js'
|
||||
```
|
||||
|
||||
---
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
<template>
|
||||
<div class="html-widget">
|
||||
<div :id="elementId" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import WidgetMixin from '@/mixins/WidgetMixin';
|
||||
|
||||
export default {
|
||||
mixins: [WidgetMixin],
|
||||
computed: {
|
||||
html() {
|
||||
return this.options.html || '';
|
||||
},
|
||||
css() {
|
||||
return this.options.css || '';
|
||||
},
|
||||
script() {
|
||||
return this.options.script || '';
|
||||
},
|
||||
scriptSrc() {
|
||||
return this.options.scriptSrc || '';
|
||||
},
|
||||
elementId() {
|
||||
return `elem-${Math.round(Math.random() * 10000)}`;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.initiate();
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.eventListener) {
|
||||
document.removeEventListener(this.eventListener);
|
||||
}
|
||||
},
|
||||
data: () => ({
|
||||
eventListener: null,
|
||||
}),
|
||||
methods: {
|
||||
/* Injects users content */
|
||||
injectHtml() {
|
||||
if (this.html) {
|
||||
const element = document.getElementById(this.elementId);
|
||||
element.innerHTML = this.html;
|
||||
}
|
||||
if (this.css) {
|
||||
const styleElem = document.createElement('style');
|
||||
styleElem.textContent = this.css;
|
||||
document.head.append(styleElem);
|
||||
}
|
||||
if (this.script) {
|
||||
const scriptElem = document.createElement('script');
|
||||
scriptElem.text = this.script;
|
||||
document.head.append(scriptElem);
|
||||
}
|
||||
if (this.scriptSrc) {
|
||||
const scriptElem = document.createElement('script');
|
||||
scriptElem.src = this.scriptSrc;
|
||||
document.head.append(scriptElem);
|
||||
}
|
||||
},
|
||||
/* What for the DOM to finish loading, before proceeding */
|
||||
initiate() {
|
||||
if (document.readyState === 'complete' || document.readyState === 'loaded') {
|
||||
this.injectHtml();
|
||||
} else {
|
||||
this.eventListener = document.addEventListener('DOMContentLoaded', () => {
|
||||
this.injectHtml();
|
||||
});
|
||||
}
|
||||
},
|
||||
update() {
|
||||
this.injectHtml();
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.html-widget {
|
||||
width: 100%;
|
||||
min-height: 240px;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -102,6 +102,13 @@
|
|||
@error="handleError"
|
||||
:ref="widgetRef"
|
||||
/>
|
||||
<EmbedWidget
|
||||
v-else-if="widgetType === 'embed'"
|
||||
:options="widgetOptions"
|
||||
@loading="setLoaderState"
|
||||
@error="handleError"
|
||||
:ref="widgetRef"
|
||||
/>
|
||||
<!-- No widget type specified -->
|
||||
<div v-else>{{ handleError('No widget type was specified') }}</div>
|
||||
</div>
|
||||
|
@ -127,8 +134,9 @@ import XkcdComic from '@/components/Widgets/XkcdComic.vue';
|
|||
import ExchangeRates from '@/components/Widgets/ExchangeRates.vue';
|
||||
import StockPriceChart from '@/components/Widgets/StockPriceChart.vue';
|
||||
import Jokes from '@/components/Widgets/Jokes.vue';
|
||||
import IframeWidget from '@/components/Widgets/IframeWidget.vue';
|
||||
import Flights from '@/components/Widgets/Flights.vue';
|
||||
import IframeWidget from '@/components/Widgets/IframeWidget.vue';
|
||||
import EmbedWidget from '@/components/Widgets/EmbedWidget.vue';
|
||||
|
||||
export default {
|
||||
name: 'Widget',
|
||||
|
@ -147,8 +155,9 @@ export default {
|
|||
ExchangeRates,
|
||||
StockPriceChart,
|
||||
Jokes,
|
||||
IframeWidget,
|
||||
Flights,
|
||||
IframeWidget,
|
||||
EmbedWidget,
|
||||
},
|
||||
props: {
|
||||
widget: Object,
|
||||
|
|
Loading…
Reference in New Issue