mirror of
https://forgejo.merr.is/annika/isl-vue3.git
synced 2025-12-11 10:56:31 -05:00
I Think I've Successfully Re-Added Auth
This commit is contained in:
parent
5c0d3c2fd7
commit
d914b7cbd6
18 changed files with 269 additions and 93 deletions
BIN
bun.lockb
BIN
bun.lockb
Binary file not shown.
|
|
@ -14,11 +14,12 @@
|
||||||
"format": "prettier --write src/"
|
"format": "prettier --write src/"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@zitadel/vue": "^1.0.0",
|
|
||||||
"axios": "^1.6.5",
|
"axios": "^1.6.5",
|
||||||
"axios-retry": "^4.0.0",
|
"axios-retry": "^4.0.0",
|
||||||
|
"oidc-client-ts": "^3.0.1",
|
||||||
"pinia": "^2.1.7",
|
"pinia": "^2.1.7",
|
||||||
"vue": "^3.3.11",
|
"vue": "^3.3.11",
|
||||||
|
"vue-oidc-client": "^1.0.0-alpha.5",
|
||||||
"vue-router": "^4.2.5",
|
"vue-router": "^4.2.5",
|
||||||
"vuetify": "^3.4.10"
|
"vuetify": "^3.4.10"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
{
|
{
|
||||||
"apiBaseURL": "http://localhost:3000"
|
"apiBaseURL": "http://coder.local.merr.is:3000",
|
||||||
|
"oidcAuthority": "https://auth.joes.moosenet.work",
|
||||||
|
"oidcClientID": "255988227184328707@isekai:_slow_life_calculator",
|
||||||
|
"oidcProjectID": "255987963094106115"
|
||||||
}
|
}
|
||||||
14
src/App.vue
14
src/App.vue
|
|
@ -1,25 +1,13 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { RouterView } from 'vue-router'
|
import { RouterView } from 'vue-router'
|
||||||
import GlobalHeader from '@/components/GlobalHeader.vue'
|
import GlobalHeader from '@/components/GlobalHeader.vue'
|
||||||
import { storeToRefs } from 'pinia'
|
|
||||||
import { usePowerItems } from './stores/powerItems'
|
|
||||||
import { computed } from 'vue'
|
|
||||||
|
|
||||||
const { blessingPowerItems, fellowPowerItems, intimacyPowerItems } = storeToRefs(usePowerItems())
|
|
||||||
|
|
||||||
const isLoaded = computed(
|
|
||||||
() =>
|
|
||||||
!blessingPowerItems.value.keys().next().done &&
|
|
||||||
!fellowPowerItems.value.keys().next().done &&
|
|
||||||
!intimacyPowerItems.value.keys().next().done
|
|
||||||
)
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<v-app>
|
<v-app>
|
||||||
<GlobalHeader />
|
<GlobalHeader />
|
||||||
<v-main class="d-flex">
|
<v-main class="d-flex">
|
||||||
<RouterView v-if="isLoaded" />
|
<RouterView />
|
||||||
</v-main>
|
</v-main>
|
||||||
<v-footer app>
|
<v-footer app>
|
||||||
<div>Copyright Annika Merris 2024</div>
|
<div>Copyright Annika Merris 2024</div>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { usePowerItems } from '@/stores/powerItems'
|
||||||
import type { DataTableHeader } from '@/types/DataTableHeader'
|
import type { DataTableHeader } from '@/types/DataTableHeader'
|
||||||
import type { PowerItem } from '@/types/PowerItem'
|
import type { PowerItem } from '@/types/PowerItem'
|
||||||
import type { Ref } from 'vue'
|
import type { Ref } from 'vue'
|
||||||
import { computed, ref } from 'vue'
|
import { computed, ref, watch } from 'vue'
|
||||||
import { useDisplay } from 'vuetify'
|
import { useDisplay } from 'vuetify'
|
||||||
import type { VDataTable } from 'vuetify/components'
|
import type { VDataTable } from 'vuetify/components'
|
||||||
|
|
||||||
|
|
@ -128,11 +128,19 @@ const getColor = computed(() => (rarity: number): string => {
|
||||||
})
|
})
|
||||||
const allSelected = computed(() => events.value.length === selectedEvents.value.length)
|
const allSelected = computed(() => events.value.length === selectedEvents.value.length)
|
||||||
const partialSelected = computed(() => selectedEvents.value.length > 0)
|
const partialSelected = computed(() => selectedEvents.value.length > 0)
|
||||||
toggle()
|
const isLoading = computed((): boolean => props.items.keys()?.next().done ?? false)
|
||||||
|
watch(isLoading, (newLoading) => {
|
||||||
|
if (!newLoading) {
|
||||||
|
toggle()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (!isLoading.value) {
|
||||||
|
toggle()
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<v-card fluid>
|
<v-card fluid :loading="isLoading">
|
||||||
<v-card-title>Special Items</v-card-title>
|
<v-card-title>Special Items</v-card-title>
|
||||||
<v-card-subtitle>Items from events</v-card-subtitle>
|
<v-card-subtitle>Items from events</v-card-subtitle>
|
||||||
<v-card-item>
|
<v-card-item>
|
||||||
|
|
|
||||||
|
|
@ -78,10 +78,11 @@ const getColor = computed(() => (rarity: number): string => {
|
||||||
return 'green'
|
return 'green'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
const isLoading = computed((): boolean => props.items.keys()?.next().done ?? false)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<v-card>
|
<v-card :loading="isLoading">
|
||||||
<v-card-title>Standard Items</v-card-title>
|
<v-card-title>Standard Items</v-card-title>
|
||||||
<v-card-subtitle>Items that exist all the time</v-card-subtitle>
|
<v-card-subtitle>Items that exist all the time</v-card-subtitle>
|
||||||
<v-card-item>
|
<v-card-item>
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue'
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
standardTotal: number
|
itemType: string
|
||||||
minimumTotal: number
|
standardTotal: number
|
||||||
maximumTotal: number
|
minimumTotal: number
|
||||||
averageTotal: number
|
maximumTotal: number
|
||||||
|
averageTotal: number
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
|
|
@ -17,17 +18,17 @@ const aveIncrease = computed(() => props.standardTotal + props.averageTotal)
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<v-card>
|
<v-card>
|
||||||
<v-card-title>Overall Blessing Power Increase</v-card-title>
|
<v-card-title>Overall {{ itemType }} Power Increase</v-card-title>
|
||||||
<v-card-item>
|
<v-card-item>
|
||||||
<v-list density="compact">
|
<v-list density="compact">
|
||||||
<v-list-item>
|
<v-list-item>
|
||||||
<v-list-item-title>Minimum: {{ minIncrease }}</v-list-item-title>
|
<v-list-item-title>Minimum: {{ minIncrease }}</v-list-item-title>
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
<v-list-item>
|
<v-list-item>
|
||||||
<v-list-item-title>Maximum: {{ maxIncrease }}</v-list-item-title>
|
<v-list-item-title>Maximum: {{ maxIncrease }}</v-list-item-title>
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
<v-list-item>
|
<v-list-item>
|
||||||
<v-list-item-title>Mean: {{ aveIncrease }}</v-list-item-title>
|
<v-list-item-title>Mean: {{ aveIncrease }}</v-list-item-title>
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
</v-list>
|
</v-list>
|
||||||
</v-card-item>
|
</v-card-item>
|
||||||
|
|
|
||||||
66
src/main.ts
66
src/main.ts
|
|
@ -2,17 +2,17 @@ import './assets/main.css'
|
||||||
|
|
||||||
import { createApp } from 'vue'
|
import { createApp } from 'vue'
|
||||||
import { createPinia } from 'pinia'
|
import { createPinia } from 'pinia'
|
||||||
|
|
||||||
import App from './App.vue'
|
|
||||||
import router from './router'
|
|
||||||
|
|
||||||
// Vuetify
|
// Vuetify
|
||||||
import 'vuetify/styles'
|
import 'vuetify/styles'
|
||||||
import '@mdi/font/css/materialdesignicons.css'
|
import '@mdi/font/css/materialdesignicons.css'
|
||||||
import { createVuetify } from 'vuetify'
|
import { createVuetify } from 'vuetify'
|
||||||
import axios from 'axios'
|
|
||||||
import zitadelAuth from '@/services/zitadelAuth'
|
import App from './App.vue'
|
||||||
import { apiBaseURL } from './types/ConfigSymbols'
|
import { apiBaseURL, oidc } from './types/ConfigSymbols'
|
||||||
|
import { configureOidc } from './services/authentikAuth'
|
||||||
|
import router from './router'
|
||||||
|
import { getConfig } from './services/siteConfig'
|
||||||
|
import type { Config } from './types/Config'
|
||||||
|
|
||||||
const vuetify = createVuetify({
|
const vuetify = createVuetify({
|
||||||
icons: {
|
icons: {
|
||||||
|
|
@ -23,32 +23,30 @@ const vuetify = createVuetify({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// Stuff to get OIDC auth working through Zitadel
|
const conf: Config = await getConfig().then((c: Config | null): Config => {
|
||||||
declare module 'vue' {
|
if (c === null) {
|
||||||
interface ComponentCustomProperties {
|
throw new Error("config was null")
|
||||||
$zitadel: typeof zitadelAuth
|
}
|
||||||
|
return c
|
||||||
|
}).catch((reason) => {
|
||||||
|
console.log(reason)
|
||||||
|
throw new Error(reason);
|
||||||
|
})
|
||||||
|
|
||||||
|
const authentikAuth = await configureOidc()
|
||||||
|
authentikAuth.startup().then((ok: boolean) => {
|
||||||
|
if (ok) {
|
||||||
|
const app = createApp(App)
|
||||||
|
const pinia = createPinia()
|
||||||
|
|
||||||
|
app.use(router)
|
||||||
|
app.use(vuetify)
|
||||||
|
app.use(pinia)
|
||||||
|
|
||||||
|
app.provide(oidc, authentikAuth)
|
||||||
|
|
||||||
|
app.provide(apiBaseURL, conf.apiBaseURL)
|
||||||
|
|
||||||
|
app.mount('#app')
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
zitadelAuth.oidcAuth.startup().then(() => {
|
|
||||||
const app = createApp(App)
|
|
||||||
const pinia = createPinia()
|
|
||||||
|
|
||||||
app.use(router)
|
|
||||||
app.use(vuetify)
|
|
||||||
app.use(pinia)
|
|
||||||
|
|
||||||
app.config.globalProperties.$zitadel = zitadelAuth
|
|
||||||
|
|
||||||
// Fetch my config
|
|
||||||
axios
|
|
||||||
.get('/config.json?noCache=' + Date.now())
|
|
||||||
.then((resp) => {
|
|
||||||
app.provide(apiBaseURL, resp.data.apiBaseURL)
|
|
||||||
|
|
||||||
app.mount('#app')
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.log(err)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,12 @@
|
||||||
import zitadelAuth from '@/services/zitadelAuth'
|
import { configureOidc } from '@/services/authentikAuth'
|
||||||
|
import { getConfig } from '@/services/siteConfig'
|
||||||
|
import type { Config } from '@/types/Config'
|
||||||
|
import type { OidcAuth } from 'vue-oidc-client/vue3'
|
||||||
import { createRouter, createWebHistory } from 'vue-router'
|
import { createRouter, createWebHistory } from 'vue-router'
|
||||||
|
|
||||||
|
const oidcAuth: OidcAuth = await configureOidc().then((value: OidcAuth): OidcAuth => value)
|
||||||
|
const config: Config = await getConfig().then((value: Config | null): Config => value !== null ? value : {} as Config)
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHistory(import.meta.env.BASE_URL),
|
history: createWebHistory(import.meta.env.BASE_URL),
|
||||||
routes: [
|
routes: [
|
||||||
|
|
@ -34,7 +40,7 @@ const router = createRouter({
|
||||||
path: '/login',
|
path: '/login',
|
||||||
name: 'login',
|
name: 'login',
|
||||||
meta: {
|
meta: {
|
||||||
authName: zitadelAuth.oidcAuth.authName
|
authName: oidcAuth.authName
|
||||||
},
|
},
|
||||||
component: () => import('@/views/Login.vue')
|
component: () => import('@/views/Login.vue')
|
||||||
},
|
},
|
||||||
|
|
@ -42,14 +48,25 @@ const router = createRouter({
|
||||||
path: '/admin',
|
path: '/admin',
|
||||||
name: 'admin',
|
name: 'admin',
|
||||||
meta: {
|
meta: {
|
||||||
authName: zitadelAuth.oidcAuth.authName
|
authName: oidcAuth.authName
|
||||||
},
|
},
|
||||||
component: () =>
|
component: () =>
|
||||||
zitadelAuth.hasRole('admin') ? import('@/views/Admin.vue') : import('@/views/NoAccess.vue')
|
hasRole('admin') ? import('@/views/Admin.vue') : import('@/views/NoAccess.vue')
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
zitadelAuth.oidcAuth.useRouter(router)
|
const hasRole = (role: string) => {
|
||||||
|
if (config.oidcProjectID === undefined) {
|
||||||
|
throw new Error('Config was not loaded')
|
||||||
|
}
|
||||||
|
const roles = oidcAuth.userProfile[`urn:zitadel:iam:org:project:${config.oidcProjectID}:roles`] as Array<any>
|
||||||
|
if (!roles) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return roles.find(r => r[role])
|
||||||
|
}
|
||||||
|
|
||||||
|
oidcAuth!.useRouter(router)
|
||||||
|
|
||||||
export default router
|
export default router
|
||||||
|
|
|
||||||
80
src/services/authentikAuth.ts
Normal file
80
src/services/authentikAuth.ts
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
import type { User } from 'oidc-client'
|
||||||
|
import { createOidcAuth, SignInType, type OidcAuth, LogLevel } from 'vue-oidc-client/vue3'
|
||||||
|
import { getConfig } from './siteConfig'
|
||||||
|
import type { Config } from '@/types/Config'
|
||||||
|
|
||||||
|
const loco = window.location
|
||||||
|
const appRootUrl = `${loco.protocol}//${loco.host}${import.meta.env.BASE_URL}`
|
||||||
|
|
||||||
|
let authObj = null as OidcAuth | null
|
||||||
|
|
||||||
|
export async function configureOidc() {
|
||||||
|
if (authObj) return Promise.resolve(authObj)
|
||||||
|
const appConfig: Config = await getConfig().then((c) => {
|
||||||
|
if (c === null) {
|
||||||
|
throw new Error("config was null")
|
||||||
|
}
|
||||||
|
return c
|
||||||
|
}).catch((reason) => {
|
||||||
|
console.log(reason)
|
||||||
|
throw new Error(reason);
|
||||||
|
})
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
authority: appConfig.oidcAuthority,
|
||||||
|
client_id: appConfig.oidcClientID,
|
||||||
|
response_type: 'code',
|
||||||
|
scope: 'openid profile email api offline_access'
|
||||||
|
}
|
||||||
|
|
||||||
|
authObj = createOidcAuth(
|
||||||
|
'main',
|
||||||
|
SignInType.Window,
|
||||||
|
appRootUrl,
|
||||||
|
{
|
||||||
|
...config,
|
||||||
|
// test use
|
||||||
|
prompt: 'login'
|
||||||
|
},
|
||||||
|
console,
|
||||||
|
LogLevel.Debug
|
||||||
|
)
|
||||||
|
|
||||||
|
// handle events
|
||||||
|
authObj.events.addAccessTokenExpiring(function () {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log('access token expiring')
|
||||||
|
})
|
||||||
|
|
||||||
|
authObj.events.addAccessTokenExpired(function () {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log('access token expired')
|
||||||
|
})
|
||||||
|
|
||||||
|
authObj.events.addSilentRenewError(function (err: Error) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.error('silent renew error', err)
|
||||||
|
})
|
||||||
|
|
||||||
|
authObj.events.addUserLoaded(function (user: User) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log('user loaded', user)
|
||||||
|
})
|
||||||
|
|
||||||
|
authObj.events.addUserUnloaded(function () {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log('user unloaded')
|
||||||
|
})
|
||||||
|
|
||||||
|
authObj.events.addUserSignedOut(function () {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log('user signed out')
|
||||||
|
})
|
||||||
|
|
||||||
|
authObj.events.addUserSessionChanged(function () {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log('user session changed')
|
||||||
|
})
|
||||||
|
|
||||||
|
return authObj
|
||||||
|
}
|
||||||
18
src/services/siteConfig.ts
Normal file
18
src/services/siteConfig.ts
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
import type { Config } from '@/types/Config'
|
||||||
|
import axios from 'axios'
|
||||||
|
|
||||||
|
let configObject = null as Config | null
|
||||||
|
|
||||||
|
export async function getConfig() {
|
||||||
|
if (configObject) return Promise.resolve(configObject)
|
||||||
|
|
||||||
|
configObject = await axios.get('/config.json?noCache=' + Date.now()).then((resp) => {
|
||||||
|
return {
|
||||||
|
apiBaseURL: resp.data.apiBaseURL,
|
||||||
|
oidcAuthority: resp.data.oidcAuthority,
|
||||||
|
oidcClientID: resp.data.oidcClientID,
|
||||||
|
oidcProjectID: resp.data.oidcProjectID
|
||||||
|
} as Config
|
||||||
|
})
|
||||||
|
return configObject
|
||||||
|
}
|
||||||
|
|
@ -3,8 +3,7 @@ import axios, { type AxiosRequestConfig } from 'axios'
|
||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import { computed, ref, toRaw } from 'vue'
|
import { computed, ref, toRaw } from 'vue'
|
||||||
import axiosRetry from 'axios-retry'
|
import axiosRetry from 'axios-retry'
|
||||||
import { getCurrentInstance } from 'vue'
|
import { apiBaseURL as apiBaseURLKey } from '@/types/ConfigSymbols'
|
||||||
import { apiBaseURL, apiBaseURL as apiBaseURLKey } from '@/types/ConfigSymbols'
|
|
||||||
import { inject } from 'vue'
|
import { inject } from 'vue'
|
||||||
|
|
||||||
const BLESSING = 1
|
const BLESSING = 1
|
||||||
|
|
@ -21,21 +20,26 @@ const noCacheConfig: AxiosRequestConfig = {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const usePowerItems = defineStore('powerItems', () => {
|
export const usePowerItems = defineStore('powerItems', () => {
|
||||||
|
//#region privateVariables
|
||||||
const BLESSING_POWER_ITEM_STORAGE = 'BLESSING_POWER_ITEM_STORAGE'
|
const BLESSING_POWER_ITEM_STORAGE = 'BLESSING_POWER_ITEM_STORAGE'
|
||||||
const FELLOW_POWER_ITEM_STORAGE = 'FELLOW_POWER_ITEM_STORAGE'
|
const FELLOW_POWER_ITEM_STORAGE = 'FELLOW_POWER_ITEM_STORAGE'
|
||||||
const INTIMACY_POWER_ITEM_STORAGE = 'INTIMACY_POWER_ITEM_STORAGE'
|
const INTIMACY_POWER_ITEM_STORAGE = 'INTIMACY_POWER_ITEM_STORAGE'
|
||||||
|
const apiBaseURL = inject(apiBaseURLKey)!
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
//#region state
|
||||||
const blessingPowerItems = ref(new Map<string, PowerItem>())
|
const blessingPowerItems = ref(new Map<string, PowerItem>())
|
||||||
const fellowPowerItems = ref(new Map<string, PowerItem>())
|
const fellowPowerItems = ref(new Map<string, PowerItem>())
|
||||||
const intimacyPowerItems = ref(new Map<string, PowerItem>())
|
const intimacyPowerItems = ref(new Map<string, PowerItem>())
|
||||||
const isLoadComplete = ref(false)
|
//#endregion
|
||||||
const apiBaseURL = inject(apiBaseURLKey)!
|
|
||||||
|
|
||||||
axiosRetry(axios, {
|
axiosRetry(axios, {
|
||||||
retries: 3,
|
retries: 3,
|
||||||
retryDelay: axiosRetry.exponentialDelay
|
retryDelay: axiosRetry.exponentialDelay
|
||||||
})
|
})
|
||||||
|
|
||||||
async function fetchPowerItems() {
|
//#region loaders
|
||||||
|
async function fetchBlessingItems() {
|
||||||
axios
|
axios
|
||||||
.get(apiBaseURL + '/powerItems/byType/' + BLESSING + '/asMap', noCacheConfig)
|
.get(apiBaseURL + '/powerItems/byType/' + BLESSING + '/asMap', noCacheConfig)
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
|
|
@ -52,6 +56,8 @@ export const usePowerItems = defineStore('powerItems', () => {
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.log(err)
|
console.log(err)
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
async function fetchFellowItems() {
|
||||||
axios
|
axios
|
||||||
.get(apiBaseURL + '/powerItems/byType/' + FELLOW + '/asMap', noCacheConfig)
|
.get(apiBaseURL + '/powerItems/byType/' + FELLOW + '/asMap', noCacheConfig)
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
|
|
@ -68,6 +74,8 @@ export const usePowerItems = defineStore('powerItems', () => {
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.log(err)
|
console.log(err)
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
async function fetchIntimacyItems() {
|
||||||
axios
|
axios
|
||||||
.get(apiBaseURL + '/powerItems/byType/' + INTIMACY + '/asMap', noCacheConfig)
|
.get(apiBaseURL + '/powerItems/byType/' + INTIMACY + '/asMap', noCacheConfig)
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
|
|
@ -84,9 +92,10 @@ export const usePowerItems = defineStore('powerItems', () => {
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.log(err)
|
console.log(err)
|
||||||
})
|
})
|
||||||
isLoadComplete.value = true
|
|
||||||
}
|
}
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
//#region setters
|
||||||
function updateOwned(key: string, newOwned: number) {
|
function updateOwned(key: string, newOwned: number) {
|
||||||
let cur = blessingPowerItems.value.get(key)
|
let cur = blessingPowerItems.value.get(key)
|
||||||
if (cur !== undefined) {
|
if (cur !== undefined) {
|
||||||
|
|
@ -118,16 +127,6 @@ export const usePowerItems = defineStore('powerItems', () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapToObj(map: Map<string, PowerItem>) {
|
|
||||||
return Array.from(map).reduce((obj, [key, value]) => {
|
|
||||||
// Doing weird magic to work with maps is infuriating, and I haven't found a better solution for this.
|
|
||||||
// So ignore that error TypeScript, I (don't) know what I'm doing!
|
|
||||||
// @ts-ignore: noImplicitAny
|
|
||||||
obj[key] = value
|
|
||||||
return obj
|
|
||||||
}, {})
|
|
||||||
}
|
|
||||||
|
|
||||||
function addPowerItem(newItem: PowerItem): Promise<PowerItem | null> {
|
function addPowerItem(newItem: PowerItem): Promise<PowerItem | null> {
|
||||||
const resultPromise: Promise<PowerItem | null> = new Promise((resolve, reject) => {
|
const resultPromise: Promise<PowerItem | null> = new Promise((resolve, reject) => {
|
||||||
axios
|
axios
|
||||||
|
|
@ -140,7 +139,9 @@ export const usePowerItems = defineStore('powerItems', () => {
|
||||||
|
|
||||||
return resultPromise
|
return resultPromise
|
||||||
}
|
}
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
//#region computed
|
||||||
const totalBlessingPower = computed(() =>
|
const totalBlessingPower = computed(() =>
|
||||||
[...blessingPowerItems.value.values()].reduce(
|
[...blessingPowerItems.value.values()].reduce(
|
||||||
(accumulator: number, currentValue: PowerItem) => {
|
(accumulator: number, currentValue: PowerItem) => {
|
||||||
|
|
@ -323,15 +324,29 @@ export const usePowerItems = defineStore('powerItems', () => {
|
||||||
0
|
0
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
//#endregion
|
||||||
|
|
||||||
fetchPowerItems()
|
//#region helpers
|
||||||
|
function mapToObj(map: Map<string, PowerItem>) {
|
||||||
|
return Array.from(map).reduce((obj, [key, value]) => {
|
||||||
|
// Doing weird magic to work with maps is infuriating, and I haven't found a better solution for this.
|
||||||
|
// So ignore that error TypeScript, I (don't) know what I'm doing!
|
||||||
|
// @ts-ignore: noImplicitAny
|
||||||
|
obj[key] = value
|
||||||
|
return obj
|
||||||
|
}, {})
|
||||||
|
}
|
||||||
|
//#endregion
|
||||||
|
|
||||||
return {
|
return {
|
||||||
blessingPowerItems,
|
blessingPowerItems,
|
||||||
fellowPowerItems,
|
fellowPowerItems,
|
||||||
intimacyPowerItems,
|
intimacyPowerItems,
|
||||||
isLoadComplete,
|
|
||||||
fetchPowerItems,
|
fetchBlessingItems,
|
||||||
|
fetchFellowItems,
|
||||||
|
fetchIntimacyItems,
|
||||||
|
|
||||||
updateOwned,
|
updateOwned,
|
||||||
totalBlessingPower,
|
totalBlessingPower,
|
||||||
standardBlessingItems,
|
standardBlessingItems,
|
||||||
|
|
|
||||||
6
src/types/Config.ts
Normal file
6
src/types/Config.ts
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
export type Config = {
|
||||||
|
apiBaseURL: string,
|
||||||
|
oidcAuthority: string,
|
||||||
|
oidcClientID: string,
|
||||||
|
oidcProjectID: string,
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,12 @@
|
||||||
import type { InjectionKey } from "vue";
|
import type { InjectionKey } from "vue";
|
||||||
|
import type { OidcAuth } from "vue-oidc-client/vue3";
|
||||||
|
|
||||||
const apiBaseURL = Symbol() as InjectionKey<string>
|
const apiBaseURL = Symbol() as InjectionKey<string>
|
||||||
|
const oidcProjectID = Symbol() as InjectionKey<string>
|
||||||
|
const oidc = Symbol() as InjectionKey<OidcAuth>
|
||||||
|
|
||||||
export {
|
export {
|
||||||
apiBaseURL
|
apiBaseURL,
|
||||||
|
oidcProjectID,
|
||||||
|
oidc
|
||||||
}
|
}
|
||||||
|
|
@ -4,6 +4,7 @@ import StandardItemsCard from '@/components/StandardItemsCard.vue'
|
||||||
import SummaryCard from '@/components/SummaryCard.vue'
|
import SummaryCard from '@/components/SummaryCard.vue'
|
||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
import { usePowerItems } from '@/stores/powerItems'
|
import { usePowerItems } from '@/stores/powerItems'
|
||||||
|
import { onBeforeMount } from 'vue'
|
||||||
|
|
||||||
const {
|
const {
|
||||||
standardBlessingItems,
|
standardBlessingItems,
|
||||||
|
|
@ -13,6 +14,15 @@ const {
|
||||||
specialBlessingItemsMaxTotal,
|
specialBlessingItemsMaxTotal,
|
||||||
specialBlessingItemsAveTotal
|
specialBlessingItemsAveTotal
|
||||||
} = storeToRefs(usePowerItems())
|
} = storeToRefs(usePowerItems())
|
||||||
|
|
||||||
|
onBeforeMount(() => {
|
||||||
|
if (standardBlessingItems.value.keys().next().done) {
|
||||||
|
usePowerItems().fetchBlessingItems()
|
||||||
|
}
|
||||||
|
if (specialBlessingItems.value.keys().next().done) {
|
||||||
|
usePowerItems().fetchBlessingItems()
|
||||||
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
@ -34,6 +44,7 @@ const {
|
||||||
/>
|
/>
|
||||||
<SummaryCard
|
<SummaryCard
|
||||||
class="ma-2 align-self-start"
|
class="ma-2 align-self-start"
|
||||||
|
item-type="Blessing"
|
||||||
:standard-total="standardBlessingItemTotal"
|
:standard-total="standardBlessingItemTotal"
|
||||||
:minimum-total="specialBlessingItemsMinTotal"
|
:minimum-total="specialBlessingItemsMinTotal"
|
||||||
:maximum-total="specialBlessingItemsMaxTotal"
|
:maximum-total="specialBlessingItemsMaxTotal"
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import StandardItemsCard from '@/components/StandardItemsCard.vue'
|
||||||
import SummaryCard from '@/components/SummaryCard.vue'
|
import SummaryCard from '@/components/SummaryCard.vue'
|
||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
import { usePowerItems } from '@/stores/powerItems'
|
import { usePowerItems } from '@/stores/powerItems'
|
||||||
|
import { onBeforeMount } from 'vue'
|
||||||
|
|
||||||
const {
|
const {
|
||||||
standardFellowItems,
|
standardFellowItems,
|
||||||
|
|
@ -13,6 +14,15 @@ const {
|
||||||
specialFellowItemsMaxTotal,
|
specialFellowItemsMaxTotal,
|
||||||
specialFellowItemsAveTotal
|
specialFellowItemsAveTotal
|
||||||
} = storeToRefs(usePowerItems())
|
} = storeToRefs(usePowerItems())
|
||||||
|
|
||||||
|
onBeforeMount(() => {
|
||||||
|
if (standardFellowItems.value.keys().next().done) {
|
||||||
|
usePowerItems().fetchFellowItems()
|
||||||
|
}
|
||||||
|
if (specialFellowItems.value.keys().next().done) {
|
||||||
|
usePowerItems().fetchFellowItems()
|
||||||
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
@ -33,6 +43,7 @@ const {
|
||||||
:average-total="specialFellowItemsAveTotal"
|
:average-total="specialFellowItemsAveTotal"
|
||||||
/>
|
/>
|
||||||
<SummaryCard
|
<SummaryCard
|
||||||
|
item-type="Fellow"
|
||||||
class="ma-2 align-self-start"
|
class="ma-2 align-self-start"
|
||||||
:standard-total="standardFellowItemTotal"
|
:standard-total="standardFellowItemTotal"
|
||||||
:minimum-total="specialFellowItemsMinTotal"
|
:minimum-total="specialFellowItemsMinTotal"
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import StandardItemsCard from '@/components/StandardItemsCard.vue'
|
||||||
import SummaryCard from '@/components/SummaryCard.vue'
|
import SummaryCard from '@/components/SummaryCard.vue'
|
||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
import { usePowerItems } from '@/stores/powerItems'
|
import { usePowerItems } from '@/stores/powerItems'
|
||||||
|
import { onBeforeMount } from 'vue'
|
||||||
|
|
||||||
const {
|
const {
|
||||||
standardIntimacyItems,
|
standardIntimacyItems,
|
||||||
|
|
@ -13,6 +14,15 @@ const {
|
||||||
specialIntimacyItemsMaxTotal,
|
specialIntimacyItemsMaxTotal,
|
||||||
specialIntimacyItemsAveTotal
|
specialIntimacyItemsAveTotal
|
||||||
} = storeToRefs(usePowerItems())
|
} = storeToRefs(usePowerItems())
|
||||||
|
|
||||||
|
onBeforeMount(() => {
|
||||||
|
if (standardIntimacyItems.value.keys().next().done) {
|
||||||
|
usePowerItems().fetchIntimacyItems()
|
||||||
|
}
|
||||||
|
if (specialIntimacyItems.value.keys().next().done) {
|
||||||
|
usePowerItems().fetchIntimacyItems()
|
||||||
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
@ -33,6 +43,7 @@ const {
|
||||||
:average-total="specialIntimacyItemsAveTotal"
|
:average-total="specialIntimacyItemsAveTotal"
|
||||||
/>
|
/>
|
||||||
<SummaryCard
|
<SummaryCard
|
||||||
|
item-type="Intimacy"
|
||||||
class="ma-2 align-self-start"
|
class="ma-2 align-self-start"
|
||||||
:standard-total="standardIntimacyItemTotal"
|
:standard-total="standardIntimacyItemTotal"
|
||||||
:minimum-total="specialIntimacyItemsMinTotal"
|
:minimum-total="specialIntimacyItemsMinTotal"
|
||||||
|
|
|
||||||
|
|
@ -28,14 +28,15 @@
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { getCurrentInstance } from 'vue';
|
import { oidc } from '@/types/ConfigSymbols';
|
||||||
|
import { inject } from 'vue';
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { defineComponent } from 'vue'
|
import { defineComponent } from 'vue'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
computed: {
|
computed: {
|
||||||
user() {
|
user() {
|
||||||
return this.$zitadel.oidcAuth.userProfile
|
return inject(oidc)?.userProfile
|
||||||
},
|
},
|
||||||
claims() {
|
claims() {
|
||||||
if (this.user) {
|
if (this.user) {
|
||||||
|
|
@ -51,11 +52,12 @@ export default defineComponent({
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
const zitadel = ref(getCurrentInstance()?.appContext.config.globalProperties.$zitadel!)
|
const zitadel = ref(inject(oidc))
|
||||||
const user = ref(zitadel.value.oidcAuth.userProfile)
|
const user = ref(zitadel.value?.userProfile)
|
||||||
const signout = function() {
|
const signout = function() {
|
||||||
if (user.value) {
|
if (user.value) {
|
||||||
zitadel.value.oidcAuth.signOut()
|
zitadel.value?.signOut()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
console.log(zitadel.value)
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue