refactor: update HistoryConsole to new request messages + use accordion

This commit is contained in:
axolotle 2024-08-05 17:13:26 +02:00
parent fa22d11bee
commit 4979058f54
2 changed files with 49 additions and 79 deletions

View file

@ -22,7 +22,7 @@
@import '~bootstrap/scss/nav'; @import '~bootstrap/scss/nav';
@import '~bootstrap/scss/navbar'; @import '~bootstrap/scss/navbar';
@import '~bootstrap/scss/card'; @import '~bootstrap/scss/card';
// @import "~bootstrap/scss/accordion"; @import "~bootstrap/scss/accordion";
@import '~bootstrap/scss/breadcrumb'; @import '~bootstrap/scss/breadcrumb';
// @import "~bootstrap/scss/pagination"; // @import "~bootstrap/scss/pagination";
@import '~bootstrap/scss/badge'; @import '~bootstrap/scss/badge';
@ -273,6 +273,7 @@ code {
[data-bs-theme='dark'] & { [data-bs-theme='dark'] & {
background-color: $gray-800; background-color: $gray-800;
color: $gray-400;
} }
} }

View file

@ -1,35 +1,28 @@
<script setup lang="ts"> <script setup lang="ts">
import type { BCard } from 'bootstrap-vue-next' import type { BAccordion, BCard } from 'bootstrap-vue-next'
import { getCurrentInstance, nextTick, ref } from 'vue' import { computed, nextTick, ref } from 'vue'
import MessageListGroup from '@/components/MessageListGroup.vue' import MessageListGroup from '@/components/MessageListGroup.vue'
import QueryHeader from '@/components/QueryHeader.vue' import QueryHeader from '@/components/QueryHeader.vue'
import { useStoreGetters } from '@/store/utils' import { useRequests } from '@/composables/useRequests'
// FIXME prop `value` not used? const { historyList, showModal } = useRequests()
const props = withDefaults(
defineProps<{
value?: boolean
height?: number | string
}>(),
{
value: false,
height: 30,
},
)
const { history, lastAction, waiting, error } = useStoreGetters()
const rootElem = ref<InstanceType<typeof BCard> | null>(null) const rootElem = ref<InstanceType<typeof BCard> | null>(null)
const historyElem = ref<HTMLElement | null>(null) const historyElem = ref<InstanceType<typeof BAccordion> | null>(null)
const open = ref(false) const open = ref(false)
function scrollToAction(actionIndex: number) { const lastAction = computed(() => {
return historyList.value[historyList.value.length - 1]
})
async function scrollToAction(actionIndex: number) {
await nextTick()
const actionCard = rootElem.value!.$el.querySelector( const actionCard = rootElem.value!.$el.querySelector(
'#messages-collapse-' + actionIndex, '#messages-collapse-' + actionIndex,
).parentElement ).parentElement
const headerOffset = actionCard.firstElementChild.offsetHeight const headerOffset = actionCard.firstElementChild.offsetHeight - 7
// Can't use `scrollIntoView()` here since it will also scroll in the main content. // Can't use `scrollIntoView()` here since it will also scroll in the main content.
historyElem.value!.scrollTop = actionCard.offsetTop - headerOffset historyElem.value!.$el.scrollTop = actionCard.offsetTop - headerOffset
} }
async function onLastActionClick() { async function onLastActionClick() {
@ -37,14 +30,13 @@ async function onLastActionClick() {
open.value = true open.value = true
await nextTick() await nextTick()
} }
const hElem = historyElem.value! const hElem = historyElem.value!.$el
const lastActionCard = hElem.lastElementChild as HTMLElement const lastActionCard = hElem.lastElementChild as HTMLElement
const lastCollapsable = lastActionCard.querySelector('.collapse') const lastCollapsable = lastActionCard.querySelector('.collapse')
if (lastCollapsable && !lastCollapsable.classList.contains('show')) { if (lastCollapsable && !lastCollapsable.classList.contains('show')) {
// FIXME not sure root emits still work with bvn const btn = lastActionCard.querySelector('.accordion-button') as HTMLElement
const { emit: rootEmit } = getCurrentInstance()! btn.click()
rootEmit('bv::toggle::collapse', lastCollapsable.id)
// `scrollToAction` will be triggered and will handle the scrolling. // `scrollToAction` will be triggered and will handle the scrolling.
} else { } else {
const headerElem = lastActionCard.firstElementChild as HTMLElement const headerElem = lastActionCard.firstElementChild as HTMLElement
@ -64,7 +56,7 @@ function onHistoryBarClick(e: MouseEvent) {
const { nodeName, parentElement } = e.target as HTMLElement const { nodeName, parentElement } = e.target as HTMLElement
if (nodeName === 'BUTTON' || parentElement?.nodeName === 'BUTTON') return if (nodeName === 'BUTTON' || parentElement?.nodeName === 'BUTTON') return
const hElem = historyElem.value! const hElem = historyElem.value!.$el
let mousePos = e.clientY let mousePos = e.clientY
const onMouseMove = ({ clientY }: MouseEvent) => { const onMouseMove = ({ clientY }: MouseEvent) => {
@ -142,7 +134,7 @@ function onHistoryBarClick(e: MouseEvent) {
v-if="lastAction" v-if="lastAction"
size="sm" size="sm"
pill pill
class="ms-auto py-0" class="ms-auto me-2 py-0"
:variant="open ? 'light' : 'best'" :variant="open ? 'light' : 'best'"
@click.prevent="onLastActionClick" @click.prevent="onLastActionClick"
@keyup.enter.space.prevent="onLastActionClick" @keyup.enter.space.prevent="onLastActionClick"
@ -152,64 +144,43 @@ function onHistoryBarClick(e: MouseEvent) {
<QueryHeader <QueryHeader
v-if="lastAction" v-if="lastAction"
:request="lastAction" :request="lastAction"
class="w-auto ms-2 xs-hide" type="overlay"
class="w-auto d-none d-sm-flex"
/> />
</BCardHeader> </BCardHeader>
<!-- ACTION LIST -->
<BCollapse id="console-collapse" v-model="open"> <BCollapse id="console-collapse" v-model="open">
<div class="accordion" role="tablist" id="history" ref="historyElem"> <BAccordion id="history" ref="historyElem" flush free>
<p v-if="history.length === 0" class="alert m-0 px-2 py-1"> <p v-if="historyList.length === 0" class="alert m-0 px-2 py-1">
{{ $t('history.is_empty') }} {{ $t('history.is_empty') }}
</p> </p>
<BAccordionItem
<!-- ACTION LIST --> v-for="(request, i) in historyList"
<BCard v-else
v-for="(action, i) in history" :id="`messages-collapse-${i}`"
:key="i" :key="i"
no-body header-class="sticky-top"
class="rounded-0 rounded-top border-start-0 border-right-0" button-class="d-flex p-2"
header-tag="div"
@show="scrollToAction(i)"
> >
<!-- ACTION --> <template #title>
<BCardHeader
header-tag="header"
header-bg-variant="white"
class="sticky-top d-flex"
>
<!-- ACTION DESC -->
<QueryHeader <QueryHeader
role="tab" :request="request"
v-b-toggle=" type="history"
action.messages.length ? 'messages-collapse-' + i : undefined class="me-2"
" @show-error="showModal"
:request="action"
show-time
show-error
/> />
</BCardHeader> </template>
<MessageListGroup :messages="request.action.messages" />
<!-- ACTION MESSAGES --> </BAccordionItem>
<BCollapse </BAccordion>
v-if="action.messages.length"
:id="'messages-collapse-' + i"
accordion="my-accordion"
role="tabpanel"
@shown="scrollToAction(i)"
@hide="scrollToAction(i)"
>
<MessageListGroup :messages="action.messages" />
</BCollapse>
</BCard>
</div>
</BCollapse> </BCollapse>
</BCard> </BCard>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
// reset default style
.card + .card {
margin-top: 0;
}
.card-header { .card-header {
padding: $tooltip-padding-y $tooltip-padding-x; padding: $tooltip-padding-y $tooltip-padding-x;
} }
@ -247,7 +218,7 @@ function onHistoryBarClick(e: MouseEvent) {
} }
// Hacky disable of collapse animation // Hacky disable of collapse animation
.collapsing { :deep(.collapsing) {
transition: none !important; transition: none !important;
height: auto !important; height: auto !important;
display: block !important; display: block !important;
@ -262,14 +233,12 @@ function onHistoryBarClick(e: MouseEvent) {
max-height: none; max-height: none;
} }
> .card { > :deep(.accordion) {
// reset bootstrap's `overflow: hidden` that prevent sticky headers to work properly. // overlap borders
overflow: visible; margin-top: -1px;
}
&:first-of-type { :deep(.accordion-body) {
// hide first top border that conflicts with the console header's bottom border. padding: 0;
margin-top: -1px;
}
} }
[aria-controls] { [aria-controls] {