feat: add full text search

This commit is contained in:
2023-08-01 20:21:31 +02:00
parent 181c15f5f5
commit 7267cb88a3
16 changed files with 242 additions and 179 deletions
+35 -42
View File
@@ -43,7 +43,7 @@
<v-col> <v-col>
<v-btn-toggle <v-btn-toggle
v-if='$vuetify.breakpoint.smAndUp' v-if='$vuetify.breakpoint.smAndUp'
v-model='range' v-model='state.range'
mandatory mandatory
> >
<v-btn v-for='r in ranges' :key='r.value' text :value='r.value'> <v-btn v-for='r in ranges' :key='r.value' text :value='r.value'>
@@ -52,7 +52,7 @@
</v-btn-toggle> </v-btn-toggle>
<v-select <v-select
v-else v-else
v-model='range' v-model='state.range'
outline outline
:items='ranges' :items='ranges'
item-text='name' item-text='name'
@@ -60,6 +60,19 @@
/> />
</v-col> </v-col>
</v-row> </v-row>
<v-row wrap>
<v-col cols='12' sm='8'>
<v-text-field
v-model='state.search'
append-outer-icon='mdi-magnify'
:label="$t('events.filter')"
:placeholder="$t('events.filter')"
/>
</v-col>
<v-col cols='12' sm='4'>
<v-checkbox v-model='state.includeHidden' :label='$t("events.includeHidden")' />
</v-col>
</v-row>
<list <list
:events='events' :events='events'
:has-user='isAuthenticated' :has-user='isAuthenticated'
@@ -78,16 +91,14 @@
<script lang='ts'> <script lang='ts'>
import { computed, defineComponent, ref, watch } from 'vue' import { computed, defineComponent, ref, watch } from 'vue'
import { useNuxtApp } from '@nuxt/bridge/dist/runtime'
import List from './List/index.vue' import List from './List/index.vue'
import { useAuth } from '~/plugins/auth' import { useAuth } from '~/plugins/auth'
import { useTranslation } from '~/plugins/i18n' import { useTranslation } from '~/plugins/i18n'
import { import {
FindEventsQueryVariables, FindEventsQueryVariables,
Range,
useFetchAddressLazyQuery, useFetchAddressLazyQuery,
useFindEventsLazyQuery, useFindEventsQuery,
useSaveOriginMutation, useSaveOriginMutation,
useToggleIgnoreBandMutation, useToggleIgnoreBandMutation,
useToggleIgnoreCityMutation, useToggleIgnoreCityMutation,
@@ -95,6 +106,7 @@ import {
useToggleIgnoreMunicipalityMutation, useToggleIgnoreMunicipalityMutation,
useToggleIgnoreStateMutation useToggleIgnoreStateMutation
} from '~/graphql/generated/operations' } from '~/graphql/generated/operations'
import { useState } from '~/store'
export default defineComponent({ export default defineComponent({
name: 'EventsPage', name: 'EventsPage',
@@ -102,45 +114,26 @@ export default defineComponent({
List List
}, },
setup() { setup() {
const { $store } = useNuxtApp() const state = useState()
const { t } = useTranslation() const { t } = useTranslation()
$store.commit('setTitle', t('app.links.events')) state.setTitle(t('app.links.events'))
const { loading: authLoading, isAuthenticated } = useAuth() const { loading: authLoading, isAuthenticated } = useAuth()
const route = useRoute() const variables = ref<FindEventsQueryVariables>({
const router = useRouter() range: state.range,
const validRange = (value: string | null | (string|null)[]): Range | undefined => { includeOrigins: isAuthenticated.value || false,
if (!value) { search: state.search,
return Range.OneWeek includeHidden: state.includeHidden
} })
if (Array.isArray(value)) { const { result, refetch } = useFindEventsQuery(() => variables.value)
return validRange(value[0]) watch([state, isAuthenticated], () => {
} variables.value.range = state.range
return Object.values(Range).includes(value as Range) ? value as Range : Range.OneWeek variables.value.search = state.search
} variables.value.includeHidden = state.includeHidden
const range = computed({ variables.value.includeOrigins = isAuthenticated.value || false
get: () => validRange(route.query.range), refetch(variables.value)
set: (value) => {
router.push(`/?range=${validRange(value)}`)
}
}) })
const variables = ref<FindEventsQueryVariables>({ includeOrigins: false})
const { result, refetch, load } = useFindEventsLazyQuery(variables)
const events = computed(() => result.value?.events ?? []) const events = computed(() => result.value?.events ?? [])
const origins = computed(() => result.value?.origins ?? []) const origins = computed(() => result.value?.origins ?? [])
watch(
() => route.query.range,
(r) => {
if (!authLoading.value) {
variables.value = {
range: r ? r as Range : Range.OneWeek,
includeOrigins: isAuthenticated.value || false
}
load()
refetch(variables.value)
}
},
{ immediate: true }
)
const submitting = ref(true) const submitting = ref(true)
const ranges = [ const ranges = [
{ name: '1 vecka', value: 'ONE_WEEK' }, { name: '1 vecka', value: 'ONE_WEEK' },
@@ -158,11 +151,11 @@ export default defineComponent({
originsTemp.push(origin.value) originsTemp.push(origin.value)
} }
variables.value = { variables.value = {
range: range.value, ...variables.value,
range: state.range,
origins: originsTemp, origins: originsTemp,
includeOrigins: isAuthenticated.value || false includeOrigins: isAuthenticated.value || false
} }
load()
refetch(variables.value) refetch(variables.value)
} }
@@ -243,7 +236,7 @@ export default defineComponent({
return { return {
authLoading, authLoading,
isAuthenticated, isAuthenticated,
range, state,
events, events,
origins, origins,
submitting, submitting,
+3 -3
View File
@@ -62,7 +62,6 @@
<script lang='ts'> <script lang='ts'>
import { computed, ref } from 'vue' import { computed, ref } from 'vue'
import { useNuxtApp } from '@nuxt/bridge/dist/runtime'
import List from './List/index.vue' import List from './List/index.vue'
import { useAuth } from '~/plugins/auth' import { useAuth } from '~/plugins/auth'
@@ -75,6 +74,7 @@ import {
useToggleIgnoreMunicipalityMutation, useToggleIgnoreMunicipalityMutation,
useToggleIgnoreStateMutation useToggleIgnoreStateMutation
} from '~/graphql/generated/operations' } from '~/graphql/generated/operations'
import { useState } from '~/store'
export default { export default {
name: 'FiltersPage', name: 'FiltersPage',
@@ -82,9 +82,9 @@ export default {
List List
}, },
setup() { setup() {
const { $store } = useNuxtApp() const state = useState()
const { t } = useTranslation() const { t } = useTranslation()
$store.commit('setTitle', t('app.links.filters')) state.setTitle(t('app.links.filters'))
const { isAuthenticated } = useAuth() const { isAuthenticated } = useAuth()
const { result, loading, refetch } = useFetchFiltersQuery() const { result, loading, refetch } = useFetchFiltersQuery()
const bands = computed(() => result.value?.bands ?? []) const bands = computed(() => result.value?.bands ?? [])
+3 -3
View File
@@ -60,7 +60,6 @@
<script lang='ts'> <script lang='ts'>
import { computed, defineComponent, ref } from 'vue' import { computed, defineComponent, ref } from 'vue'
import { useNuxtApp } from '@nuxt/bridge/dist/runtime'
import { useAuth } from '~/plugins/auth' import { useAuth } from '~/plugins/auth'
import { useTranslation } from '~/plugins/i18n' import { useTranslation } from '~/plugins/i18n'
import { import {
@@ -69,13 +68,14 @@ import {
useRemoveOriginMutation, useRemoveOriginMutation,
useSaveOriginMutation useSaveOriginMutation
} from '~/graphql/generated/operations' } from '~/graphql/generated/operations'
import { useState } from '~/store'
export default defineComponent({ export default defineComponent({
name: 'OriginsPage', name: 'OriginsPage',
setup() { setup() {
const { $store } = useNuxtApp() const state = useState()
const { t } = useTranslation() const { t } = useTranslation()
$store.commit('setTitle', t('app.links.origins')) state.setTitle(t('app.links.origins'))
const { isAuthenticated } = useAuth() const { isAuthenticated } = useAuth()
const { result, loading, refetch } = useFindOriginsQuery() const { result, loading, refetch } = useFindOriginsQuery()
const origins = computed(() => result.value?.origins ?? []) const origins = computed(() => result.value?.origins ?? [])
+13 -2
View File
@@ -152,8 +152,10 @@ export type QueryAddressFromLatLngArgs = {
export type QueryEventsArgs = { export type QueryEventsArgs = {
includeHidden?: InputMaybe<Scalars['Boolean']['input']>;
origins?: InputMaybe<Array<Scalars['String']['input']>>; origins?: InputMaybe<Array<Scalars['String']['input']>>;
range?: InputMaybe<Range>; range?: InputMaybe<Range>;
search?: InputMaybe<Scalars['String']['input']>;
}; };
export enum Range { export enum Range {
@@ -229,6 +231,8 @@ export type FindEventsQueryVariables = Exact<{
range?: InputMaybe<Range>; range?: InputMaybe<Range>;
origins?: InputMaybe<Array<Scalars['String']['input']> | Scalars['String']['input']>; origins?: InputMaybe<Array<Scalars['String']['input']> | Scalars['String']['input']>;
includeOrigins: Scalars['Boolean']['input']; includeOrigins: Scalars['Boolean']['input'];
search?: InputMaybe<Scalars['String']['input']>;
includeHidden?: InputMaybe<Scalars['Boolean']['input']>;
}>; }>;
@@ -487,8 +491,13 @@ export function useFetchFiltersLazyQuery(options: VueApolloComposable.UseQueryOp
} }
export type FetchFiltersQueryCompositionFunctionResult = VueApolloComposable.UseQueryReturn<FetchFiltersQuery, FetchFiltersQueryVariables>; export type FetchFiltersQueryCompositionFunctionResult = VueApolloComposable.UseQueryReturn<FetchFiltersQuery, FetchFiltersQueryVariables>;
export const FindEventsDocument = gql` export const FindEventsDocument = gql`
query FindEvents($range: Range, $origins: [String!], $includeOrigins: Boolean!) { query FindEvents($range: Range, $origins: [String!], $includeOrigins: Boolean!, $search: String, $includeHidden: Boolean) {
events: Events(range: $range, origins: $origins) { events: Events(
range: $range
origins: $origins
search: $search
includeHidden: $includeHidden
) {
date date
time time
band { band {
@@ -526,6 +535,8 @@ export const FindEventsDocument = gql`
* range: // value for 'range' * range: // value for 'range'
* origins: // value for 'origins' * origins: // value for 'origins'
* includeOrigins: // value for 'includeOrigins' * includeOrigins: // value for 'includeOrigins'
* search: // value for 'search'
* includeHidden: // value for 'includeHidden'
* }); * });
*/ */
export function useFindEventsQuery(variables: FindEventsQueryVariables | VueCompositionApi.Ref<FindEventsQueryVariables> | ReactiveFunction<FindEventsQueryVariables>, options: VueApolloComposable.UseQueryOptions<FindEventsQuery, FindEventsQueryVariables> | VueCompositionApi.Ref<VueApolloComposable.UseQueryOptions<FindEventsQuery, FindEventsQueryVariables>> | ReactiveFunction<VueApolloComposable.UseQueryOptions<FindEventsQuery, FindEventsQueryVariables>> = {}) { export function useFindEventsQuery(variables: FindEventsQueryVariables | VueCompositionApi.Ref<FindEventsQueryVariables> | ReactiveFunction<FindEventsQueryVariables>, options: VueApolloComposable.UseQueryOptions<FindEventsQuery, FindEventsQueryVariables> | VueCompositionApi.Ref<VueApolloComposable.UseQueryOptions<FindEventsQuery, FindEventsQueryVariables>> | ReactiveFunction<VueApolloComposable.UseQueryOptions<FindEventsQuery, FindEventsQueryVariables>> = {}) {
+2 -2
View File
@@ -1,5 +1,5 @@
query FindEvents($range: Range, $origins: [String!], $includeOrigins: Boolean!) { query FindEvents($range: Range, $origins: [String!], $includeOrigins: Boolean!, $search: String, $includeHidden: Boolean) {
events: Events(range: $range, origins: $origins) { events: Events(range: $range, origins: $origins, search: $search, includeHidden: $includeHidden) {
date date
time time
band { band {
+79 -95
View File
@@ -1,121 +1,105 @@
# source: https://dancefinder.unbound.se/graph/ # This file was generated. Do not edit manually.
# timestamp: Wed Jul 03 2019 13:36:10 GMT+0200 (Central European Summer Time)
"""Band""" schema {
query: Query
mutation: Mutation
}
"The @defer directive may be specified on a fragment spread to imply de-prioritization, that causes the fragment to be omitted in the initial response, and delivered as a subsequent response afterward. A query with @defer directive will cause the request to potentially return multiple responses, where non-deferred data is delivered in the initial response and data deferred delivered in a subsequent response. @include and @skip take precedence over @defer."
directive @defer(if: Boolean = true, label: String) on FRAGMENT_SPREAD | INLINE_FRAGMENT
"Band"
type Band { type Band {
created: LocalDateTime!
id: Int id: Int
name: String! name: String!
created: LocalDateTime!
} }
"""DanceHall""" "DanceHall"
type DanceHall { type DanceHall {
id: Int
name: String
city: String city: String
municipality: String created: LocalDateTime!
state: String id: Int
latitude: Float latitude: Float
longitude: Float longitude: Float
created: LocalDateTime! municipality: String
name: String
state: String
} }
"""DanceHallDistance""" "DanceHallDistance"
type DanceHallDistance { type DanceHallDistance {
origin: String!
distance: Int! distance: Int!
duration: String! duration: String!
origin: String!
} }
"""Event""" "Event"
type Event { type Event {
id: Int "The band of the event"
"""The date of the event"""
date: LocalDate!
"""The time of the event"""
time: String
"""Additional information regarding the event"""
extraInfo: String
created: LocalDateTime!
"""The band of the event"""
band: Band band: Band
created: LocalDateTime!
"""The place of the event""" "The place of the event"
danceHall: DanceHall danceHall: DanceHall
"The date of the event"
""" date: LocalDate!
The driving distances and driving durations to the event from the provided origins "The driving distances and driving durations to the event from the provided origins"
"""
distances: [DanceHallDistance!]! distances: [DanceHallDistance!]!
"Additional information regarding the event"
extraInfo: String
id: Int
"The time of the event"
time: String
}
type Mutation {
"Remove provided origin from authenticated user"
RemoveOrigin(origin: String!): Boolean!
"Save provided origin for authenticated user"
SaveOrigin(origin: String!): Boolean!
"Toggle band in ignore list"
ToggleIgnoreBand(name: String!): Boolean!
"Toggle city in ignore list"
ToggleIgnoreCity(name: String!): Boolean!
"Toggle dance hall in ignore list"
ToggleIgnoreDanceHall(name: String!): Boolean!
"Toggle municipality in ignore list"
ToggleIgnoreMunicipality(name: String!): Boolean!
"Toggle state in ignore list"
ToggleIgnoreState(name: String!): Boolean!
}
type Query {
"Fetch address for provided lat/long"
AddressFromLatLng(latlng: String!): String!
"Find bands given provided criteria"
Bands: [Band!]!
"Find dance halls given provided criteria"
DanceHalls: [DanceHall!]!
"Find events given provided criteria"
Events(includeHidden: Boolean, origins: [String!], range: Range, search: String): [Event!]!
"Fetch ignored bands for authenticated user"
IgnoredBands: [String!]!
"Fetch ignored cities for authenticated user"
IgnoredCities: [String!]!
"Fetch ignored dance halls for authenticated user"
IgnoredDanceHalls: [String!]!
"Fetch ignored municipalities for authenticated user"
IgnoredMunicipalities: [String!]!
"Fetch ignored states for authenticated user"
IgnoredStates: [String!]!
"Fetch origins for authenticated user"
Origins: [String!]!
}
enum Range {
ONE_MONTH
ONE_QUARTER
ONE_WEEK
ONE_YEAR
TWO_WEEKS
} }
scalar LocalDate scalar LocalDate
scalar LocalDateTime scalar LocalDateTime
type Mutation {
"""Toggle band in ignore list"""
ToggleIgnoreBand(name: String!): Boolean!
"""Toggle dance hall in ignore list"""
ToggleIgnoreDanceHall(name: String!): Boolean!
"""Toggle city in ignore list"""
ToggleIgnoreCity(name: String!): Boolean!
"""Toggle municipality in ignore list"""
ToggleIgnoreMunicipality(name: String!): Boolean!
"""Toggle state in ignore list"""
ToggleIgnoreState(name: String!): Boolean!
"""Save provided origin for authenticated user"""
SaveOrigin(origin: String!): Boolean!
"""Remove provided origin from authenticated user"""
RemoveOrigin(origin: String!): Boolean!
}
type Query {
"""Find events given provided criteria"""
Events(range: Range, origins: [String!]): [Event!]!
"""Find bands given provided criteria"""
Bands: [Band!]!
"""Find dance halls given provided criteria"""
DanceHalls: [DanceHall!]!
"""Fetch origins for authenticated user"""
Origins: [String!]!
"""Fetch address for provided lat/long"""
AddressFromLatLng(latlng: String!): String!
"""Fetch ignored bands for authenticated user"""
IgnoredBands: [String!]!
"""Fetch ignored dance halls for authenticated user"""
IgnoredDanceHalls: [String!]!
"""Fetch ignored cities for authenticated user"""
IgnoredCities: [String!]!
"""Fetch ignored municipalities for authenticated user"""
IgnoredMunicipalities: [String!]!
"""Fetch ignored states for authenticated user"""
IgnoredStates: [String!]!
}
enum Range {
ONE_MONTH
ONE_YEAR
TWO_WEEKS
ONE_QUARTER
ONE_WEEK
}
+3 -2
View File
@@ -6,14 +6,15 @@
<script> <script>
import { getCurrentInstance } from 'vue' import { getCurrentInstance } from 'vue'
import { getDarkMode } from '../../utils/localStorage' import { useState } from '~/store'
export default { export default {
name: 'ThemedLayout', name: 'ThemedLayout',
setup() { setup() {
const instance = getCurrentInstance() const instance = getCurrentInstance()
const state = useState()
if (instance) { if (instance) {
instance.proxy.$vuetify.theme.dark = getDarkMode() instance.proxy.$vuetify.theme.dark = state.darkMode
} }
} }
} }
+5 -6
View File
@@ -81,11 +81,10 @@
<script> <script>
import { computed, getCurrentInstance, provide, ref } from 'vue' import { computed, getCurrentInstance, provide, ref } from 'vue'
import { useNuxtApp } from '@nuxt/bridge/dist/runtime'
import { DefaultApolloClient } from '@vue/apollo-composable' import { DefaultApolloClient } from '@vue/apollo-composable'
import Themed from './components/themed' import Themed from './components/themed'
import { setDarkMode } from '~/utils/localStorage'
import { useAuth } from '~/plugins/auth' import { useAuth } from '~/plugins/auth'
import { useState } from '~/store'
export default { export default {
name: 'DefaultLayout', name: 'DefaultLayout',
@@ -97,9 +96,8 @@ export default {
if (instance) { if (instance) {
provide(DefaultApolloClient, instance.proxy.$apollo) provide(DefaultApolloClient, instance.proxy.$apollo)
} }
const { $store } = useNuxtApp() const state = useState()
const router = useRouter() const router = useRouter()
const { title } = $store.state
const onRedirectCallback = (appState) => { const onRedirectCallback = (appState) => {
router.push( router.push(
appState && appState.targetUrl appState && appState.targetUrl
@@ -124,7 +122,7 @@ export default {
set: (val) => { set: (val) => {
if (instance) { if (instance) {
instance.proxy.$vuetify.theme.dark = val instance.proxy.$vuetify.theme.dark = val
setDarkMode(instance.proxy.$vuetify.theme.dark) state.setDarkMode(instance.proxy.$vuetify.theme.dark)
} }
} }
}) })
@@ -136,6 +134,7 @@ export default {
instance.proxy.$vuetify.lang.current = newLocale instance.proxy.$vuetify.lang.current = newLocale
instance.proxy.$i18n.locale = newLocale instance.proxy.$i18n.locale = newLocale
} }
state.setLocale(newLocale)
} }
}) })
@@ -143,7 +142,7 @@ export default {
locale.value = instance.proxy.$i18n.locale locale.value = instance.proxy.$i18n.locale
return { return {
title, title: state.title,
loading, loading,
isAuthenticated, isAuthenticated,
user, user,
+3 -1
View File
@@ -111,11 +111,13 @@ export default defineNuxtConfig({
}, },
modules: [ modules: [
'@nuxtjs/i18n', '@nuxtjs/i18n',
'@pinia/nuxt',
'@nuxtjs/sentry' '@nuxtjs/sentry'
], ],
plugins: [ plugins: [
'~/plugins/apollo', '~/plugins/apollo',
'~/plugins/i18n' '~/plugins/i18n',
'~/plugins/pinia'
], ],
router: { router: {
middleware: ['auth'] middleware: ['auth']
+4 -2
View File
@@ -28,6 +28,7 @@
"@nuxtjs/i18n": "^7.3.1", "@nuxtjs/i18n": "^7.3.1",
"@nuxtjs/sentry": "^7.3.1", "@nuxtjs/sentry": "^7.3.1",
"@nuxtjs/vuetify": "^1.12.3", "@nuxtjs/vuetify": "^1.12.3",
"@pinia/nuxt": "^0.4.11",
"@snyk/protect": "^1.1198.0", "@snyk/protect": "^1.1198.0",
"@vue/apollo-composable": "^4.0.0-beta.8", "@vue/apollo-composable": "^4.0.0-beta.8",
"@vueuse/core": "^10.3.0", "@vueuse/core": "^10.3.0",
@@ -37,13 +38,14 @@
"graphql-tag": "^2.12.6", "graphql-tag": "^2.12.6",
"node-sass": "^9.0.0", "node-sass": "^9.0.0",
"nuxt-edge": "latest", "nuxt-edge": "latest",
"pinia": "^2.1.6",
"pinia-plugin-persistedstate": "^3.2.0",
"sass-loader": "^10.1.1", "sass-loader": "^10.1.1",
"vue": "2.7.14", "vue": "2.7.14",
"vue-demi": "^0.14.5", "vue-demi": "^0.14.5",
"vue-server-renderer": "2.7.14", "vue-server-renderer": "2.7.14",
"vue-template-compiler": "2.7.14", "vue-template-compiler": "2.7.14",
"vuetify": "^2.7.0", "vuetify": "^2.7.0"
"vuex": "3.6.2"
}, },
"devDependencies": { "devDependencies": {
"@babel/runtime-corejs3": "^7.22.6", "@babel/runtime-corejs3": "^7.22.6",
+10
View File
@@ -0,0 +1,10 @@
import { createPersistedState } from 'pinia-plugin-persistedstate'
import { defineNuxtPlugin } from '#app'
export default defineNuxtPlugin(({ $pinia }) => {
$pinia.use(
createPersistedState({
key: (id) => `dancefinder_${id}`
})
)
})
-9
View File
@@ -1,9 +0,0 @@
export const state = () => ({
title: ''
})
export const mutations = {
setTitle(currentState, title) {
currentState.title = title
}
}
+49
View File
@@ -0,0 +1,49 @@
import { defineStore } from 'pinia'
import { Range } from '~/graphql/generated/operations'
export const useState = defineStore(
'state',
() => {
const title = ref<string>('')
const darkMode = ref(false)
const locale = ref('sv')
const range = ref<Range | undefined>(Range.OneWeek)
const search = ref('')
const includeHidden = ref(false)
const setTitle = (s: string) => {
title.value = s
}
const setDarkMode = (b: boolean) => {
darkMode.value = b
}
const setLocale = (l: string) => {
locale.value = l
}
const setSearch = (s: string) => {
search.value = s
}
const setIncludeHidden = (b: boolean) => {
includeHidden.value = b
}
const setRange = (r: Range | undefined) => {
range.value = r
}
return {
title,
darkMode,
locale,
search,
includeHidden,
range,
setTitle,
setDarkMode,
setLocale,
setSearch,
setIncludeHidden,
setRange
}
},
{
persist: true
}
)
+6 -2
View File
@@ -15,7 +15,9 @@ export default {
city: 'City:', city: 'City:',
municipality: 'Municipality:', municipality: 'Municipality:',
state: 'State:', state: 'State:',
hide: 'Hide' hide: 'Hide',
filter: 'Full text search',
includeHidden: 'Include hidden'
}, },
sv: { sv: {
title: 'Dancefinder - Evenemang', title: 'Dancefinder - Evenemang',
@@ -33,6 +35,8 @@ export default {
city: 'Stad:', city: 'Stad:',
municipality: 'Kommun:', municipality: 'Kommun:',
state: 'Län:', state: 'Län:',
hide: 'Dölj' hide: 'Dölj',
filter: 'Fritext-sökning',
includeHidden: 'Inkludera dolda'
} }
} }
-9
View File
@@ -1,9 +0,0 @@
const DARK_MODE_KEY = 'dancefinder-dark-mode'
const LOCALE_KEY = 'dancefinder-locale'
const getDarkMode = () => JSON.parse(localStorage.getItem(DARK_MODE_KEY))
const setDarkMode = (mode) => localStorage.setItem(DARK_MODE_KEY, JSON.stringify(mode))
const getLocale = () => localStorage.getItem(LOCALE_KEY)
const setLocale = (locale) => localStorage.setItem(LOCALE_KEY, locale)
export { getDarkMode, setDarkMode, getLocale, setLocale }
+27 -1
View File
@@ -3424,6 +3424,14 @@
tslib "^2.5.0" tslib "^2.5.0"
webcrypto-core "^1.7.7" webcrypto-core "^1.7.7"
"@pinia/nuxt@^0.4.11":
version "0.4.11"
resolved "https://registry.yarnpkg.com/@pinia/nuxt/-/nuxt-0.4.11.tgz#1b3f728ae112d45deff5971376e05b8a8d64f720"
integrity sha512-bhuNFngJpmBCdAqWguezNJ/oJFR7wvKieqiZrmmdmPR07XjsidAw8RLXHMZE9kUm32M9E6T057OBbG/22jERTg==
dependencies:
"@nuxt/kit" "^3.5.0"
pinia ">=2.1.0"
"@pkgr/utils@^2.3.1": "@pkgr/utils@^2.3.1":
version "2.4.2" version "2.4.2"
resolved "https://registry.yarnpkg.com/@pkgr/utils/-/utils-2.4.2.tgz#9e638bbe9a6a6f165580dc943f138fd3309a2cbc" resolved "https://registry.yarnpkg.com/@pkgr/utils/-/utils-2.4.2.tgz#9e638bbe9a6a6f165580dc943f138fd3309a2cbc"
@@ -4324,6 +4332,11 @@
optionalDependencies: optionalDependencies:
prettier "^1.18.2 || ^2.0.0" prettier "^1.18.2 || ^2.0.0"
"@vue/devtools-api@^6.5.0":
version "6.5.0"
resolved "https://registry.yarnpkg.com/@vue/devtools-api/-/devtools-api-6.5.0.tgz#98b99425edee70b4c992692628fa1ea2c1e57d07"
integrity sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q==
"@vueuse/core@^10.3.0": "@vueuse/core@^10.3.0":
version "10.3.0" version "10.3.0"
resolved "https://registry.yarnpkg.com/@vueuse/core/-/core-10.3.0.tgz#b2dab7821ef206811b925fc935163c38056fd82b" resolved "https://registry.yarnpkg.com/@vueuse/core/-/core-10.3.0.tgz#b2dab7821ef206811b925fc935163c38056fd82b"
@@ -12077,6 +12090,19 @@ pify@^5.0.0:
resolved "https://registry.yarnpkg.com/pify/-/pify-5.0.0.tgz#1f5eca3f5e87ebec28cc6d54a0e4aaf00acc127f" resolved "https://registry.yarnpkg.com/pify/-/pify-5.0.0.tgz#1f5eca3f5e87ebec28cc6d54a0e4aaf00acc127f"
integrity sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA== integrity sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==
pinia-plugin-persistedstate@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/pinia-plugin-persistedstate/-/pinia-plugin-persistedstate-3.2.0.tgz#9932ca2ae88aa6c0d6763bebc6447d7bd1f097d0"
integrity sha512-tZbNGf2vjAQcIm7alK40sE51Qu/m9oWr+rEgNm/2AWr1huFxj72CjvpQcIQzMknDBJEkQznCLAGtJTIcLKrKdw==
pinia@>=2.1.0, pinia@^2.1.6:
version "2.1.6"
resolved "https://registry.yarnpkg.com/pinia/-/pinia-2.1.6.tgz#e88959f14b61c4debd9c42d0c9944e2875cbe0fa"
integrity sha512-bIU6QuE5qZviMmct5XwCesXelb5VavdOWKWaB17ggk++NUwQWWbP5YnsONTk3b752QkW9sACiR81rorpeOMSvQ==
dependencies:
"@vue/devtools-api" "^6.5.0"
vue-demi ">=0.14.5"
pkg-dir@^3.0.0: pkg-dir@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3"
@@ -15753,7 +15779,7 @@ vuetify@^2.6, vuetify@^2.7.0:
resolved "https://registry.yarnpkg.com/vuetify/-/vuetify-2.7.0.tgz#a2c999da30072a62a2d577f0aafd996b276cc149" resolved "https://registry.yarnpkg.com/vuetify/-/vuetify-2.7.0.tgz#a2c999da30072a62a2d577f0aafd996b276cc149"
integrity sha512-eDb+lbtB9e+FRbOPIIyXwgwgc2M6gvhHkhSgggzM0hmKh1XM34YStZbM865viH0AfpxGZIOsRcs0S+OtdyOB+Q== integrity sha512-eDb+lbtB9e+FRbOPIIyXwgwgc2M6gvhHkhSgggzM0hmKh1XM34YStZbM865viH0AfpxGZIOsRcs0S+OtdyOB+Q==
vuex@3.6.2, vuex@^3.6.2: vuex@^3.6.2:
version "3.6.2" version "3.6.2"
resolved "https://registry.yarnpkg.com/vuex/-/vuex-3.6.2.tgz#236bc086a870c3ae79946f107f16de59d5895e71" resolved "https://registry.yarnpkg.com/vuex/-/vuex-3.6.2.tgz#236bc086a870c3ae79946f107f16de59d5895e71"
integrity sha512-ETW44IqCgBpVomy520DT5jf8n0zoCac+sxWnn+hMe/CzaSejb/eVw2YToiXYX+Ex/AuHHia28vWTq4goAexFbw== integrity sha512-ETW44IqCgBpVomy520DT5jf8n0zoCac+sxWnn+hMe/CzaSejb/eVw2YToiXYX+Ex/AuHHia28vWTq4goAexFbw==