update
This commit is contained in:
1 parent
70066f3086
commit
0348f84255
4 files changed
+260
-36
No files matched your search
+47
-20
@@ -1,6 +1,20 @@
|
||||
import _axios, { AxiosInstance } from 'axios'
|
||||
|
||||
export type IType = 'character' | 'vocabulary' | 'sentence'
|
||||
export type ITypeLevel = 'character' | 'vocabulary'
|
||||
export type IType = ITypeLevel | 'sentence'
|
||||
|
||||
export interface ILevelBrowserByType {
|
||||
whatToShow: string[]
|
||||
}
|
||||
|
||||
export type ILevelBrowser = Record<ITypeLevel, ILevelBrowserByType>
|
||||
|
||||
export interface IUserSettings {
|
||||
identifier: string
|
||||
level: number
|
||||
levelMin?: number
|
||||
level_browser?: ILevelBrowser
|
||||
}
|
||||
|
||||
export interface IEntry {
|
||||
id: string
|
||||
@@ -41,18 +55,19 @@ class Api {
|
||||
}
|
||||
|
||||
setApiKey()
|
||||
const r = await this.user_getSettings()
|
||||
|
||||
if (r) return r
|
||||
apiKey = ''
|
||||
setApiKey()
|
||||
|
||||
return null
|
||||
return await this.isAuthorized().then((r) => {
|
||||
if (!r) {
|
||||
apiKey = ''
|
||||
setApiKey()
|
||||
}
|
||||
return r
|
||||
})
|
||||
}
|
||||
|
||||
async isAuthorized(): Promise<boolean> {
|
||||
if (this._isAuthorized && !this._user) {
|
||||
const r = await this.user_getSettings()
|
||||
const r = await this.user_getSettings({ select: ['identifier'] })
|
||||
if (r) {
|
||||
this._user = r.identifier
|
||||
this._isAuthorized = true
|
||||
@@ -62,21 +77,15 @@ class Api {
|
||||
return this._isAuthorized
|
||||
}
|
||||
|
||||
async user_getSettings() {
|
||||
async user_getSettings(params: { select: (keyof IUserSettings)[] }) {
|
||||
const r = await this.axios
|
||||
.get('/api/user', {
|
||||
params: {
|
||||
select: 'level,levelMin,identifier',
|
||||
...params,
|
||||
select: params.select.join(','),
|
||||
},
|
||||
})
|
||||
.then(
|
||||
(r) =>
|
||||
r.data as {
|
||||
level: number
|
||||
levelMin?: number
|
||||
identifier: string
|
||||
}
|
||||
)
|
||||
.then((r) => r.data as IUserSettings)
|
||||
.then((r) => ({
|
||||
...r,
|
||||
levelMin: r.levelMin || 1,
|
||||
@@ -84,13 +93,16 @@ class Api {
|
||||
.catch(() => null)
|
||||
|
||||
if (!r) {
|
||||
return
|
||||
return null
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
async user_updateSettings(u: { levelMin: number }) {
|
||||
async user_updateSettings(u: {
|
||||
levelMin?: number
|
||||
level_browser?: ILevelBrowser
|
||||
}) {
|
||||
return await this.axios.patch('/api/user', u)
|
||||
}
|
||||
|
||||
@@ -258,6 +270,21 @@ class Api {
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
async library_getLevelList(payload: {
|
||||
type: ITypeLevel
|
||||
settings: ILevelBrowserByType
|
||||
}) {
|
||||
return await this.axios.post('/api/library/getLevelList', payload).then(
|
||||
(r) =>
|
||||
r.data as {
|
||||
result: {
|
||||
entry: string
|
||||
level: number
|
||||
}[]
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export const api = new Api()
|
||||
@@ -0,0 +1,146 @@
|
||||
<template>
|
||||
<section>
|
||||
<div class="LevelPage container">
|
||||
<div class="field">
|
||||
<label class="label">Filter</label>
|
||||
<b-field>
|
||||
<b-radio-button
|
||||
v-model="whatToShow"
|
||||
native-value="all"
|
||||
type="is-success"
|
||||
>
|
||||
Show all
|
||||
</b-radio-button>
|
||||
<b-radio-button
|
||||
v-model="whatToShow"
|
||||
native-value="learning"
|
||||
type="is-warning"
|
||||
>
|
||||
Learning
|
||||
</b-radio-button>
|
||||
<b-radio-button
|
||||
v-model="whatToShow"
|
||||
native-value="all-quiz"
|
||||
type="is-info"
|
||||
>
|
||||
All quiz
|
||||
</b-radio-button>
|
||||
</b-field>
|
||||
</div>
|
||||
|
||||
<section class="card">
|
||||
<div class="card-content">
|
||||
<LibraryCard
|
||||
v-for="{ level, entries } in sublist"
|
||||
:key="level"
|
||||
:title="`Level ${level}`"
|
||||
:entries="entries.map((entry) => ({ entry }))"
|
||||
:type="type"
|
||||
:open="true"
|
||||
/>
|
||||
|
||||
<b-pagination
|
||||
class="mt-4"
|
||||
v-if="list.length > perPage"
|
||||
v-model="page"
|
||||
:total="list.length"
|
||||
:per-page="perPage"
|
||||
icon-prev="angle-left"
|
||||
icon-next="angle-right"
|
||||
@change="(p) => (page = p)"
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Prop, Vue, Watch } from 'vue-property-decorator'
|
||||
import { api, ILevelBrowser, ITypeLevel } from '~/assets/api'
|
||||
|
||||
@Component<LevelCard>({
|
||||
created() {
|
||||
this.init()
|
||||
},
|
||||
})
|
||||
export default class LevelCard extends Vue {
|
||||
@Prop() type!: ITypeLevel
|
||||
|
||||
isLoading = true
|
||||
|
||||
list: {
|
||||
level: number
|
||||
entries: string[]
|
||||
}[] = []
|
||||
|
||||
settings: ILevelBrowser = {
|
||||
character: {
|
||||
whatToShow: ['all'],
|
||||
},
|
||||
vocabulary: {
|
||||
whatToShow: ['all'],
|
||||
},
|
||||
}
|
||||
page = 1
|
||||
perPage = 5
|
||||
|
||||
get sublist() {
|
||||
return this.list.slice(
|
||||
(this.page - 1) * this.perPage,
|
||||
this.page * this.perPage
|
||||
)
|
||||
}
|
||||
|
||||
async init() {
|
||||
const r = await api.user_getSettings({
|
||||
select: ['level_browser'],
|
||||
})
|
||||
|
||||
if (r?.level_browser) {
|
||||
this.settings = r.level_browser
|
||||
}
|
||||
|
||||
await this.setCurrentData()
|
||||
this.isLoading = false
|
||||
}
|
||||
|
||||
async setCurrentData() {
|
||||
const { result } = await api.library_getLevelList({
|
||||
type: this.type,
|
||||
settings: this.settings[this.type],
|
||||
})
|
||||
|
||||
const allData = new Map<number, string[]>()
|
||||
|
||||
result.map(({ entry, level }) => {
|
||||
const levelData = allData.get(level) || []
|
||||
levelData.push(entry)
|
||||
allData.set(level, levelData)
|
||||
})
|
||||
|
||||
this.list = Array.from(allData)
|
||||
.sort(([lv1], [lv2]) => lv1 - lv2)
|
||||
.map(([level, entries]) => ({ level, entries }))
|
||||
}
|
||||
|
||||
@Watch('settings')
|
||||
async onSettingsChanged() {
|
||||
this.page = 1
|
||||
this.setCurrentData()
|
||||
await api.user_updateSettings({
|
||||
level_browser: this.settings,
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.tag {
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
.b-table {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,25 @@
|
||||
<template>
|
||||
<b-tabs :value="1">
|
||||
<b-tab-item label="Character">
|
||||
<level-card type="character" />
|
||||
</b-tab-item>
|
||||
<b-tab-item label="Vocabulary">
|
||||
<level-card type="vocabulary" />
|
||||
</b-tab-item>
|
||||
</b-tabs>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator'
|
||||
import LevelCard from '../cards/LevelCard.vue'
|
||||
|
||||
@Component<LevelTab>({
|
||||
components: {
|
||||
LevelCard,
|
||||
},
|
||||
created() {
|
||||
this.$emit('title', 'Level')
|
||||
},
|
||||
})
|
||||
export default class LevelTab extends Vue {}
|
||||
</script>
|
||||
+42
-16
@@ -1,11 +1,19 @@
|
||||
import { actionTree, getAccessorType, mutationTree } from 'typed-vuex'
|
||||
import { api } from '~/assets/api'
|
||||
import { jsonClone } from '~/assets/util'
|
||||
|
||||
const TAB_SETTINGS = 'TABS_SETTINGS'
|
||||
|
||||
interface ISettings {
|
||||
level: number | null
|
||||
levelMin: number | null
|
||||
sentenceMin: number | null
|
||||
sentenceMax: number | null
|
||||
}
|
||||
|
||||
interface ITab {
|
||||
title: string
|
||||
component: string
|
||||
permanent?: boolean
|
||||
query: Record<string, string>
|
||||
}
|
||||
|
||||
export const state = () => ({
|
||||
@@ -16,12 +24,7 @@ export const state = () => ({
|
||||
sentenceMax: null,
|
||||
} as ISettings,
|
||||
isApp: false,
|
||||
tabs: [] as {
|
||||
title: string
|
||||
component: string
|
||||
permanent?: boolean
|
||||
query: Record<string, string>
|
||||
}[],
|
||||
tabs: [] as ITab[],
|
||||
activeTab: 0,
|
||||
identifier: '',
|
||||
})
|
||||
@@ -33,9 +36,26 @@ export const mutations = mutationTree(state, {
|
||||
SET_IS_APP(state, isApp: boolean) {
|
||||
state.isApp = isApp
|
||||
},
|
||||
SET_ALL_TABS(
|
||||
state,
|
||||
o: {
|
||||
tabs: ITab[]
|
||||
activeTab: number
|
||||
} = state
|
||||
) {
|
||||
localStorage.setItem(
|
||||
TAB_SETTINGS,
|
||||
JSON.stringify({
|
||||
tabs: o.tabs,
|
||||
activeTabs: o.activeTab,
|
||||
})
|
||||
)
|
||||
state.tabs = jsonClone(o.tabs)
|
||||
state.activeTab = jsonClone(o.activeTab)
|
||||
},
|
||||
SET_TAB_TITLE(state, { i, title }: { i: number; title: string }) {
|
||||
state.tabs[i].title = title
|
||||
state.tabs = JSON.parse(JSON.stringify(state.tabs))
|
||||
this.SET_ALL_TABS(state)
|
||||
},
|
||||
ADD_TAB(
|
||||
state,
|
||||
@@ -70,6 +90,7 @@ export const mutations = mutationTree(state, {
|
||||
}
|
||||
|
||||
state.activeTab = state.tabs.length - 1
|
||||
this.SET_ALL_TABS(state)
|
||||
},
|
||||
DELETE_TAB(state, { i }: { i: number }) {
|
||||
state.tabs.splice(i, 1)
|
||||
@@ -78,16 +99,15 @@ export const mutations = mutationTree(state, {
|
||||
state.activeTab = state.tabs.length - 1
|
||||
}
|
||||
|
||||
state.tabs = JSON.parse(JSON.stringify(state.tabs))
|
||||
this.SET_ALL_TABS(state)
|
||||
},
|
||||
SET_TAB_COMPONENT(state, { i, component }: { i: number; component: string }) {
|
||||
state.tabs[i].component = component
|
||||
|
||||
state.tabs = JSON.parse(JSON.stringify(state.tabs))
|
||||
state.activeTab = i
|
||||
this.SET_ALL_TABS(state)
|
||||
},
|
||||
SET_TAB_CURRENT(state, { i }: { i: number }) {
|
||||
state.activeTab = i
|
||||
this.SET_ALL_TABS(state)
|
||||
},
|
||||
SET_IDENTIFIER(state, name: string) {
|
||||
state.identifier = name
|
||||
@@ -97,8 +117,16 @@ export const mutations = mutationTree(state, {
|
||||
export const actions = actionTree(
|
||||
{ state, mutations },
|
||||
{
|
||||
async nuxtServerInit({ dispatch, commit }) {
|
||||
await dispatch('updateSetings')
|
||||
|
||||
const settings = localStorage.getItem(TAB_SETTINGS)
|
||||
if (settings) commit('SET_ALL_TABS', JSON.parse(settings))
|
||||
},
|
||||
async updateSettings({ commit }) {
|
||||
const r = await api.user_getSettings()
|
||||
const r = await api.user_getSettings({
|
||||
select: ['identifier', 'levelMin', 'level'],
|
||||
})
|
||||
commit('SET_IS_APP', !!r)
|
||||
commit('SET_IDENTIFIER', r?.identifier || '')
|
||||
|
||||
@@ -115,8 +143,6 @@ export const actions = actionTree(
|
||||
commit('SET_SETTINGS', {
|
||||
level: r?.level || null,
|
||||
levelMin: r?.levelMin || null,
|
||||
sentenceMin: null,
|
||||
sentenceMax: null,
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user