Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 53 additions & 45 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,62 +7,70 @@
<script lang="ts">
import Component from 'vue-class-component'
import Vue from 'vue'
import { Action, Getter } from 'vuex-class'
import { RoomAction, Locale, GameName, RoomGetters } from '@/store/modules/room'
import { AuthenticationActions, AuthenticationGetters, ExtendedJWT, JWT_KEY } from '@/store/modules/authentication'
import { namespace } from 'vuex-class'
import { Namespaces } from '@/store'
import { Api } from './store/modules/types'
import { getWowsApiData } from '@/games/wows/api'
import { GameName, Locale, RoomAction, RoomGetters } from '@/store/modules/room'
import { AuthenticationActions, AuthenticationGetters, ExtendedJWT, JWT_KEY } from '@/store/modules/authentication'

@Component({
name: 'TheApp'
})
const authNamespace = namespace(Namespaces.AUTH)
const roomNamespace = namespace(Namespaces.ROOM)

@Component({
name: 'TheApp'
})
export default class TheApp extends Vue {
@Action(`room/${RoomAction.SET_GAME_NAME}`) setGameName!: (name: string) => void
@Action(`room/${RoomAction.SET_GAME_API}`) setGameApi!: (api: Api) => void
@Action(`room/${RoomAction.SET_LOCALE}`) setLocale!: (locale: Locale) => void
@Getter(`room/${RoomGetters.GAME_NAME}`) game!: GameName
@Action(`authentication/${AuthenticationActions.AUTHENTICATE}`) authenticate!: (token: string) => Promise<ExtendedJWT>
@Action(`authentication/${AuthenticationActions.CHECK_TOKEN_EXPIRY}`) checkTokenExpiry!: () => Promise<boolean>
@Action(`authentication/${AuthenticationActions.STORE_TOKEN}`) storeToken!: (token: string) => void
@Getter(`authentication/${AuthenticationGetters.JWT}`) jwt!: ExtendedJWT
@roomNamespace.Action(RoomAction.SET_GAME_NAME) setGameName!: (name: string) => void
@roomNamespace.Action(RoomAction.SET_GAME_API) setGameApi!: (api: Api) => void
@roomNamespace.Action(RoomAction.SET_LOCALE) setLocale!: (locale: Locale) => void
@roomNamespace.Getter(RoomGetters.GAME_NAME) game!: GameName
@authNamespace.Action(AuthenticationActions.AUTHENTICATE) authenticate!: (token: string) => Promise<ExtendedJWT>
@authNamespace.Action(AuthenticationActions.STORE_TOKEN) storeToken!: (token: string) => void
@authNamespace.Action(AuthenticationActions.CHECK_TOKEN_EXPIRY) checkTokenExpiry!: () => Promise<boolean>
@authNamespace.Action(AuthenticationActions.LOAD_PROVIDERS) loadProviders!: () => void
@authNamespace.Getter(AuthenticationGetters.JWT) jwt!: ExtendedJWT

async created () {
this.setGameName(GameName['WOWS'])
this.setLocale(Locale['EN'])
this.initAuthentication()
}
async created () {
this.setGameName(GameName['WOWS'])
this.setLocale(Locale['EN'])
this.initAuthentication()
}

async initAuthentication () {
const localToken = localStorage.getItem(JWT_KEY)
async initAuthentication () {
this.loadProviders()
const localToken = localStorage.getItem(JWT_KEY)

if (this.checkTokenExpiry()) {
if (this.$route?.query?.code) {
this.authenticate(this.$route.query.code as string).then(jwt => this.storeToken(jwt.encoded))
} else if (localToken !== null) {
this.authenticate(localToken)
}
if (localToken) {
switch (this.game) {
case GameName['WOWS']:
await getWowsApiData(localToken, this.setGameApi)
break
default: break
if (this.checkTokenExpiry()) {
if (this.$route?.query?.code) {
this.authenticate(this.$route.query.code as string).then(jwt => this.storeToken(jwt.encoded))
} else if (localToken !== null) {
this.authenticate(localToken)
}
if (localToken) {
switch (this.game) {
case GameName['WOWS']:
await getWowsApiData(localToken, this.setGameApi)
break
default:
break
}
}
}
}
}
}
</script>
<style lang="scss">
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
height: 100vh;
background-color: $room-secondary;
font-size: $app-fontsize;
}
html, .v-application--wrap {
overflow: hidden;
}
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
height: 100vh;
background-color: $room-secondary;
font-size: $app-fontsize;
}

html, .v-application--wrap {
overflow: hidden;
}
</style>
66 changes: 32 additions & 34 deletions src/components/navigation/LoginCard.vue
Original file line number Diff line number Diff line change
@@ -1,52 +1,50 @@
<template>
<v-card>
<v-card-title>Login</v-card-title>
<v-divider></v-divider>
<v-card class="login-card">
<v-card-title class="custom-login-card-title">
<div>{{ $t('navigation.login.card.title') }}</div>
<v-btn icon @click="closeHandler" v-if="isMobile">
<v-icon>fa-times</v-icon>
</v-btn>
</v-card-title>
<v-card-text>
<h4>Please select a realm to log in with</h4>
<provider-block v-for="(provider, name) in providers"
:provider-name="name" :provider="provider" :key="name">
</provider-block>
</v-card-text>
<v-card-actions>
<v-btn color="primary" @click="authEU" depressed>
EU
</v-btn>
<v-btn color="primary" @click="authNA" depressed>
NA
</v-btn>
<v-btn color="primary" @click="authASIA" depressed>
ASIA
</v-btn>
<v-btn color="primary" @click="authRU" depressed>
CIS
</v-btn>
</v-card-actions>
</v-card>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
import { Component, Emit, Prop, Vue } from 'vue-property-decorator'
import { namespace } from 'vuex-class'
import { Namespaces } from '@/store'
import { AuthenticationActions, JWTRegion } from '@/store/modules/authentication'
import { AuthenticationActions, AuthenticationGetters } from '@/store/modules/authentication'
import { Providers } from '@/util/ProvidersUtil'
import ProviderBlock from '@/components/navigation/login/ProviderBlock.vue'

const authNamespace = namespace(Namespaces.AUTH)

@Component({
name: 'g-login-card'
name: 'LoginCard',
components: {
ProviderBlock
}
})
export default class extends Vue {
@authNamespace.Action(AuthenticationActions.LOGIN_WG) authenticate!: (region: string) => void;
authEU () {
this.authenticate(JWTRegion.EU)
}
authNA () {
this.authenticate(JWTRegion.NA)
}
authASIA () {
this.authenticate(JWTRegion.SA)
}
authRU () {
this.authenticate(JWTRegion.RU)
}
@authNamespace.Action(AuthenticationActions.LOGIN_WG) authenticate!: (endpoint: string) => void
@authNamespace.Getter(AuthenticationGetters.PROVIDERS) providers!: Providers
@Prop({ default: false }) isMobile!: boolean

@Emit() closeHandler () {
return null
}
}
</script>

<style scoped>
.custom-login-card-title {
font-weight: bold;
display: flex;
justify-content: space-between;
}
</style>
78 changes: 44 additions & 34 deletions src/components/navigation/TheUserMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,17 @@
<v-icon size="20">fa-user-circle</v-icon>
</v-btn>
</template>
<span>Sign in / Sign out</span>
<span>{{ $t('user.profile') }}</span>
</v-tooltip>
</template>
<v-list>
<v-list-item v-if="isAuth" @click="logout">
<v-list-item-title>Logout</v-list-item-title>
<v-list-item v-if="isAuth" @click="onClickLogout">
<v-list-item-title>{{ $t('navigation.login.logout') }}</v-list-item-title>
</v-list-item>
<v-list-item v-else @click="doOpen">
<v-list-item-title>Login</v-list-item-title>
<v-dialog v-model="dialogOpen" @click:outside="dialogOpen = false" max-width="300px">
<g-login-card></g-login-card>
<v-list-item v-else @click="openLoginDialog">
<v-list-item-title>{{ $t('navigation.login.title') }}</v-list-item-title>
<v-dialog v-model="isDialogOpen" @click:outside="onClickCloseLoginDialog" max-width="500px">
<login-card></login-card>
</v-dialog>
</v-list-item>
<v-list-item
Expand All @@ -41,14 +41,14 @@
</v-list>
</v-menu>
<v-list v-else dense style="width: 100%;">
<v-subheader>User Profile</v-subheader>
<v-list-item v-if="isAuth" @click="logout">
<v-list-item-title>Logout</v-list-item-title>
<v-subheader>{{ $t('user.profile') }}</v-subheader>
<v-list-item v-if="isAuth" @click="onClickLogout">
<v-list-item-title>{{ $t('navigation.login.logout') }}</v-list-item-title>
</v-list-item>
<v-list-item v-else @click="doOpen">
<v-list-item-title>Login</v-list-item-title>
<v-dialog v-model="dialogOpen" @click:outside="dialogOpen = false" fullscreen>
<g-login-card></g-login-card>
<v-list-item v-else @click="openLoginDialog">
<v-list-item-title>{{ $t('navigation.login.title') }}</v-list-item-title>
<v-dialog v-model="isDialogOpen" @click:outside="onClickCloseLoginDialog" fullscreen>
<login-card :is-mobile="isMobile" v-on:close-handler="onClickCloseLoginDialog"></login-card>
</v-dialog>
</v-list-item>
<v-list-item
Expand All @@ -68,35 +68,45 @@ import { Component, Prop, Vue } from 'vue-property-decorator'
import { namespace } from 'vuex-class'
import { Namespaces } from '@/store'
import { AuthenticationActions, AuthenticationGetters } from '@/store/modules/authentication'
import GLoginCard from '@/components/navigation/LoginCard.vue'

interface UserMenuItem {
text: string;
title: string;
}
import LoginCard from '@/components/navigation/LoginCard.vue'

const authNamespace = namespace(Namespaces.AUTH)

@Component({
name: 'TheUserMenu',
components: { GLoginCard }
})
interface UserMenuItem {
text: string;
title: string;
}

@Component({
name: 'TheUserMenu',
components: { LoginCard }
})
export default class TheUserMenu extends Vue {
@Prop() private isMobile!: boolean;
@authNamespace.Getter(AuthenticationGetters.IS_AUTH) isAuth!: boolean
@authNamespace.Action(AuthenticationActions.LOGIN_WG) authenticate!: (region: string) => void;
@authNamespace.Action(AuthenticationActions.LOGOUT) logout!: () => void
@authNamespace.Action(AuthenticationActions.LOGOUT) onClickLogout!: () => void

dialogOpen = false
doOpen () {
setTimeout(() => { this.dialogOpen = true })
}
userMenuItems: UserMenuItem[] = []
@Prop() private mobile!: boolean

// eslint-disable-next-line
userMenuItemsClickHandler (item: UserMenuItem) {
// do stuff
}
isDialogOpen = false

openLoginDialog () {
setTimeout(() => {
this.isDialogOpen = true
})
}

onClickCloseLoginDialog () {
this.isDialogOpen = false
}

userMenuItems: UserMenuItem[] = []

// eslint-disable-next-line
userMenuItemsClickHandler(item: UserMenuItem) {
// do stuff
}
}

</script>
Expand Down
50 changes: 50 additions & 0 deletions src/components/navigation/login/ProviderBlock.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<template>
<div class="custom-provider-container">
<h3>{{providerName}}</h3>
<v-divider>
</v-divider>
<div class="custom-login-btn-container">
<v-btn v-for="entry of entries" @click="authenticate(entry.endpoint)" :key="entry.key"
class="login-btn" color="primary">
{{entry.key}}
</v-btn>
</div>
</div>
</template>

<script lang="ts">

import { Component, Prop, Vue } from 'vue-property-decorator'
import { AuthenticationActions } from '@/store/modules/authentication'
import { namespace } from 'vuex-class'
import { Namespaces } from '@/store'
import { Provider } from '@/util/ProvidersUtil'

const authNamespace = namespace(Namespaces.AUTH)

@Component({
name: 'ProviderBlock'
})
export default class extends Vue {
@Prop() providerName!: string
@Prop() provider!: Provider
@authNamespace.Action(AuthenticationActions.LOGIN_WG) authenticate!: (endpoint: string) => void

get entries () {
return this.provider.entries
}
}
</script>

<style scoped lang="scss">
.custom-login-btn-container {
margin-top: 5px;
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-column-gap: 5px;
}

.custom-provider-container {
margin-top: 10px;
}
</style>
Loading