chore: upgrade to Vue3/Vuetify3
@@ -1,36 +1,38 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
root: true,
|
|
||||||
env: {
|
|
||||||
browser: true,
|
|
||||||
node: true
|
|
||||||
},
|
|
||||||
parser: 'vue-eslint-parser',
|
parser: 'vue-eslint-parser',
|
||||||
plugins: [
|
|
||||||
'@typescript-eslint'
|
|
||||||
],
|
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
parser: '@typescript-eslint/parser',
|
parser: '@typescript-eslint/parser',
|
||||||
requireConfigFile: false
|
sourceType: 'module',
|
||||||
},
|
},
|
||||||
extends: [
|
extends: ['@nuxtjs/eslint-config-typescript', 'eslint:recommended', 'plugin:vue/vue3-recommended'],
|
||||||
'@nuxtjs',
|
rules: {
|
||||||
'@nuxtjs/eslint-config-typescript',
|
'vue/valid-v-slot': 'off',
|
||||||
'plugin:nuxt/recommended'
|
'arrow-parens': ['error', 'always'],
|
||||||
],
|
'comma-dangle': ['error', 'always-multiline'],
|
||||||
// add your custom rules here
|
'space-before-function-paren': ['error', {
|
||||||
rules: {},
|
anonymous: 'never',
|
||||||
|
named: 'never',
|
||||||
|
asyncArrow: 'always',
|
||||||
|
}],
|
||||||
|
'@typescript-eslint/consistent-type-imports': ['error', {
|
||||||
|
fixStyle: 'inline-type-imports',
|
||||||
|
}],
|
||||||
|
},
|
||||||
|
plugins: [],
|
||||||
|
ignorePatterns: ['nuxt.config.ts'],
|
||||||
overrides: [
|
overrides: [
|
||||||
{
|
{
|
||||||
files: ['pages/**/*.vue', 'layouts/*.vue'],
|
files: ['pages/**/*.vue', 'layouts/*.vue'],
|
||||||
rules: {
|
rules: {
|
||||||
'vue/multi-word-component-names': 'off'
|
'vue/multi-word-component-names': 'off',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
files: ['graphql/generated/*.ts'],
|
files: ['graphql/generated/*.ts'],
|
||||||
rules: {
|
rules: {
|
||||||
'no-use-before-define': 'off'
|
'no-use-before-define': 'off',
|
||||||
}
|
'no-unused-vars': 'off',
|
||||||
}
|
},
|
||||||
]
|
},
|
||||||
|
],
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ COPY ./package.json ./yarn.lock ./.snyk ./
|
|||||||
RUN yarn install --frozen-lockfile
|
RUN yarn install --frozen-lockfile
|
||||||
|
|
||||||
COPY ./ ./
|
COPY ./ ./
|
||||||
RUN yarn build && yarn lint
|
RUN yarn run generate && yarn lint
|
||||||
#RUN yarn start:ci & yarn wait && yarn test:cypress
|
#RUN yarn start:ci & yarn wait && yarn test:cypress
|
||||||
|
|
||||||
FROM nginx
|
FROM nginx
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
<template>
|
|
||||||
<v-layout
|
|
||||||
row
|
|
||||||
wrap
|
|
||||||
>
|
|
||||||
<v-flex xs12 sm6>
|
|
||||||
<v-icon>mdi-home</v-icon>
|
|
||||||
<span><strong>{{ distance.origin }}</strong></span>
|
|
||||||
</v-flex>
|
|
||||||
<v-flex xs12 sm6>
|
|
||||||
<v-icon>mdi-car</v-icon>
|
|
||||||
<span>{{ numericDistance }} km</span>
|
|
||||||
<v-icon>mdi-clock-outline</v-icon>
|
|
||||||
<span>{{ distance.duration }}</span>
|
|
||||||
</v-flex>
|
|
||||||
</v-layout>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang='ts'>
|
|
||||||
import { computed, PropType } from 'vue'
|
|
||||||
import { DanceHallDistance } from '~/graphql/generated/operations'
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
distance: {
|
|
||||||
type: Object as PropType<DanceHallDistance>,
|
|
||||||
required: true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
const numericDistance = computed(() =>
|
|
||||||
Number(props.distance.distance / 1000).toLocaleString('sv-SE', {
|
|
||||||
minimumFractionDigits: 2,
|
|
||||||
maximumFractionDigits: 2
|
|
||||||
}))
|
|
||||||
</script>
|
|
||||||
@@ -1,80 +1,81 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-card flat outlined rounded class="mx-3 my-3 rounded-xl">
|
<v-card flat variant="outlined" rounded="xl">
|
||||||
<v-card-title primary-title>
|
<v-card-title v-if="event.band" primary-title>
|
||||||
<h3 class="headline mb-0">
|
<h3 class="headline mb-0">
|
||||||
<v-icon
|
<v-icon
|
||||||
v-if="hasUser"
|
v-if="hasUser"
|
||||||
class="ml-1 mr-1"
|
class="ml-1 mr-1 text-medium-emphasis"
|
||||||
medium
|
size="small"
|
||||||
title="Dölj"
|
title="Dölj"
|
||||||
@click="toggleIgnore('band', event.band.name)"
|
@click="toggleIgnore('band', event.band.name)"
|
||||||
>
|
>
|
||||||
mdi-eye-off
|
mdi-eye-off
|
||||||
</v-icon>{{ event.band.name }}
|
</v-icon>
|
||||||
|
{{ event.band.name }}
|
||||||
</h3>
|
</h3>
|
||||||
</v-card-title>
|
</v-card-title>
|
||||||
<v-container>
|
<v-card-text>
|
||||||
<v-layout row wrap>
|
<v-row wrap>
|
||||||
<v-flex
|
<v-col
|
||||||
xs12
|
xs="12"
|
||||||
sm6
|
sm="6"
|
||||||
>
|
>
|
||||||
<strong class="mr-1" v-text="$t('events.date')" />{{
|
<strong class="mr-1" v-text="$t('events.date')" />{{
|
||||||
event.date
|
event.date
|
||||||
}}
|
}}
|
||||||
({{ weekday }} {{ daysUntil }})
|
({{ weekday }} {{ daysUntil }})
|
||||||
</v-flex>
|
</v-col>
|
||||||
<v-flex v-if="event.time" xs12 sm6>
|
<v-col v-if="event.time" xs="12" sm="6">
|
||||||
<strong class="mr-1" v-text="$t('events.time')" />{{
|
<strong class="mr-1" v-text="$t('events.time')" />{{
|
||||||
event.time
|
event.time
|
||||||
}}
|
}}
|
||||||
</v-flex>
|
</v-col>
|
||||||
</v-layout>
|
</v-row>
|
||||||
<v-layout row wrap>
|
<v-row v-if="event.danceHall" wrap>
|
||||||
<v-flex
|
<v-col
|
||||||
xs12
|
xs="12"
|
||||||
sm6
|
sm="6"
|
||||||
md3
|
md="3"
|
||||||
>
|
>
|
||||||
<strong class="mr-1" v-text="$t('events.hall')" />
|
<strong class="mr-1" v-text="$t('events.hall')" />
|
||||||
<v-icon
|
<v-icon
|
||||||
v-if="hasUser"
|
v-if="hasUser"
|
||||||
class="ml-1 mr-1"
|
class="ml-1 mr-1 text-medium-emphasis"
|
||||||
small
|
size="small"
|
||||||
:title="$t('events.hide')"
|
:title="$t('events.hide')"
|
||||||
@click="toggleIgnore('danceHall', event.danceHall.name)"
|
@click="toggleIgnore('danceHall', event.danceHall.name)"
|
||||||
>
|
>
|
||||||
mdi-eye-off
|
mdi-eye-off
|
||||||
</v-icon>
|
</v-icon>
|
||||||
{{ event.danceHall.name }}
|
{{ event.danceHall.name }}
|
||||||
</v-flex>
|
</v-col>
|
||||||
<v-flex
|
<v-col
|
||||||
xs12
|
xs="12"
|
||||||
sm6
|
sm="6"
|
||||||
md3
|
md="3"
|
||||||
>
|
>
|
||||||
<strong class="mr-1" v-text="$t('events.city')" />
|
<strong class="mr-1" v-text="$t('events.city')" />
|
||||||
<v-icon
|
<v-icon
|
||||||
v-if="hasUser"
|
v-if="hasUser"
|
||||||
class="ml-1 mr-1"
|
class="ml-1 mr-1 text-medium-emphasis"
|
||||||
small
|
size="small"
|
||||||
:title="$t('events.hide')"
|
:title="$t('events.hide')"
|
||||||
@click="toggleIgnore('city', event.danceHall.city)"
|
@click="toggleIgnore('city', event.danceHall.city)"
|
||||||
>
|
>
|
||||||
mdi-eye-off
|
mdi-eye-off
|
||||||
</v-icon>
|
</v-icon>
|
||||||
{{ event.danceHall.city }}
|
{{ event.danceHall.city }}
|
||||||
</v-flex>
|
</v-col>
|
||||||
<v-flex
|
<v-col
|
||||||
xs12
|
xs="12"
|
||||||
sm6
|
sm="6"
|
||||||
md3
|
md="3"
|
||||||
>
|
>
|
||||||
<strong class="mr-1" v-text="$t('events.municipality')" />
|
<strong class="mr-1" v-text="$t('events.municipality')" />
|
||||||
<v-icon
|
<v-icon
|
||||||
v-if="hasUser"
|
v-if="hasUser"
|
||||||
class="ml-1 mr-1"
|
class="ml-1 mr-1 text-medium-emphasis"
|
||||||
small
|
size="small"
|
||||||
:title="$t('events.hide')"
|
:title="$t('events.hide')"
|
||||||
@click="
|
@click="
|
||||||
toggleIgnore('municipality', event.danceHall.municipality)
|
toggleIgnore('municipality', event.danceHall.municipality)
|
||||||
@@ -83,27 +84,27 @@
|
|||||||
mdi-eye-off
|
mdi-eye-off
|
||||||
</v-icon>
|
</v-icon>
|
||||||
{{ event.danceHall.municipality }}
|
{{ event.danceHall.municipality }}
|
||||||
</v-flex>
|
</v-col>
|
||||||
<v-flex
|
<v-col
|
||||||
xs12
|
xs="12"
|
||||||
sm6
|
sm="6"
|
||||||
md3
|
md="3"
|
||||||
>
|
>
|
||||||
<strong class="mr-1" v-text="$t('events.state')" />
|
<strong class="mr-1" v-text="$t('events.state')" />
|
||||||
<v-icon
|
<v-icon
|
||||||
v-if="hasUser"
|
v-if="hasUser"
|
||||||
class="ml-1 mr-1"
|
class="ml-1 mr-1 text-medium-emphasis"
|
||||||
small
|
size="small"
|
||||||
:title="$t('events.hide')"
|
:title="$t('events.hide')"
|
||||||
@click="toggleIgnore('state', event.danceHall.state)"
|
@click="toggleIgnore('state', event.danceHall.state)"
|
||||||
>
|
>
|
||||||
mdi-eye-off
|
mdi-eye-off
|
||||||
</v-icon>
|
</v-icon>
|
||||||
{{ event.danceHall.state }}
|
{{ event.danceHall.state }}
|
||||||
</v-flex>
|
</v-col>
|
||||||
</v-layout>
|
</v-row>
|
||||||
<distance-display v-for="distance in event.distances" :key="distance.origin" :distance="distance" />
|
<distance-display v-for="distance in event.distances" :key="distance.origin" :distance="distance" />
|
||||||
</v-container>
|
</v-card-text>
|
||||||
</v-card>
|
</v-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -112,30 +113,31 @@
|
|||||||
import { format, formatDistanceToNow, parseISO } from 'date-fns'
|
import { format, formatDistanceToNow, parseISO } from 'date-fns'
|
||||||
|
|
||||||
import { enGB, sv } from 'date-fns/locale'
|
import { enGB, sv } from 'date-fns/locale'
|
||||||
import { computed, getCurrentInstance, PropType } from 'vue'
|
import { computed, type PropType } from 'vue'
|
||||||
import { Event } from '~/graphql/generated/operations'
|
import { useI18n } from '#i18n'
|
||||||
import DistanceDisplay from '~/components/pages/events/Event/distance.vue'
|
import { type Event } from '~/graphql/generated/operations'
|
||||||
|
import DistanceDisplay from '~/components/pages/events/event-distance.vue'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
event: {
|
event: {
|
||||||
type: Object as PropType<Event>,
|
type: Object as PropType<Event>,
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
hasUser: {
|
hasUser: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
toggleIgnore: {
|
toggleIgnore: {
|
||||||
type: Function,
|
type: Function,
|
||||||
required: true
|
required: true,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
const instance = getCurrentInstance()
|
const { locale: currentLocale } = useI18n()
|
||||||
const locale = computed(() => (instance?.proxy.$i18n.locale ?? 'sv') === 'en' ? enGB : sv)
|
const locale = computed(() => (currentLocale.value ?? 'sv') === 'en' ? enGB : sv)
|
||||||
const time = computed(() => (props.event.time || '').split('-')[0].replace('.', ':'))
|
const time = computed(() => (props.event.time || '').split('-')[0].replace('.', ':'))
|
||||||
const weekday = computed(() => format(parseISO(props.event.date), 'EEEE', { locale: locale.value }))
|
const weekday = computed(() => format(parseISO(props.event.date), 'EEEE', { locale: locale.value }))
|
||||||
const daysUntil = computed(() => formatDistanceToNow(parseISO(`${props.event.date}T${time.value}`), {
|
const daysUntil = computed(() => formatDistanceToNow(parseISO(`${props.event.date}T${time.value}`), {
|
||||||
addSuffix: true,
|
addSuffix: true,
|
||||||
locale: locale.value
|
locale: locale.value,
|
||||||
}))
|
}))
|
||||||
</script>
|
</script>
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
<template>
|
||||||
|
<v-row
|
||||||
|
wrap
|
||||||
|
>
|
||||||
|
<v-col xs="12" sm="6">
|
||||||
|
<v-icon class="me-1">
|
||||||
|
mdi-home
|
||||||
|
</v-icon>
|
||||||
|
<span><strong>{{ distance.origin }}</strong></span>
|
||||||
|
</v-col>
|
||||||
|
<v-col xs="12" sm="6">
|
||||||
|
<v-icon class="me-1">
|
||||||
|
mdi-car
|
||||||
|
</v-icon>
|
||||||
|
<span>{{ numericDistance }} km</span>
|
||||||
|
<v-icon class="ms-2 me-1">
|
||||||
|
mdi-clock-outline
|
||||||
|
</v-icon>
|
||||||
|
<span>{{ distance.duration }}</span>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang='ts'>
|
||||||
|
import { computed, type PropType } from 'vue'
|
||||||
|
import { type DanceHallDistance } from '~/graphql/generated/operations'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
distance: {
|
||||||
|
type: Object as PropType<DanceHallDistance>,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
const numericDistance = computed(() =>
|
||||||
|
Number(props.distance.distance / 1000).toLocaleString('sv-SE', {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
}))
|
||||||
|
</script>
|
||||||
@@ -1,34 +1,34 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<v-row v-for="event in events" :key="event.id" wrap>
|
<v-row v-for="event in events" :key="event.id" wrap>
|
||||||
<v-flex xs12>
|
<v-col xs="12">
|
||||||
<event-card
|
<event-card
|
||||||
:event="event"
|
:event="event"
|
||||||
:has-user="hasUser"
|
:has-user="hasUser"
|
||||||
:toggle-ignore="toggleIgnore"
|
:toggle-ignore="toggleIgnore"
|
||||||
/>
|
/>
|
||||||
</v-flex>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang='ts'>
|
<script setup lang='ts'>
|
||||||
import { type PropType } from 'vue'
|
import { type PropType } from 'vue'
|
||||||
import EventCard from '../Event/index.vue'
|
import EventCard from './event-card.vue'
|
||||||
import { type Event } from '~/graphql/generated/operations'
|
import { type Event } from '~/graphql/generated/operations'
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
hasUser: {
|
hasUser: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
toggleIgnore: {
|
toggleIgnore: {
|
||||||
type: Function,
|
type: Function,
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
events: {
|
events: {
|
||||||
type: Array as PropType<Event[]>,
|
type: Array as PropType<Event[]>,
|
||||||
required: true
|
required: true,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
@@ -10,14 +10,15 @@
|
|||||||
<v-col xs="12">
|
<v-col xs="12">
|
||||||
<v-text-field
|
<v-text-field
|
||||||
v-model="origin"
|
v-model="origin"
|
||||||
|
variant="underlined"
|
||||||
:label="$t('origins.origin')"
|
:label="$t('origins.origin')"
|
||||||
:placeholder="$t('origins.geolocation')"
|
:placeholder="$t('origins.geolocation')"
|
||||||
>
|
>
|
||||||
<template #append-outer>
|
<template #append>
|
||||||
<v-tooltip top>
|
<v-tooltip top>
|
||||||
<template #activator="{ on }">
|
<template #activator="{ props }">
|
||||||
<v-icon
|
<v-icon
|
||||||
v-on="on"
|
v-bind="props"
|
||||||
@click="fetchAddressFn()"
|
@click="fetchAddressFn()"
|
||||||
>
|
>
|
||||||
mdi-crosshairs-gps
|
mdi-crosshairs-gps
|
||||||
@@ -28,10 +29,10 @@
|
|||||||
</template>
|
</template>
|
||||||
<template #prepend>
|
<template #prepend>
|
||||||
<v-tooltip v-if="isAuthenticated" top>
|
<v-tooltip v-if="isAuthenticated" top>
|
||||||
<template #activator="{ on }">
|
<template #activator="{ props }">
|
||||||
<v-icon
|
<v-icon
|
||||||
:disabled="!origin"
|
:disabled="!origin"
|
||||||
v-on="on"
|
v-bind="props"
|
||||||
@click="saveOriginFn(origin)"
|
@click="saveOriginFn(origin)"
|
||||||
>
|
>
|
||||||
mdi-bookmark-plus-outline
|
mdi-bookmark-plus-outline
|
||||||
@@ -46,20 +47,20 @@
|
|||||||
<v-row wrap>
|
<v-row wrap>
|
||||||
<v-col>
|
<v-col>
|
||||||
<v-btn-toggle
|
<v-btn-toggle
|
||||||
v-if="$vuetify.breakpoint.smAndUp"
|
v-if="smAndUp"
|
||||||
v-model="state.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" variant="outlined" :value="r.value">
|
||||||
<span v-text="$t(`events.range.${r.value}`)" />
|
<span v-text="$t(`events.range.${r.value}`)" />
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</v-btn-toggle>
|
</v-btn-toggle>
|
||||||
<v-select
|
<v-select
|
||||||
v-else
|
v-else
|
||||||
v-model="state.range"
|
v-model="state.range"
|
||||||
outline
|
variant="outlined"
|
||||||
:items="ranges"
|
:items="ranges"
|
||||||
item-text="name"
|
item-title="name"
|
||||||
item-value="value"
|
item-value="value"
|
||||||
/>
|
/>
|
||||||
</v-col>
|
</v-col>
|
||||||
@@ -68,6 +69,7 @@
|
|||||||
<v-col cols="12" sm="8">
|
<v-col cols="12" sm="8">
|
||||||
<v-text-field
|
<v-text-field
|
||||||
v-model="state.search"
|
v-model="state.search"
|
||||||
|
variant="underlined"
|
||||||
append-outer-icon="mdi-magnify"
|
append-outer-icon="mdi-magnify"
|
||||||
:label="$t('events.filter')"
|
:label="$t('events.filter')"
|
||||||
:placeholder="$t('events.filter')"
|
:placeholder="$t('events.filter')"
|
||||||
@@ -95,11 +97,12 @@
|
|||||||
|
|
||||||
<script setup lang='ts'>
|
<script setup lang='ts'>
|
||||||
import { computed, ref, watch } from 'vue'
|
import { computed, ref, watch } from 'vue'
|
||||||
import EventList from './List/index.vue'
|
import { useAuth0 } from '@auth0/auth0-vue'
|
||||||
import { useAuth } from '~/plugins/auth'
|
import { useDisplay } from 'vuetify'
|
||||||
import { useTranslation } from '~/plugins/i18n'
|
import { useI18n } from '#i18n'
|
||||||
|
import EventList from './event-list.vue'
|
||||||
import {
|
import {
|
||||||
FindEventsQueryVariables,
|
type FindEventsQueryVariables,
|
||||||
useFetchAddressLazyQuery,
|
useFetchAddressLazyQuery,
|
||||||
useFindEventsQuery,
|
useFindEventsQuery,
|
||||||
useSaveOriginMutation,
|
useSaveOriginMutation,
|
||||||
@@ -107,20 +110,21 @@ import {
|
|||||||
useToggleIgnoreCityMutation,
|
useToggleIgnoreCityMutation,
|
||||||
useToggleIgnoreDanceHallMutation,
|
useToggleIgnoreDanceHallMutation,
|
||||||
useToggleIgnoreMunicipalityMutation,
|
useToggleIgnoreMunicipalityMutation,
|
||||||
useToggleIgnoreStateMutation
|
useToggleIgnoreStateMutation,
|
||||||
} from '~/graphql/generated/operations'
|
} from '~/graphql/generated/operations'
|
||||||
import { useState } from '~/store'
|
import { useState } from '~/store'
|
||||||
|
|
||||||
const state = useState()
|
const state = useState()
|
||||||
|
const { smAndUp } = useDisplay()
|
||||||
const range = computed(() => state.range)
|
const range = computed(() => state.range)
|
||||||
const { t } = useTranslation()
|
const { t } = useI18n()
|
||||||
state.setTitle(t('app.links.events'))
|
state.setTitle(t('app.links.events'))
|
||||||
const { isAuthenticated } = useAuth()
|
const { isAuthenticated } = useAuth0()
|
||||||
const variables = ref<FindEventsQueryVariables>({
|
const variables = ref<FindEventsQueryVariables>({
|
||||||
range: state.range,
|
range: state.range,
|
||||||
includeOrigins: isAuthenticated.value || false,
|
includeOrigins: isAuthenticated.value || false,
|
||||||
search: state.search,
|
search: state.search,
|
||||||
includeHidden: state.includeHidden
|
includeHidden: state.includeHidden,
|
||||||
})
|
})
|
||||||
const { result, refetch } = useFindEventsQuery(() => variables.value)
|
const { result, refetch } = useFindEventsQuery(() => variables.value)
|
||||||
watch([state, isAuthenticated], () => {
|
watch([state, isAuthenticated], () => {
|
||||||
@@ -137,7 +141,7 @@ const ranges = [
|
|||||||
{ name: '2 veckor', value: 'TWO_WEEKS' },
|
{ name: '2 veckor', value: 'TWO_WEEKS' },
|
||||||
{ name: '1 månad', value: 'ONE_MONTH' },
|
{ name: '1 månad', value: 'ONE_MONTH' },
|
||||||
{ name: '1 kvartal', value: 'ONE_QUARTER' },
|
{ name: '1 kvartal', value: 'ONE_QUARTER' },
|
||||||
{ name: '1 år', value: 'ONE_YEAR' }
|
{ name: '1 år', value: 'ONE_YEAR' },
|
||||||
]
|
]
|
||||||
const snackbar = ref({ active: false, color: 'success', text: '' })
|
const snackbar = ref({ active: false, color: 'success', text: '' })
|
||||||
|
|
||||||
@@ -151,7 +155,7 @@ const fetchEvents = () => {
|
|||||||
...variables.value,
|
...variables.value,
|
||||||
range: state.range,
|
range: state.range,
|
||||||
origins: originsTemp,
|
origins: originsTemp,
|
||||||
includeOrigins: isAuthenticated.value || false
|
includeOrigins: isAuthenticated.value || false,
|
||||||
}
|
}
|
||||||
refetch(variables.value)
|
refetch(variables.value)
|
||||||
}
|
}
|
||||||
@@ -217,7 +221,7 @@ const fetchAddressFn = () => {
|
|||||||
window.navigator.geolocation.getCurrentPosition((pos) => {
|
window.navigator.geolocation.getCurrentPosition((pos) => {
|
||||||
loadFetchAddress()
|
loadFetchAddress()
|
||||||
doFetchAddress({
|
doFetchAddress({
|
||||||
latlng: `${pos.coords.latitude},${pos.coords.longitude}`
|
latlng: `${pos.coords.latitude},${pos.coords.longitude}`,
|
||||||
})?.then((result) => {
|
})?.then((result) => {
|
||||||
origin.value = result.data.address
|
origin.value = result.data.address
|
||||||
})
|
})
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
<template>
|
|
||||||
<v-card flat outlined class="mx-3 my-3 rounded-xl">
|
|
||||||
<v-card-title>
|
|
||||||
<span v-text="$tc(title, model.length)" />
|
|
||||||
</v-card-title>
|
|
||||||
<v-list>
|
|
||||||
<v-list-item v-for="item in model" :key="item">
|
|
||||||
<v-list-item-action @click="toggleIgnore(type, item)">
|
|
||||||
<v-tooltip top>
|
|
||||||
<template #activator="{ on }">
|
|
||||||
<v-icon v-on="on">
|
|
||||||
mdi-delete-outline
|
|
||||||
</v-icon>
|
|
||||||
</template>
|
|
||||||
<span v-text="$t('filters.remove')" />
|
|
||||||
</v-tooltip>
|
|
||||||
</v-list-item-action>
|
|
||||||
<v-list-item-title><span v-text="item" /></v-list-item-title>
|
|
||||||
</v-list-item>
|
|
||||||
</v-list>
|
|
||||||
</v-card>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang='ts'>
|
|
||||||
defineProps({
|
|
||||||
model: {
|
|
||||||
type: Array,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
title: {
|
|
||||||
type: String,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
type: {
|
|
||||||
type: String,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
toggleIgnore: {
|
|
||||||
type: Function,
|
|
||||||
required: true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
<template>
|
||||||
|
<v-card flat variant="outlined" rounded="xl" class="mx-3 my-3">
|
||||||
|
<v-card-title>
|
||||||
|
<span v-text="$t(title, model.length)" />
|
||||||
|
</v-card-title>
|
||||||
|
<v-list>
|
||||||
|
<v-list-item v-for="item in model" :key="item" :title="item">
|
||||||
|
<template #prepend>
|
||||||
|
<v-list-item-action @click="toggleIgnore(type, item)">
|
||||||
|
<v-tooltip top>
|
||||||
|
<template #activator="{ props }">
|
||||||
|
<v-icon v-bind="props">
|
||||||
|
mdi-delete-outline
|
||||||
|
</v-icon>
|
||||||
|
</template>
|
||||||
|
<span v-text="$t('filters.remove')" />
|
||||||
|
</v-tooltip>
|
||||||
|
</v-list-item-action>
|
||||||
|
</template>
|
||||||
|
</v-list-item>
|
||||||
|
</v-list>
|
||||||
|
</v-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang='ts'>
|
||||||
|
defineProps({
|
||||||
|
model: {
|
||||||
|
type: Array,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
toggleIgnore: {
|
||||||
|
type: Function,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
</script>
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div :key="isAuthenticated">
|
<div :key="isAuthenticated ? 'true' : 'false'">
|
||||||
<v-container fluid grid-list-md class="app-fade-in">
|
<v-container fluid grid-list-md class="app-fade-in">
|
||||||
<v-row wrap>
|
<v-row wrap>
|
||||||
<v-col cols="12">
|
<v-col cols="12">
|
||||||
@@ -62,23 +62,23 @@
|
|||||||
|
|
||||||
<script setup lang='ts'>
|
<script setup lang='ts'>
|
||||||
import { computed, ref } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
import List from './List/index.vue'
|
import { useAuth0 } from '@auth0/auth0-vue'
|
||||||
import { useAuth } from '~/plugins/auth'
|
import { useI18n } from '#i18n'
|
||||||
import { useTranslation } from '~/plugins/i18n'
|
import List from './filter-list.vue'
|
||||||
import {
|
import {
|
||||||
useFetchFiltersQuery,
|
useFetchFiltersQuery,
|
||||||
useToggleIgnoreBandMutation,
|
useToggleIgnoreBandMutation,
|
||||||
useToggleIgnoreCityMutation,
|
useToggleIgnoreCityMutation,
|
||||||
useToggleIgnoreDanceHallMutation,
|
useToggleIgnoreDanceHallMutation,
|
||||||
useToggleIgnoreMunicipalityMutation,
|
useToggleIgnoreMunicipalityMutation,
|
||||||
useToggleIgnoreStateMutation
|
useToggleIgnoreStateMutation,
|
||||||
} from '~/graphql/generated/operations'
|
} from '~/graphql/generated/operations'
|
||||||
import { useState } from '~/store'
|
import { useState } from '~/store'
|
||||||
|
|
||||||
const state = useState()
|
const state = useState()
|
||||||
const { t } = useTranslation()
|
const { t } = useI18n()
|
||||||
state.setTitle(t('app.links.filters'))
|
state.setTitle(t('app.links.filters'))
|
||||||
const { isAuthenticated } = useAuth()
|
const { isAuthenticated } = useAuth0()
|
||||||
const { result, refetch } = useFetchFiltersQuery()
|
const { result, refetch } = useFetchFiltersQuery()
|
||||||
const bands = computed(() => result.value?.bands ?? [])
|
const bands = computed(() => result.value?.bands ?? [])
|
||||||
const cities = computed(() => result.value?.cities ?? [])
|
const cities = computed(() => result.value?.cities ?? [])
|
||||||
@@ -2,17 +2,18 @@
|
|||||||
<div :key="isAuthenticated ? 'true' : 'false'">
|
<div :key="isAuthenticated ? 'true' : 'false'">
|
||||||
<v-container fluid grid-list-md class="app-fade-in">
|
<v-container fluid grid-list-md class="app-fade-in">
|
||||||
<v-layout row wrap>
|
<v-layout row wrap>
|
||||||
<v-flex xs12>
|
<v-col xs="12">
|
||||||
<v-text-field
|
<v-text-field
|
||||||
v-model="origin"
|
v-model="origin"
|
||||||
|
variant="underlined"
|
||||||
:label="$t('origins.origin')"
|
:label="$t('origins.origin')"
|
||||||
:placeholder="$t('origins.geolocation')"
|
:placeholder="$t('origins.geolocation')"
|
||||||
>
|
>
|
||||||
<template #append-outer>
|
<template #append>
|
||||||
<v-tooltip top>
|
<v-tooltip top>
|
||||||
<template #activator="{ on }">
|
<template #activator="{ props }">
|
||||||
<v-icon
|
<v-icon
|
||||||
v-on="on"
|
v-bind="props"
|
||||||
@click="fetchAddressFn()"
|
@click="fetchAddressFn()"
|
||||||
>
|
>
|
||||||
mdi-crosshairs-gps
|
mdi-crosshairs-gps
|
||||||
@@ -23,10 +24,10 @@
|
|||||||
</template>
|
</template>
|
||||||
<template #prepend>
|
<template #prepend>
|
||||||
<v-tooltip top>
|
<v-tooltip top>
|
||||||
<template #activator="{ on }">
|
<template #activator="{ props }">
|
||||||
<v-icon
|
<v-icon
|
||||||
:disabled="!origin"
|
:disabled="!origin"
|
||||||
v-on="on"
|
v-bind="props"
|
||||||
@click="saveOriginFn(origin)"
|
@click="saveOriginFn(origin)"
|
||||||
>
|
>
|
||||||
mdi-bookmark-plus-outline
|
mdi-bookmark-plus-outline
|
||||||
@@ -36,14 +37,14 @@
|
|||||||
</v-tooltip>
|
</v-tooltip>
|
||||||
</template>
|
</template>
|
||||||
</v-text-field>
|
</v-text-field>
|
||||||
</v-flex>
|
</v-col>
|
||||||
</v-layout>
|
</v-layout>
|
||||||
<v-layout v-for="o in origins" :key="o" row wrap>
|
<v-layout v-for="o in origins" :key="o" row wrap>
|
||||||
<v-flex xs12>
|
<v-col xs="12">
|
||||||
<v-tooltip top>
|
<v-tooltip top>
|
||||||
<template #activator="{ on }">
|
<template #activator="{ props }">
|
||||||
<v-icon
|
<v-icon
|
||||||
v-on="on"
|
v-bind="props"
|
||||||
@click="removeOriginFn(o)"
|
@click="removeOriginFn(o)"
|
||||||
>
|
>
|
||||||
mdi-delete-outline
|
mdi-delete-outline
|
||||||
@@ -52,7 +53,7 @@
|
|||||||
<span v-text="$t('origins.remove')" />
|
<span v-text="$t('origins.remove')" />
|
||||||
</v-tooltip>
|
</v-tooltip>
|
||||||
<span>{{ o }}</span>
|
<span>{{ o }}</span>
|
||||||
</v-flex>
|
</v-col>
|
||||||
</v-layout>
|
</v-layout>
|
||||||
</v-container>
|
</v-container>
|
||||||
<v-snackbar
|
<v-snackbar
|
||||||
@@ -67,20 +68,20 @@
|
|||||||
|
|
||||||
<script setup lang='ts'>
|
<script setup lang='ts'>
|
||||||
import { computed, ref } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
import { useAuth } from '~/plugins/auth'
|
import { useAuth0 } from '@auth0/auth0-vue'
|
||||||
import { useTranslation } from '~/plugins/i18n'
|
import { useI18n } from '#i18n'
|
||||||
import {
|
import {
|
||||||
useFetchAddressLazyQuery,
|
useFetchAddressLazyQuery,
|
||||||
useFindOriginsQuery,
|
useFindOriginsQuery,
|
||||||
useRemoveOriginMutation,
|
useRemoveOriginMutation,
|
||||||
useSaveOriginMutation
|
useSaveOriginMutation,
|
||||||
} from '~/graphql/generated/operations'
|
} from '~/graphql/generated/operations'
|
||||||
import { useState } from '~/store'
|
import { useState } from '~/store'
|
||||||
|
|
||||||
const state = useState()
|
const state = useState()
|
||||||
const { t } = useTranslation()
|
const { t } = useI18n()
|
||||||
state.setTitle(t('app.links.origins'))
|
state.setTitle(t('app.links.origins'))
|
||||||
const { isAuthenticated } = useAuth()
|
const { isAuthenticated } = useAuth0()
|
||||||
const { result, refetch } = useFindOriginsQuery()
|
const { result, refetch } = useFindOriginsQuery()
|
||||||
const origins = computed(() => result.value?.origins ?? [])
|
const origins = computed(() => result.value?.origins ?? [])
|
||||||
const snackbar = ref({ active: false, color: 'success', text: '' })
|
const snackbar = ref({ active: false, color: 'success', text: '' })
|
||||||
@@ -93,7 +94,7 @@ const fetchAddressFn = () => {
|
|||||||
window.navigator.geolocation.getCurrentPosition((pos) => {
|
window.navigator.geolocation.getCurrentPosition((pos) => {
|
||||||
load()
|
load()
|
||||||
doFetchAddress({
|
doFetchAddress({
|
||||||
latlng: `${pos.coords.latitude},${pos.coords.longitude}`
|
latlng: `${pos.coords.latitude},${pos.coords.longitude}`,
|
||||||
})?.then((res) => {
|
})?.then((res) => {
|
||||||
origin.value = res.data.address
|
origin.value = res.data.address
|
||||||
})
|
})
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import * as VueApolloComposable from '@vue/apollo-composable'
|
import * as VueApolloComposable from '@vue/apollo-composable'
|
||||||
import * as VueCompositionApi from 'vue'
|
import type * as VueCompositionApi from 'vue'
|
||||||
import { gql } from '@/utils/gql'
|
import { gql } from '@/utils/gql'
|
||||||
export type Maybe<T> = T | null | undefined;
|
export type Maybe<T> = T | null | undefined;
|
||||||
export type InputMaybe<T> = T | null | undefined;
|
export type InputMaybe<T> = T | null | undefined;
|
||||||
@@ -246,7 +246,7 @@ export const RemoveOriginDocument = gql`
|
|||||||
* },
|
* },
|
||||||
* });
|
* });
|
||||||
*/
|
*/
|
||||||
export function useRemoveOriginMutation (options: VueApolloComposable.UseMutationOptions<RemoveOriginMutation, RemoveOriginMutationVariables> | ReactiveFunction<VueApolloComposable.UseMutationOptions<RemoveOriginMutation, RemoveOriginMutationVariables>> = {}) {
|
export function useRemoveOriginMutation(options: VueApolloComposable.UseMutationOptions<RemoveOriginMutation, RemoveOriginMutationVariables> | ReactiveFunction<VueApolloComposable.UseMutationOptions<RemoveOriginMutation, RemoveOriginMutationVariables>> = {}) {
|
||||||
return VueApolloComposable.useMutation<RemoveOriginMutation, RemoveOriginMutationVariables>(RemoveOriginDocument, options)
|
return VueApolloComposable.useMutation<RemoveOriginMutation, RemoveOriginMutationVariables>(RemoveOriginDocument, options)
|
||||||
}
|
}
|
||||||
export type RemoveOriginMutationCompositionFunctionResult = VueApolloComposable.UseMutationReturn<RemoveOriginMutation, RemoveOriginMutationVariables>;
|
export type RemoveOriginMutationCompositionFunctionResult = VueApolloComposable.UseMutationReturn<RemoveOriginMutation, RemoveOriginMutationVariables>;
|
||||||
@@ -273,7 +273,7 @@ export const SaveOriginDocument = gql`
|
|||||||
* },
|
* },
|
||||||
* });
|
* });
|
||||||
*/
|
*/
|
||||||
export function useSaveOriginMutation (options: VueApolloComposable.UseMutationOptions<SaveOriginMutation, SaveOriginMutationVariables> | ReactiveFunction<VueApolloComposable.UseMutationOptions<SaveOriginMutation, SaveOriginMutationVariables>> = {}) {
|
export function useSaveOriginMutation(options: VueApolloComposable.UseMutationOptions<SaveOriginMutation, SaveOriginMutationVariables> | ReactiveFunction<VueApolloComposable.UseMutationOptions<SaveOriginMutation, SaveOriginMutationVariables>> = {}) {
|
||||||
return VueApolloComposable.useMutation<SaveOriginMutation, SaveOriginMutationVariables>(SaveOriginDocument, options)
|
return VueApolloComposable.useMutation<SaveOriginMutation, SaveOriginMutationVariables>(SaveOriginDocument, options)
|
||||||
}
|
}
|
||||||
export type SaveOriginMutationCompositionFunctionResult = VueApolloComposable.UseMutationReturn<SaveOriginMutation, SaveOriginMutationVariables>;
|
export type SaveOriginMutationCompositionFunctionResult = VueApolloComposable.UseMutationReturn<SaveOriginMutation, SaveOriginMutationVariables>;
|
||||||
@@ -300,7 +300,7 @@ export const ToggleIgnoreBandDocument = gql`
|
|||||||
* },
|
* },
|
||||||
* });
|
* });
|
||||||
*/
|
*/
|
||||||
export function useToggleIgnoreBandMutation (options: VueApolloComposable.UseMutationOptions<ToggleIgnoreBandMutation, ToggleIgnoreBandMutationVariables> | ReactiveFunction<VueApolloComposable.UseMutationOptions<ToggleIgnoreBandMutation, ToggleIgnoreBandMutationVariables>> = {}) {
|
export function useToggleIgnoreBandMutation(options: VueApolloComposable.UseMutationOptions<ToggleIgnoreBandMutation, ToggleIgnoreBandMutationVariables> | ReactiveFunction<VueApolloComposable.UseMutationOptions<ToggleIgnoreBandMutation, ToggleIgnoreBandMutationVariables>> = {}) {
|
||||||
return VueApolloComposable.useMutation<ToggleIgnoreBandMutation, ToggleIgnoreBandMutationVariables>(ToggleIgnoreBandDocument, options)
|
return VueApolloComposable.useMutation<ToggleIgnoreBandMutation, ToggleIgnoreBandMutationVariables>(ToggleIgnoreBandDocument, options)
|
||||||
}
|
}
|
||||||
export type ToggleIgnoreBandMutationCompositionFunctionResult = VueApolloComposable.UseMutationReturn<ToggleIgnoreBandMutation, ToggleIgnoreBandMutationVariables>;
|
export type ToggleIgnoreBandMutationCompositionFunctionResult = VueApolloComposable.UseMutationReturn<ToggleIgnoreBandMutation, ToggleIgnoreBandMutationVariables>;
|
||||||
@@ -327,7 +327,7 @@ export const ToggleIgnoreCityDocument = gql`
|
|||||||
* },
|
* },
|
||||||
* });
|
* });
|
||||||
*/
|
*/
|
||||||
export function useToggleIgnoreCityMutation (options: VueApolloComposable.UseMutationOptions<ToggleIgnoreCityMutation, ToggleIgnoreCityMutationVariables> | ReactiveFunction<VueApolloComposable.UseMutationOptions<ToggleIgnoreCityMutation, ToggleIgnoreCityMutationVariables>> = {}) {
|
export function useToggleIgnoreCityMutation(options: VueApolloComposable.UseMutationOptions<ToggleIgnoreCityMutation, ToggleIgnoreCityMutationVariables> | ReactiveFunction<VueApolloComposable.UseMutationOptions<ToggleIgnoreCityMutation, ToggleIgnoreCityMutationVariables>> = {}) {
|
||||||
return VueApolloComposable.useMutation<ToggleIgnoreCityMutation, ToggleIgnoreCityMutationVariables>(ToggleIgnoreCityDocument, options)
|
return VueApolloComposable.useMutation<ToggleIgnoreCityMutation, ToggleIgnoreCityMutationVariables>(ToggleIgnoreCityDocument, options)
|
||||||
}
|
}
|
||||||
export type ToggleIgnoreCityMutationCompositionFunctionResult = VueApolloComposable.UseMutationReturn<ToggleIgnoreCityMutation, ToggleIgnoreCityMutationVariables>;
|
export type ToggleIgnoreCityMutationCompositionFunctionResult = VueApolloComposable.UseMutationReturn<ToggleIgnoreCityMutation, ToggleIgnoreCityMutationVariables>;
|
||||||
@@ -354,7 +354,7 @@ export const ToggleIgnoreDanceHallDocument = gql`
|
|||||||
* },
|
* },
|
||||||
* });
|
* });
|
||||||
*/
|
*/
|
||||||
export function useToggleIgnoreDanceHallMutation (options: VueApolloComposable.UseMutationOptions<ToggleIgnoreDanceHallMutation, ToggleIgnoreDanceHallMutationVariables> | ReactiveFunction<VueApolloComposable.UseMutationOptions<ToggleIgnoreDanceHallMutation, ToggleIgnoreDanceHallMutationVariables>> = {}) {
|
export function useToggleIgnoreDanceHallMutation(options: VueApolloComposable.UseMutationOptions<ToggleIgnoreDanceHallMutation, ToggleIgnoreDanceHallMutationVariables> | ReactiveFunction<VueApolloComposable.UseMutationOptions<ToggleIgnoreDanceHallMutation, ToggleIgnoreDanceHallMutationVariables>> = {}) {
|
||||||
return VueApolloComposable.useMutation<ToggleIgnoreDanceHallMutation, ToggleIgnoreDanceHallMutationVariables>(ToggleIgnoreDanceHallDocument, options)
|
return VueApolloComposable.useMutation<ToggleIgnoreDanceHallMutation, ToggleIgnoreDanceHallMutationVariables>(ToggleIgnoreDanceHallDocument, options)
|
||||||
}
|
}
|
||||||
export type ToggleIgnoreDanceHallMutationCompositionFunctionResult = VueApolloComposable.UseMutationReturn<ToggleIgnoreDanceHallMutation, ToggleIgnoreDanceHallMutationVariables>;
|
export type ToggleIgnoreDanceHallMutationCompositionFunctionResult = VueApolloComposable.UseMutationReturn<ToggleIgnoreDanceHallMutation, ToggleIgnoreDanceHallMutationVariables>;
|
||||||
@@ -381,7 +381,7 @@ export const ToggleIgnoreMunicipalityDocument = gql`
|
|||||||
* },
|
* },
|
||||||
* });
|
* });
|
||||||
*/
|
*/
|
||||||
export function useToggleIgnoreMunicipalityMutation (options: VueApolloComposable.UseMutationOptions<ToggleIgnoreMunicipalityMutation, ToggleIgnoreMunicipalityMutationVariables> | ReactiveFunction<VueApolloComposable.UseMutationOptions<ToggleIgnoreMunicipalityMutation, ToggleIgnoreMunicipalityMutationVariables>> = {}) {
|
export function useToggleIgnoreMunicipalityMutation(options: VueApolloComposable.UseMutationOptions<ToggleIgnoreMunicipalityMutation, ToggleIgnoreMunicipalityMutationVariables> | ReactiveFunction<VueApolloComposable.UseMutationOptions<ToggleIgnoreMunicipalityMutation, ToggleIgnoreMunicipalityMutationVariables>> = {}) {
|
||||||
return VueApolloComposable.useMutation<ToggleIgnoreMunicipalityMutation, ToggleIgnoreMunicipalityMutationVariables>(ToggleIgnoreMunicipalityDocument, options)
|
return VueApolloComposable.useMutation<ToggleIgnoreMunicipalityMutation, ToggleIgnoreMunicipalityMutationVariables>(ToggleIgnoreMunicipalityDocument, options)
|
||||||
}
|
}
|
||||||
export type ToggleIgnoreMunicipalityMutationCompositionFunctionResult = VueApolloComposable.UseMutationReturn<ToggleIgnoreMunicipalityMutation, ToggleIgnoreMunicipalityMutationVariables>;
|
export type ToggleIgnoreMunicipalityMutationCompositionFunctionResult = VueApolloComposable.UseMutationReturn<ToggleIgnoreMunicipalityMutation, ToggleIgnoreMunicipalityMutationVariables>;
|
||||||
@@ -408,7 +408,7 @@ export const ToggleIgnoreStateDocument = gql`
|
|||||||
* },
|
* },
|
||||||
* });
|
* });
|
||||||
*/
|
*/
|
||||||
export function useToggleIgnoreStateMutation (options: VueApolloComposable.UseMutationOptions<ToggleIgnoreStateMutation, ToggleIgnoreStateMutationVariables> | ReactiveFunction<VueApolloComposable.UseMutationOptions<ToggleIgnoreStateMutation, ToggleIgnoreStateMutationVariables>> = {}) {
|
export function useToggleIgnoreStateMutation(options: VueApolloComposable.UseMutationOptions<ToggleIgnoreStateMutation, ToggleIgnoreStateMutationVariables> | ReactiveFunction<VueApolloComposable.UseMutationOptions<ToggleIgnoreStateMutation, ToggleIgnoreStateMutationVariables>> = {}) {
|
||||||
return VueApolloComposable.useMutation<ToggleIgnoreStateMutation, ToggleIgnoreStateMutationVariables>(ToggleIgnoreStateDocument, options)
|
return VueApolloComposable.useMutation<ToggleIgnoreStateMutation, ToggleIgnoreStateMutationVariables>(ToggleIgnoreStateDocument, options)
|
||||||
}
|
}
|
||||||
export type ToggleIgnoreStateMutationCompositionFunctionResult = VueApolloComposable.UseMutationReturn<ToggleIgnoreStateMutation, ToggleIgnoreStateMutationVariables>;
|
export type ToggleIgnoreStateMutationCompositionFunctionResult = VueApolloComposable.UseMutationReturn<ToggleIgnoreStateMutation, ToggleIgnoreStateMutationVariables>;
|
||||||
@@ -433,10 +433,10 @@ export const FetchAddressDocument = gql`
|
|||||||
* latlng: // value for 'latlng'
|
* latlng: // value for 'latlng'
|
||||||
* });
|
* });
|
||||||
*/
|
*/
|
||||||
export function useFetchAddressQuery (variables: FetchAddressQueryVariables | VueCompositionApi.Ref<FetchAddressQueryVariables> | ReactiveFunction<FetchAddressQueryVariables>, options: VueApolloComposable.UseQueryOptions<FetchAddressQuery, FetchAddressQueryVariables> | VueCompositionApi.Ref<VueApolloComposable.UseQueryOptions<FetchAddressQuery, FetchAddressQueryVariables>> | ReactiveFunction<VueApolloComposable.UseQueryOptions<FetchAddressQuery, FetchAddressQueryVariables>> = {}) {
|
export function useFetchAddressQuery(variables: FetchAddressQueryVariables | VueCompositionApi.Ref<FetchAddressQueryVariables> | ReactiveFunction<FetchAddressQueryVariables>, options: VueApolloComposable.UseQueryOptions<FetchAddressQuery, FetchAddressQueryVariables> | VueCompositionApi.Ref<VueApolloComposable.UseQueryOptions<FetchAddressQuery, FetchAddressQueryVariables>> | ReactiveFunction<VueApolloComposable.UseQueryOptions<FetchAddressQuery, FetchAddressQueryVariables>> = {}) {
|
||||||
return VueApolloComposable.useQuery<FetchAddressQuery, FetchAddressQueryVariables>(FetchAddressDocument, variables, options)
|
return VueApolloComposable.useQuery<FetchAddressQuery, FetchAddressQueryVariables>(FetchAddressDocument, variables, options)
|
||||||
}
|
}
|
||||||
export function useFetchAddressLazyQuery (variables: FetchAddressQueryVariables | VueCompositionApi.Ref<FetchAddressQueryVariables> | ReactiveFunction<FetchAddressQueryVariables>, options: VueApolloComposable.UseQueryOptions<FetchAddressQuery, FetchAddressQueryVariables> | VueCompositionApi.Ref<VueApolloComposable.UseQueryOptions<FetchAddressQuery, FetchAddressQueryVariables>> | ReactiveFunction<VueApolloComposable.UseQueryOptions<FetchAddressQuery, FetchAddressQueryVariables>> = {}) {
|
export function useFetchAddressLazyQuery(variables?: FetchAddressQueryVariables | VueCompositionApi.Ref<FetchAddressQueryVariables> | ReactiveFunction<FetchAddressQueryVariables>, options: VueApolloComposable.UseQueryOptions<FetchAddressQuery, FetchAddressQueryVariables> | VueCompositionApi.Ref<VueApolloComposable.UseQueryOptions<FetchAddressQuery, FetchAddressQueryVariables>> | ReactiveFunction<VueApolloComposable.UseQueryOptions<FetchAddressQuery, FetchAddressQueryVariables>> = {}) {
|
||||||
return VueApolloComposable.useLazyQuery<FetchAddressQuery, FetchAddressQueryVariables>(FetchAddressDocument, variables, options)
|
return VueApolloComposable.useLazyQuery<FetchAddressQuery, FetchAddressQueryVariables>(FetchAddressDocument, variables, options)
|
||||||
}
|
}
|
||||||
export type FetchAddressQueryCompositionFunctionResult = VueApolloComposable.UseQueryReturn<FetchAddressQuery, FetchAddressQueryVariables>;
|
export type FetchAddressQueryCompositionFunctionResult = VueApolloComposable.UseQueryReturn<FetchAddressQuery, FetchAddressQueryVariables>;
|
||||||
@@ -462,10 +462,10 @@ export const FetchFiltersDocument = gql`
|
|||||||
* @example
|
* @example
|
||||||
* const { result, loading, error } = useFetchFiltersQuery();
|
* const { result, loading, error } = useFetchFiltersQuery();
|
||||||
*/
|
*/
|
||||||
export function useFetchFiltersQuery (options: VueApolloComposable.UseQueryOptions<FetchFiltersQuery, FetchFiltersQueryVariables> | VueCompositionApi.Ref<VueApolloComposable.UseQueryOptions<FetchFiltersQuery, FetchFiltersQueryVariables>> | ReactiveFunction<VueApolloComposable.UseQueryOptions<FetchFiltersQuery, FetchFiltersQueryVariables>> = {}) {
|
export function useFetchFiltersQuery(options: VueApolloComposable.UseQueryOptions<FetchFiltersQuery, FetchFiltersQueryVariables> | VueCompositionApi.Ref<VueApolloComposable.UseQueryOptions<FetchFiltersQuery, FetchFiltersQueryVariables>> | ReactiveFunction<VueApolloComposable.UseQueryOptions<FetchFiltersQuery, FetchFiltersQueryVariables>> = {}) {
|
||||||
return VueApolloComposable.useQuery<FetchFiltersQuery, FetchFiltersQueryVariables>(FetchFiltersDocument, {}, options)
|
return VueApolloComposable.useQuery<FetchFiltersQuery, FetchFiltersQueryVariables>(FetchFiltersDocument, {}, options)
|
||||||
}
|
}
|
||||||
export function useFetchFiltersLazyQuery (options: VueApolloComposable.UseQueryOptions<FetchFiltersQuery, FetchFiltersQueryVariables> | VueCompositionApi.Ref<VueApolloComposable.UseQueryOptions<FetchFiltersQuery, FetchFiltersQueryVariables>> | ReactiveFunction<VueApolloComposable.UseQueryOptions<FetchFiltersQuery, FetchFiltersQueryVariables>> = {}) {
|
export function useFetchFiltersLazyQuery(options: VueApolloComposable.UseQueryOptions<FetchFiltersQuery, FetchFiltersQueryVariables> | VueCompositionApi.Ref<VueApolloComposable.UseQueryOptions<FetchFiltersQuery, FetchFiltersQueryVariables>> | ReactiveFunction<VueApolloComposable.UseQueryOptions<FetchFiltersQuery, FetchFiltersQueryVariables>> = {}) {
|
||||||
return VueApolloComposable.useLazyQuery<FetchFiltersQuery, FetchFiltersQueryVariables>(FetchFiltersDocument, {}, options)
|
return VueApolloComposable.useLazyQuery<FetchFiltersQuery, FetchFiltersQueryVariables>(FetchFiltersDocument, {}, options)
|
||||||
}
|
}
|
||||||
export type FetchFiltersQueryCompositionFunctionResult = VueApolloComposable.UseQueryReturn<FetchFiltersQuery, FetchFiltersQueryVariables>;
|
export type FetchFiltersQueryCompositionFunctionResult = VueApolloComposable.UseQueryReturn<FetchFiltersQuery, FetchFiltersQueryVariables>;
|
||||||
@@ -518,10 +518,10 @@ export const FindEventsDocument = gql`
|
|||||||
* includeHidden: // value for 'includeHidden'
|
* 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>> = {}) {
|
||||||
return VueApolloComposable.useQuery<FindEventsQuery, FindEventsQueryVariables>(FindEventsDocument, variables, options)
|
return VueApolloComposable.useQuery<FindEventsQuery, FindEventsQueryVariables>(FindEventsDocument, variables, options)
|
||||||
}
|
}
|
||||||
export function useFindEventsLazyQuery (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 useFindEventsLazyQuery(variables?: FindEventsQueryVariables | VueCompositionApi.Ref<FindEventsQueryVariables> | ReactiveFunction<FindEventsQueryVariables>, options: VueApolloComposable.UseQueryOptions<FindEventsQuery, FindEventsQueryVariables> | VueCompositionApi.Ref<VueApolloComposable.UseQueryOptions<FindEventsQuery, FindEventsQueryVariables>> | ReactiveFunction<VueApolloComposable.UseQueryOptions<FindEventsQuery, FindEventsQueryVariables>> = {}) {
|
||||||
return VueApolloComposable.useLazyQuery<FindEventsQuery, FindEventsQueryVariables>(FindEventsDocument, variables, options)
|
return VueApolloComposable.useLazyQuery<FindEventsQuery, FindEventsQueryVariables>(FindEventsDocument, variables, options)
|
||||||
}
|
}
|
||||||
export type FindEventsQueryCompositionFunctionResult = VueApolloComposable.UseQueryReturn<FindEventsQuery, FindEventsQueryVariables>;
|
export type FindEventsQueryCompositionFunctionResult = VueApolloComposable.UseQueryReturn<FindEventsQuery, FindEventsQueryVariables>;
|
||||||
@@ -543,10 +543,10 @@ export const FindOriginsDocument = gql`
|
|||||||
* @example
|
* @example
|
||||||
* const { result, loading, error } = useFindOriginsQuery();
|
* const { result, loading, error } = useFindOriginsQuery();
|
||||||
*/
|
*/
|
||||||
export function useFindOriginsQuery (options: VueApolloComposable.UseQueryOptions<FindOriginsQuery, FindOriginsQueryVariables> | VueCompositionApi.Ref<VueApolloComposable.UseQueryOptions<FindOriginsQuery, FindOriginsQueryVariables>> | ReactiveFunction<VueApolloComposable.UseQueryOptions<FindOriginsQuery, FindOriginsQueryVariables>> = {}) {
|
export function useFindOriginsQuery(options: VueApolloComposable.UseQueryOptions<FindOriginsQuery, FindOriginsQueryVariables> | VueCompositionApi.Ref<VueApolloComposable.UseQueryOptions<FindOriginsQuery, FindOriginsQueryVariables>> | ReactiveFunction<VueApolloComposable.UseQueryOptions<FindOriginsQuery, FindOriginsQueryVariables>> = {}) {
|
||||||
return VueApolloComposable.useQuery<FindOriginsQuery, FindOriginsQueryVariables>(FindOriginsDocument, {}, options)
|
return VueApolloComposable.useQuery<FindOriginsQuery, FindOriginsQueryVariables>(FindOriginsDocument, {}, options)
|
||||||
}
|
}
|
||||||
export function useFindOriginsLazyQuery (options: VueApolloComposable.UseQueryOptions<FindOriginsQuery, FindOriginsQueryVariables> | VueCompositionApi.Ref<VueApolloComposable.UseQueryOptions<FindOriginsQuery, FindOriginsQueryVariables>> | ReactiveFunction<VueApolloComposable.UseQueryOptions<FindOriginsQuery, FindOriginsQueryVariables>> = {}) {
|
export function useFindOriginsLazyQuery(options: VueApolloComposable.UseQueryOptions<FindOriginsQuery, FindOriginsQueryVariables> | VueCompositionApi.Ref<VueApolloComposable.UseQueryOptions<FindOriginsQuery, FindOriginsQueryVariables>> | ReactiveFunction<VueApolloComposable.UseQueryOptions<FindOriginsQuery, FindOriginsQueryVariables>> = {}) {
|
||||||
return VueApolloComposable.useLazyQuery<FindOriginsQuery, FindOriginsQueryVariables>(FindOriginsDocument, {}, options)
|
return VueApolloComposable.useLazyQuery<FindOriginsQuery, FindOriginsQueryVariables>(FindOriginsDocument, {}, options)
|
||||||
}
|
}
|
||||||
export type FindOriginsQueryCompositionFunctionResult = VueApolloComposable.UseQueryReturn<FindOriginsQuery, FindOriginsQueryVariables>;
|
export type FindOriginsQueryCompositionFunctionResult = VueApolloComposable.UseQueryReturn<FindOriginsQuery, FindOriginsQueryVariables>;
|
||||||
@@ -557,6 +557,6 @@ export interface PossibleTypesResultData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const result: PossibleTypesResultData = {
|
const result: PossibleTypesResultData = {
|
||||||
possibleTypes: {}
|
possibleTypes: {},
|
||||||
}
|
}
|
||||||
export default result
|
export default result
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import { defineI18nConfig } from '#i18n'
|
||||||
|
|
||||||
|
export default defineI18nConfig(() => ({
|
||||||
|
legacy: false,
|
||||||
|
fallbackLocale: 'sv',
|
||||||
|
}))
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div>
|
|
||||||
<slot />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang='ts'>
|
|
||||||
import { getCurrentInstance } from 'vue'
|
|
||||||
import { useState } from '~/store'
|
|
||||||
|
|
||||||
const instance = getCurrentInstance()
|
|
||||||
const state = useState()
|
|
||||||
if (instance) {
|
|
||||||
instance.proxy.$vuetify.theme.dark = state.darkMode
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,140 +1,91 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-app :key="$i18n.locale + isAuthenticated">
|
<v-app :key="$i18n.locale + isAuthenticated">
|
||||||
<themed>
|
|
||||||
<v-navigation-drawer v-model="nav" temporary app>
|
<v-navigation-drawer v-model="nav" temporary app>
|
||||||
<v-list dense>
|
<v-list dense>
|
||||||
|
<v-list-item v-if="!user" link :title="$t('app.login')" @click="doLogin" />
|
||||||
|
<v-list-item v-if="isAuthenticated && user" :title="user.name" :prepend-avatar="user.picture" />
|
||||||
<v-list-item>
|
<v-list-item>
|
||||||
<v-list-item-action>
|
<v-switch v-model="darkMode" color="primary" :label="$t('app.darkMode')" hide-details class="ms-1" />
|
||||||
<v-switch v-model="darkMode" />
|
|
||||||
</v-list-item-action>
|
|
||||||
<v-list-item-title>{{ $t('app.darkMode') }}</v-list-item-title>
|
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
<v-list-item @click="locale = 'en'">
|
<v-list-item title="In English" :to="switchLocalePath('en')">
|
||||||
<v-list-item-title>In English 🇬🇧</v-list-item-title>
|
<template #prepend>
|
||||||
|
<div class="d-flex d-inline-flex text-h5 me-8">
|
||||||
|
🇬🇧
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
<v-list-item @click="locale = 'sv'">
|
<v-list-item title="På Svenska" :to="switchLocalePath('sv')">
|
||||||
<v-list-item-title>På Svenska 🇸🇪</v-list-item-title>
|
<template #prepend>
|
||||||
</v-list-item>
|
<div class="d-flex d-inline-flex text-h5 me-8">
|
||||||
<v-list-item v-if="!user" link @click="doLogin">
|
🇸🇪
|
||||||
<v-list-item-title>{{ $t('app.login') }}</v-list-item-title>
|
</div>
|
||||||
</v-list-item>
|
</template>
|
||||||
<v-list-item v-if="isAuthenticated && user">
|
|
||||||
<v-list-item-avatar>
|
|
||||||
<v-img :src="user.picture" :alt="user.name" />
|
|
||||||
</v-list-item-avatar>
|
|
||||||
<v-list-item-content>
|
|
||||||
<v-list-item-title><span v-text="user.name" /></v-list-item-title>
|
|
||||||
</v-list-item-content>
|
|
||||||
</v-list-item>
|
|
||||||
<v-list-item link to="/">
|
|
||||||
<v-list-item-action>
|
|
||||||
<v-icon>mdi-calendar-outline</v-icon>
|
|
||||||
</v-list-item-action>
|
|
||||||
<v-list-item-title>{{ $t('app.links.events') }}</v-list-item-title>
|
|
||||||
</v-list-item>
|
|
||||||
<v-list-item v-if="isAuthenticated" link to="/origins/">
|
|
||||||
<v-list-item-action>
|
|
||||||
<v-icon>mdi-home</v-icon>
|
|
||||||
</v-list-item-action>
|
|
||||||
<v-list-item-title>{{ $t('app.links.origins') }}</v-list-item-title>
|
|
||||||
</v-list-item>
|
|
||||||
<v-list-item v-if="isAuthenticated" link to="/filters/">
|
|
||||||
<v-list-item-action>
|
|
||||||
<v-icon>mdi-magnify</v-icon>
|
|
||||||
</v-list-item-action>
|
|
||||||
<v-list-item-title>{{ $t('app.links.filters') }}</v-list-item-title>
|
|
||||||
</v-list-item>
|
|
||||||
<v-list-item v-if="isAuthenticated" link>
|
|
||||||
<v-list-item-action>
|
|
||||||
<v-icon>exit_to_app</v-icon>
|
|
||||||
</v-list-item-action>
|
|
||||||
<v-list-item-content @click="doLogout">
|
|
||||||
<v-list-item-title>{{ $t('app.logout') }}</v-list-item-title>
|
|
||||||
</v-list-item-content>
|
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
|
<v-list-item to="/" :title="$t('app.links.events')" prepend-icon="mdi-calendar-outline" />
|
||||||
|
<v-list-item v-if="isAuthenticated" to="/origins/" :title="$t('app.links.origins')" prepend-icon="mdi-home" />
|
||||||
|
<v-list-item v-if="isAuthenticated" to="/filters/" :title="$t('app.links.filters')" prepend-icon="mdi-magnify" />
|
||||||
|
<v-list-item v-if="isAuthenticated" link :title="$t('app.logout')" prepend-icon="mdi-exit-to-app" @click="doLogout" />
|
||||||
</v-list>
|
</v-list>
|
||||||
</v-navigation-drawer>
|
</v-navigation-drawer>
|
||||||
<v-app-bar app scroll-off-screen>
|
<v-app-bar app scroll-off-screen>
|
||||||
<v-app-bar-nav-icon @click="nav = !nav" />
|
<v-app-bar-nav-icon @click="nav = !nav" />
|
||||||
<v-toolbar-title><span v-text="title" /></v-toolbar-title>
|
<v-toolbar-title :title="title" />
|
||||||
<v-spacer />
|
<v-spacer />
|
||||||
<v-toolbar-items>
|
<v-toolbar-items>
|
||||||
<v-list-item v-if="isAuthenticated && user">
|
<v-list-item v-if="isAuthenticated && user" :prepend-avatar="user.picture" :title="user.name" />
|
||||||
<v-list-item-avatar>
|
|
||||||
<v-img :src="user.picture" :alt="user.name" />
|
|
||||||
</v-list-item-avatar>
|
|
||||||
<v-list-item-content>
|
|
||||||
<v-list-item-title><span v-text="user.name" /></v-list-item-title>
|
|
||||||
</v-list-item-content>
|
|
||||||
</v-list-item>
|
|
||||||
</v-toolbar-items>
|
</v-toolbar-items>
|
||||||
</v-app-bar>
|
</v-app-bar>
|
||||||
<v-main>
|
<v-main>
|
||||||
<v-container v-if="!loading" fluid>
|
<v-container v-if="!isLoading" fluid>
|
||||||
<nuxt />
|
<slot />
|
||||||
</v-container>
|
</v-container>
|
||||||
</v-main>
|
</v-main>
|
||||||
</themed>
|
|
||||||
</v-app>
|
</v-app>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang='ts'>
|
<script setup lang='ts'>
|
||||||
|
import { computed, onMounted, ref } from 'vue'
|
||||||
import { computed, getCurrentInstance, provide, ref } from 'vue'
|
import { useTheme } from 'vuetify'
|
||||||
import { DefaultApolloClient } from '@vue/apollo-composable'
|
import { useAuth0 } from '@auth0/auth0-vue'
|
||||||
import Themed from './components/themed.vue'
|
import { useSwitchLocalePath } from '#i18n'
|
||||||
import { useAuth } from '~/plugins/auth'
|
|
||||||
import { useState } from '~/store'
|
import { useState } from '~/store'
|
||||||
|
|
||||||
const instance = getCurrentInstance()
|
const switchLocalePath = useSwitchLocalePath()
|
||||||
if (instance) {
|
|
||||||
provide(DefaultApolloClient, instance.proxy.$apollo)
|
|
||||||
}
|
|
||||||
const state = useState()
|
const state = useState()
|
||||||
const router = useRouter()
|
const { isLoading, isAuthenticated, user, loginWithRedirect, logout } =
|
||||||
const onRedirectCallback = (appState) => {
|
useAuth0()
|
||||||
router.push(
|
|
||||||
appState && appState.targetUrl
|
|
||||||
? appState.targetUrl
|
|
||||||
: window.location.pathname
|
|
||||||
)
|
|
||||||
}
|
|
||||||
const { loading, isAuthenticated, user, loginWithRedirect, logout } =
|
|
||||||
useAuth(onRedirectCallback)
|
|
||||||
const doLogin = () => {
|
const doLogin = () => {
|
||||||
loginWithRedirect({
|
loginWithRedirect({
|
||||||
appState: { targetUrl: window.location.pathname }
|
appState: { targetUrl: window.location.pathname },
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const doLogout = () => {
|
const doLogout = () => {
|
||||||
logout({
|
logout({
|
||||||
logoutParams: {
|
logoutParams: {
|
||||||
returnTo: window.location.origin
|
returnTo: window.location.origin,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const darkMode = computed({
|
const theme = useTheme()
|
||||||
get: () => (instance ? instance.proxy.$vuetify.theme.dark : false),
|
onMounted(() => {
|
||||||
set: (val) => {
|
if (state.darkMode) {
|
||||||
if (instance) {
|
theme.global.name.value = 'dark'
|
||||||
instance.proxy.$vuetify.theme.dark = val
|
} else {
|
||||||
state.setDarkMode(instance.proxy.$vuetify.theme.dark)
|
theme.global.name.value = 'light'
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const locale = computed({
|
const darkMode = computed<boolean>({
|
||||||
get: () => (instance ? instance.proxy.$i18n.locale : 'sv'),
|
get: () => theme.global.current.value.dark,
|
||||||
set: (newLocale) => {
|
set: (value: boolean) => {
|
||||||
if (instance) {
|
state.setDarkMode(value)
|
||||||
instance.proxy.$i18n.setLocaleCookie(newLocale)
|
if (value) {
|
||||||
instance.proxy.$vuetify.lang.current = newLocale
|
theme.global.name.value = 'dark'
|
||||||
instance.proxy.$i18n.locale = newLocale
|
} else {
|
||||||
}
|
theme.global.name.value = 'light'
|
||||||
state.setLocale(newLocale)
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const nav = ref(false)
|
const nav = ref(false)
|
||||||
locale.value = instance.proxy.$i18n.locale
|
|
||||||
const title = computed(() => state.title)
|
const title = computed(() => state.title)
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
import { useAuth } from '~/plugins/auth'
|
|
||||||
|
|
||||||
export default ({ app: { router } }) => {
|
|
||||||
const onRedirectCallback = (appState) => {
|
|
||||||
router.push(
|
|
||||||
appState && appState.targetUrl
|
|
||||||
? appState.targetUrl
|
|
||||||
: window.location.pathname
|
|
||||||
)
|
|
||||||
}
|
|
||||||
useAuth(onRedirectCallback)
|
|
||||||
}
|
|
||||||
@@ -1,151 +1,61 @@
|
|||||||
import { defineNuxtConfig } from '@nuxt/bridge'
|
import vuetify, { transformAssetUrls } from 'vite-plugin-vuetify'
|
||||||
import translations from './translations'
|
import { defineNuxtConfig } from 'nuxt/config'
|
||||||
import numberFormats from './translations/numberFormats'
|
|
||||||
|
|
||||||
export default defineNuxtConfig({
|
export default defineNuxtConfig({
|
||||||
alias: {
|
|
||||||
tslib: 'tslib/tslib.es6.js'
|
|
||||||
},
|
|
||||||
bridge: {
|
|
||||||
meta: true
|
|
||||||
},
|
|
||||||
build: {
|
build: {
|
||||||
extend (config) {
|
transpile: ['vuetify', 'date-fns'],
|
||||||
config.module.rules.push({
|
|
||||||
include: /node_modules/,
|
|
||||||
test: /\.mjs$/,
|
|
||||||
type: 'javascript/auto'
|
|
||||||
})
|
|
||||||
},
|
|
||||||
babel: {
|
|
||||||
presets ({ isServer }) {
|
|
||||||
return [
|
|
||||||
[
|
|
||||||
// require.resolve('@nuxt/babel-preset-app'),
|
|
||||||
require.resolve('@nuxt/babel-preset-app-edge'), // For nuxt-edge users
|
|
||||||
{
|
|
||||||
buildTarget: isServer ? 'server' : 'client',
|
|
||||||
corejs: { version: 3 }
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
loaders: {
|
|
||||||
vue: {
|
|
||||||
prettify: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
transpile: ['date-fns', '@unhead/vue', 'unhead']
|
|
||||||
},
|
|
||||||
buildModules: [
|
|
||||||
// https://go.nuxtjs.dev/eslint
|
|
||||||
['@nuxtjs/eslint-module', { exclude: ['graphql/generated', 'node_modules'] }],
|
|
||||||
// https://go.nuxtjs.dev/stylelint
|
|
||||||
'@nuxtjs/stylelint-module',
|
|
||||||
// https://go.nuxtjs.dev/vuetify
|
|
||||||
'@nuxtjs/vuetify'
|
|
||||||
],
|
|
||||||
css: ['vuetify/dist/vuetify.css', '~/assets/scss/global.scss'],
|
|
||||||
env: {
|
|
||||||
graphqlApi: process.env.GRAPHQL_API
|
|
||||||
},
|
|
||||||
head: {
|
|
||||||
link: [
|
|
||||||
{
|
|
||||||
rel: 'apple-touch-icon',
|
|
||||||
sizes: '180x180',
|
|
||||||
href: '/apple-touch-icon.png'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
rel: 'icon',
|
|
||||||
type: 'image/png',
|
|
||||||
sizes: '32x32',
|
|
||||||
href: '/favicon-32x32.png'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
rel: 'icon',
|
|
||||||
type: 'image/png',
|
|
||||||
sizes: '16x16',
|
|
||||||
href: '/favicon-16x16.png'
|
|
||||||
},
|
|
||||||
{ rel: 'manifest', href: '/site.webmanifest' },
|
|
||||||
{ rel: 'mask-icon', href: '/safari-pinned-tab.svg', color: '#7f0aff' },
|
|
||||||
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' },
|
|
||||||
{
|
|
||||||
rel: 'stylesheet',
|
|
||||||
href: 'https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
rel: 'stylesheet',
|
|
||||||
href: 'https://fonts.googleapis.com/css?family=Material+Icons'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
rel: 'stylesheet',
|
|
||||||
href: 'https://cdn.materialdesignicons.com/3.3.92/css/materialdesignicons.min.css'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
meta: [
|
|
||||||
{
|
|
||||||
name: 'viewport',
|
|
||||||
content:
|
|
||||||
'width=device-width, initial-scale=1, user-scalable=no, minimal-ui'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
|
devtools: { enabled: true },
|
||||||
i18n: {
|
i18n: {
|
||||||
strategy: 'prefix_and_default',
|
|
||||||
detectBrowserLanguage: {
|
detectBrowserLanguage: {
|
||||||
useCookie: true,
|
useCookie: true,
|
||||||
cookieKey: 'nuxt_i18n_redirected',
|
cookieKey: 'nuxt_i18n_redirected',
|
||||||
|
redirectOn: 'root', // recommended
|
||||||
alwaysRedirect: true,
|
alwaysRedirect: true,
|
||||||
fallbackLocale: 'sv'
|
fallbackLocale: 'sv',
|
||||||
},
|
},
|
||||||
|
langDir: 'translations',
|
||||||
|
lazy: true,
|
||||||
locales: [
|
locales: [
|
||||||
{
|
{ code: 'sv', name: 'Svenska', file: 'sv.ts' },
|
||||||
code: 'en',
|
{ code: 'en', name: 'English', file: 'en.ts' },
|
||||||
iso: 'en-US'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: 'sv',
|
|
||||||
iso: 'sv-SE'
|
|
||||||
}
|
|
||||||
],
|
],
|
||||||
defaultLocale: 'sv',
|
defaultLocale: 'sv',
|
||||||
vueI18n: {
|
vueI18n: './i18n.config.ts', // if you are using custom path, default
|
||||||
fallbackLocale: 'sv',
|
|
||||||
messages: translations,
|
|
||||||
numberFormats
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
modules: [
|
modules: [
|
||||||
'@nuxtjs/i18n',
|
(_options, nuxt) => {
|
||||||
'@pinia/nuxt',
|
nuxt.hooks.hook('vite:extendConfig', (config) => {
|
||||||
'@nuxtjs/sentry'
|
// @ts-expect-error
|
||||||
],
|
config.plugins.push(
|
||||||
plugins: [
|
vuetify({
|
||||||
'~/plugins/apollo',
|
autoImport: true,
|
||||||
'~/plugins/i18n',
|
// styles: { configFile: "assets/settings.scss" },
|
||||||
'~/plugins/pinia'
|
}),
|
||||||
],
|
)
|
||||||
router: {
|
})
|
||||||
middleware: ['auth']
|
|
||||||
},
|
},
|
||||||
sentry: {
|
'@nuxtjs/eslint-module',
|
||||||
dsn: 'https://da2e8d42185a4013909d49955432a116@o365290.ingest.sentry.io/5187660',
|
'@pinia/nuxt',
|
||||||
config: {
|
'@pinia-plugin-persistedstate/nuxt',
|
||||||
tracing: {
|
'@nuxtjs/i18n',
|
||||||
tracesSampleRate: 1.0,
|
'@nuxt/devtools',
|
||||||
browserTracing: {},
|
],
|
||||||
vueOptions: {
|
piniaPersistedstate: {
|
||||||
trackComponents: true
|
cookieOptions: {
|
||||||
}
|
sameSite: 'strict',
|
||||||
}
|
},
|
||||||
} // Additional config
|
storage: 'localStorage',
|
||||||
},
|
},
|
||||||
ssr: false,
|
ssr: false,
|
||||||
target: 'static',
|
vite: {
|
||||||
vuetify: {
|
resolve: {
|
||||||
optionsPath: './vuetify.options.js'
|
dedupe: ['pinia'],
|
||||||
}
|
},
|
||||||
|
vue: {
|
||||||
|
template: {
|
||||||
|
transformAssetUrls,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -7,76 +7,67 @@
|
|||||||
"author": "Joakim Olsson <joakim@unbound.se>",
|
"author": "Joakim Olsson <joakim@unbound.se>",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "nuxi dev",
|
"build": "nuxt build",
|
||||||
"build": "nuxi generate",
|
"dev": "nuxt dev",
|
||||||
"start": "nuxi preview",
|
"generate": "nuxt generate",
|
||||||
|
"preview": "nuxt preview",
|
||||||
|
"postinstall": "nuxt prepare",
|
||||||
"lint:js": "eslint --ext \".ts,.js,.cjs,.vue\" --ignore-path .gitignore .",
|
"lint:js": "eslint --ext \".ts,.js,.cjs,.vue\" --ignore-path .gitignore .",
|
||||||
"lint:style": "stylelint \"**/*.{css,scss,sass,html,vue}\" --ignore-path .gitignore",
|
"lint:style": "stylelint \"**/*.{css,scss,sass,html,vue}\" --ignore-path .gitignore",
|
||||||
"lint": "yarn lint:js && yarn lint:style",
|
"lint": "yarn lint:js && yarn lint:style",
|
||||||
"lintfix": "yarn lint:js --fix && yarn lint:style --fix",
|
"lintfix": "yarn lint:js --fix && yarn lint:style --fix",
|
||||||
"prepare": "husky install",
|
|
||||||
"test": "jest",
|
|
||||||
"codegen": "graphql-codegen && eslint --ext \".ts\" --ignore-path .gitignore graphql/generated/operations.ts --fix"
|
"codegen": "graphql-codegen && eslint --ext \".ts\" --ignore-path .gitignore graphql/generated/operations.ts --fix"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"devDependencies": {
|
||||||
"@apollo/client": "^3.9.2",
|
"@commitlint/cli": "^18.6.0",
|
||||||
"@auth0/auth0-spa-js": "^2.1.3",
|
"@commitlint/config-conventional": "^18.6.0",
|
||||||
|
"@graphql-codegen/cli": "^5.0.0",
|
||||||
|
"@graphql-codegen/fragment-matcher": "^5.0.0",
|
||||||
"@graphql-codegen/typescript": "^4.0.1",
|
"@graphql-codegen/typescript": "^4.0.1",
|
||||||
"@graphql-codegen/typescript-operations": "^4.0.1",
|
"@graphql-codegen/typescript-operations": "^4.0.1",
|
||||||
"@graphql-codegen/typescript-vue-apollo": "^4.1.0",
|
"@graphql-codegen/typescript-vue-apollo": "^4.1.0",
|
||||||
"@nuxtjs/i18n": "^7.3.1",
|
"@nuxt/devtools": "^1.0.8",
|
||||||
"@nuxtjs/sentry": "^8.0.6",
|
"@nuxtjs/eslint-config-typescript": "^12.1.0",
|
||||||
"@nuxtjs/vuetify": "^1.12.3",
|
"@nuxtjs/eslint-module": "^4.1.0",
|
||||||
|
"@nuxtjs/i18n": "^8.0.1",
|
||||||
|
"@pinia-plugin-persistedstate/nuxt": "^1.2.0",
|
||||||
|
"@types/vuelidate": "^0.7.21",
|
||||||
|
"@typescript-eslint/parser": "^6.20.0",
|
||||||
|
"@vue/test-utils": "^2.4.4",
|
||||||
|
"esbuild": "^0.20.0",
|
||||||
|
"eslint": "^8.56.0",
|
||||||
|
"eslint-plugin-nuxt": "^4.0.0",
|
||||||
|
"eslint-plugin-vue": "^9.21.1",
|
||||||
|
"nuxt": "^3.10.0",
|
||||||
|
"postcss-html": "^1.6.0",
|
||||||
|
"sass": "^1.70.0",
|
||||||
|
"stylelint": "^16.2.1",
|
||||||
|
"stylelint-config-recommended-vue": "^1.5.0",
|
||||||
|
"stylelint-config-standard": "^36.0.0",
|
||||||
|
"typescript": "^5.3.3",
|
||||||
|
"vite-plugin-vuetify": "^2.0.1",
|
||||||
|
"vue": "^3.4.15",
|
||||||
|
"vue-router": "^4.2.5",
|
||||||
|
"vuetify": "^3.5.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@apollo/client": "^3.9.2",
|
||||||
|
"@auth0/auth0-vue": "^2.3.3",
|
||||||
|
"@mdi/font": "^7.4.47",
|
||||||
"@pinia/nuxt": "^0.5.1",
|
"@pinia/nuxt": "^0.5.1",
|
||||||
"@snyk/protect": "^1.1276.0",
|
"@sentry/browser": "^7.99.0",
|
||||||
|
"@snyk/graphlib": "^3.4.0",
|
||||||
|
"@snyk/lodash": "^4.17.15-patch",
|
||||||
"@vue/apollo-composable": "^4.0.1",
|
"@vue/apollo-composable": "^4.0.1",
|
||||||
"@vueuse/core": "^10.7.2",
|
"@vuelidate/core": "^2.0.3",
|
||||||
"core-js": "3",
|
"@vuelidate/validators": "^2.0.4",
|
||||||
|
"@vuepic/vue-datepicker": "^7.4.1",
|
||||||
|
"apollo-link-sentry": "^3.3.0",
|
||||||
"date-fns": "^3.3.1",
|
"date-fns": "^3.3.1",
|
||||||
"graphql": "^16.8.1",
|
"graphql": "^16.8.1",
|
||||||
"graphql-tag": "^2.12.6",
|
"graphql-tag": "^2.12.6",
|
||||||
"node-sass": "^9.0.0",
|
|
||||||
"nuxt-edge": "latest",
|
|
||||||
"pinia": "^2.1.7",
|
"pinia": "^2.1.7",
|
||||||
"pinia-plugin-persistedstate": "^3.2.1",
|
"subscriptions-transport-ws": "^0.11.0",
|
||||||
"sass-loader": "^10.1.1",
|
"vue-debounce": "^5.0.0"
|
||||||
"vue": "2.7.16",
|
}
|
||||||
"vue-demi": "^0.14.7",
|
|
||||||
"vue-server-renderer": "2.7.16",
|
|
||||||
"vue-template-compiler": "2.7.16",
|
|
||||||
"vuetify": "^2.7.1"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@babel/runtime-corejs3": "^7.23.9",
|
|
||||||
"@graphql-codegen/cli": "^5.0.0",
|
|
||||||
"@graphql-codegen/fragment-matcher": "^5.0.0",
|
|
||||||
"@nuxt/bridge": "npm:@nuxt/bridge-edge",
|
|
||||||
"@nuxt/types": "^2.17.3",
|
|
||||||
"@nuxtjs/eslint-config-typescript": "^12.1.0",
|
|
||||||
"@nuxtjs/eslint-module": "^4.1.0",
|
|
||||||
"@nuxtjs/stylelint-module": "^5.1.0",
|
|
||||||
"@typescript-eslint/eslint-plugin": "^5.62.0",
|
|
||||||
"@typescript-eslint/parser": "^5.62.0",
|
|
||||||
"babel-eslint": "^10.0.3",
|
|
||||||
"cli-engine": "^4.7.6",
|
|
||||||
"cypress": "^13.6.4",
|
|
||||||
"eslint": "^8.56.0",
|
|
||||||
"eslint-config-airbnb-base": "^15.0.0",
|
|
||||||
"eslint-loader": "^4.0.2",
|
|
||||||
"eslint-plugin-import": "^2.29.1",
|
|
||||||
"eslint-plugin-nuxt": "^4.0.0",
|
|
||||||
"eslint-plugin-vue": "^9.21.1",
|
|
||||||
"husky": "^9.0.10",
|
|
||||||
"nuxi": "^3.10.0",
|
|
||||||
"postcss-html": "^1.6.0",
|
|
||||||
"stylelint": "^14.16.1",
|
|
||||||
"stylelint-config-recommended-vue": "^1.5.0",
|
|
||||||
"stylelint-config-standard": "^29.0.0",
|
|
||||||
"typescript": "^5.3.3",
|
|
||||||
"wait-on": "^7.2.0"
|
|
||||||
},
|
|
||||||
"resolutions": {
|
|
||||||
"eslint-webpack-plugin": "^2.0.0"
|
|
||||||
},
|
|
||||||
"snyk": true
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,11 +4,11 @@
|
|||||||
|
|
||||||
<script setup lang='ts'>
|
<script setup lang='ts'>
|
||||||
import { useHead } from '@unhead/vue'
|
import { useHead } from '@unhead/vue'
|
||||||
import Filters from '../components/pages/filters/index.vue'
|
import { useI18n } from '#i18n'
|
||||||
import { useTranslation } from '~/plugins/i18n'
|
import Filters from '../components/pages/filters/filter-page.vue'
|
||||||
|
|
||||||
const { t } = useTranslation()
|
const { t } = useI18n()
|
||||||
useHead({
|
useHead({
|
||||||
title: t('filters.title')
|
title: t('filters.title'),
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -4,11 +4,11 @@
|
|||||||
|
|
||||||
<script setup lang='ts'>
|
<script setup lang='ts'>
|
||||||
import { useHead } from '@unhead/vue'
|
import { useHead } from '@unhead/vue'
|
||||||
import Events from '~/components/pages/events/index.vue'
|
import { useI18n } from '#i18n'
|
||||||
import { useTranslation } from '~/plugins/i18n'
|
import Events from '~/components/pages/events/event-page.vue'
|
||||||
|
|
||||||
const { t } = useTranslation()
|
const { t } = useI18n()
|
||||||
useHead({
|
useHead({
|
||||||
title: t('events.title')
|
title: t('events.title'),
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -4,11 +4,11 @@
|
|||||||
|
|
||||||
<script setup lang='ts'>
|
<script setup lang='ts'>
|
||||||
import { useHead } from '@unhead/vue'
|
import { useHead } from '@unhead/vue'
|
||||||
import Origins from '../components/pages/origins/index.vue'
|
import { useI18n } from '#i18n'
|
||||||
import { useTranslation } from '~/plugins/i18n'
|
import Origins from '../components/pages/origins/origin-page.vue'
|
||||||
|
|
||||||
const { t } = useTranslation()
|
const { t } = useI18n()
|
||||||
useHead({
|
useHead({
|
||||||
title: t('origins.title')
|
title: t('origins.title'),
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
import { ApolloClient, createHttpLink, InMemoryCache } from '@apollo/client/core'
|
|
||||||
import { setContext } from '@apollo/client/link/context'
|
|
||||||
import { useAuth } from './auth'
|
|
||||||
|
|
||||||
const apiUrl = process.env.graphqlApi || '/query'
|
|
||||||
|
|
||||||
const cache = new InMemoryCache()
|
|
||||||
|
|
||||||
const httpLink = createHttpLink({
|
|
||||||
uri: apiUrl
|
|
||||||
})
|
|
||||||
|
|
||||||
const getToken = (options) => {
|
|
||||||
const { getTokenSilently } = useAuth()
|
|
||||||
return getTokenSilently(options)
|
|
||||||
}
|
|
||||||
|
|
||||||
const authLink = setContext((_, { headers }) => {
|
|
||||||
return getToken()
|
|
||||||
.then(token => ({
|
|
||||||
headers: {
|
|
||||||
...headers,
|
|
||||||
authorization: token ? `Bearer ${token}` : ''
|
|
||||||
}
|
|
||||||
})).catch(() => {
|
|
||||||
return {}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
const link = authLink.concat(httpLink)
|
|
||||||
|
|
||||||
const instance = new ApolloClient({
|
|
||||||
connectToDevTools: true,
|
|
||||||
link,
|
|
||||||
cache,
|
|
||||||
defaultOptions: {
|
|
||||||
query: {
|
|
||||||
fetchPolicy: 'cache-and-network'
|
|
||||||
},
|
|
||||||
watchQuery: {
|
|
||||||
fetchPolicy: 'cache-and-network'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
export default function (_, inject) {
|
|
||||||
inject('apollo', instance)
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,138 @@
|
|||||||
|
import {
|
||||||
|
ApolloClient,
|
||||||
|
ApolloLink,
|
||||||
|
createHttpLink,
|
||||||
|
from,
|
||||||
|
InMemoryCache,
|
||||||
|
split,
|
||||||
|
} from '@apollo/client/core'
|
||||||
|
import { WebSocketLink } from '@apollo/client/link/ws'
|
||||||
|
import { setContext } from '@apollo/client/link/context'
|
||||||
|
import { getMainDefinition } from '@apollo/client/utilities'
|
||||||
|
import { SentryLink } from 'apollo-link-sentry'
|
||||||
|
import * as Sentry from '@sentry/browser'
|
||||||
|
import { type GetTokenSilentlyOptions } from '@auth0/auth0-spa-js'
|
||||||
|
import { DefaultApolloClient, provideApolloClient } from '@vue/apollo-composable'
|
||||||
|
import type { Auth0VueClient } from '@auth0/auth0-vue'
|
||||||
|
import { defineNuxtPlugin, useNuxtApp } from '#app'
|
||||||
|
import { envConfig } from '~/utils/environment'
|
||||||
|
// The side effect of patching fetch() has to occur before configuring Apollo Client
|
||||||
|
// https://github.com/getsentry/sentry-javascript/issues/2860#issuecomment-684514367
|
||||||
|
import './sentry'
|
||||||
|
|
||||||
|
const apiUrl = envConfig(window.location.hostname).apiUrl
|
||||||
|
const wsUrl = apiUrl.replace(/^http/, 'ws')
|
||||||
|
|
||||||
|
const cache = new InMemoryCache({
|
||||||
|
typePolicies: {
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const getToken = async (options: GetTokenSilentlyOptions) => {
|
||||||
|
const nuxtApp = useNuxtApp()
|
||||||
|
const auth0: Auth0VueClient = nuxtApp.$auth0 as Auth0VueClient
|
||||||
|
return await auth0.getAccessTokenSilently(options).catch((err) => {
|
||||||
|
Sentry.captureException(err, {
|
||||||
|
extra: {
|
||||||
|
function: 'getTokenSilently',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return undefined
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const httpLink = createHttpLink({
|
||||||
|
uri: apiUrl,
|
||||||
|
})
|
||||||
|
|
||||||
|
const wsLink = new WebSocketLink({
|
||||||
|
uri: wsUrl,
|
||||||
|
options: {
|
||||||
|
reconnect: true,
|
||||||
|
lazy: true,
|
||||||
|
connectionParams: () => {
|
||||||
|
return getToken({}).then((token) => ({
|
||||||
|
authToken: token,
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const authLink = setContext(async (_, { headers }) => {
|
||||||
|
return await getToken({}).then((token) => ({
|
||||||
|
headers: {
|
||||||
|
...headers,
|
||||||
|
authorization: token ? `Bearer ${token}` : '',
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
|
||||||
|
const traceHeaders = setContext((_, { headers }) => {
|
||||||
|
const th = Sentry.getCurrentHub().traceHeaders()
|
||||||
|
return {
|
||||||
|
headers: {
|
||||||
|
...headers,
|
||||||
|
...th,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const sentryTransactionLink = new ApolloLink((operation, forward) => {
|
||||||
|
const existingTransaction = Sentry.getCurrentHub()
|
||||||
|
.getScope()
|
||||||
|
?.getTransaction()
|
||||||
|
// Create a transaction if one does not exist in order to work around
|
||||||
|
// https://github.com/getsentry/sentry-javascript/issues/3169
|
||||||
|
// https://github.com/getsentry/sentry-javascript/issues/4072
|
||||||
|
const transaction =
|
||||||
|
existingTransaction ??
|
||||||
|
Sentry.startTransaction({
|
||||||
|
name: `Apollo Request: ${operation.operationName}`,
|
||||||
|
})
|
||||||
|
|
||||||
|
Sentry.getCurrentHub().configureScope((scope) => scope.setSpan(transaction))
|
||||||
|
|
||||||
|
operation.setContext({ tracing: { transaction } })
|
||||||
|
return forward(operation).map((data) => {
|
||||||
|
operation.getContext().tracing?.transaction?.finish()
|
||||||
|
return data
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const link = sentryTransactionLink.concat(
|
||||||
|
traceHeaders.concat(
|
||||||
|
from([
|
||||||
|
new SentryLink({}),
|
||||||
|
split(
|
||||||
|
({ query }) => {
|
||||||
|
const definition = getMainDefinition(query)
|
||||||
|
return (
|
||||||
|
definition.kind === 'OperationDefinition' &&
|
||||||
|
definition.operation === 'subscription'
|
||||||
|
)
|
||||||
|
},
|
||||||
|
authLink.concat(wsLink),
|
||||||
|
authLink.concat(httpLink),
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
const instance = new ApolloClient({
|
||||||
|
connectToDevTools: true,
|
||||||
|
link,
|
||||||
|
cache,
|
||||||
|
defaultOptions: {
|
||||||
|
query: {
|
||||||
|
fetchPolicy: 'cache-first',
|
||||||
|
},
|
||||||
|
watchQuery: {
|
||||||
|
fetchPolicy: 'cache-and-network',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
export default defineNuxtPlugin((nuxtApp) => {
|
||||||
|
nuxtApp.provide(DefaultApolloClient[Symbol.toStringTag], instance)
|
||||||
|
provideApolloClient(instance)
|
||||||
|
})
|
||||||
@@ -1,141 +0,0 @@
|
|||||||
import {
|
|
||||||
createAuth0Client,
|
|
||||||
Auth0Client,
|
|
||||||
GetTokenSilentlyOptions,
|
|
||||||
IdToken,
|
|
||||||
LogoutOptions,
|
|
||||||
RedirectLoginOptions,
|
|
||||||
User
|
|
||||||
} from '@auth0/auth0-spa-js'
|
|
||||||
import { Ref, ref } from 'vue'
|
|
||||||
|
|
||||||
/** Define a default action to perform after authentication */
|
|
||||||
const DEFAULT_REDIRECT_CALLBACK = (_: any) =>
|
|
||||||
window.history.replaceState({}, document.title, window.location.pathname)
|
|
||||||
|
|
||||||
interface Client {
|
|
||||||
loading: Ref<boolean>
|
|
||||||
isAuthenticated: Ref<boolean>
|
|
||||||
user: Ref<User | undefined>
|
|
||||||
auth0Client?: Promise<Auth0Client>
|
|
||||||
error: Ref
|
|
||||||
handleRedirectCallback: () => Promise<void>
|
|
||||||
loginWithRedirect: (o: RedirectLoginOptions) => Promise<void>
|
|
||||||
getIdTokenClaims: () => Promise<void | IdToken | undefined>
|
|
||||||
getTokenSilently: (o: GetTokenSilentlyOptions) => Promise<string | void>
|
|
||||||
logout: (o: LogoutOptions) => Promise<void>
|
|
||||||
}
|
|
||||||
|
|
||||||
let instance: Client
|
|
||||||
|
|
||||||
const params = (new URL(window.location.href)).searchParams
|
|
||||||
const domain = params.get('domain') || 'unbound.eu.auth0.com'
|
|
||||||
|
|
||||||
export const useAuth = (onRedirectCallback: (appState?: any) => void = DEFAULT_REDIRECT_CALLBACK) => {
|
|
||||||
if (instance) {
|
|
||||||
return instance
|
|
||||||
}
|
|
||||||
const options = {
|
|
||||||
domain,
|
|
||||||
clientId: 'orQfnvCPUR5C3mJkKoiWLQHOVQsBn60e',
|
|
||||||
authorizationParams: {
|
|
||||||
audience: 'http://dancefinder.unbound.se',
|
|
||||||
redirect_uri: window.location.origin
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
instance = {
|
|
||||||
loading: ref(true),
|
|
||||||
isAuthenticated: ref(false),
|
|
||||||
user: ref(undefined),
|
|
||||||
auth0Client: undefined,
|
|
||||||
error: ref(null),
|
|
||||||
/** Handles the callback when logging in using a redirect */
|
|
||||||
handleRedirectCallback: () => {
|
|
||||||
instance.loading.value = true
|
|
||||||
return instance.auth0Client!.then(client => client.handleRedirectCallback())
|
|
||||||
.then(() => {
|
|
||||||
return instance.auth0Client?.then(client => client.getUser())
|
|
||||||
.then((user) => {
|
|
||||||
instance.user.value = user
|
|
||||||
instance.isAuthenticated.value = true
|
|
||||||
instance.error.value = null
|
|
||||||
}
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.catch((e) => {
|
|
||||||
instance.error.value = e
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
instance.loading.value = false
|
|
||||||
})
|
|
||||||
},
|
|
||||||
/** Authenticates the user using the redirect method */
|
|
||||||
loginWithRedirect: (o: RedirectLoginOptions) => {
|
|
||||||
return instance.auth0Client!.then(client => client.loginWithRedirect(o))
|
|
||||||
.catch((e) => {
|
|
||||||
instance.error.value = e
|
|
||||||
})
|
|
||||||
},
|
|
||||||
/** Returns all the claims present in the ID token */
|
|
||||||
getIdTokenClaims: () => {
|
|
||||||
return instance.auth0Client!.then(client => client.getIdTokenClaims())
|
|
||||||
},
|
|
||||||
/** Returns the access token. If the token is invalid or missing, a new one is retrieved */
|
|
||||||
getTokenSilently: (o: GetTokenSilentlyOptions) => {
|
|
||||||
return instance.auth0Client!.then((client) => {
|
|
||||||
return client.getTokenSilently(o).catch((e) => {
|
|
||||||
instance.error.value = e
|
|
||||||
})
|
|
||||||
})
|
|
||||||
},
|
|
||||||
/** Logs the user out and removes their session on the authorization server */
|
|
||||||
logout: (o: LogoutOptions) => {
|
|
||||||
return instance.auth0Client!.then(client => client.logout(o))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const fetchUser = () => {
|
|
||||||
return instance.auth0Client!.then(client => client.isAuthenticated())
|
|
||||||
.then((a) => {
|
|
||||||
instance.auth0Client?.then(client => client.getUser()
|
|
||||||
.then((u) => {
|
|
||||||
instance.isAuthenticated.value = a
|
|
||||||
instance.user.value = u
|
|
||||||
instance.error.value = null
|
|
||||||
}))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// Create a new instance of the SDK client using members of the given options object
|
|
||||||
instance.auth0Client = createAuth0Client(options)
|
|
||||||
instance.auth0Client
|
|
||||||
.then((client) => {
|
|
||||||
instance.loading.value = true
|
|
||||||
// If the user is returning to the app after authentication..
|
|
||||||
if (
|
|
||||||
window.location.search.includes('state=') && (
|
|
||||||
window.location.search.includes('code=') ||
|
|
||||||
window.location.search.includes('error=')
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
// handle the redirect and retrieve tokens
|
|
||||||
return client.handleRedirectCallback()
|
|
||||||
.then((result) => {
|
|
||||||
// Notify subscribers that the redirect callback has happened, passing the appState
|
|
||||||
// (useful for retrieving any pre-authentication state)
|
|
||||||
onRedirectCallback(result.appState)
|
|
||||||
// Initialize our internal authentication state
|
|
||||||
return fetchUser()
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
return fetchUser()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((e) => {
|
|
||||||
instance.error.value = e
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
instance.loading.value = false
|
|
||||||
})
|
|
||||||
return instance
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import { createAuth0 } from '@auth0/auth0-vue'
|
||||||
|
import { defineNuxtPlugin } from '#app'
|
||||||
|
import { envConfig } from '~/utils/environment'
|
||||||
|
|
||||||
|
export default defineNuxtPlugin((nuxtApp) => {
|
||||||
|
const options = envConfig(window.location.hostname).auth
|
||||||
|
const auth0 = createAuth0(options)
|
||||||
|
nuxtApp.vueApp.use(auth0)
|
||||||
|
nuxtApp.provide('auth0', auth0)
|
||||||
|
})
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
import Vue from 'vue'
|
|
||||||
import hooks from '@u3u/vue-hooks'
|
|
||||||
|
|
||||||
Vue.use(hooks)
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
let i18n = null
|
|
||||||
let localePath = null
|
|
||||||
|
|
||||||
export const useTranslation = () => {
|
|
||||||
return {
|
|
||||||
t: i18n.t.bind(i18n),
|
|
||||||
localePath
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ({ app }) => {
|
|
||||||
i18n = app.i18n
|
|
||||||
localePath = app.localePath
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
import { createPersistedState } from 'pinia-plugin-persistedstate'
|
|
||||||
import { defineNuxtPlugin } from '#app'
|
|
||||||
|
|
||||||
export default defineNuxtPlugin(({ $pinia }) => {
|
|
||||||
$pinia.use(
|
|
||||||
createPersistedState({
|
|
||||||
key: id => `dancefinder_${id}`
|
|
||||||
})
|
|
||||||
)
|
|
||||||
})
|
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import * as Sentry from '@sentry/browser'
|
||||||
|
import { defineNuxtPlugin } from '#app'
|
||||||
|
import { envConfig } from '~/utils/environment'
|
||||||
|
|
||||||
|
const env = envConfig(window.location.hostname)
|
||||||
|
|
||||||
|
Sentry.init({
|
||||||
|
enabled: env.sentryEnabled,
|
||||||
|
dsn: 'https://da2e8d42185a4013909d49955432a116@o365290.ingest.sentry.io/5187660',
|
||||||
|
integrations: [
|
||||||
|
new Sentry.BrowserTracing({ traceFetch: false }),
|
||||||
|
Sentry.replayIntegration(),
|
||||||
|
],
|
||||||
|
environment: env.name,
|
||||||
|
tracesSampleRate: env.tracesSampleRate,
|
||||||
|
replaysSessionSampleRate: env.replaysSessionSampleRate,
|
||||||
|
replaysOnErrorSampleRate: env.replaysOnErrorSampleRate,
|
||||||
|
})
|
||||||
|
|
||||||
|
export default defineNuxtPlugin(() => {
|
||||||
|
})
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
import Vue from 'vue'
|
|
||||||
import Vuetify from 'vuetify'
|
|
||||||
|
|
||||||
Vue.use(Vuetify)
|
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import { createVuetify } from 'vuetify'
|
||||||
|
import { defineNuxtPlugin } from '#app'
|
||||||
|
|
||||||
|
import '@mdi/font/css/materialdesignicons.css'
|
||||||
|
import 'vuetify/styles'
|
||||||
|
|
||||||
|
export default defineNuxtPlugin((app) => {
|
||||||
|
const vuetify = createVuetify({
|
||||||
|
theme: {
|
||||||
|
defaultTheme: 'light',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
app.vueApp.use(vuetify)
|
||||||
|
})
|
||||||
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
@@ -1,4 +1,5 @@
|
|||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
|
import { ref } from 'vue'
|
||||||
import { Range } from '~/graphql/generated/operations'
|
import { Range } from '~/graphql/generated/operations'
|
||||||
|
|
||||||
export const useState = defineStore(
|
export const useState = defineStore(
|
||||||
@@ -40,10 +41,12 @@ export const useState = defineStore(
|
|||||||
setLocale,
|
setLocale,
|
||||||
setSearch,
|
setSearch,
|
||||||
setIncludeHidden,
|
setIncludeHidden,
|
||||||
setRange
|
setRange,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
persist: true
|
persist: {
|
||||||
}
|
key: 'dancefinder_state',
|
||||||
|
},
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ module.exports = {
|
|||||||
customSyntax: 'postcss-html',
|
customSyntax: 'postcss-html',
|
||||||
extends: [
|
extends: [
|
||||||
'stylelint-config-standard',
|
'stylelint-config-standard',
|
||||||
'stylelint-config-recommended-vue'
|
'stylelint-config-recommended-vue',
|
||||||
],
|
],
|
||||||
// add your custom config here
|
// add your custom config here
|
||||||
// https://stylelint.io/user-guide/configuration
|
// https://stylelint.io/user-guide/configuration
|
||||||
rules: {}
|
rules: {},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
export default {
|
||||||
|
title: 'Dancefinder',
|
||||||
|
login: 'Login',
|
||||||
|
logout: 'Log out',
|
||||||
|
darkMode: 'Dark mode',
|
||||||
|
links: {
|
||||||
|
events: 'Events',
|
||||||
|
filters: 'Filters',
|
||||||
|
origins: 'Origins',
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
export default {
|
||||||
|
title: 'Dancefinder',
|
||||||
|
login: 'Logga in',
|
||||||
|
logout: 'Logga ut',
|
||||||
|
darkMode: 'Mörkt läge',
|
||||||
|
links: {
|
||||||
|
events: 'Evenemang',
|
||||||
|
filters: 'Hantera filter',
|
||||||
|
origins: 'Hantera startpunkter',
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
export default {
|
|
||||||
en: {
|
|
||||||
title: 'Dancefinder',
|
|
||||||
login: 'Login',
|
|
||||||
logout: 'Log out',
|
|
||||||
darkMode: 'Dark mode',
|
|
||||||
links: {
|
|
||||||
events: 'Events',
|
|
||||||
filters: 'Filters',
|
|
||||||
origins: 'Origins'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
sv: {
|
|
||||||
title: 'Dancefinder',
|
|
||||||
login: 'Logga in',
|
|
||||||
logout: 'Logga ut',
|
|
||||||
darkMode: 'Mörkt läge',
|
|
||||||
links: {
|
|
||||||
events: 'Evenemang',
|
|
||||||
filters: 'Hantera filter',
|
|
||||||
origins: 'Hantera startpunkter'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import { defineI18nLocale } from '#i18n'
|
||||||
|
import app from './app-en'
|
||||||
|
import events from './events-en'
|
||||||
|
import filters from './filters-en'
|
||||||
|
import origins from './origins-en'
|
||||||
|
|
||||||
|
export default defineI18nLocale(() => {
|
||||||
|
return {
|
||||||
|
app,
|
||||||
|
events,
|
||||||
|
filters,
|
||||||
|
origins,
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
export default {
|
||||||
|
title: 'Dancefinder - Events',
|
||||||
|
login: 'NB! Login to handle filtering of the list',
|
||||||
|
range: {
|
||||||
|
ONE_WEEK: '1 week',
|
||||||
|
TWO_WEEKS: '2 weeks',
|
||||||
|
ONE_MONTH: '1 month',
|
||||||
|
ONE_QUARTER: '1 quarter',
|
||||||
|
ONE_YEAR: '1 year',
|
||||||
|
},
|
||||||
|
date: 'Date:',
|
||||||
|
time: 'Time:',
|
||||||
|
hall: 'Where:',
|
||||||
|
city: 'City:',
|
||||||
|
municipality: 'Municipality:',
|
||||||
|
state: 'State:',
|
||||||
|
hide: 'Hide',
|
||||||
|
filter: 'Full text search',
|
||||||
|
includeHidden: 'Include hidden',
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
export default {
|
||||||
|
title: 'Dancefinder - Evenemang',
|
||||||
|
login: 'OBS! Logga in för att kunna filtrera listan',
|
||||||
|
range: {
|
||||||
|
ONE_WEEK: '1 vecka',
|
||||||
|
TWO_WEEKS: '2 veckor',
|
||||||
|
ONE_MONTH: '1 månad',
|
||||||
|
ONE_QUARTER: '1 kvartal',
|
||||||
|
ONE_YEAR: '1 år',
|
||||||
|
},
|
||||||
|
date: 'Datum:',
|
||||||
|
time: 'Tid:',
|
||||||
|
hall: 'Var:',
|
||||||
|
city: 'Stad:',
|
||||||
|
municipality: 'Kommun:',
|
||||||
|
state: 'Län:',
|
||||||
|
hide: 'Dölj',
|
||||||
|
filter: 'Fritext-sökning',
|
||||||
|
includeHidden: 'Inkludera dolda',
|
||||||
|
}
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
export default {
|
|
||||||
en: {
|
|
||||||
title: 'Dancefinder - Events',
|
|
||||||
login: 'NB! Login to handle filtering of the list',
|
|
||||||
range: {
|
|
||||||
ONE_WEEK: '1 week',
|
|
||||||
TWO_WEEKS: '2 weeks',
|
|
||||||
ONE_MONTH: '1 month',
|
|
||||||
ONE_QUARTER: '1 quarter',
|
|
||||||
ONE_YEAR: '1 year'
|
|
||||||
},
|
|
||||||
date: 'Date:',
|
|
||||||
time: 'Time:',
|
|
||||||
hall: 'Where:',
|
|
||||||
city: 'City:',
|
|
||||||
municipality: 'Municipality:',
|
|
||||||
state: 'State:',
|
|
||||||
hide: 'Hide',
|
|
||||||
filter: 'Full text search',
|
|
||||||
includeHidden: 'Include hidden'
|
|
||||||
},
|
|
||||||
sv: {
|
|
||||||
title: 'Dancefinder - Evenemang',
|
|
||||||
login: 'OBS! Logga in för att kunna filtrera listan',
|
|
||||||
range: {
|
|
||||||
ONE_WEEK: '1 vecka',
|
|
||||||
TWO_WEEKS: '2 veckor',
|
|
||||||
ONE_MONTH: '1 månad',
|
|
||||||
ONE_QUARTER: '1 kvartal',
|
|
||||||
ONE_YEAR: '1 år'
|
|
||||||
},
|
|
||||||
date: 'Datum:',
|
|
||||||
time: 'Tid:',
|
|
||||||
hall: 'Var:',
|
|
||||||
city: 'Stad:',
|
|
||||||
municipality: 'Kommun:',
|
|
||||||
state: 'Län:',
|
|
||||||
hide: 'Dölj',
|
|
||||||
filter: 'Fritext-sökning',
|
|
||||||
includeHidden: 'Inkludera dolda'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
export default {
|
||||||
|
title: 'Dancefinder - Filters',
|
||||||
|
band: 'No bands | 1 band | {count} bands',
|
||||||
|
hall: 'No dance halls | 1 dance hall | {count} dance halls',
|
||||||
|
city: 'No cities | 1 city | {count} cities',
|
||||||
|
municipality: 'No municipalities | 1 municipality | {count} municipalities',
|
||||||
|
state: 'No states | 1 state | {count} states',
|
||||||
|
remove: 'Remove filter',
|
||||||
|
success: 'Filter for {name} is removed',
|
||||||
|
failure: 'Filter for {name} could not be removed',
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
export default {
|
||||||
|
title: 'Dancefinder - Filter',
|
||||||
|
band: 'Inga band | 1 band | {count} band',
|
||||||
|
hall: 'Inga danslokaler | 1 danslokal | {count} danslokaler',
|
||||||
|
city: 'Ingen stad | 1 stad | {count} städer',
|
||||||
|
municipality: 'Ingen kommun | 1 kommun | {count} kommuner',
|
||||||
|
state: 'Inget län | 1 län | {count} län',
|
||||||
|
remove: 'Ta bort filter',
|
||||||
|
success: 'Filtrering av {name} har tagits bort',
|
||||||
|
failure: 'Filtrering av {name} kunde inte tas bort',
|
||||||
|
}
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
export default {
|
|
||||||
en: {
|
|
||||||
title: 'Dancefinder - Filters',
|
|
||||||
band: 'No bands | 1 band | {count} bands',
|
|
||||||
hall: 'No dance halls | 1 dance hall | {count} dance halls',
|
|
||||||
city: 'No cities | 1 city | {count} cities',
|
|
||||||
municipality: 'No municipalities | 1 municipality | {count} municipalities',
|
|
||||||
state: 'No states | 1 state | {count} states',
|
|
||||||
remove: 'Remove filter',
|
|
||||||
success: 'Filter for {name} is removed',
|
|
||||||
failure: 'Filter for {name} could not be removed'
|
|
||||||
},
|
|
||||||
sv: {
|
|
||||||
title: 'Dancefinder - Filter',
|
|
||||||
band: 'Inga band | 1 band | {count} band',
|
|
||||||
hall: 'Inga danslokaler | 1 danslokal | {count} danslokaler',
|
|
||||||
city: 'Ingen stad | 1 stad | {count} städer',
|
|
||||||
municipality: 'Ingen kommun | 1 kommun | {count} kommuner',
|
|
||||||
state: 'Inget län | 1 län | {count} län',
|
|
||||||
remove: 'Ta bort filter',
|
|
||||||
success: 'Filtrering av {name} har tagits bort',
|
|
||||||
failure: 'Filtrering av {name} kunde inte tas bort'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
import app from './app'
|
|
||||||
import events from './events'
|
|
||||||
import filters from './filters'
|
|
||||||
import origins from './origins'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
en: {
|
|
||||||
app: app.en,
|
|
||||||
events: events.en,
|
|
||||||
filters: filters.en,
|
|
||||||
origins: origins.en
|
|
||||||
},
|
|
||||||
sv: {
|
|
||||||
app: app.sv,
|
|
||||||
events: events.sv,
|
|
||||||
filters: filters.sv,
|
|
||||||
origins: origins.sv
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
export default {
|
|
||||||
en: {
|
|
||||||
currency: {
|
|
||||||
style: 'currency',
|
|
||||||
currency: 'USD'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
sv: {
|
|
||||||
currency: {
|
|
||||||
style: 'currency',
|
|
||||||
currency: 'SEK'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
export default {
|
||||||
|
title: 'Dancefinder - Origins',
|
||||||
|
origin: 'Origin',
|
||||||
|
geolocation: 'Address/geolocation (WGS84)',
|
||||||
|
fetchAddress: 'Fetch current position',
|
||||||
|
save: 'Save origin',
|
||||||
|
remove: 'Remove origin',
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
export default {
|
||||||
|
title: 'Dancefinder - Startpunkter',
|
||||||
|
origin: 'Startpunkt',
|
||||||
|
geolocation: 'Address/geokoordinat (WGS84)',
|
||||||
|
fetchAddress: 'Hämta nuvarande position',
|
||||||
|
save: 'Spara startpunkt',
|
||||||
|
remove: 'Ta bort startpunkt',
|
||||||
|
}
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
export default {
|
|
||||||
en: {
|
|
||||||
title: 'Dancefinder - Origins',
|
|
||||||
origin: 'Origin',
|
|
||||||
geolocation: 'Address/geolocation (WGS84)',
|
|
||||||
fetchAddress: 'Fetch current position',
|
|
||||||
save: 'Save origin',
|
|
||||||
remove: 'Remove origin'
|
|
||||||
},
|
|
||||||
sv: {
|
|
||||||
title: 'Dancefinder - Startpunkter',
|
|
||||||
origin: 'Startpunkt',
|
|
||||||
geolocation: 'Address/geokoordinat (WGS84)',
|
|
||||||
fetchAddress: 'Hämta nuvarande position',
|
|
||||||
save: 'Spara startpunkt',
|
|
||||||
remove: 'Ta bort startpunkt'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import { defineI18nLocale } from '#i18n'
|
||||||
|
import app from './app-sv'
|
||||||
|
import events from './events-sv'
|
||||||
|
import filters from './filters-sv'
|
||||||
|
import origins from './origins-sv'
|
||||||
|
|
||||||
|
export default defineI18nLocale(() => {
|
||||||
|
return {
|
||||||
|
app,
|
||||||
|
events,
|
||||||
|
filters,
|
||||||
|
origins,
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
export default {
|
|
||||||
sv: {
|
|
||||||
close: 'Stäng',
|
|
||||||
dataIterator: {
|
|
||||||
pageText: '{0}-{1} av {2}',
|
|
||||||
noResultsText: 'Inga matchande resultat',
|
|
||||||
loadingText: 'Laddar...'
|
|
||||||
},
|
|
||||||
dataTable: {
|
|
||||||
itemsPerPageText: 'Rader per sida:',
|
|
||||||
ariaLabel: {
|
|
||||||
sortDescending:
|
|
||||||
': Sorterad minskande. Aktivera för att ta bort sortering.',
|
|
||||||
sortAscending: ': Sorterad ökande. Aktivera för att sortera minskande.',
|
|
||||||
sortNone: ': Ej sorterad. Aktivera för att sortera ökande.'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
dataFooter: {
|
|
||||||
itemsPerPageText: 'Per sida:',
|
|
||||||
itemsPerPageAll: 'Alla',
|
|
||||||
nextPage: 'Nästa sida',
|
|
||||||
prevPage: 'Föregående sida',
|
|
||||||
firstPage: 'Första sidan',
|
|
||||||
lastPage: 'Sista sidan'
|
|
||||||
},
|
|
||||||
datePicker: {
|
|
||||||
itemsSelected: '{0} valda'
|
|
||||||
},
|
|
||||||
noDataText: 'Ingen data tillgänglig',
|
|
||||||
carousel: {
|
|
||||||
prev: 'Föregående yta',
|
|
||||||
next: 'Nästa yta'
|
|
||||||
},
|
|
||||||
calendar: {
|
|
||||||
moreEvents: '{0} fler'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,28 +1,4 @@
|
|||||||
{
|
{
|
||||||
"extends": "./.nuxt/tsconfig.json",
|
// https://nuxt.com/docs/guide/concepts/typescript
|
||||||
"compilerOptions": {
|
"extends": "./.nuxt/tsconfig.json"
|
||||||
"target": "ES2018",
|
|
||||||
"module": "ESNext",
|
|
||||||
"moduleResolution": "Node",
|
|
||||||
"lib": [
|
|
||||||
"ESNext",
|
|
||||||
"ESNext.AsyncIterable",
|
|
||||||
"DOM"
|
|
||||||
],
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"allowJs": true,
|
|
||||||
"sourceMap": true,
|
|
||||||
"strict": true,
|
|
||||||
"noEmit": true,
|
|
||||||
"baseUrl": ".",
|
|
||||||
"types": [
|
|
||||||
"@types/node",
|
|
||||||
"@nuxt/types",
|
|
||||||
"@nuxtjs/i18n",
|
|
||||||
"@nuxtjs/sentry"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"exclude": [
|
|
||||||
"node_modules"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
import { type Auth0ClientOptions, type CacheLocation } from '@auth0/auth0-spa-js'
|
||||||
|
|
||||||
|
interface EnvConfig {
|
||||||
|
name: string
|
||||||
|
apiUrl: string
|
||||||
|
auth: Auth0ClientOptions
|
||||||
|
dev: boolean
|
||||||
|
sentryEnabled: boolean
|
||||||
|
tracesSampleRate: number
|
||||||
|
replaysSessionSampleRate: number
|
||||||
|
replaysOnErrorSampleRate: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export const envConfig = (host: string): EnvConfig => {
|
||||||
|
const options = {
|
||||||
|
useRefreshTokens: true,
|
||||||
|
cacheLocation: 'localstorage' as CacheLocation,
|
||||||
|
authorizationParams: {
|
||||||
|
audience: 'http://dancefinder.unbound.se',
|
||||||
|
redirect_uri: window.location.origin,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
const prod = {
|
||||||
|
...options,
|
||||||
|
domain: 'unbound.eu.auth0.com',
|
||||||
|
clientId: 'orQfnvCPUR5C3mJkKoiWLQHOVQsBn60e',
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (host) {
|
||||||
|
case 'localhost':
|
||||||
|
return {
|
||||||
|
name: 'development',
|
||||||
|
apiUrl: 'http://localhost:6080/query',
|
||||||
|
auth: prod,
|
||||||
|
dev: true,
|
||||||
|
sentryEnabled: false,
|
||||||
|
tracesSampleRate: 1.0,
|
||||||
|
replaysSessionSampleRate: 1.0,
|
||||||
|
replaysOnErrorSampleRate: 1.0,
|
||||||
|
}
|
||||||
|
case 'dancefinder.unbound.se':
|
||||||
|
return {
|
||||||
|
name: 'production',
|
||||||
|
apiUrl: 'https://dancefinder.unbound.se/query',
|
||||||
|
auth: prod,
|
||||||
|
dev: false,
|
||||||
|
sentryEnabled: true,
|
||||||
|
tracesSampleRate: 1.0,
|
||||||
|
replaysSessionSampleRate: 0.1,
|
||||||
|
replaysOnErrorSampleRate: 1.0,
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw new Error(`unexpected host: ${host}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { gql as apolloGql } from '@apollo/client/core'
|
import { gql as apolloGql } from '@apollo/client/core'
|
||||||
import { markRaw } from 'vue'
|
import { markRaw } from 'vue'
|
||||||
|
|
||||||
export function gql (literals: string | readonly string[], ...args: any[]) {
|
export function gql(literals: string | readonly string[], ...args: any[]) {
|
||||||
return markRaw(apolloGql(literals, ...args))
|
return markRaw(apolloGql(literals, ...args))
|
||||||
}
|
}
|
||||||
|
|||||||