🔀 Merge pull request #175 from Lissy93/FEATURE/improved-search

[FEATURE] Improved Search
This commit is contained in:
Alicia Sykes 2021-08-22 18:01:34 +01:00 committed by GitHub
commit 04726e91b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 363 additions and 128 deletions

View File

@ -1,5 +1,10 @@
# Changelog
## ⚡️ 1.6.6 - Improved Search & Shortcuts [PR #175](https://github.com/Lissy93/dashy/pull/175)
- Refactors the search algorithm to improve performance and code reusability
- Updates search to ignore case, special characters and minor-typos
- Adds the option for user to specify tags, which can be used for searching
## ✨ 1.6.5 - Adds support for Secure Authentication using Keycloak [PR #174](https://github.com/Lissy93/dashy/pull/174)
- Major restructure of auth config
- Implements keycloak support, adds docs and updates schema
@ -23,6 +28,7 @@
## 💄 1.6.1 - Adds new Theme [PR #166](https://github.com/Lissy93/dashy/issues/166)
- Adds Dashy theme, for use in the dev dashboard
## ✨ 1.5.9 - New Minimal/ Startpage View [PR #155](https://github.com/Lissy93/dashy/issues/155)
- Adds a new view, called minimal view, designed to be like a light-weight startpage
- Implemented all the required features (filtering, opening methods, icons, etc) into minimal view

View File

@ -1,20 +0,0 @@
---
name: "Add your Dashboard to the Showcase \U0001F5BC"
about: Share a screenshot of your dashboard to the Readme showcase!
title: "[SHOWCASE_REQUEST]"
labels: ''
assignees: ''
---
Please read the instructions here first:
https://github.com/Lissy93/dashy/blob/master/docs/showcase.md#submitting-your-dashboard
### Complete the Following
- **Title of Dashboard**:
- **Link to Screenshot**:
- **Would you like your name/ username included**: Yes/ No
- **Link to your Website/ Profile/ Twitter** (optional)
- **Description** (optional)
Either attach your screenshot here, or include a link to the CDN / image hosting service.

View File

@ -1,7 +1,9 @@
name: Bug Report 🐛
description: Report something that's not working the way it's (probably) intended to
title: '[BUG] <title>'
labels: '\U0001F41B Bug'
labels: ['🐛 Bug']
assignees:
- lissy93
body:
- type: dropdown
id: environment
@ -34,6 +36,7 @@ body:
attributes:
label: Additional info
description: Logs? Screenshots? Yes, please.
placeholder: If the issue happens during build-time, include terminal logs. For run-time errors, include browser logs which you can view in the Dev Tools (F12), under the Console tab. Take care to blank out any personal info.
validations:
required: false
- type: checkboxes
@ -42,7 +45,7 @@ body:
label: Please tick the boxes
description: Before submitting, please ensure that
options:
- label: You are using the latest, or recent version of Dashy
- label: You are using a [supported](https://github.com/Lissy93/dashy/blob/master/.github/SECURITY.md#supported-versions) version of Dashy (check the first two digits of the version number)
required: true
- label: You've checked that this [issue hasn't already been raised](https://github.com/Lissy93/dashy/issues?q=is%3Aissue)
required: true

View File

@ -1,17 +0,0 @@
---
name: "Feature Request \U0001F984"
about: Suggest an idea for future development of Dashy
title: "[FEATURE_REQUEST]"
labels: "\U0001F984 Feature Request"
assignees: Lissy93
---
**Is your feature request related to a problem? If so, please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Priority**:
Low: Nice to have / Medium: Would be useful / High: The app does not function without it

View File

@ -0,0 +1,62 @@
name: Bug Report 🐛
description: Suggest an idea for future development of Dashy
title: '[FEATURE_REQUEST] <title>'
labels: ['\U0001F984 Feature Request']
body:
# Field 1 - Is it bug-related
- type: textarea
id: issue
attributes:
label: Is your feature request related to a problem? If so, please describe.
description:
placeholder: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
validations:
required: false
# Field 2 - Describe feature
- type: textarea
id: solution
attributes:
label: Describe the solution you'd like
placeholder: An outline of how you would like this to be implemented, include as much details as possible
validations:
required: true
# Field 3 - Priority
- type: dropdown
id: priority
attributes:
label: Priority
description: How urgent is the development of this feature
options:
- Low (Nice-to-have)
- Medium (Would be very useful)
- High (The app does not function without it)
validations:
required: true
# Field 3 - Can the user implement
- type: dropdown
id: canImplement
attributes:
label: Is this something you would be keen to implement
description: Are you raising this ticket in order to get an issue number for your PR?
options:
- 'No'
- 'Maybe'
- 'Yes!'
validations:
required: false
# Final text
- type: markdown
attributes:
value: |-
## Thanks 🙏
Thank you for your feature suggestion, you should expect a reply within 48 hours :)
Please note that there is no guarantee that your idea will be implemented
If you haven't already done so, please Star the Dashy's repository on GitHub, to help other users discover it
validations:
required: false

