From 0074c636b69da3086e6a9cce489977d16e854cb9 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Thu, 23 Dec 2021 08:58:52 +0000 Subject: [PATCH] :construction: Commiting to switch computers... --- docs/widgets.md | 61 ++++++++++++++++++++++++--- src/components/Widgets/StatPing.vue | 6 ++- src/components/Widgets/WidgetBase.vue | 26 ++++++++++++ src/utils/ConfigSchema.json | 26 ++++++++++-- 4 files changed, 110 insertions(+), 9 deletions(-) diff --git a/docs/widgets.md b/docs/widgets.md index 08c368de..baebe4b5 100644 --- a/docs/widgets.md +++ b/docs/widgets.md @@ -23,7 +23,7 @@ Dashy has support for displaying dynamic content in the form of widgets. There a - [GitHub Trending](#github-trending) - [GitHub Profile Stats](#github-profile-stats) - [Public IP Address](#public-ip) -- [Self-Hosted Services Widgets](#dynamic-widgets) +- [Self-Hosted Services Widgets](#self-hosted-services-widgets) - [System Info](#system-info) - [Cron Monitoring](#cron-monitoring-health-checks) - [CPU History](#cpu-history-netdata) @@ -38,10 +38,11 @@ Dashy has support for displaying dynamic content in the form of widgets. There a - [HTML Embed Widget](#html-embedded-widget) - [API Response](#api-response) - [Data Feed](#data-feed) -- [Custom Widgets](#custom-widgets) +- [Usage & Customizations](#usage--customizations) - [Widget Usage Guide](#widget-usage-guide) - - [Widget Styling](#widget-styling) - - [Build your own Widget](#build-your-own-widget) + - [Continuous Updates](#continuous-updates) + - [Custom CSS Styling](#widget-styling) + - [Building a Widget](#build-your-own-widget) ## General Widgets @@ -862,18 +863,68 @@ Show live data from an RSS-enabled service. The only required parameter is `rssU --- -## Custom Widgets +## Usage & Customizations ### Widget Usage Guide +Like items, widgets are placed under sections. You may have one or more widgets per section. + +In your YAML config file, this will look something like: + +```yaml +sections: +- name: Today + icon: far fa-calendar-day + widgets: + - type: clock + options: + format: en-GB + - type: weather + options: + apiKey: 6e29c7d514cf890f846d58178b6d418f + city: London + units: metric +``` + +> In this example, there is a single section, named "Today", using a Calendar icon from Font-Awesome. It has 2 widgets, a clock and the current weather. + +--- + +### Continuous Updates + +By default, a widget which displays dynamic data from an external source, will only fetch results on page load. If you would like to keep data updated at all times, you can enable **Continuous Updates**. This is done by setting a time value in the `updateInterval` field. + +The value of `updateInterval` is optional, and is specified and seconds. It must be more than `10` and less than `7200`. + +For example, the following widget displaying stats from Pi-Hole will update ever 20 seconds. + +```yaml +widgets: +- type: pi-hole-stats + updateInterval: 20 + options: + hostname: http://192.168.130.2 +``` + +Note that if you have many widgets, and set them to continuously update frequently, you will notice a hit to performance. A widget that relies on data from an external API, will also consume your usage quota faster, if set to keep updating. --- ### Widget Styling +Like elsewhere in Dashy, all colours can be easily modified with CSS variables. + +Widgets use the following color variables, which can be overridden if desired: +- `--widget-text-color` - Text color, defaults to `--primary` +- `--widget-background-color` - Background color, defaults to `--background-darker` +- `--widget-accent-color` - Accent color, defaults to `--background` + +For more info on how to apply custom variables, see the [Theming Docs](/docs/theming.md#setting-custom-css-in-the-ui) --- ### Build your own Widget +Widgets are built in a modular fashion, making it easy for anyone to create their own custom components. + 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. diff --git a/src/components/Widgets/StatPing.vue b/src/components/Widgets/StatPing.vue index 7fa4be5c..d34c47f0 100644 --- a/src/components/Widgets/StatPing.vue +++ b/src/components/Widgets/StatPing.vue @@ -57,6 +57,9 @@ export default { if (!this.options.hostname) this.error('A hostname is required'); return this.options.hostname; }, + limit() { + return this.options.limit; + }, proxyReqEndpoint() { const baseUrl = process.env.VUE_APP_DOMAIN || window.location.origin; return `${baseUrl}${serviceEndpoints.corsProxy}`; @@ -114,7 +117,7 @@ export default { return 'unknown'; }, processData(data) { - const services = []; + let services = []; data.forEach((service) => { services.push({ name: service.name, @@ -128,6 +131,7 @@ export default { lastFailure: this.getTimeAgo(service.last_error), }); }); + if (this.limit) services = services.slice(0, this.limit); this.services = services; }, }, diff --git a/src/components/Widgets/WidgetBase.vue b/src/components/Widgets/WidgetBase.vue index 693e19e6..f36c72de 100644 --- a/src/components/Widgets/WidgetBase.vue +++ b/src/components/Widgets/WidgetBase.vue @@ -290,6 +290,7 @@ export default { loading: false, error: false, errorMsg: null, + updater: null, // Stores interval }), computed: { /* Returns the widget type, shows error if not specified */ @@ -308,6 +309,20 @@ export default { widgetRef() { return `widget-${this.widgetType}-${this.index}`; }, + /* Returns either `false` or a number in ms to continuously update widget data */ + updateInterval() { + const usersInterval = this.widget.updateInterval; + if (!usersInterval) return false; + // If set to `true`, then default to 30 seconds + if (typeof usersInterval === 'boolean') return 30 * 1000; + // If set to a number, and within valid range, return user choice + if (typeof usersInterval === 'number' + && usersInterval >= 10 + && usersInterval < 7200) { + return usersInterval * 1000; + } + return false; + }, }, methods: { /* Calls update data method on widget */ @@ -328,6 +343,17 @@ export default { this.loading = loading; }, }, + mounted() { + // If continuous updates enabled, create interval + if (this.updateInterval) { + this.updater = setInterval(() => { + this.update(); + }, this.updateInterval); + } + }, + beforeDestroy() { + clearInterval(this.updater); + }, }; diff --git a/src/utils/ConfigSchema.json b/src/utils/ConfigSchema.json index a4d84141..24099f23 100644 --- a/src/utils/ConfigSchema.json +++ b/src/utils/ConfigSchema.json @@ -488,8 +488,7 @@ "title": "Items", "type": "object", "required": [ - "name", - "items" + "name" ], "additionalProperties": false, "properties": { @@ -716,9 +715,30 @@ } } } + }, + "widgets": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "title": "Widget Type", + "type": "string", + "description": "The type of widget to use, see docs for supported options" + }, + "options": { + "title": "Widget Options", + "type": "object", + "description": "Configuration options for widget. Varies depending on widget type, see docs for all options" + } + } + } } } } } } -} +} \ No newline at end of file