FEATURE: locale

REFACTOR: actie menu and navigation
This commit is contained in:
ma-silva 2023-04-07 00:00:59 +08:00
parent ba3ec32c44
commit eb1102fe3d
17 changed files with 11869 additions and 63 deletions

1
components.d.ts vendored
View File

@ -11,6 +11,7 @@ declare module '@vue/runtime-core' {
export interface GlobalComponents {
Content: typeof import('./src/components/Content.vue')['default']
ElAside: typeof import('element-plus/es')['ElAside']
ElButton: typeof import('element-plus/es')['ElButton']
ElCol: typeof import('element-plus/es')['ElCol']
ElCollapse: typeof import('element-plus/es')['ElCollapse']
ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem']

View File

@ -17,6 +17,7 @@
"element-plus": "^2.3.0",
"pinia": "^2.0.32",
"vue": "^3.2.47",
"vue-i18n": "9",
"vue-router": "^4.1.6"
},
"devDependencies": {

View File

@ -1,24 +1,30 @@
<script setup lang="ts">
import { ref, inject, onBeforeMount } from 'vue'
import { onBeforeRouteUpdate, useRoute } from 'vue-router'
import { getDescription } from '../obp/resource-docs'
import { getOperationDetails } from '../obp/resource-docs'
const description = ref('')
const summary = ref('')
const docs = inject('OBP-ResourceDocs')
const setOperationDetails = (id: string): void => {
const operation = getOperationDetails(docs, id)
description.value = operation.description
summary.value = operation.summary
}
onBeforeMount(() => {
const route = useRoute()
description.value = getDescription(docs, route.params.id)
setOperationDetails(route.params.id)
})
onBeforeRouteUpdate((to) => {
description.value = getDescription(docs, to.params.id)
setOperationDetails(to.params.id)
})
</script>
<template>
<main>
Description:
{{ $route.params.id }}
<span>{{ summary }}</span>
<div v-html="description"></div>
</main>
</template>

View File

@ -1,27 +1,56 @@
<script setup lang="ts">
import { ArrowDown } from '@element-plus/icons-vue'
const clearActiveTab = () => {
const activeLinks = document.querySelectorAll('#header-nav')
for (const active of activeLinks) {
active.style.backgroundColor = 'transparent'
}
}
const setActive = (event) => {
clearActiveTab()
const target = event.target
target.style.backgroundColor = '#eef0f4'
}
</script>
<template>
<img alt="OBP logo" class="logo" src="@/assets/logo2x-1.png" />
<nav>
<RouterLink class="router-link" to="/">Portal Home</RouterLink>
<RouterLink class="router-link" to="/api">API Explorer</RouterLink>
<RouterLink class="router-link" to="/glossary">Glossary</RouterLink>
<RouterLink class="router-link" to="/">API Manager</RouterLink>
<span class="el-dropdown-link">
<RouterLink class="router-link" to="/">More</RouterLink>
<el-icon class="el-icon--right">
<arrow-down />
</el-icon>
</span>
<span class="el-dropdown-link">
<RouterLink class="router-link" to="/">Spaces</RouterLink>
<el-icon class="el-icon--right">
<arrow-down />
</el-icon>
</span>
<RouterLink class="login-button router-link" to="/login">Login</RouterLink>
<nav id="nav">
<RouterView name="header">
<RouterLink class="router-link" active="true" id="header-nav" to="/" @click="setActive">{{
$t('header.portal_home')
}}</RouterLink>
<RouterLink class="router-link" id="header-nav" to="/api" @click="setActive">{{
$t('header.api_explorer')
}}</RouterLink>
<RouterLink class="router-link" id="header-nav" to="/glossary" @click="setActive">{{
$t('header.glossary')
}}</RouterLink>
<RouterLink class="router-link" id="header-nav" to="/api_manager" @click="setActive">{{
$t('header.api_manager')
}}</RouterLink>
<span class="el-dropdown-link">
<RouterLink class="router-link" id="header-nav" to="/more" @click="setActive">{{
$t('header.more')
}}</RouterLink>
<el-icon class="el-icon--right">
<arrow-down />
</el-icon>
</span>
<span class="el-dropdown-link">
<RouterLink class="router-link" id="header-nav" to="/spaces" @click="setActive">{{
$t('header.spaces')
}}</RouterLink>
<el-icon class="el-icon--right">
<arrow-down />
</el-icon>
</span>
<RouterLink class="login-button router-link" to="/login" @click="setActive">{{
$t('header.login')
}}</RouterLink>
</RouterView>
</nav>
</template>
@ -57,6 +86,7 @@ nav {
.router-link {
padding: 9px;
margin: 3px;
color: #39455f;
font-family: 'Roboto';
font-size: 14px;
@ -65,7 +95,7 @@ nav {
}
.router-link:hover {
background-color: #eef0f4;
background-color: #eef0f4 !important;
}
.logo {

View File

@ -1,5 +1,11 @@
<script setup lang="ts">
import { ArrowDown } from '@element-plus/icons-vue'
import { inject } from 'vue'
const i18n = inject('i18n')
const handleLocale = (command: string) => {
i18n.global.locale.value = command
}
</script>
<template>
@ -7,17 +13,21 @@ import { ArrowDown } from '@element-plus/icons-vue'
<el-col :span="12" class="menu-left">Menu left</el-col>
<el-col :span="12" class="menu-right">
Menu right &nbsp;&nbsp;&nbsp;&nbsp;
<el-dropdown class="menu-right">
<el-dropdown class="menu-right" @command="handleLocale">
<span class="el-dropdown-link">
EN
{{ $i18n.locale }}
<el-icon class="el-icon--right">
<arrow-down />
</el-icon>
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item>EN</el-dropdown-item>
<el-dropdown-item disabled>SP</el-dropdown-item>
<el-dropdown-item
v-for="locale in $i18n.availableLocales"
:key="`locale-${locale}`"
:command="locale"
>{{ locale }}</el-dropdown-item
>
</el-dropdown-menu>
</template>
</el-dropdown>

View File

@ -1,8 +1,42 @@
<script setup lang="ts"></script>
<script setup lang="ts">
import { ref, inject, onBeforeMount } from 'vue'
import { onBeforeRouteUpdate, useRoute } from 'vue-router'
import { getOperationDetails } from '../obp/resource-docs'
const url = ref('')
const method = ref('')
const successResponse = ref('')
const roles = ref('')
const docs = inject('OBP-ResourceDocs')
const setOperationDetails = (id: string): void => {
const operation = getOperationDetails(docs, id)
url.value = operation.specified_url
method.value = operation.request_verb
successResponse.value = operation.success_response_body
roles.value = operation.roles
}
onBeforeMount(() => {
const route = useRoute()
setOperationDetails(route.params.id)
})
onBeforeRouteUpdate((to) => {
setOperationDetails(to.params.id)
})
</script>
<template>
<main>
Preview
{{ $route.params.id }}
{{ $route.params.id }} <br />
{{ url }} <el-button type="primary">{{ method }}</el-button> <br />
<div>
TYPICAL SUCCESSFUL RESPONSE: <br />
{{ successResponse }}
</div>
<div>
REQUIRED ROLES: <br />
{{ roles }}
</div>
</main>
</template>

View File

@ -4,25 +4,48 @@ import { Search } from '@element-plus/icons-vue'
const groups = ref({})
const sortedKeys = ref([])
const activeKeys = ref([])
const form = reactive({
search: ''
})
onBeforeMount(() => {
groups.value = inject('OBP-GroupedResourceDocs')!
sortedKeys.value = Object.keys(groups.value).sort()
activeKeys.value = Object.keys(groups.value)
sortedKeys.value = activeKeys.value.sort()
})
const clearActiveTab = () => {
const active = document.querySelector('.active-api-router-tab')
if (active) {
const child = active.firstChild
if (child.style) {
child.style.color = '#39455f'
}
active.classList.remove('active-api-router-tab')
}
}
const setActive = (event) => {
clearActiveTab()
const target = event.target
if (target.tagName === 'A') {
target.classList.add('active-api-router-link')
target.style.color = '#52b165'
target.parentElement.classList.add('active-api-router-tab')
}
}
</script>
<template>
<el-form :model="form" label-width="120px">
<el-input v-model="form.search" class="w-50 m-1" placeholder="Search" :prefix-icon="Search" />
</el-form>
<el-collapse v-model="sortedKeys">
<el-collapse v-model="activeKeys">
<el-collapse-item title="My Collections" name="1"> </el-collapse-item>
<el-collapse-item v-for="key in sortedKeys" :title="key" :key="key" :name="key">
<div class="el-tabs--right">
<div v-for="item in groups[key]" :key="item" class="api-router-tab">
<div v-for="item in groups[key]" :key="item" class="api-router-tab" @click="setActive">
<RouterLink
class="api-router-link"
:to="{ name: 'api', params: { id: item.operation_id } }"
@ -44,7 +67,7 @@ onBeforeMount(() => {
.api-router-link {
width: 100%;
margin-left: 15px;
font-family: 'Roboto' !important;
font-family: 'Roboto';
text-decoration: none;
color: #39455f;
display: inline-block;
@ -54,12 +77,13 @@ onBeforeMount(() => {
border-left: 2px solid var(--el-menu-border-color);
}
.api-router-tab:hover {
.api-router-tab:hover,
.active-api-router-tab {
border-left: 2px solid #52b165;
/*cursor: pointer;*/
}
.api-router-tab:hover .api-router-link {
.api-router-tab:hover .api-router-link,
.active-api-router-link {
color: #52b165;
}
</style>

12
src/language/en.json Normal file
View File

@ -0,0 +1,12 @@
{
"header": {
"portal_home": "Portal Home",
"portal_home": "Portal Home",
"api_explorer": "API Explorer",
"api_manager": "API Manager",
"glossary": "Glossary",
"more": "More",
"spaces": "Spaces",
"login": "Log on"
}
}

11
src/language/es.json Normal file
View File

@ -0,0 +1,11 @@
{
"header": {
"portal_home": "Portal de inicio",
"api_explorer": "Explorador de API",
"api_manager": "Administrador de API",
"glossary": "Glosario",
"more": "Mas",
"spaces": "Espacio",
"login": "Iniciar sesión"
}
}

9
src/language/index.ts Normal file
View File

@ -0,0 +1,9 @@
import en from './en.json'
import es from './es.json'
export const defaultLocale = 'EN'
export const languages = {
EN: en,
ES: es
}

View File

@ -3,6 +3,8 @@ import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'
import { createI18n } from 'vue-i18n'
import { languages, defaultLocale } from './language'
import { getOBPResourceDocs, getGroupedResourceDocs } from './obp/resource-docs'
@ -16,6 +18,15 @@ import './assets/main.css'
app.provide('OBP-ResourceDocs', docs)
app.provide('OBP-GroupedResourceDocs', groupedDocs)
const messages = Object.assign(languages)
const i18n = createI18n({
locale: defaultLocale,
fallbackLocale: 'ES',
messages
})
app.provide('i18n', i18n)
app.use(i18n)
app.use(createPinia())
app.use(router)

11601
src/obp/resource-docs.json Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,23 +1,25 @@
import { Version, API, get } from 'obp-typescript/src/api/client'
import type { APIClientConfig, DirectLoginAuthentication } from 'obp-typescript/src/api/client'
import { Any, GetAny } from 'obp-typescript/src/api/any'
import docs from './resource-docs.json'
//import { Any, GetAny } from 'obp-typescript/src/api/any'
//import { Version, API, get } from 'obp-typescript/src/api/client'
//import type { APIClientConfig, DirectLoginAuthentication } from 'obp-typescript/src/api/client'
const VERSION = 'v5.1.0'
const directLogin: DirectLoginAuthentication = {
username: process.env.OBP_USERNAME,
password: process.env.OBP_PASSWORD,
consumerKey: process.env.OBP_CONSUMER_KEY
}
const clientConfig: APIClientConfig = {
baseUri: 'https://apisandbox.openbankproject.com',
version: Version.v510,
authentication: directLogin
}
//const VERSION = 'v5.1.0'
//const directLogin: DirectLoginAuthentication = {
// username: process.env.OBP_USERNAME,
// password: process.env.OBP_PASSWORD,
// consumerKey: process.env.OBP_CONSUMER_KEY
//}
//
//const clientConfig: APIClientConfig = {
// baseUri: 'https://apisandbox.openbankproject.com',
// version: Version.v510,
// authentication: directLogin
//}
// Get Resource Docs
export async function getOBPResourceDocs(): Promise<any> {
return await get<API.Any>(clientConfig, Any)(GetAny)(`/resource-docs/${VERSION}/obp`)
//return await get<API.Any>(clientConfig, Any)(GetAny)(`/resource-docs/${VERSION}/obp`)
return docs
}
export async function getGroupedResourceDocs(docs: any): Promise<any> {
@ -29,6 +31,6 @@ export async function getGroupedResourceDocs(docs: any): Promise<any> {
}, {})
}
export function getDescription(docs: any, operation_id: string): any {
return docs.resource_docs.filter((doc) => doc.operation_id === operation_id)[0].description
export function getOperationDetails(docs: any, operation_id: string): any {
return docs.resource_docs.filter((doc) => doc.operation_id === operation_id)[0]
}

View File

@ -16,16 +16,18 @@ import Menu from '../components/Menu.vue'
</el-header>
<el-container>
<el-aside width="50%">
Center
<!--Middle -->
<RouterView name="body" />
</el-aside>
<el-aside class="preview" width="50%">
<!--Right -->
Right
<!--right -->
<RouterView class="preview" name="preview" />
</el-aside>
</el-container>
<el-footer>Footer</el-footer>
<el-footer>
<!--Bottom -->
Footer
</el-footer>
</el-container>
</el-main>
</el-container>

View File

@ -1,4 +1,5 @@
{
"resolveJsonModule": true,
"files": [],
"references": [
{

View File

@ -25,6 +25,9 @@ export default defineConfig({
}
},
define: {
'process.env': process.env
'process.env': process.env,
__VUE_I18N_FULL_INSTALL__: true,
__VUE_I18N_LEGACY_API__: false,
__INTLIFY_PROD_DEVTOOLS__: false,
}
})

View File

@ -461,6 +461,44 @@
resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45"
integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==
"@intlify/core-base@9.2.2":
version "9.2.2"
resolved "https://registry.yarnpkg.com/@intlify/core-base/-/core-base-9.2.2.tgz#5353369b05cc9fe35cab95fe20afeb8a4481f939"
integrity sha512-JjUpQtNfn+joMbrXvpR4hTF8iJQ2sEFzzK3KIESOx+f+uwIjgw20igOyaIdhfsVVBCds8ZM64MoeNSx+PHQMkA==
dependencies:
"@intlify/devtools-if" "9.2.2"
"@intlify/message-compiler" "9.2.2"
"@intlify/shared" "9.2.2"
"@intlify/vue-devtools" "9.2.2"
"@intlify/devtools-if@9.2.2":
version "9.2.2"
resolved "https://registry.yarnpkg.com/@intlify/devtools-if/-/devtools-if-9.2.2.tgz#b13d9ac4b4e2fe6d2e7daa556517a8061fe8bd39"
integrity sha512-4ttr/FNO29w+kBbU7HZ/U0Lzuh2cRDhP8UlWOtV9ERcjHzuyXVZmjyleESK6eVP60tGC9QtQW9yZE+JeRhDHkg==
dependencies:
"@intlify/shared" "9.2.2"
"@intlify/message-compiler@9.2.2":
version "9.2.2"
resolved "https://registry.yarnpkg.com/@intlify/message-compiler/-/message-compiler-9.2.2.tgz#e42ab6939b8ae5b3d21faf6a44045667a18bba1c"
integrity sha512-IUrQW7byAKN2fMBe8z6sK6riG1pue95e5jfokn8hA5Q3Bqy4MBJ5lJAofUsawQJYHeoPJ7svMDyBaVJ4d0GTtA==
dependencies:
"@intlify/shared" "9.2.2"
source-map "0.6.1"
"@intlify/shared@9.2.2":
version "9.2.2"
resolved "https://registry.yarnpkg.com/@intlify/shared/-/shared-9.2.2.tgz#5011be9ca2b4ab86f8660739286e2707f9abb4a5"
integrity sha512-wRwTpsslgZS5HNyM7uDQYZtxnbI12aGiBZURX3BTR9RFIKKRWpllTsgzHWvj3HKm3Y2Sh5LPC1r0PDCKEhVn9Q==
"@intlify/vue-devtools@9.2.2":
version "9.2.2"
resolved "https://registry.yarnpkg.com/@intlify/vue-devtools/-/vue-devtools-9.2.2.tgz#b95701556daf7ebb3a2d45aa3ae9e6415aed8317"
integrity sha512-+dUyqyCHWHb/UcvY1MlIpO87munedm3Gn6E9WWYdWrMuYLcoIoOEVDWSS8xSwtlPU+kA+MEQTP6Q1iI/ocusJg==
dependencies:
"@intlify/core-base" "9.2.2"
"@intlify/shared" "9.2.2"
"@jridgewell/gen-mapping@^0.1.0":
version "0.1.1"
resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996"
@ -849,7 +887,7 @@
"@vue/compiler-dom" "3.2.47"
"@vue/shared" "3.2.47"
"@vue/devtools-api@^6.4.5", "@vue/devtools-api@^6.5.0":
"@vue/devtools-api@^6.2.1", "@vue/devtools-api@^6.4.5", "@vue/devtools-api@^6.5.0":
version "6.5.0"
resolved "https://registry.yarnpkg.com/@vue/devtools-api/-/devtools-api-6.5.0.tgz#98b99425edee70b4c992692628fa1ea2c1e57d07"
integrity sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q==
@ -3046,7 +3084,7 @@ source-map-js@^1.0.2:
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
source-map@^0.6.1, source-map@~0.6.1:
source-map@0.6.1, source-map@^0.6.1, source-map@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
@ -3480,6 +3518,16 @@ vue-eslint-parser@^9.0.0, vue-eslint-parser@^9.0.1:
lodash "^4.17.21"
semver "^7.3.6"
vue-i18n@9:
version "9.2.2"
resolved "https://registry.yarnpkg.com/vue-i18n/-/vue-i18n-9.2.2.tgz#aeb49d9424923c77e0d6441e3f21dafcecd0e666"
integrity sha512-yswpwtj89rTBhegUAv9Mu37LNznyu3NpyLQmozF3i1hYOhwpG8RjcjIFIIfnu+2MDZJGSZPXaKWvnQA71Yv9TQ==
dependencies:
"@intlify/core-base" "9.2.2"
"@intlify/shared" "9.2.2"
"@intlify/vue-devtools" "9.2.2"
"@vue/devtools-api" "^6.2.1"
vue-router@^4.1.6:
version "4.1.6"
resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-4.1.6.tgz#b70303737e12b4814578d21d68d21618469375a1"