diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md
index a7818f4bb4..527d4d007c 100644
--- a/.github/CHANGELOG.md
+++ b/.github/CHANGELOG.md
@@ -1,5 +1,23 @@
# Changelog
+## ✨ 2.0.9 Adds Multi-Page Support [PR #663](https://github.com/Lissy93/dashy/pull/663)
+- Fix KeyCloak API URL (#564)
+- Fix guest has config access (#590)
+- Fix collapsible content in multi-page support (#626)
+- Fix layout and item size buttons ( #629)
+- Refactor make request in RSS widget (#632)
+- Fix material-design-icons header in schema (#640)
+- Add option to hide seconds in clock widget (#644)
+- Fix pageInfo not being read in router (#645)
+- Fix startingView not honored (#646)
+- Fix Status Check default (#651)
+- Add option to hide image in SportsScores Widget (#654)
+- Add Adventure-basic theme (#655)
+- Write docs for sub-items (#657)
+- Add Font-Awesome displaying as square to troubleshooting guide (#659)
+- Show expand / collapse in context menu (#660)
+- Only deploy new release when relevant files have changed
+
## ✨ 2.0.8 Adds Multi-Page Support [PR #617](https://github.com/Lissy93/dashy/pull/617)
- Adds support for multiple pages per-dashboard
- Adds new attribute at root of main config file: `pages`
diff --git a/.github/LATEST_CHANGELOG.md b/.github/LATEST_CHANGELOG.md
index bbd4106b92..89e76a44d4 100644
--- a/.github/LATEST_CHANGELOG.md
+++ b/.github/LATEST_CHANGELOG.md
@@ -1,4 +1,17 @@
-## ✨ 2.0.8 Adds Multi-Page Support [PR #617](https://github.com/Lissy93/dashy/pull/617)
-- Adds support for multiple pages per-dashboard
-- Adds new attribute at root of main config file: `pages`
-- Updates router and nav-bar to automatically create paths for both local and remote configs
+## ✨ 2.0.9 Adds Multi-Page Support [PR #663](https://github.com/Lissy93/dashy/pull/663)
+- Fix KeyCloak API URL (#564)
+- Fix guest has config access (#590)
+- Fix collapsible content in multi-page support (#626)
+- Fix layout and item size buttons ( #629)
+- Refactor make request in RSS widget (#632)
+- Fix material-design-icons header in schema (#640)
+- Add option to hide seconds in clock widget (#644)
+- Fix pageInfo not being read in router (#645)
+- Fix startingView not honored (#646)
+- Fix Status Check default (#651)
+- Add option to hide image in SportsScores Widget (#654)
+- Add Adventure-basic theme (#655)
+- Write docs for sub-items (#657)
+- Add Font-Awesome displaying as square to troubleshooting guide (#659)
+- Show expand / collapse in context menu (#660)
+- Only deploy new release when relevant files have changed
diff --git a/.github/workflows/docker-build-publish.yml b/.github/workflows/docker-build-publish.yml
index 72d05010a7..287aa910e5 100644
--- a/.github/workflows/docker-build-publish.yml
+++ b/.github/workflows/docker-build-publish.yml
@@ -6,6 +6,11 @@ on:
push:
branches: ['master']
tags: [v*]
+ paths:
+ - '**.js'
+ - 'src/**'
+ - 'public/**'
+ - 'services/**'
env:
DH_IMAGE: ${{ secrets.DOCKER_REPO }}
diff --git a/README.md b/README.md
index b3b14f5cc8..38c155ce80 100644
--- a/README.md
+++ b/README.md
@@ -408,14 +408,15 @@ Dashy supports multiple languages and locales. When available, your language sho
- 🇳🇱 **Dutch**: `nl` - Contributed by **[@evroon](https://github.com/evroon)**
- 🇲🇫 **French**: `fr` - Contributed by **[@EVOTk](https://github.com/EVOTk)**
- 🇩🇪 **German**: `de` - Contributed by **[@Niklashere](https://github.com/Niklashere)**
+- 🇮🇹 **Italian**: `it` - Contributed by **[@alexdelprete](https://github.com/alexdelprete)**
- 🇳🇴 **Norwegian Bokmål**: `nb` - Contributed by **[@rubjo](https://github.com/rubjo)**
- 🇵🇱 **Polish**: `pl` - Contributed by **[@skaarj1989](https://github.com/skaarj1989)**
+- 🇵🇹 **Portuguese**: `pt` - Contributed by **[@LeoColman](https://github.com/LeoColman)**
- 🇪🇸 **Spanish**: `es` - Contributed by **[@lu4t](https://github.com/lu4t)**
- 🇸🇮 **Slovenian**: `sl` - Contributed by **[@UrekD](https://github.com/UrekD)**
- 🇸🇪 **Swedish**: `sv` - Contributed by **[@BOZG](https://github.com/BOZG)**
-- 🇮🇹 **Italian**: `it` - Contributed by **[@alexdelprete](https://github.com/alexdelprete)**
-- 🇵🇹 **Portuguese**: `pt` - Contributed by **[@LeoColman](https://github.com/LeoColman)**
-- 🇷🇺 **Russian**: `ru` - Contributed by Anon
+- 🇹🇼 **Traditional Chinese**: `zh-TW` - Contributed by **[@stanly0726](https://github.com/stanly0726)**
+- 🇷🇺 **Russian**: `ru`
- 🇦🇪 **Arabic**: `ar`
- 🇮🇳 **Hindi**: `hi`
- 🇯🇵 **Japanese**: `ja`
diff --git a/docs/authentication.md b/docs/authentication.md
index 8a74ce8408..4b8e0e67fd 100644
--- a/docs/authentication.md
+++ b/docs/authentication.md
@@ -146,6 +146,8 @@ appConfig:
clientId: 'dashy'
```
+Note that if you are using Keycloak V 17 or older, you will also need to set `legacySupport: true` (also under `appConfig.auth.keycloak`). This is because the API endpoint was updated in later versions.
+
### 4. Add groups and roles (Optional)
Keycloak allows you to assign users roles and groups. You can use these values to configure who can access various sections in Dashy.
Keycloak server administration and configuration is a deep topic; please refer to the [server admin guide](https://www.keycloak.org/docs/latest/server_admin/index.html#assigning-permissions-and-access-using-roles-and-groups) to see details about creating and assigning roles and groups.
diff --git a/docs/configuring.md b/docs/configuring.md
index e09bc4a661..2ef8268cf0 100644
--- a/docs/configuring.md
+++ b/docs/configuring.md
@@ -163,6 +163,7 @@ For more info, see the **[Authentication Docs](/docs/authentication.md)**
**`serverUrl`** | `string` | Required | The URL (or URL/ IP + Port) where your keycloak server is running
**`realm`** | `string` | Required | The name of the realm (must already be created) that you want to use
**`clientId`** | `string` | Required | The Client ID of the client you created for use with Dashy
+**`legacySupport`** | `boolean` | _Optional_ | If using Keycloak 17 or older, then set this to `true`
**[⬆️ Back to Top](#configuring)**
diff --git a/docs/pages-and-sections.md b/docs/pages-and-sections.md
index ad19faf24b..f55c62f6a4 100644
--- a/docs/pages-and-sections.md
+++ b/docs/pages-and-sections.md
@@ -56,3 +56,43 @@ The following example shows creating a config, publishing it as a [Gist](https:/
Only top-level fields supported by sub-pages are `pageInfo` and `sections`. The `appConfig` and `pages` will always be inherited from your main `conf.yml` file. Other than that, sub-pages behave exactly the same as your default view, and can contain sections, items, widgets and page info like nav links, title and logo.
Note that since page paths are required by the router, they are set at build-time, not run-time, and so a rebuild (happens automatically) is required for changes to page paths to take effect (this only applies to changes to the `pages` array, rebuild isn't required for editing page content).
+
+
+## Sub-Items
+
+A normal section will contain zero or more items, for example:
+
+```yaml
+- name: Coding
+ icon: far fa-code
+ items:
+ - title: GitHub
+ url: https://github.com/
+ - title: StackOverflow
+ url: http://stackoverflow.com/
+```
+
+But items can also be grouped together, referred to as sub-items. This is useful for a group of less frequently used items, which you don't want to take up too much space, or for action buttons (_coming soon_).
+
+Item groups may also have an optional title.
+
+```yaml
+- name: Coding
+ icon: far fa-code
+ items:
+ - title: Normal Item 1
+ - title: Normal Item 2
+ - subItems:
+ - title: JavaScript
+ url: https://developer.mozilla.org
+ icon: si-javascript
+ - title: TypeScript
+ url: https://www.typescriptlang.org/docs
+ icon: si-typescript
+ - title: Svelt
+ url: https://svelte.dev/docs
+ icon: si-svelte
+ - title: Go
+ url: https://go.dev/doc
+ icon: si-go
+```
diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md
index 4ba5729f3e..b69d48e4d1 100644
--- a/docs/troubleshooting.md
+++ b/docs/troubleshooting.md
@@ -30,12 +30,13 @@
- [Diagnosing Widget Errors](#widget-errors)
- [Fixing Widget CORS Errors](#widget-cors-errors)
- [Weather Forecast Widget 401](#weather-forecast-widget-401)
-- [Keycloak Redirect Error](#keycloak-redirect-error)
+- [Font Awesome Icons not Displaying](#font-awesome-icons-not-displaying)
- [How-To Open Browser Console](#how-to-open-browser-console)
- [Git Contributions not Displaying](#git-contributions-not-displaying)
---
+
## `Refused to Connect` in Modal or Workspace View
This is not an issue with Dashy, but instead caused by the target app preventing direct access through embedded elements.
@@ -214,6 +215,13 @@ You should also ensure that Keycloak is correctly configured, with a user, realm
For more details on how to set headers, see the [Example Headers](/docs/management.md#setting-headers) in the management docs, or reference the documentation for your proxy.
+If you're running in Kubernetes, you will need to enable CORS ingress rules, see [docs](https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#enable-cors), e.g:
+
+```
+nginx.ingress.kubernetes.io/cors-allow-origin: "https://dashy.example.com"
+nginx.ingress.kubernetes.io/enable-cors: "true"
+```
+
See also: #479, #409, #507, #491, #341, #520
---
@@ -412,22 +420,19 @@ A future update will be pushed out, to use a free weather forecasting API.
---
-## Keycloak Redirect Error
+## Font Awesome Icons not Displaying
-Firstly, ensure that in your Keycloak instance you have populated the Valid Redirect URIs field ([screenshot](https://user-images.githubusercontent.com/1862727/148599768-db4ee4f8-72c5-402d-8f00-051d999e6267.png)) with the URL to your Dashy instance.
+Usually, Font Awesome will be automatically enabled if one or more of your icons are using Font-Awesome. If this is not happening, then you can always manually enable (or disable) Font Awesome by setting: [`appConfig`](/docs/configuring.md#appconfig-optional).`enableFontAwesome` to `true`.
-You may need to specify CORS headers on your Keycloak instance, to allow requests coming from Dashy, e.g:
+If you are trying to use a premium icon, then you must have a [Pro License](https://fontawesome.com/plans). You'll then need to specify your Pro plan API key under `appConfig.fontAwesomeKey`. You can find this key, by logging into your FA account, navigate to Account → [Kits](https://fontawesome.com/kits) → New Kit → Copy Kit Code. The code is a 10-digit alpha-numeric code, and is also visible within the new kit's URL, for example: `81e48ce079`.
-```
-Access-Control-Allow-Origin: https://dashy.example.com
-```
+Be sure that you're specifying the icon category and name correctly. You're icon should look be `[category] fa-[icon-name]`. The following categories are supported: `far` _(regular)_, `fas` _(solid)_, `fal`_(light)_, `fad` _(duo-tone)_ and `fab`_(brands)_. With the exception of brands, you'll usually want all your icons to be in from same category, so they look uniform.
-If you're running in Kubernetes, you will need to enable CORS ingress rules, see [docs](https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#enable-cors), e.g:
+Ensure the icon you are trying to use, is available within [FontAwesome Version 5](https://fontawesome.com/v5/search).
-```
-nginx.ingress.kubernetes.io/cors-allow-origin: "https://dashy.example.com"
-nginx.ingress.kubernetes.io/enable-cors: "true"
-```
+Examples: `fab fa-raspberry-pi`, `fas fa-database`, `fas fa-server`, `fas fa-ethernet`
+
+Finally, check the [browser console](#how-to-open-browser-console) for any error messages, and raise a ticket if the issue persists.
---
diff --git a/docs/widgets.md b/docs/widgets.md
index 02f2d13d0e..1f8e1fd257 100644
--- a/docs/widgets.md
+++ b/docs/widgets.md
@@ -97,6 +97,7 @@ A simple, live-updating time and date widget with time-zone support. All fields
**`format`** | `string` | _Optional_ | A country code for displaying the date and time in local format. Specified as `[ISO-3166]-[ISO-639]`, for example: `en-AU`. See [here](https://www.fincher.org/Utilities/CountryLanguageList.shtml) for a full list of locales. Defaults to the browser / device's region
**`customCityName`** | `string` | _Optional_ | By default the city from the time-zone is shown, but setting this value will override that text
**`hideDate`** | `boolean` | _Optional_ | If set to `true`, the date and city will not be shown. Defaults to `false`
+**`hideSeconds`** | `boolean` | _Optional_ | If set to `true`, seconds will not be shown. Defaults to `false`
##### Example
@@ -713,6 +714,7 @@ Show recent scores and upcoming matches from your favourite sports team. Data is
**`pastOrFuture`** | `string` | __Optional__ | Set to `past` to show scores for recent games, or `future` to show upcoming games. Defaults to `past`. You can change this within the UI
**`apiKey`** | `string` | __Optional__ | Optionally specify your API key, which you can sign up for at [TheSportsDB.com](https://www.thesportsdb.com/)
**`limit`** | `number` | __Optional__ | To limit output to a certain number of matches, defaults to `15`
+**`hideImage`** | `boolean` | __Optional__ | Set to `true` to not render the team / match banner image, defaults to `false`
##### Example
diff --git a/package.json b/package.json
index 1a85325b01..73f73e725f 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "Dashy",
- "version": "2.0.8",
+ "version": "2.0.9",
"license": "MIT",
"main": "server",
"author": "Alicia Sykes (https://aliciasykes.com)",
@@ -47,6 +47,7 @@
},
"devDependencies": {
"@architect/sandbox": "^4.5.2",
+ "@babel/preset-env": "^7.17.10",
"@vue/cli-plugin-babel": "^4.5.15",
"@vue/cli-plugin-eslint": "^4.5.15",
"@vue/cli-plugin-pwa": "^4.5.15",
@@ -87,6 +88,12 @@
"parser": "babel-eslint"
}
},
+ "babel": {
+ "presets": [
+ "@vue/app",
+ "@babel/preset-env"
+ ]
+ },
"postcss": {
"plugins": {
"autoprefixer": {}
diff --git a/src/assets/interface-icons/section-expand-collapse.svg b/src/assets/interface-icons/section-expand-collapse.svg
new file mode 100644
index 0000000000..c9cf291ed5
--- /dev/null
+++ b/src/assets/interface-icons/section-expand-collapse.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/locales/en.json b/src/assets/locales/en.json
index 9c38e9abd7..a064eb670d 100644
--- a/src/assets/locales/en.json
+++ b/src/assets/locales/en.json
@@ -195,6 +195,7 @@
"section": {
"open-section": "Open Section",
"edit-section": "Edit",
+ "expand-collapse": "Expand / Collapse",
"move-section": "Move To",
"remove-section": "Remove"
}
diff --git a/src/components/LinkItems/Collapsable.vue b/src/components/LinkItems/Collapsable.vue
index bed3bad9fb..75f4bc376d 100644
--- a/src/components/LinkItems/Collapsable.vue
+++ b/src/components/LinkItems/Collapsable.vue
@@ -1,14 +1,16 @@
-
@@ -32,7 +31,6 @@ import ThemeSelector from '@/components/Settings/ThemeSelector';
import LayoutSelector from '@/components/Settings/LayoutSelector';
import ItemSizeSelector from '@/components/Settings/ItemSizeSelector';
import AuthButtons from '@/components/Settings/AuthButtons';
-import KeyboardShortcutInfo from '@/components/Settings/KeyboardShortcutInfo';
import AppInfoModal from '@/components/Configuration/AppInfoModal';
import IconOpen from '@/assets/interface-icons/config-open-settings.svg';
import IconClose from '@/assets/interface-icons/config-close.svg';
@@ -57,7 +55,6 @@ export default {
LayoutSelector,
ItemSizeSelector,
AuthButtons,
- KeyboardShortcutInfo,
AppInfoModal,
IconOpen,
IconClose,
diff --git a/src/components/Settings/ThemeSelector.vue b/src/components/Settings/ThemeSelector.vue
index 081caf4c99..51e0be9fad 100644
--- a/src/components/Settings/ThemeSelector.vue
+++ b/src/components/Settings/ThemeSelector.vue
@@ -106,15 +106,17 @@ export default {
mounted() {
const initialTheme = this.getInitialTheme();
this.selectedTheme = initialTheme;
- // Pass all user custom stylesheets to the themehelper
- const added = Object.keys(this.externalThemes).map(
- name => this.themeHelper.add(name, this.externalThemes[name]),
- );
// Quicker loading, if the theme is local we can apply it immidiatley
if (this.isThemeLocal(initialTheme)) {
this.updateTheme(initialTheme);
+ }
+
// If it's an external stylesheet, then wait for promise to resolve
- } else if (initialTheme !== Defaults.theme) {
+ if (this.externalThemes && Object.entries(this.externalThemes).length > 0) {
+ const added = Object.keys(this.externalThemes).map(
+ name => this.themeHelper.add(name, this.externalThemes[name]),
+ );
+ // Once, added, then apply users initial theme
Promise.all(added).then(() => {
this.updateTheme(initialTheme);
});
diff --git a/src/components/Widgets/BlacklistCheck.vue b/src/components/Widgets/BlacklistCheck.vue
index edf5e4197e..ad5975b9d0 100644
--- a/src/components/Widgets/BlacklistCheck.vue
+++ b/src/components/Widgets/BlacklistCheck.vue
@@ -58,7 +58,7 @@ export default {
if (!this.ipAddress) {
this.getUsersIpAddress(); return;
}
- this.defaultTimeout = 20000;
+ this.defaultTimeout = 200000;
const options = { Authorization: `Basic ${this.apiKey}` };
this.makeRequest(this.endpoint, options).then(this.processData);
},
diff --git a/src/components/Widgets/Clock.vue b/src/components/Widgets/Clock.vue
index aa5ccc513c..717bad628e 100644
--- a/src/components/Widgets/Clock.vue
+++ b/src/components/Widgets/Clock.vue
@@ -36,6 +36,9 @@ export default {
if (this.options.customCityName) return this.options.customCityName;
return this.timeZone.split('/')[1].replaceAll('_', ' ');
},
+ showSeconds() {
+ return !this.options.hideSeconds;
+ },
},
methods: {
update() {
@@ -48,7 +51,7 @@ export default {
timeZone: this.timeZone,
hour: 'numeric',
minute: 'numeric',
- second: 'numeric',
+ ...(this.showSeconds && { second: 'numeric' }),
}).format();
},
/* Get and format the date */
diff --git a/src/components/Widgets/RssFeed.vue b/src/components/Widgets/RssFeed.vue
index e00807dc8a..94f8398a5b 100644
--- a/src/components/Widgets/RssFeed.vue
+++ b/src/components/Widgets/RssFeed.vue
@@ -31,7 +31,6 @@