mirror of
https://github.com/Lissy93/dashy.git
synced 2025-07-06 13:24:44 +02:00
✨ 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)
|
- [Exchange Rates](#exchange-rates)
|
||||||
- [Stock Price History](#stock-price-history)
|
- [Stock Price History](#stock-price-history)
|
||||||
- [Joke of the Day](#joke)
|
- [Joke of the Day](#joke)
|
||||||
|
- [Flight Data](#flight-data)
|
||||||
- [Self-Hosted Services Widgets](#dynamic-widgets)
|
- [Self-Hosted Services Widgets](#dynamic-widgets)
|
||||||
- [Dynamic Widgets](#dynamic-widgets)
|
- [Dynamic Widgets](#dynamic-widgets)
|
||||||
- [Iframe Widget](#iframe-widget)
|
- [Iframe Widget](#iframe-widget)
|
||||||
- [HTML Widget](#html-widget)
|
- [HTML Embed Widget](#html-embedded-widget)
|
||||||
- [Build your own Widget](#build-your-own-widget)
|
- [Build your own Widget](#build-your-own-widget)
|
||||||
|
|
||||||
## General Widgets
|
## 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
|
**`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
|
##### Example
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- type: iframe
|
- type: embed
|
||||||
options:
|
options:
|
||||||
url: https://fiatleak.com/
|
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'
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
86
src/components/Widgets/EmbedWidget.vue
Normal file
86
src/components/Widgets/EmbedWidget.vue
Normal file
@ -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"
|
@error="handleError"
|
||||||
:ref="widgetRef"
|
:ref="widgetRef"
|
||||||
/>
|
/>
|
||||||
|
<EmbedWidget
|
||||||
|
v-else-if="widgetType === 'embed'"
|
||||||
|
:options="widgetOptions"
|
||||||
|
@loading="setLoaderState"
|
||||||
|
@error="handleError"
|
||||||
|
:ref="widgetRef"
|
||||||
|
/>
|
||||||
<!-- No widget type specified -->
|
<!-- No widget type specified -->
|
||||||
<div v-else>{{ handleError('No widget type was specified') }}</div>
|
<div v-else>{{ handleError('No widget type was specified') }}</div>
|
||||||
</div>
|
</div>
|
||||||
@ -127,8 +134,9 @@ 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 IframeWidget from '@/components/Widgets/IframeWidget.vue';
|
|
||||||
import Flights from '@/components/Widgets/Flights.vue';
|
import Flights from '@/components/Widgets/Flights.vue';
|
||||||
|
import IframeWidget from '@/components/Widgets/IframeWidget.vue';
|
||||||
|
import EmbedWidget from '@/components/Widgets/EmbedWidget.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Widget',
|
name: 'Widget',
|
||||||
@ -147,8 +155,9 @@ export default {
|
|||||||
ExchangeRates,
|
ExchangeRates,
|
||||||
StockPriceChart,
|
StockPriceChart,
|
||||||
Jokes,
|
Jokes,
|
||||||
IframeWidget,
|
|
||||||
Flights,
|
Flights,
|
||||||
|
IframeWidget,
|
||||||
|
EmbedWidget,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
widget: Object,
|
widget: Object,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user