Skip to content

Commit

Permalink
Highlight lyrics that match search result
Browse files Browse the repository at this point in the history
  • Loading branch information
imba28 committed Aug 31, 2024
1 parent d651d7c commit 8fe720c
Show file tree
Hide file tree
Showing 9 changed files with 120 additions and 27 deletions.
7 changes: 4 additions & 3 deletions assets/components/AppNavbar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
is-nav
>
<b-navbar-nav class="ml-auto">
<search-form @search="search" />
<search-form :value="searchStore.keywords" @input="search" />
</b-navbar-nav>

<b-navbar-nav class="ml-auto">
Expand Down Expand Up @@ -55,7 +55,7 @@
import SearchForm from './SearchForm.vue';
import {AuthApi} from '@/openapi';
import querystring from 'querystring';
import {useAuthStore} from '@/stores/auth';
import {useAuthStore, useSearchStore} from '@/stores';
import {mapStores} from 'pinia';
const authClient = new AuthApi();
Expand All @@ -65,10 +65,11 @@ export default {
SearchForm,
},
computed: {
...mapStores(useAuthStore),
...mapStores(useAuthStore, useSearchStore),
},
methods: {
search(query) {
this.searchStore.keywords = query;
this.$router.push({name: 'search', params: {q: query}}).catch(() => {});
},
async logout() {
Expand Down
33 changes: 33 additions & 0 deletions assets/components/HighlightWords.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<template>
<WordHighlighter
:query="keywords"
:caseSensitive="false"
:splitBySpace="true"
:diacriticsSensitive="true"
highlightClass="mark"
>
<slot></slot>
</WordHighlighter>
</template>

<script>
import WordHighlighter from 'vue-word-highlighter';
export default {
components: {WordHighlighter},
props: {
keywords: {
type: String,
},
},
};
</script>

<style>
.mark {
background-color: var(--primary);
padding: 0;
box-shadow: 0 0 3px rgba(0,0,0,0.15);
color: var(--white);
}
</style>
4 changes: 2 additions & 2 deletions assets/components/SearchForm.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ describe('SearchForm', () => {

await fireEvent.click(getByRole('button'));

expect(emitted().search).toHaveLength(1);
expect(emitted().input).toHaveLength(1);
});

test('Emitted event contains the entered input value', async () => {
Expand All @@ -18,6 +18,6 @@ describe('SearchForm', () => {
await fireEvent.update(getByRole('textbox'), query);
await fireEvent.click(getByRole('button'));

expect(emitted().search[0][0]).toEqual(query);
expect(emitted().input[0][0]).toEqual(query);
});
});
8 changes: 7 additions & 1 deletion assets/components/SearchForm.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<b-nav-form
class="search-form"
@submit.prevent="$emit('search', query)"
@submit.prevent="$emit('input', query)"
>
<b-input-group>
<b-form-input
Expand All @@ -25,11 +25,17 @@

<script>
export default {
props: {
value: String,
},
data() {
return {
query: '',
};
},
mounted() {
this.query = this.value;
},
};
</script>

Expand Down
2 changes: 2 additions & 0 deletions assets/stores/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export {useAuthStore} from './auth';
export {useSearchStore} from './search';
9 changes: 9 additions & 0 deletions assets/stores/search.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import {defineStore} from 'pinia';

export const useSearchStore = defineStore({
id: 'search',
persist: true,
state: () => ({
keywords: '',
}),
});
11 changes: 7 additions & 4 deletions assets/views/TrackDetailView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,9 @@
:style="textareaStyle"
/>
<div v-else-if="track.lyrics">
<span class="lyrics-text">{{ track.lyrics }}</span>
<HighlightWords :keywords="searchStore.keywords" class="lyrics-text">
{{ track.lyrics }}
</HighlightWords>
</div>
<div v-else-if="track.lyricsImportErrorCount > maxImportErrorCount">
<small class="text-warning">Lyrics not found. Import
Expand All @@ -151,14 +153,15 @@
import {ImportApi, Lyrics, TracksApi} from '@/openapi';
import ErrorBox from '@/components/ErrorBox';
import {mapStores} from 'pinia';
import {useAuthStore} from '@/stores/auth';
import {useAuthStore, useSearchStore} from '@/stores';
import LoadingButton from '@/components/LoadingButton';
import HighlightWords from '@/components/HighlightWords';
const api = new TracksApi();
const importApi = new ImportApi();
export default {
components: {LoadingButton, ErrorBox},
components: {LoadingButton, ErrorBox, HighlightWords},
data: () => ({
track: null,
notFound: false,
Expand All @@ -167,7 +170,7 @@ export default {
importingLyrics: false,
}),
computed: {
...mapStores(useAuthStore),
...mapStores(useAuthStore, useSearchStore),
textareaStyle() {
const lineBreaks = this.track.lyrics.match(/\n/g);
if (!lineBreaks) {
Expand Down
68 changes: 53 additions & 15 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"dependencies": {
"@babel/polyfill": "^7.11.5",
"@fortawesome/fontawesome-free": "^6.1.1",
"@vue/composition-api": "^1.6.2",
"@vue/composition-api": "^1.7.2",
"bootstrap": "^4.6.0",
"bootstrap-vue": "^2.17.3",
"bootswatch": "^4.6.0",
Expand All @@ -29,7 +29,8 @@
"superagent": "^7.1.6",
"vue": "^2.6.14",
"vue-router": "^3.5.1",
"vue-toastification": "^1.7.14"
"vue-toastification": "^1.7.14",
"vue-word-highlighter": "^1.2.4"
},
"devDependencies": {
"@babel/core": "^7.12.16",
Expand Down

0 comments on commit 8fe720c

Please sign in to comment.