mirror of
https://github.com/OpenBankProject/API-Explorer-II.git
synced 2026-02-06 10:47:04 +00:00
Svelte drop downs for Version and Message Docs
This commit is contained in:
parent
046ba2d96d
commit
1a8dfb3975
7
components.d.ts
vendored
7
components.d.ts
vendored
@ -22,9 +22,6 @@ declare module 'vue' {
|
|||||||
ElCollapse: typeof import('element-plus/es')['ElCollapse']
|
ElCollapse: typeof import('element-plus/es')['ElCollapse']
|
||||||
ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem']
|
ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem']
|
||||||
ElContainer: typeof import('element-plus/es')['ElContainer']
|
ElContainer: typeof import('element-plus/es')['ElContainer']
|
||||||
ElContainter: typeof import('element-plus/es')['ElContainter']
|
|
||||||
ElDescriptions: typeof import('element-plus/es')['ElDescriptions']
|
|
||||||
ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem']
|
|
||||||
ElDivider: typeof import('element-plus/es')['ElDivider']
|
ElDivider: typeof import('element-plus/es')['ElDivider']
|
||||||
ElDropdown: typeof import('element-plus/es')['ElDropdown']
|
ElDropdown: typeof import('element-plus/es')['ElDropdown']
|
||||||
ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
|
ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
|
||||||
@ -36,8 +33,6 @@ declare module 'vue' {
|
|||||||
ElIcon: typeof import('element-plus/es')['ElIcon']
|
ElIcon: typeof import('element-plus/es')['ElIcon']
|
||||||
ElInput: typeof import('element-plus/es')['ElInput']
|
ElInput: typeof import('element-plus/es')['ElInput']
|
||||||
ElMain: typeof import('element-plus/es')['ElMain']
|
ElMain: typeof import('element-plus/es')['ElMain']
|
||||||
ElMenu: typeof import('element-plus/es')['ElMenu']
|
|
||||||
ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
|
|
||||||
ElRow: typeof import('element-plus/es')['ElRow']
|
ElRow: typeof import('element-plus/es')['ElRow']
|
||||||
ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
|
ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
|
||||||
ElTag: typeof import('element-plus/es')['ElTag']
|
ElTag: typeof import('element-plus/es')['ElTag']
|
||||||
@ -45,12 +40,12 @@ declare module 'vue' {
|
|||||||
GlossarySearchNav: typeof import('./src/components/GlossarySearchNav.vue')['default']
|
GlossarySearchNav: typeof import('./src/components/GlossarySearchNav.vue')['default']
|
||||||
HeaderNav: typeof import('./src/components/HeaderNav.vue')['default']
|
HeaderNav: typeof import('./src/components/HeaderNav.vue')['default']
|
||||||
Menu: typeof import('./src/components/Menu.vue')['default']
|
Menu: typeof import('./src/components/Menu.vue')['default']
|
||||||
MessageDocsContent: typeof import('./src/components/MessageDocsContent.vue')['default']
|
|
||||||
MessageDocsSearchNav: typeof import('./src/components/MessageDocsSearchNav.vue')['default']
|
MessageDocsSearchNav: typeof import('./src/components/MessageDocsSearchNav.vue')['default']
|
||||||
Preview: typeof import('./src/components/Preview.vue')['default']
|
Preview: typeof import('./src/components/Preview.vue')['default']
|
||||||
RouterLink: typeof import('vue-router')['RouterLink']
|
RouterLink: typeof import('vue-router')['RouterLink']
|
||||||
RouterView: typeof import('vue-router')['RouterView']
|
RouterView: typeof import('vue-router')['RouterView']
|
||||||
SearchNav: typeof import('./src/components/SearchNav.vue')['default']
|
SearchNav: typeof import('./src/components/SearchNav.vue')['default']
|
||||||
|
SvelteDropdown: typeof import('./src/components/SvelteDropdown.vue')['default']
|
||||||
ToolCall: typeof import('./src/components/ToolCall.vue')['default']
|
ToolCall: typeof import('./src/components/ToolCall.vue')['default']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
258
src-svelte/Dropdown.svelte
Normal file
258
src-svelte/Dropdown.svelte
Normal file
@ -0,0 +1,258 @@
|
|||||||
|
<!--
|
||||||
|
- Open Bank Project - API Explorer II
|
||||||
|
- Copyright (C) 2023-2024, TESOBE GmbH
|
||||||
|
-
|
||||||
|
- This program is free software: you can redistribute it and/or modify
|
||||||
|
- it under the terms of the GNU Affero General Public License as published by
|
||||||
|
- the Free Software Foundation, either version 3 of the License, or
|
||||||
|
- (at your option) any later version.
|
||||||
|
-
|
||||||
|
- This program is distributed in the hope that it will be useful,
|
||||||
|
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
- GNU Affero General Public License for more details.
|
||||||
|
-
|
||||||
|
- You should have received a copy of the GNU Affero General Public License
|
||||||
|
- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
-
|
||||||
|
- Email: contact@tesobe.com
|
||||||
|
- TESOBE GmbH
|
||||||
|
- Osloerstrasse 16/17
|
||||||
|
- Berlin 13359, Germany
|
||||||
|
-
|
||||||
|
- This product includes software developed at
|
||||||
|
- TESOBE (http://www.tesobe.com/)
|
||||||
|
-
|
||||||
|
-->
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
interface Props {
|
||||||
|
label?: string
|
||||||
|
items?: string[]
|
||||||
|
hoverColor?: string
|
||||||
|
backgroundColor?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
let {
|
||||||
|
label = 'Dropdown',
|
||||||
|
items = [],
|
||||||
|
hoverColor = '#32b9ce',
|
||||||
|
backgroundColor = '#e8f4f8'
|
||||||
|
}: Props = $props()
|
||||||
|
|
||||||
|
let isOpen = $state(false)
|
||||||
|
let dropdownRef = $state<HTMLDivElement>()
|
||||||
|
let timeoutId: number | null = null
|
||||||
|
|
||||||
|
function handleMouseEnter() {
|
||||||
|
if (timeoutId) {
|
||||||
|
clearTimeout(timeoutId)
|
||||||
|
timeoutId = null
|
||||||
|
}
|
||||||
|
isOpen = true
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleMouseLeave() {
|
||||||
|
timeoutId = window.setTimeout(() => {
|
||||||
|
isOpen = false
|
||||||
|
}, 1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSelect(item: string) {
|
||||||
|
const event = new CustomEvent('select', {
|
||||||
|
detail: item,
|
||||||
|
bubbles: true,
|
||||||
|
composed: true
|
||||||
|
})
|
||||||
|
dropdownRef?.dispatchEvent(event)
|
||||||
|
isOpen = false
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleClickOutside(event: MouseEvent) {
|
||||||
|
if (dropdownRef && !dropdownRef.contains(event.target as Node)) {
|
||||||
|
isOpen = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleEscape(event: KeyboardEvent) {
|
||||||
|
if (event.key === 'Escape') {
|
||||||
|
isOpen = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$effect(() => {
|
||||||
|
if (isOpen) {
|
||||||
|
document.addEventListener('click', handleClickOutside)
|
||||||
|
document.addEventListener('keydown', handleEscape)
|
||||||
|
return () => {
|
||||||
|
document.removeEventListener('click', handleClickOutside)
|
||||||
|
document.removeEventListener('keydown', handleEscape)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div
|
||||||
|
bind:this={dropdownRef}
|
||||||
|
class="dropdown-container"
|
||||||
|
style:--hover-bg={backgroundColor}
|
||||||
|
style:--hover-color={hoverColor}
|
||||||
|
onmouseenter={handleMouseEnter}
|
||||||
|
onmouseleave={handleMouseLeave}
|
||||||
|
role="navigation"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
class="dropdown-trigger"
|
||||||
|
onclick={() => isOpen = !isOpen}
|
||||||
|
aria-expanded={isOpen}
|
||||||
|
aria-haspopup="true"
|
||||||
|
>
|
||||||
|
{label}
|
||||||
|
<svg
|
||||||
|
class="arrow-icon"
|
||||||
|
class:rotated={isOpen}
|
||||||
|
viewBox="0 0 1024 1024"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path fill="currentColor" d="M831.872 340.864 512 652.672 192.128 340.864a30.592 30.592 0 0 0-42.752 0 29.12 29.12 0 0 0 0 41.6L489.664 714.24a32 32 0 0 0 44.672 0l340.288-331.712a29.12 29.12 0 0 0 0-41.728 30.592 30.592 0 0 0-42.752 0z"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{#if isOpen}
|
||||||
|
<div class="dropdown-menu">
|
||||||
|
<div class="dropdown-content">
|
||||||
|
{#each items as item}
|
||||||
|
<button
|
||||||
|
class="dropdown-item"
|
||||||
|
onclick={() => handleSelect(item)}
|
||||||
|
>
|
||||||
|
{item}
|
||||||
|
</button>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.dropdown-container {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-trigger {
|
||||||
|
padding: 9px;
|
||||||
|
margin: 3px;
|
||||||
|
color: #39455f;
|
||||||
|
font-family: 'Roboto', sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
text-decoration: none;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-trigger:hover {
|
||||||
|
background-color: var(--hover-bg) !important;
|
||||||
|
color: var(--hover-color) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arrow-icon {
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
transition: transform 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arrow-icon.rotated {
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-menu {
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
right: 0;
|
||||||
|
margin-top: 4px;
|
||||||
|
background: white;
|
||||||
|
border: 1px solid #e4e7ed;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||||||
|
z-index: 2000;
|
||||||
|
min-width: 180px;
|
||||||
|
max-width: 280px;
|
||||||
|
animation: fadeIn 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeIn {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-8px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-content {
|
||||||
|
max-height: 400px;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: 6px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-item {
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px 20px;
|
||||||
|
margin: 0;
|
||||||
|
color: #606266;
|
||||||
|
font-family: 'Roboto', sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
text-align: left;
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-item:hover {
|
||||||
|
background-color: var(--hover-bg);
|
||||||
|
color: var(--hover-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-item:active {
|
||||||
|
background-color: var(--hover-bg);
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Custom scrollbar styling */
|
||||||
|
.dropdown-content::-webkit-scrollbar {
|
||||||
|
width: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-content::-webkit-scrollbar-track {
|
||||||
|
background: #f5f5f5;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-content::-webkit-scrollbar-thumb {
|
||||||
|
background: #c1c1c1;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-content::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: #a8a8a8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Firefox scrollbar */
|
||||||
|
.dropdown-content {
|
||||||
|
scrollbar-width: thin;
|
||||||
|
scrollbar-color: #c1c1c1 #f5f5f5;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -27,7 +27,6 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, inject, watchEffect, onMounted, computed } from 'vue'
|
import { ref, inject, watchEffect, onMounted, computed } from 'vue'
|
||||||
import { ArrowDown } from '@element-plus/icons-vue'
|
|
||||||
import { useRoute, useRouter } from 'vue-router'
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
import { OBP_API_DEFAULT_RESOURCE_DOC_VERSION, getCurrentUser } from '../obp'
|
import { OBP_API_DEFAULT_RESOURCE_DOC_VERSION, getCurrentUser } from '../obp'
|
||||||
import { getOBPAPIVersions } from '../obp/api-version'
|
import { getOBPAPIVersions } from '../obp/api-version'
|
||||||
@ -38,6 +37,7 @@ import {
|
|||||||
HEADER_LINKS_BACKGROUND_COLOR as headerLinksBackgroundColorSetting
|
HEADER_LINKS_BACKGROUND_COLOR as headerLinksBackgroundColorSetting
|
||||||
} from '../obp/style-setting'
|
} from '../obp/style-setting'
|
||||||
import { obpApiActiveVersionsKey, obpGroupedMessageDocsKey, obpMyCollectionsEndpointKey } from '@/obp/keys'
|
import { obpApiActiveVersionsKey, obpGroupedMessageDocsKey, obpMyCollectionsEndpointKey } from '@/obp/keys'
|
||||||
|
import SvelteDropdown from './SvelteDropdown.vue'
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
@ -82,7 +82,11 @@ const handleMore = (command: string) => {
|
|||||||
if (element !== null) {
|
if (element !== null) {
|
||||||
element.textContent = command;
|
element.textContent = command;
|
||||||
}
|
}
|
||||||
if (command.includes('_')) {
|
if (command === '/message-docs') {
|
||||||
|
// Navigate to message docs list
|
||||||
|
console.log('Navigating to message docs list')
|
||||||
|
router.push({ name: 'message-docs-list' })
|
||||||
|
} else if (command.includes('_')) {
|
||||||
console.log('Navigating to message docs:', command)
|
console.log('Navigating to message docs:', command)
|
||||||
router.push({ name: 'message-docs', params: { id: command } })
|
router.push({ name: 'message-docs', params: { id: command } })
|
||||||
} else {
|
} else {
|
||||||
@ -145,31 +149,24 @@ const getCurrentPath = () => {
|
|||||||
<a v-if="showObpApiManagerButton && hasObpApiManagerHost" v-bind:href="obpApiManagerHost" class="router-link" id="header-nav-api-manager">
|
<a v-if="showObpApiManagerButton && hasObpApiManagerHost" v-bind:href="obpApiManagerHost" class="router-link" id="header-nav-api-manager">
|
||||||
{{ $t('header.api_manager') }}
|
{{ $t('header.api_manager') }}
|
||||||
</a>
|
</a>
|
||||||
<el-dropdown
|
<SvelteDropdown
|
||||||
class="menu-right router-link"
|
class="menu-right"
|
||||||
id="header-nav-more"
|
id="header-nav-versions"
|
||||||
@command="handleMore"
|
label="Versions"
|
||||||
trigger="hover"
|
:items="obpApiVersions"
|
||||||
placement="bottom-end"
|
:hover-color="headerLinksHoverColor"
|
||||||
:teleported="true"
|
:background-color="headerLinksBackgroundColor"
|
||||||
max-height="700px"
|
@select="handleMore"
|
||||||
>
|
/>
|
||||||
<span class="el-dropdown-link">
|
<SvelteDropdown
|
||||||
{{ $t('header.more') }}
|
class="menu-right"
|
||||||
<el-icon class="el-icon--right">
|
id="header-nav-message-docs"
|
||||||
<arrow-down />
|
label="Message Docs"
|
||||||
</el-icon>
|
:items="obpMessageDocs"
|
||||||
</span>
|
:hover-color="headerLinksHoverColor"
|
||||||
<template #dropdown>
|
:background-color="headerLinksBackgroundColor"
|
||||||
<el-dropdown-menu>
|
@select="handleMore"
|
||||||
<el-dropdown-item v-for="value in obpApiVersions" :command="value" :key="value">{{
|
/>
|
||||||
value
|
|
||||||
}}</el-dropdown-item>
|
|
||||||
<el-dropdown-item v-for="value in obpMessageDocs" :command="value" :key="value">
|
|
||||||
Message Docs for: {{ value }}</el-dropdown-item>
|
|
||||||
</el-dropdown-menu>
|
|
||||||
</template>
|
|
||||||
</el-dropdown>
|
|
||||||
<!--<span class="el-dropdown-link">
|
<!--<span class="el-dropdown-link">
|
||||||
<RouterLink class="router-link" id="header-nav-spaces" to="/spaces">{{
|
<RouterLink class="router-link" id="header-nav-spaces" to="/spaces">{{
|
||||||
$t('header.spaces')
|
$t('header.spaces')
|
||||||
@ -261,21 +258,10 @@ a.logoff-button {
|
|||||||
color: #39455f;
|
color: #39455f;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*override element plus*/
|
/* Custom dropdown containers */
|
||||||
.el-dropdown-menu__item:hover {
|
#header-nav-versions,
|
||||||
color: v-bind(headerLinksHoverColor) !important;
|
#header-nav-message-docs {
|
||||||
}
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
/* Fix dropdown menu overflow */
|
|
||||||
.el-dropdown-menu {
|
|
||||||
max-height: 400px;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ensure dropdown trigger behaves correctly */
|
|
||||||
#header-nav-more .el-dropdown-link {
|
|
||||||
cursor: pointer;
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
123
src/components/SvelteDropdown.vue
Normal file
123
src/components/SvelteDropdown.vue
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
<!--
|
||||||
|
- Open Bank Project - API Explorer II
|
||||||
|
- Copyright (C) 2023-2024, TESOBE GmbH
|
||||||
|
-
|
||||||
|
- This program is free software: you can redistribute it and/or modify
|
||||||
|
- it under the terms of the GNU Affero General Public License as published by
|
||||||
|
- the Free Software Foundation, either version 3 of the License, or
|
||||||
|
- (at your option) any later version.
|
||||||
|
-
|
||||||
|
- This program is distributed in the hope that it will be useful,
|
||||||
|
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
- GNU Affero General Public License for more details.
|
||||||
|
-
|
||||||
|
- You should have received a copy of the GNU Affero General Public License
|
||||||
|
- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
-
|
||||||
|
- Email: contact@tesobe.com
|
||||||
|
- TESOBE GmbH
|
||||||
|
- Osloerstrasse 16/17
|
||||||
|
- Berlin 13359, Germany
|
||||||
|
-
|
||||||
|
- This product includes software developed at
|
||||||
|
- TESOBE (http://www.tesobe.com/)
|
||||||
|
-
|
||||||
|
-->
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, onMounted, onBeforeUnmount, watch } from 'vue'
|
||||||
|
import { mount, unmount } from 'svelte'
|
||||||
|
import Dropdown from '../../src-svelte/Dropdown.svelte'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
label?: string
|
||||||
|
items?: string[]
|
||||||
|
hoverColor?: string
|
||||||
|
backgroundColor?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
label: 'Dropdown',
|
||||||
|
items: () => [],
|
||||||
|
hoverColor: '#32b9ce',
|
||||||
|
backgroundColor: '#e8f4f8'
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
select: [value: string]
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const containerRef = ref<HTMLDivElement>()
|
||||||
|
let svelteComponent: any = null
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (containerRef.value) {
|
||||||
|
try {
|
||||||
|
svelteComponent = mount(Dropdown, {
|
||||||
|
target: containerRef.value,
|
||||||
|
props: {
|
||||||
|
label: props.label,
|
||||||
|
items: props.items,
|
||||||
|
hoverColor: props.hoverColor,
|
||||||
|
backgroundColor: props.backgroundColor
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Listen for the custom 'select' event from Svelte component
|
||||||
|
containerRef.value.addEventListener('select', (event: Event) => {
|
||||||
|
const customEvent = event as CustomEvent
|
||||||
|
emit('select', customEvent.detail)
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to mount Svelte Dropdown:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
if (svelteComponent) {
|
||||||
|
try {
|
||||||
|
unmount(svelteComponent)
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to unmount Svelte Dropdown:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Watch for prop changes and update Svelte component
|
||||||
|
watch(
|
||||||
|
() => props.items,
|
||||||
|
(newItems) => {
|
||||||
|
if (svelteComponent && containerRef.value) {
|
||||||
|
// Remount with new props
|
||||||
|
unmount(svelteComponent)
|
||||||
|
svelteComponent = mount(Dropdown, {
|
||||||
|
target: containerRef.value,
|
||||||
|
props: {
|
||||||
|
label: props.label,
|
||||||
|
items: newItems,
|
||||||
|
hoverColor: props.hoverColor,
|
||||||
|
backgroundColor: props.backgroundColor
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Re-add event listener
|
||||||
|
containerRef.value.addEventListener('select', (event: Event) => {
|
||||||
|
const customEvent = event as CustomEvent
|
||||||
|
emit('select', customEvent.detail)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div ref="containerRef" class="svelte-dropdown-wrapper"></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.svelte-dropdown-wrapper {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -29,6 +29,7 @@ import { createRouter, createWebHistory } from 'vue-router'
|
|||||||
import GlossaryView from '../views/GlossaryView.vue'
|
import GlossaryView from '../views/GlossaryView.vue'
|
||||||
import HelpView from '../views/HelpView.vue'
|
import HelpView from '../views/HelpView.vue'
|
||||||
import MessageDocsView from '../views/MessageDocsView.vue'
|
import MessageDocsView from '../views/MessageDocsView.vue'
|
||||||
|
import MessageDocsListView from '../views/MessageDocsListView.vue'
|
||||||
import BodyView from '../views/BodyView.vue'
|
import BodyView from '../views/BodyView.vue'
|
||||||
import Content from '../components/Content.vue'
|
import Content from '../components/Content.vue'
|
||||||
import Preview from '../components/Preview.vue'
|
import Preview from '../components/Preview.vue'
|
||||||
@ -63,6 +64,11 @@ export default async function router(): Promise<any> {
|
|||||||
name: 'help',
|
name: 'help',
|
||||||
component: isServerActive ? HelpView : InternalServerErrorView
|
component: isServerActive ? HelpView : InternalServerErrorView
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/message-docs',
|
||||||
|
name: 'message-docs-list',
|
||||||
|
component: isServerActive ? MessageDocsListView : InternalServerErrorView
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/message-docs/:id',
|
path: '/message-docs/:id',
|
||||||
name: 'message-docs',
|
name: 'message-docs',
|
||||||
|
|||||||
107
src/views/MessageDocsListView.vue
Normal file
107
src/views/MessageDocsListView.vue
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
<!--
|
||||||
|
- Open Bank Project - API Explorer II
|
||||||
|
- Copyright (C) 2023-2024, TESOBE GmbH
|
||||||
|
-
|
||||||
|
- This program is free software: you can redistribute it and/or modify
|
||||||
|
- it under the terms of the GNU Affero General Public License as published by
|
||||||
|
- the Free Software Foundation, either version 3 of the License, or
|
||||||
|
- (at your option) any later version.
|
||||||
|
-
|
||||||
|
- This program is distributed in the hope that it will be useful,
|
||||||
|
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
- GNU Affero General Public License for more details.
|
||||||
|
-
|
||||||
|
- You should have received a copy of the GNU Affero General Public License
|
||||||
|
- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
-
|
||||||
|
- Email: contact@tesobe.com
|
||||||
|
- TESOBE GmbH
|
||||||
|
- Osloerstrasse 16/17
|
||||||
|
- Berlin 13359, Germany
|
||||||
|
-
|
||||||
|
- This product includes software developed at
|
||||||
|
- TESOBE (http://www.tesobe.com/)
|
||||||
|
-
|
||||||
|
-->
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, inject, computed } from 'vue'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
import { obpGroupedMessageDocsKey } from '@/obp/keys'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const groupedMessageDocs = ref(inject(obpGroupedMessageDocsKey)!)
|
||||||
|
|
||||||
|
const connectorList = computed(() => {
|
||||||
|
return Object.keys(groupedMessageDocs.value || {}).sort()
|
||||||
|
})
|
||||||
|
|
||||||
|
function navigateToConnector(connectorId: string) {
|
||||||
|
router.push(`/message-docs/${connectorId}`)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<el-container class="message-docs-list-container">
|
||||||
|
<el-main>
|
||||||
|
<h1>Message Documentation</h1>
|
||||||
|
|
||||||
|
<div class="message-docs-list">
|
||||||
|
<div v-if="connectorList.length === 0" class="empty-message">
|
||||||
|
No message documentation available
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<a
|
||||||
|
v-for="connector in connectorList"
|
||||||
|
:key="connector"
|
||||||
|
@click="navigateToConnector(connector)"
|
||||||
|
class="message-doc-link"
|
||||||
|
>
|
||||||
|
{{ connector }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-main>
|
||||||
|
</el-container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.message-docs-list-container {
|
||||||
|
min-height: calc(100vh - 60px);
|
||||||
|
padding: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #303133;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-docs-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-doc-link {
|
||||||
|
padding: 12px 16px;
|
||||||
|
color: #409eff;
|
||||||
|
text-decoration: none;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 4px;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-doc-link:hover {
|
||||||
|
background-color: #ecf5ff;
|
||||||
|
color: #337ecc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-message {
|
||||||
|
color: #909399;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
12
svelte.config.mjs
Normal file
12
svelte.config.mjs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
// Consult https://svelte.dev/docs#compile-time-svelte-preprocess
|
||||||
|
// for more information about preprocessors
|
||||||
|
preprocess: vitePreprocess(),
|
||||||
|
|
||||||
|
compilerOptions: {
|
||||||
|
// Enable runes mode for Svelte 5
|
||||||
|
runes: true
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,6 +3,7 @@ import { fileURLToPath, URL } from 'node:url'
|
|||||||
import { loadEnv, defineConfig } from 'vite'
|
import { loadEnv, defineConfig } from 'vite'
|
||||||
import vue from '@vitejs/plugin-vue'
|
import vue from '@vitejs/plugin-vue'
|
||||||
import vueJsx from '@vitejs/plugin-vue-jsx'
|
import vueJsx from '@vitejs/plugin-vue-jsx'
|
||||||
|
import { svelte } from '@sveltejs/vite-plugin-svelte'
|
||||||
|
|
||||||
import AutoImport from 'unplugin-auto-import/vite'
|
import AutoImport from 'unplugin-auto-import/vite'
|
||||||
import Components from 'unplugin-vue-components/vite'
|
import Components from 'unplugin-vue-components/vite'
|
||||||
@ -14,6 +15,7 @@ export default defineConfig({
|
|||||||
plugins: [
|
plugins: [
|
||||||
vue(),
|
vue(),
|
||||||
vueJsx(),
|
vueJsx(),
|
||||||
|
svelte(),
|
||||||
AutoImport({
|
AutoImport({
|
||||||
resolvers: [ElementPlusResolver()]
|
resolvers: [ElementPlusResolver()]
|
||||||
}),
|
}),
|
||||||
@ -28,7 +30,7 @@ export default defineConfig({
|
|||||||
alias: {
|
alias: {
|
||||||
'@': fileURLToPath(new URL('./src', import.meta.url))
|
'@': fileURLToPath(new URL('./src', import.meta.url))
|
||||||
},
|
},
|
||||||
extensions: ['.mjs', '.js', '.mts', '.ts', '.jsx', '.tsx', '.json', '.vue']
|
extensions: ['.mjs', '.js', '.mts', '.ts', '.jsx', '.tsx', '.json', '.vue', '.svelte']
|
||||||
},
|
},
|
||||||
define: {
|
define: {
|
||||||
__VUE_I18N_FULL_INSTALL__: true,
|
__VUE_I18N_FULL_INSTALL__: true,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user