mirror of
https://github.com/nocodb/nocodb.git
synced 2026-05-01 05:26:53 +00:00
145 lines
3.8 KiB
Vue
145 lines
3.8 KiB
Vue
<script lang="ts" setup>
|
|
import type { Card as AntCard } from 'ant-design-vue'
|
|
import { JobStatus, iconMap } from '#imports'
|
|
|
|
const progress = ref<Record<string, any>[]>([])
|
|
|
|
const logRef = ref<typeof AntCard>()
|
|
|
|
const autoScroll = ref(true)
|
|
|
|
const scrollToBottom = () => {
|
|
const container: HTMLDivElement = logRef.value?.$el?.firstElementChild
|
|
if (!container) return
|
|
container.scrollTop = container.scrollHeight
|
|
}
|
|
|
|
const pushProgress = (message: string, status: JobStatus | 'progress' | 'warning') => {
|
|
if (!message?.trim()) return
|
|
progress.value.push({
|
|
msg: message,
|
|
status: status === JobStatus.FAILED ? JobStatus.FAILED : message.startsWith('WARNING: ') ? 'warning' : status,
|
|
})
|
|
|
|
if (autoScroll.value) {
|
|
nextTick(scrollToBottom)
|
|
}
|
|
}
|
|
|
|
const onUserScroll = (e: Event) => {
|
|
const { scrollTop, scrollHeight, clientHeight } = e.target as HTMLDivElement
|
|
|
|
// If user is not at the bottom, disable auto-scroll
|
|
autoScroll.value = scrollTop + clientHeight >= scrollHeight - 10
|
|
}
|
|
|
|
function downloadLogs(filename: string) {
|
|
let text = ''
|
|
for (const { msg } of progress.value) {
|
|
text += `${msg}\n`
|
|
}
|
|
|
|
const element = document.createElement('a')
|
|
element.setAttribute('href', `data:text/plain;charset=utf-8,${encodeURIComponent(text)}`)
|
|
element.setAttribute('download', filename)
|
|
|
|
element.style.display = 'none'
|
|
document.body.appendChild(element)
|
|
|
|
element.click()
|
|
|
|
document.body.removeChild(element)
|
|
}
|
|
|
|
const progressEnd = computed(() =>
|
|
[JobStatus.FAILED, JobStatus.COMPLETED].includes(progress.value[progress.value.length - 1]?.status),
|
|
)
|
|
|
|
useEventListener(() => logRef.value?.$el?.firstElementChild, 'scroll', onUserScroll, {
|
|
passive: true,
|
|
})
|
|
|
|
defineExpose({
|
|
pushProgress,
|
|
})
|
|
|
|
onMounted(() => {
|
|
scrollToBottom()
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<a-card
|
|
ref="logRef"
|
|
:bordered="false"
|
|
:body-style="{
|
|
'overflow': 'auto',
|
|
'width': '100%',
|
|
'height': '100%',
|
|
'backgroundColor': '#101015',
|
|
'borderRadius': '0.5rem',
|
|
'padding': '16px !important',
|
|
'scrollbar-color': 'var(--scrollbar-thumb) var(--scrollbar-track)',
|
|
'scrollbar-width': 'thin',
|
|
'--scrollbar-thumb': '#E7E7E9',
|
|
'--scrollbar-track': 'transparent',
|
|
}"
|
|
>
|
|
<div v-for="({ msg, status }, i) in progress" :key="i">
|
|
<div v-if="status === JobStatus.FAILED" class="flex items-center">
|
|
<component :is="iconMap.closeCircle" class="text-red-500" />
|
|
|
|
<span class="text-red-500 ml-2">{{ msg }}</span>
|
|
</div>
|
|
<div v-else-if="status === 'warning'" class="flex items-center">
|
|
<component :is="iconMap.warning" class="text-yellow-500" />
|
|
|
|
<span class="text-yellow-500 ml-2">{{ msg }}</span>
|
|
</div>
|
|
<div v-else class="flex items-center">
|
|
<MdiCurrencyUsd class="text-green-500" />
|
|
|
|
<span class="text-green-500 ml-2">{{ msg }}</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div v-if="!progressEnd" class="flex items-center">
|
|
<component :is="iconMap.loading" class="text-green-500 animate-spin" />
|
|
<span class="text-green-500 ml-2">Loading...</span>
|
|
</div>
|
|
|
|
<NcButton
|
|
v-if="progressEnd"
|
|
class="!absolute z-1 right-2 bottom-2 opacity-75 hover:opacity-100 !rounded-md !w-8 !h-8"
|
|
size="small"
|
|
type="secondary"
|
|
@click="downloadLogs('logs.txt')"
|
|
>
|
|
<nc-tooltip>
|
|
<template #title>Download Logs</template>
|
|
<component :is="iconMap.download" />
|
|
</nc-tooltip>
|
|
</NcButton>
|
|
</a-card>
|
|
</template>
|
|
|
|
<style lang="scss" scoped>
|
|
.nc-progress-panel {
|
|
@apply p-6 flex-1 flex justify-center;
|
|
}
|
|
</style>
|
|
|
|
<style lang="scss">
|
|
.nc-modal-create-source {
|
|
.nc-modal {
|
|
@apply !p-0;
|
|
height: min(calc(100vh - 100px), 1024px);
|
|
max-height: min(calc(100vh - 100px), 1024px) !important;
|
|
}
|
|
}
|
|
|
|
.nc-dropdown-ext-db-type {
|
|
@apply !z-1000;
|
|
}
|
|
</style>
|