View File

@ -0,0 +1,58 @@
name: Add your Dashboard to the Showcase 🌟
description: Share a screenshot of your dashboard to the Readme showcase!
title: '[SHOWCASE] <title>'
labels: ['💯 Showcase']
body:
# 1 - Title
- type: input
id: title
attributes:
label: Title
description: Pick a title for your addition
placeholder: My Awesome Dashboard
validations:
required: false
# 2 - Link to Screenshot
- type: textarea
id: screenshot
attributes:
label: Screenshot
description: Either upload your screenshot here, or include a link to a png/jpg on a CDN / image hosting service
validations:
required: true
# 3 - Credit user
- type: dropdown
id: attribution
attributes:
label: Would you like your name/ username included?
description: This will be displayed above the screenshot to your dashboard in the showcase page
options:
- Yes
- No
validations:
required: true
# 4 - Social links
- type: input
id: links
attributes:
label: Link to your Website/ Profile/ Twitter (optional)
description: You can optionally have your name link to your profile or website. If you'd like this, include the URL to your site below
validations:
required: false
# 5 - Description
- type: textarea
id: description
attributes:
label: Description (Optional)
description: You can optionally also include a short description. If there's anything else you'd like to include, then put it here
validations:
required: false
# 6 - All done
- type: markdown
attributes:
value: |-
## That's It!
Thanks for sharing your dashboard :) You will receive an update to this ticket once it's added to the showcase
validations:
required: false

View File

