diff --git a/package.json b/package.json index 1da17ea5..79855838 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "penguin-stats-frontend", - "version": "1.1.1", + "version": "1.1.2", "private": true, "scripts": { "serve": "vue-cli-service serve", @@ -15,7 +15,6 @@ "aos": "^2.3.4", "core-js": "^2.6.5", "dayjs": "^1.8.15", - "idb": "^4.0.4", "js-cookie": "^2.2.1", "plotly.js": "^1.49.2", "vue": "^2.6.10", diff --git a/public/index.html b/public/index.html index 5746a9b0..43de3f8e 100644 --- a/public/index.html +++ b/public/index.html @@ -1,21 +1,399 @@ - - - - - - - - - 企鹅物流数据统计 - - - - -
- - + + + + + + + + + + + + + + 企鹅物流数据统计 + + + + + +
+
+ +
+
+
+
+
+
+
+
+
+ 正在加载 +
+ 首次加载可能较慢,请耐心等待 +
+ +
+
+ + + + + diff --git a/src/App.vue b/src/App.vue index 001612c1..97df1dad 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,20 +1,16 @@ @@ -289,6 +311,7 @@ import Console from "@/utils/Console"; import strings from "@/utils/strings"; import config from "@/config"; + import {mapGetters} from "vuex"; export default { name: 'App', @@ -311,6 +334,10 @@ export default { }, { id: 'ja', name: '日本語' + }, { + id: 'ko', + name: '한국어', + beta: true, } ], prefetchingResources: false, @@ -319,14 +346,21 @@ export default { } }, computed: { - dark: { + ...mapGetters('settings', ['language', 'dark']), + appDark: { get () { - return this.$store.state.settings.dark + return this.dark }, set (value) { - this.$store.commit('switchDark', value) + this.$store.commit('settings/switchDark', value) this.$vuetify.theme.dark = value } + }, + localizationMapper: { + get () { + return this.localizations.indexOf(this.localizations.find(el => el.id === this.$i18n.locale)) + }, + set () {} } }, watch: { @@ -337,15 +371,15 @@ export default { 'dark': ['onDarkChange'] }, beforeMount() { - this.routes = this.$router.options.routes.filter(el => !(el.meta.hide)); - this.$store.dispatch("fetchData", false) + this.routes = this.$router.options.routes.filter(el => !el.meta.hide); + this.$store.dispatch("data/fetch", false) }, - mounted () { + created () { this.randomizeLogo(); - this.onDarkChange(this.$store.state.settings.dark); + this.onDarkChange(this.dark); - if (this.$store.getters.language) { - this.changeLocale(this.$store.getters.language, false) + if (this.language) { + this.changeLocale(this.language, false) } else { const language = strings.getFirstBrowserLanguage(); Console.debug("[i18n] detected language", language); @@ -356,13 +390,15 @@ export default { } } - if (this.$store.state.settings.dark) { - this.$vuetify.theme.dark = this.$store.state.settings.dark + Console.debug("(before init) dark status", this.dark, this.$vuetify.theme.dark); + if (typeof this.dark === "boolean") { + this.$vuetify.theme.dark = this.dark } + Console.debug("(after init) dark status", this.dark, this.$vuetify.theme.dark) }, methods: { async refreshData () { - await this.$store.dispatch("fetchData", true); + await this.$store.dispatch("data/fetch", true); }, onDarkChange (newValue) { if (newValue) { @@ -404,7 +440,7 @@ export default { Console.debug("[i18n] locale changed to:", localeId, "| saving to vuex:", save); this.$i18n.locale = localeId; // this.$vuetify.lang.current = localeId; - if (save) this.$store.commit("changeLocale", localeId); + if (save) this.$store.commit("settings/changeLocale", localeId); document.title = `${this.$t(this.$route.meta.i18n) + ' | ' || ''}${this.$t('app.name')}`; } else { Console.debug("[i18n] Same locale"); @@ -413,9 +449,9 @@ export default { logRouteEvent (newValue) { if (newValue.name === "StatsByStage_Selected") { // Console.log(this.$store.state.dataSource, newValue.params.stageId); - this.$ga.event('result', 'fetch_' + this.$store.state.dataSource, newValue.params.stageId, 1) + this.$ga.event('result', 'fetch_' + this.$store.getters['dataSource/source'], newValue.params.stageId, 1) } else if (newValue.name === "StatsByItem_Selected") { - this.$ga.event('result', 'fetch_' + this.$store.state.dataSource, newValue.params.itemId, 1) + this.$ga.event('result', 'fetch_' + this.$store.getters['dataSource/source'], newValue.params.itemId, 1) } } } @@ -447,10 +483,12 @@ export default { } .drawer-logo:hover { - height: 320px; + height: 304px; padding: 32px; } - + .drawer-logo--two-line:hover { + height: 336px; + } .drawer-logo > .description { margin-top: 16px; text-align: center; @@ -513,4 +551,15 @@ export default { word-break: break-word; } + .monospace { + font-family: SF Mono, "Droid Sans Mono", Ubuntu Mono, Consolas, Courier New, Courier, monospace; + } + + .footer--safe-area { + padding-top: 8px !important; + /*In case the old browsers doesn't support advanced CSS calculations*/ + padding-bottom: 8px !important; + padding-bottom: calc(max(env(safe-area-inset-bottom), 8px)) !important; + } + diff --git a/src/assets/preloader_i18n.js b/src/assets/preloader_i18n.js new file mode 100644 index 00000000..62a487e8 --- /dev/null +++ b/src/assets/preloader_i18n.js @@ -0,0 +1,91 @@ +"use strict"; + +let _i18n = { + getFirstBrowserLanguageWithRegionCode () { + let nav = window.navigator, + browserLanguagePropertyKeys = ['language', 'browserLanguage', 'systemLanguage', 'userLanguage'], + i, + language, + len, + shortLanguage = null; + + // support for HTML 5.1 "navigator.languages" + if (Array.isArray(nav.languages)) { + for (i = 0; i < nav.languages.length; i++) { + language = nav.languages[i]; + len = language.length; + if (!shortLanguage && len) { + shortLanguage = language; + } + if (language && len>2) { + return language; + } + } + } + + // support for other well known properties in browsers + for (i = 0; i < browserLanguagePropertyKeys.length; i++) { + language = nav[browserLanguagePropertyKeys[i]]; + //skip this loop iteration if property is null/undefined. IE11 fix. + if (language == null) { continue; } + len = language.length; + if (!shortLanguage && len) { + shortLanguage = language; + } + if (language && len > 2) { + return language; + } + } + + return shortLanguage; + }, + getFirstBrowserLanguage () { + const language = this.getFirstBrowserLanguageWithRegionCode().replace("_", "-"); + if (!language) return "zh"; // use default + const languages = language.split("-"); + if (languages.length === 1) { + return language + } else if (languages.length === 2) { + return languages[0] + } else { + // probably malformed... + return language + } + }, + data: { + "en": { + "load_title--text": "Loading...", + "load_caption--text": "Initialization may take some time", + "load_copyright--text": "Penguin Statistics" + }, + "ja": { + "load_title--text": "読み込み中...", + "load_caption--text": "読み込みが初めて遅くなる場合があります
しばらくお待ちください", + "load_copyright--text": "ペンギン急便データ統計処理部門" + }, + "ko": { + "load_title--text": "로딩...", + "load_caption--text": "처음으로 로딩이 느려질 수 있으므로 잠시 기다려주십시오", + "load_copyright--text": "펭귄 물류 데이터 분석 부서" + }, + }, + fill (key, content) { + document.querySelector("#" + key).innerHTML = content; + }, + render () { + document.querySelector("#load_copyright_year--text").textContent = new Date().getFullYear().toString(); + let language = this.getFirstBrowserLanguage(); + if (language in this.data && typeof language === "string" && language.length <= 2) { + let messages = this.data[language]; + for (let [key, value] of Object.entries(messages)) { + this.fill(key, value) + } + } + } +}; + +try { + _i18n.render() +} catch (e) { + console.error(e) +} \ No newline at end of file diff --git a/src/components/stats/Charts.vue b/src/components/stats/Charts.vue index 455b7ffd..1c4dceec 100644 --- a/src/components/stats/Charts.vue +++ b/src/components/stats/Charts.vue @@ -104,7 +104,7 @@ export default { }, computed: { gradient() { - return this.$store.state.settings.dark ? ["white"] : ["black"]; + return this.$store.getters['settings/dark'] ? ["white"] : ["black"]; }, sparkline() { return { diff --git a/src/components/stats/DataSourceToggle.vue b/src/components/stats/DataSourceToggle.vue index 4633b78e..a6553732 100644 --- a/src/components/stats/DataSourceToggle.vue +++ b/src/components/stats/DataSourceToggle.vue @@ -23,6 +23,14 @@ "all": "全体", "personal": "個人" } + }, + "ko": { + "dataSourceToggle": { + "title": "Login Required", + "loginNotice": "Please log in before viewing personal drop data.", + "all": "All", + "personal": "Personal" + } } } @@ -89,6 +97,7 @@ \ No newline at end of file diff --git a/src/config/index.js b/src/config/index.js index 39842924..89fdccbf 100644 --- a/src/config/index.js +++ b/src/config/index.js @@ -1,6 +1,6 @@ const client = { source: "frontend-v2", - version: "v1.1.1" + version: "v1.1.2" }; export default { diff --git a/src/layouts/AboutLayout.vue b/src/layouts/AboutLayout.vue index b1313d69..79bd3210 100644 --- a/src/layouts/AboutLayout.vue +++ b/src/layouts/AboutLayout.vue @@ -1,6 +1,6 @@