mirror of
https://github.com/YunoHost/yunohost-admin.git
synced 2024-09-03 20:06:15 +02:00
refactor: update HistoryConsole to new request messages + use accordion
This commit is contained in:
parent
fa22d11bee
commit
4979058f54
2 changed files with 49 additions and 79 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
<BCollapse id="console-collapse" v-model="open">
|
|
||||||
<div class="accordion" role="tablist" id="history" ref="historyElem">
|
|
||||||
<p v-if="history.length === 0" class="alert m-0 px-2 py-1">
|
|
||||||
{{ $t('history.is_empty') }}
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<!-- ACTION LIST -->
|
<!-- ACTION LIST -->
|
||||||
<BCard
|
<BCollapse id="console-collapse" v-model="open">
|
||||||
v-for="(action, i) in history"
|
<BAccordion id="history" ref="historyElem" flush free>
|
||||||
|
<p v-if="historyList.length === 0" class="alert m-0 px-2 py-1">
|
||||||
|
{{ $t('history.is_empty') }}
|
||||||
|
</p>
|
||||||
|
<BAccordionItem
|
||||||
|
v-for="(request, i) in historyList"
|
||||||
|
v-else
|
||||||
|
: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;
|
|
||||||
|
|
||||||
&:first-of-type {
|
|
||||||
// hide first top border that conflicts with the console header's bottom border.
|
|
||||||
margin-top: -1px;
|
margin-top: -1px;
|
||||||
}
|
}
|
||||||
|
:deep(.accordion-body) {
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
[aria-controls] {
|
[aria-controls] {
|
||||||
|
|
Loading…
Reference in a new issue