@ -56,22 +56,25 @@
## Features 🌈
- Instant search by name, domain and tags - just start typing
- Full customizable keyboard shortcuts for navigation, filtering and launching apps
- Multiple built-in color themes, with UI color editor and support for custom CSS
- Customizable layout, sizes, text, component visibility, behavior and colors etc
- Many options for icons, including Font-Awesome support, auto-fetching favicon, images and emojis
- Option to show service status for each of your apps / links, for basic availability and uptime monitoring
- Choose how to launch apps, either in your browser, a pop-up modal or workspace view
- Option for full-screen background image, custom nav-bar links, html footer, title, and more
- Optional encrypted cloud backup and restore feature available
- Optional authentication with multi-user support and configurable privileges for protecting your dashboard
- Small bundle size, fully responsive UI and PWA makes the app easy to use on any device
- Easy to setup with Docker, or on bare metal, or with 1-Click cloud deployment
- Multi-language support, with more languages being added regularly
- Easy single-file YAML-based configuration, or configure app directly through the UI
- Strong focus on privacy
- Plus lots more...
- 🔎 Instant search by name, domain and tags - just start typing + customizable keyboard shortcuts
- 🎨 Multiple built-in color themes, with UI color editor and support for custom CSS
- 🧸 Many options for icons, including Font-Awesome support, auto-fetching favicon, images and emojis
- 🚦 Service status feature for each of your apps / links, for basic availability and uptime monitoring
- 💂 Optional authentication with multi-user support, configurable privileges and SSO support
- ☁ Optional encrypted cloud backup and restore feature available
- 💼 A workspace view, for easily switching between multiple apps at once
- 🛩️ A minimal view, for use as a fast-loading browser startpage
- 🖱️ Choose how to launch apps, either new tab, same tab, a pop-up modal or in the workspace view
- 🌎 Multi-language support, with more languages being added regularly
- 📏 Customizable layout, sizes, text, component visibility, behavior and colors etc
- 🖼️ Option for full-screen background image, custom nav-bar links, html footer, title, and more
- 🚀 Easy to setup with Docker, or on bare metal, or with 1-Click cloud deployment
- 🤏 Small bundle size, fully responsive UI and PWA makes the app easy to use on any device
- ⚙️ Easy single-file YAML-based configuration, with option to configure app directly through the UI
- ✨ Under active development with improvements and new features added regularly
- 🆓 100% free and open source
- 🔐 Strong focus on privacy
- 🌈 Plus lots more...
## Demo ⚡
@ -328,6 +331,17 @@ Quickly finding and launching applications is the primary aim of Dashy. To that
To start filtering, just start typing. No need to select the search bar or use any special key. You can then use either the tab key or arrow keys to select and move between results, and hit enter to launch the currently selected application. You can also use `Alt + Enter` on a selected app to launch it in a popup modal, `Ctrl + Enter` to open in new tab, or right-click on it to see all opening methods.
You can also add custom tags to a given item, to make finding them based on keywords easier. For example, in the following example, searching for 'Movies' will show 'Plex'
```yaml
items:
- title: Plex
description: Media library
icon: favicon
url: https://plex.lab.local
tags: [ movies, videos, music ]
```
For apps that you use regularly, you can set a custom keybinding. Use the `hotkey` parameter on a certain item to specify a numeric key, between `0 - 9`. You can then launch that app, by just pressing that key, which is very useful for services you use frequently.
Example:
@ -567,17 +581,18 @@ If you're new to web development, I've put together a short [list of resources](
- 🛡️ [Authentication](/docs/authentication.md) - Guide to setting up authentication to protect your dashboard
- 🧿 [Alternate Views](/docs/alternate-views.md) - Outline of available pages / views and item opening methods
- 💾 [Backup & Restore](/docs/backup-restore.md) - Guide to Dashy's cloud sync feature
- 🚦 [Status Indicators](/docs/status-indicators.md) - Using Dashy to monitor uptime and status of your apps
- 🧸 [Icons](/docs/icons.md) - Outline of all available icon types for sections and items
- 🌐 [Language Switching](/docs/multi-language-support.md) - How to change language, add a language, or update text
- 🚦 [Status Indicators](/docs/status-indicators.md) - Using Dashy to monitor uptime and status of your apps
- 🔍 [Searching & Shortcuts](/docs/searching.md) - Finding and launching your apps, and using keyboard shortcuts
- 🎨 [Theming](/docs/theming.md) - Complete guide to applying, writing and modifying themes and styles
#### Misc
- [🔐 Privacy & Security](/docs/privacy.md) - List of requests, potential issues, and security resources
- [📄 License](/LICENSE) - Copy of the MIT License
- [⚖️ Legal](/.github/LEGAL.md) - Licenses of direct dependencies
- [📏 Code of Conduct](/.github/CODE_OF_CONDUCT.md) - Contributor Covenant Code of Conduct
- [🌳 Changelog](/.github/CHANGELOG.md) - Details of recent changes, and historical versions
- 🔐 [Privacy & Security](/docs/privacy.md) - List of requests, potential issues, and security resources
- 📄 [License](/LICENSE) - Copy of the MIT License
- ⚖️ [Legal](/.github/LEGAL.md) - Licenses of direct dependencies
- 📏 [Code of Conduct](/.github/CODE_OF_CONDUCT.md) - Contributor Covenant Code of Conduct
- 🌳 [Changelog](/.github/CHANGELOG.md) - Details of recent changes, and historical versions
**[⬆️ Back to Top](#dashy)**

View File

@ -150,11 +150,13 @@ For more info, see the **[Authentication Docs](/docs/authentication.md)**
**`icon`** | `string` | _Optional_ | The icon for a given item. Can be a font-awesome icon, favicon, remote URL or local URL. See [`item.icon`](#sectionicon-and-sectionitemicon)
**`target`** | `string` | _Optional_ | The opening method for when the item is clicked, either `newtab`, `sametab`, `modal` or `workspace`. Where `newtab` will open the link in a new tab, `sametab` will open it in the current tab, and `modal` will open a pop-up modal with the content displayed within that iframe. Note that for the iframe to load, you must have set the CORS headers to either allow `*` ot allow the domain that you are hosting Dashy on, for some websites and self-hosted services, this is already set.
**`hotkey`** | `number` | _Optional_ | Give frequently opened applications a numeric hotkey, between `0 - 9`. You can then just press that key to launch that application.
**`tags`** | `string[]` | _Optional_ | A list of tags, which can be used for improved search
**`statusCheck`** | `boolean` | _Optional_ | When set to `true`, Dashy will ping the URL associated with the current service, and display its status as a dot next to the item. The value here will override `appConfig.statusCheck` so you can turn off or on checks for a given service. Defaults to `appConfig.statusCheck`, falls back to `false`
**`statusCheckUrl`** | `string` | _Optional_ | If you've enabled `statusCheck`, and want to use a different URL to what is defined under the item, then specify it here
**`statusCheckHeaders`** | `object` | _Optional_ | If you're endpoint requires any specific headers for the status checking, then define them here
**`color`** | `string` | _Optional_ | An optional color for the text and font-awesome icon to be displayed in. Note that this will override the current theme and so may not display well
**`backgroundColor`** | `string` | _Optional_ | An optional background fill color for the that given item. Again, this will override the current theme and so might not display well against the background
**`provider`** | `string` | _Optional_ | The name of the provider for a given service, useful for when including hosted apps. In some themes, this is visible under the item name
**[⬆️ Back to Top](#configuring)**

View File

@ -21,6 +21,7 @@
- [Icons](/docs/icons.md) - Outline of all available icon types for sections and items
- [Language Switching](/docs/multi-language-support.md) - Details on how to switch language, or add a new locale
- [Status Indicators](/docs/status-indicators.md) - Using Dashy to monitor uptime and status of your apps
- [Searching & Shortcuts](/docs/searching.md) - Finding and launching your apps, and using keyboard shortcuts
- [Theming](/docs/theming.md) - Complete guide to applying, writing and modifying themes and styles
### Misc

53
docs/searching.md Normal file
View File

@ -0,0 +1,53 @@
# Keyboard Shortcuts
## Searching
One of the primary purposes of Dashy is to allow you to quickly find and launch a given app. To make this as quick as possible, there is no need to touch the mouse, or press a certain key to begin searching - just start typing. Results will be filtered in real-time. No need to worry about case, special characters or small typos, these are taken care of, and your results should appear.
## Navigating
You can navigate through your items or search results using the keyboard. You can use <kbd>Tab</kbd> to cycle through results, and <kbd>Shift</kbd> + <kbd>Tab</kbd> to go backwards. Or use the arrow keys, <kbd></kbd>, <kbd></kbd>, <kbd></kbd> and <kbd></kbd>.
## Launching Apps
You can launch a elected app by hitting <kbd>Enter</kbd>. This will open the app using your default opening method, specified in `target` (either `newtab`, `sametab`, `modal` or `workspace`). You can also use <kbd>Alt</kbd> + <kbd>Enter</kbd> to open the app in a pop-up modal, or <kbd>Ctrl</kbd> + <kbd>Enter</kbd> to open it in a new tab. For all available opening methods, just right-click on an item, to bring up the context menu.
## Tags
By default, items are filtered by the `title` attribute, as well as the hostname (extracted from `url`), the `provider` and `description`. If you need to find results based on text which isn't included in these attributes, then you can add `tags` to a given item.
```yaml
items:
- title: Plex
description: Media library
icon: favicon
url: https://plex.lab.local
tags: [ movies, videos, music ]
- title: FreshRSS
description: RSS Reader
icon: favicon
url: https://freshrss.lab.local
tags: [ news, updates, blogs ]
```
In the above example, Plex will be visible when searching for 'movies', and FreshRSS with 'news'
## Custom Hotkeys
For apps that you use regularly, you can set a custom keybinding. Use the `hotkey` parameter on a certain item to specify a numeric key, between `0 - 9`. You can then launch that app, by just pressing that key, which is much quicker than searching for it, if it's an app you use frequently.
```yaml
- title: Bookstack
icon: far fa-books
url: https://bookstack.lab.local/
hotkey: 2
- title: Git Tea
icon: fab fa-git
url: https://git.lab.local/
target: workspace
hotkey: 3
```
In the above example, pressing <kbd>2</kbd> will launch Bookstack. Or hitting <kbd>3</kbd> will open Git in the workspace view.
## Clearing Search
You can clear your search term at any time, by pressing <kbd>Esc</kbd>.
This can also be used to close an open pop-up modal.

View File

@ -30,6 +30,12 @@
---
### Dashy Live
> By [@Lissy93](https://github.com/lissy93)
> A dashboard I made to manage all project development links from one place
![screenshot-dashy-live](https://raw.githubusercontent.com/Lissy93/dashy/master/docs/showcase/10-dashy-live.png)
### CFT Toolbox
![screenshot-cft-toolbox](https://raw.githubusercontent.com/Lissy93/dashy/master/docs/showcase/3-cft-toolbox.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 KiB

View File

@ -1,6 +1,6 @@
{
"name": "Dashy",
"version": "1.6.5",
"version": "1.6.6",
"license": "MIT",
"main": "server",
"scripts": {

View File

@ -1,11 +1,17 @@
<template>
<div class="css-editor-outer">
<textarea class="css-editor" v-model="customCss" />
<button class="save-button" @click="save()">{{ $t('config.css-save-btn') }}</button>
<p class="quick-note">
<b>{{ $t('config.css-note-label') }}:</b>
{{ $t('config.css-note-l1') }} {{ $t('config.css-note-l2') }} {{ $t('config.css-note-l3') }}
</p>
<!-- Add raw custom CSS -->
<div class="css-wrapper">
<h2 class="css-input-title">Custom CSS</h2>
<textarea class="css-editor" v-model="customCss" />
<button class="save-button" @click="save()">{{ $t('config.css-save-btn') }}</button>
<p class="quick-note">
<b>{{ $t('config.css-note-label') }}:</b>
{{ $t('config.css-note-l1') }} {{ $t('config.css-note-l2') }} {{ $t('config.css-note-l3') }}
</p>
</div>
<!-- UI color configurator -->
<CustomThemeMaker :themeToEdit="currentTheme" class="color-config" />
</div>
</template>
@ -31,9 +37,11 @@ export default {
};
},
methods: {
/* A regex to validate the users CSS */
validate(css) {
return css === '' || css.match(/((?:^\s*)([\w#.@*,:\-.:>,*\s]+)\s*{(?:[\s]*)((?:[A-Za-z\- \s]+[:]\s*['"0-9\w .,/()\-!%]+;?)*)*\s*}(?:\s*))/gmi);
return css === '' || css.match(/([#.@]?[\w.:> ]+)[\s]{[\r\n]?([A-Za-z\- \r\n\t]+[:][\s]*[\w ./()\-!]+;[\r\n]*(?:[A-Za-z\- \r\n\t]+[:][\s]*[\w ./()\-!]+;[\r\n]*(2)*)*)}/gmi);
},
/* Save custom CSS in browser, call inject, and show success message */
save() {
let msg = '';
if (this.validate(this.customCss)) {
@ -48,6 +56,7 @@ export default {
}
this.$toasted.show(msg);
},
/* Formats CSS, and applies it to page */
inject(userStyles) {
const cleanedCss = userStyles.replace(/<\/?[^>]+(>|$)/g, '');
const style = document.createElement('style');
@ -63,6 +72,12 @@ export default {
div.css-editor-outer {
text-align: center;
padding-bottom: 1rem;
display: flex;
flex-direction: column;
h2.css-input-title {
margin: 0.5rem 0 0.2rem;
}
}
button.save-button {
@ -104,6 +119,8 @@ p.quick-note {
width: 80%;
margin: 1rem auto;
padding: 0.5rem;
font-size: 0.9rem;
opacity: var(--dimming-factor);
border-radius: var(--curve-factor);
}

View File

@ -12,7 +12,7 @@
:style="`--open-icon: ${getUnicodeOpeningIcon()}; ${customStyles}`"
>
<!-- Item Text -->
<div :class="`tile-title ${!icon? 'bounce': ''}`" :id="`tile-${id}`" >
<div :class="`tile-title ${!icon? 'bounce no-icon': ''}`" :id="`tile-${id}`" >
<span class="text">{{ title }}</span>
<p class="description">{{ description }}</p>
</div>
@ -319,6 +319,12 @@ export default {
.tile-title {
min-width: 100px;
max-width: 160px;
&.no-icon {
text-align: left;
width: 100%;
max-width: inherit;
margin-left: 0.5rem;
}
}
}
/* Large Tile Specific Themes */

View File

@ -926,6 +926,8 @@ html[data-theme="dashy-docs"] {
border: none;
color: var(--background);
font-weight: bold;
min-width: 5rem;
text-align: center;
}
.minimal-section-heading {

View File

@ -471,6 +471,14 @@
"type": "number",
"description": "A numeric shortcut key, between 0 and 9. Useful for quickly launching frequently used applications"
},
"tags": {
"type": "array",
"description": "Tags, which can be used for improved search",
"maxItems": 12,
"items": {
"type": "string"
}
},
"color": {
"type": "string",
"description": "A custom fill color of the item"

52
src/utils/Search.js Normal file
View File

@ -0,0 +1,52 @@
/* Dashy: Licensed under MIT, (C) Alicia Sykes 2021 <https://aliciasykes.com> */
/* Tile filtering utility */
/**
* Extracts the site name from domain
* @param {string} url The URL to process
* @returns {string} The hostname from URL
*/
const getDomainFromUrl = (url) => {
if (!url) return '';
const urlPattern = /^(?:https?:\/\/)?(?:w{3}\.)?([a-z\d.-]+)\.(?:[a-z.]{2,10})(?:[/\w.-]*)*/;
const domainPattern = url.match(urlPattern);
return domainPattern ? domainPattern[1] : '';
};
/**
* Compares search term to a given data attribute
* Ignores case, special characters and order
* @param {string or other} compareStr The value to compare to
* @param {string} searchStr The users search term
* @returns {boolean} true if a match, otherwise false
*/
const filterHelper = (compareStr, searchStr) => {
if (!compareStr) return false;
const process = (input) => input.toString().toLowerCase().replace(/[^\w\s]/gi, '');
return process(compareStr).includes(process(searchStr));
};
/**
* Filter tiles based on users search term, and returns a filtered list
* Will match based on title, description, provider, hostname from url and tags
* Ignores case, special characters and other irrelevant things
* @param {array} allTiles An array of tiles
* @param {string} searchTerm The users search term
* @returns A filtered array of tiles
*/
const search = (allTiles, searchTerm) => {
if (!allTiles) return []; // If no data, then skip
return allTiles.filter((tile) => {
const {
title, description, provider, url, tags,
} = tile;
return filterHelper(title, searchTerm)
|| filterHelper(provider, searchTerm)
|| filterHelper(description, searchTerm)
|| filterHelper(tags, searchTerm)
|| filterHelper(getDomainFromUrl(url), searchTerm);
});
};
export default search;

View File

@ -38,29 +38,27 @@ module.exports = {
builtInThemes: [
'callisto',
'thebe',
'dracula',
'oblivion',
'material',
'material-dark',
'dracula',
'colorful',
'nord',
'nord-frost',
'dashy-docs',
'minimal-dark',
'minimal-light',
'oblivion',
'nord',
'nord-frost',
'cyberpunk',
'matrix',
'matrix-red',
'hacker-girl',
'raspberry-jam',
'bee',
'tiger',
'blue-purple',
'vaporware',
'material-original',
'material-dark-original',
'cyberpunk',
'vaporware',
'high-contrast-dark',
'high-contrast-light',
'dashy-docs',
],
/* Which structural components should be visible by default */
visibleComponents: {

View File

@ -1,3 +1,4 @@
<!-- Main homepage for default view -->
<template>
<div class="home" :style="getBackgroundImage()">
<!-- Search bar, layout options and settings -->
@ -9,7 +10,7 @@
:displayLayout="layout"
:iconSize="itemSizeBound"
:externalThemes="getExternalCSSLinks()"
:sections="getSections(sections)"
:sections="allSections"
:appConfig="appConfig"
:pageInfo="pageInfo"
:modalOpen="modalOpen"
@ -19,17 +20,19 @@
<div v-if="checkTheresData(sections)"
:class="`item-group-container orientation-${layout} item-size-${itemSizeBound}`">
<Section
v-for="(section, index) in getSections(sections)"
v-for="(section, index) in filteredTiles"
:key="index"
:title="section.name"
:icon="section.icon || undefined"
:displayData="getDisplayData(section)"
:groupId="`section-${index}`"
:items="filterTiles(section.items)"
:items="filterTiles(section.items, searchValue)"
:searchTerm="searchValue"
:itemSize="itemSizeBound"
@itemClicked="finishedSearching()"
@change-modal-visibility="updateModalVisibility"
:class="(filterTiles(section.items).length === 0 && searchValue) ? 'no-results' : ''"
:class="
(searchValue && filterTiles(section.items, searchValue).length === 0) ? 'no-results' : ''"
/>
</div>
<!-- Show message when there's no data to show -->
@ -43,6 +46,7 @@
import SettingsContainer from '@/components/Settings/SettingsContainer.vue';
import Section from '@/components/LinkItems/Section.vue';
import SearchUtil from '@/utils/Search';
import Defaults, { localStorageKeys, iconCdns } from '@/utils/defaults';
export default {
@ -63,6 +67,21 @@ export default {
modalOpen: false, // When true, keybindings are disabled
}),
computed: {
/* Combines sections from config file, with those in local storage */
allSections() {
// If the user has stored sections in local storage, return those
const localSections = localStorage[localStorageKeys.CONF_SECTIONS];
if (localSections) {
const json = JSON.parse(localSections);
if (json.length >= 1) return json;
}
// Otherwise, return the usuall data from conf.yml
return this.sections;
},
filteredTiles() {
const sections = this.allSections;
return sections.filter((section) => this.filterTiles(section.items, this.searchValue));
},
/* Updates layout (when button clicked), and saves in local storage */
layoutOrientation: {
get() { return this.appConfig.layout || Defaults.layout; },
@ -86,17 +105,6 @@ export default {
const localSections = localStorage[localStorageKeys.CONF_SECTIONS];
return (sections && sections.length >= 1) || (localSections && localSections.length >= 1);
},
/* Returns sections from local storage if available, otherwise uses the conf.yml */
getSections(sections) {
// If the user has stored sections in local storage, return those
const localSections = localStorage[localStorageKeys.CONF_SECTIONS];
if (localSections) {
const json = JSON.parse(localSections);
if (json.length >= 1) return json;
}
// Otherwise, return the usuall data from conf.yml
return sections;
},
/* Updates local data with search value, triggered from filter comp */
searching(searchValue) {
this.searchValue = searchValue || '';
@ -105,26 +113,9 @@ export default {
finishedSearching() {
this.$refs.filterComp.clearFilterInput();
},
/* Extracts the site name from domain, used for the searching functionality */
getDomainFromUrl(url) {
if (!url) return '';
const urlPattern = /^(?:https?:\/\/)?(?:w{3}\.)?([a-z\d.-]+)\.(?:[a-z.]{2,10})(?:[/\w.-]*)*/;
const domainPattern = url.match(urlPattern);
return domainPattern ? domainPattern[1] : '';
},
/* Returns only the tiles that match the users search query */
filterTiles(allTiles) {
if (!allTiles) return [];
return allTiles.filter((tile) => {
const {
title, description, provider, url,
} = tile;
const searchTerm = this.searchValue.toLowerCase();
return (title && title.toLowerCase().includes(searchTerm))
|| (provider && provider.toLowerCase().includes(searchTerm))
|| (description && description.toLowerCase().includes(searchTerm))
|| this.getDomainFromUrl(url).includes(searchTerm);
});
filterTiles(allTiles, searchTerm) {
return SearchUtil(allTiles, searchTerm);
},
/* Returns optional section display preferences if available */
getDisplayData(section) {
@ -163,8 +154,8 @@ export default {
/* Checks if any sections or items use icons from a given CDN */
checkIfIconLibraryNeeded(prefix) {
let isNeeded = false;
if (!this.sections) return false;
this.sections.forEach((section) => {
if (!this.allSections) return false;
this.allSections.forEach((section) => {
if (section.icon && section.icon.includes(prefix)) isNeeded = true;
section.items.forEach((item) => {
if (item.icon && item.icon.includes(prefix)) isNeeded = true;
@ -203,11 +194,11 @@ export default {
},
/* Returns true if there is more than 1 sub-result visible during searching */
checkIfResults() {
if (!this.sections) return false;
if (!this.allSections) return false;
else {
let itemsFound = true;
this.sections.forEach((section) => {
if (this.filterTiles(section.items).length > 0) itemsFound = false;
this.allSections.forEach((section) => {
if (this.filterTiles(section.items, this.searchValue).length > 0) itemsFound = false;
});
return itemsFound;
}

View File

@ -54,6 +54,7 @@ import MinimalSection from '@/components/MinimalView/MinimalSection.vue';
import MinimalHeading from '@/components/MinimalView/MinimalHeading.vue';
import MinimalSearch from '@/components/MinimalView/MinimalSearch.vue';
import { GetTheme, ApplyLocalTheme, ApplyCustomVariables } from '@/utils/ThemeHelper';
import SearchUtil from '@/utils/Search';
import Defaults, { localStorageKeys } from '@/utils/defaults';
import ConfigLauncher from '@/components/Settings/ConfigLauncher';
@ -122,16 +123,7 @@ export default {
/* Returns only the tiles that match the users search query */
filterTiles(allTiles) {
if (!allTiles) return [];
return allTiles.filter((tile) => {
const {
title, description, provider, url,
} = tile;
const searchTerm = this.searchValue.toLowerCase();
return (title && title.toLowerCase().includes(searchTerm))
|| (provider && provider.toLowerCase().includes(searchTerm))
|| (description && description.toLowerCase().includes(searchTerm))
|| this.getDomainFromUrl(url).includes(searchTerm);
});
return SearchUtil(allTiles, this.searchValue);
},
/* Update data when modal is open (so that key bindings can be disabled) */
updateModalVisibility(modalState) {