mirror of https://github.com/requarks/wiki
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
213 lines
5.2 KiB
213 lines
5.2 KiB
<template lang='pug'>
|
|
q-page.admin-terminal
|
|
.row.q-pa-md.items-center
|
|
.col-auto
|
|
img.admin-icon.animated.fadeInLeft(src='/_assets/icons/fluent-network.svg')
|
|
.col.q-pl-md
|
|
.text-h5.text-primary.animated.fadeInLeft {{ t('admin.instances.title') }}
|
|
.text-subtitle1.text-grey.animated.fadeInLeft.wait-p2s {{ t('admin.instances.subtitle') }}
|
|
.col-auto.flex
|
|
q-btn.q-mr-sm.acrylic-btn(
|
|
icon='las la-question-circle'
|
|
flat
|
|
color='grey'
|
|
:aria-label='t(`common.actions.viewDocs`)'
|
|
:href='siteStore.docsBase + `/admin/instances`'
|
|
target='_blank'
|
|
type='a'
|
|
)
|
|
q-tooltip {{ t(`common.actions.viewDocs`) }}
|
|
q-btn.q-mr-sm.acrylic-btn(
|
|
icon='las la-redo-alt'
|
|
flat
|
|
color='secondary'
|
|
:loading='state.loading > 0'
|
|
:aria-label='t(`common.actions.refresh`)'
|
|
@click='load'
|
|
)
|
|
q-tooltip {{ t(`common.actions.refresh`) }}
|
|
q-separator(inset)
|
|
.q-pa-md.q-gutter-md
|
|
q-card
|
|
q-table(
|
|
:rows='state.instances'
|
|
:columns='instancesHeaders'
|
|
row-key='name'
|
|
flat
|
|
hide-bottom
|
|
:rows-per-page-options='[0]'
|
|
:loading='state.loading > 0'
|
|
)
|
|
template(v-slot:body-cell-icon='props')
|
|
q-td(:props='props')
|
|
q-icon(name='las la-server', color='positive', size='sm')
|
|
template(v-slot:body-cell-id='props')
|
|
q-td(:props='props')
|
|
strong {{props.value}}
|
|
div: small.text-grey: strong {{props.row.ip}}
|
|
div: small.text-grey {{props.row.dbUser}}
|
|
template(v-slot:body-cell-cons='props')
|
|
q-td(:props='props')
|
|
q-chip(
|
|
icon='las la-plug'
|
|
square
|
|
size='md'
|
|
color='blue'
|
|
text-color='white'
|
|
)
|
|
span.font-robotomono {{ props.value }}
|
|
template(v-slot:body-cell-subs='props')
|
|
q-td(:props='props')
|
|
q-chip(
|
|
icon='las la-broadcast-tower'
|
|
square
|
|
size='md'
|
|
color='green'
|
|
text-color='white'
|
|
)
|
|
small.text-uppercase {{ props.value }}
|
|
template(v-slot:body-cell-firstseen='props')
|
|
q-td(:props='props')
|
|
span {{props.value}}
|
|
div: small.text-grey {{humanizeDate(props.row.dbFirstSeen)}}
|
|
template(v-slot:body-cell-lastseen='props')
|
|
q-td(:props='props')
|
|
span {{props.value}}
|
|
div: small.text-grey {{humanizeDate(props.row.dbLastSeen)}}
|
|
</template>
|
|
|
|
<script setup>
|
|
import { onMounted, reactive } from 'vue'
|
|
import { useMeta, useQuasar } from 'quasar'
|
|
import { useI18n } from 'vue-i18n'
|
|
import gql from 'graphql-tag'
|
|
import { DateTime, Duration, Interval } from 'luxon'
|
|
|
|
import { useSiteStore } from 'src/stores/site'
|
|
|
|
// QUASAR
|
|
|
|
const $q = useQuasar()
|
|
|
|
// STORES
|
|
|
|
const siteStore = useSiteStore()
|
|
|
|
// I18N
|
|
|
|
const { t } = useI18n()
|
|
|
|
// META
|
|
|
|
useMeta({
|
|
title: t('admin.instances.title')
|
|
})
|
|
|
|
// DATA
|
|
|
|
const state = reactive({
|
|
instances: [],
|
|
loading: 0
|
|
})
|
|
|
|
const instancesHeaders = [
|
|
{
|
|
align: 'center',
|
|
field: 'id',
|
|
name: 'icon',
|
|
sortable: false,
|
|
style: 'width: 15px; padding-right: 0;'
|
|
},
|
|
{
|
|
label: t('common.field.id'),
|
|
align: 'left',
|
|
field: 'id',
|
|
name: 'id',
|
|
sortable: true
|
|
},
|
|
{
|
|
label: t('admin.instances.activeConnections'),
|
|
align: 'left',
|
|
field: 'activeConnections',
|
|
name: 'cons',
|
|
sortable: true
|
|
},
|
|
{
|
|
label: t('admin.instances.activeListeners'),
|
|
align: 'left',
|
|
field: 'activeListeners',
|
|
name: 'subs',
|
|
sortable: true
|
|
},
|
|
{
|
|
label: t('admin.instances.firstSeen'),
|
|
align: 'left',
|
|
field: 'dbFirstSeen',
|
|
name: 'firstseen',
|
|
sortable: true,
|
|
format: v => DateTime.fromISO(v).toRelative()
|
|
},
|
|
{
|
|
label: t('admin.instances.lastSeen'),
|
|
align: 'left',
|
|
field: 'dbLastSeen',
|
|
name: 'lastseen',
|
|
sortable: true,
|
|
format: v => DateTime.fromISO(v).toRelative()
|
|
}
|
|
]
|
|
|
|
// METHODS
|
|
|
|
function humanizeDate (val) {
|
|
return DateTime.fromISO(val).toFormat('fff')
|
|
}
|
|
|
|
function humanizeDuration (start, end) {
|
|
const dur = Interval.fromDateTimes(DateTime.fromISO(start), DateTime.fromISO(end))
|
|
.toDuration(['hours', 'minutes', 'seconds', 'milliseconds'])
|
|
return Duration.fromObject({
|
|
...dur.hours > 0 && { hours: dur.hours },
|
|
...dur.minutes > 0 && { minutes: dur.minutes },
|
|
...dur.seconds > 0 && { seconds: dur.seconds },
|
|
...dur.milliseconds > 0 && { milliseconds: dur.milliseconds }
|
|
}).toHuman({ unitDisplay: 'narrow', listStyle: 'short' })
|
|
}
|
|
|
|
async function load () {
|
|
state.loading++
|
|
try {
|
|
const resp = await APOLLO_CLIENT.query({
|
|
query: gql`
|
|
query getSystemInstances {
|
|
systemInstances {
|
|
id
|
|
activeConnections
|
|
activeListeners
|
|
dbUser
|
|
dbFirstSeen
|
|
dbLastSeen
|
|
ip
|
|
}
|
|
}
|
|
`,
|
|
fetchPolicy: 'network-only'
|
|
})
|
|
state.instances = resp?.data?.systemInstances
|
|
} catch (err) {
|
|
$q.notify({
|
|
type: 'negative',
|
|
message: 'Failed to load list of instances.',
|
|
caption: err.message
|
|
})
|
|
}
|
|
state.loading--
|
|
}
|
|
|
|
// MOUNTED
|
|
|
|
onMounted(() => {
|
|
load()
|
|
})
|
|
</script>
|