mirror of
https://github.com/hanzo-io/press.git
synced 2026-10-30 18:56:50 +00:00
199 lines
4.7 KiB
Vue
199 lines
4.7 KiB
Vue
<template>
|
|
<Dialog
|
|
:options="{
|
|
title: `Database User (${db_user_name}) Logs`,
|
|
size: '5xl',
|
|
}"
|
|
v-model="showDialog"
|
|
>
|
|
<template #body-content>
|
|
<div>
|
|
<!-- Top Bar -->
|
|
<form
|
|
class="flex w-full flex-row items-center gap-2"
|
|
@submit.prevent="this.$resources.logs.submit()"
|
|
>
|
|
<FormControl
|
|
class="w-full"
|
|
type="text"
|
|
size="sm"
|
|
variant="subtle"
|
|
icon-left="search"
|
|
placeholder="Search Keywords (Optional)"
|
|
v-model="search_string"
|
|
/>
|
|
<FormControl
|
|
class="w-full"
|
|
type="text"
|
|
size="sm"
|
|
variant="subtle"
|
|
placeholder="Client IP (Optional)"
|
|
v-model="client_ip"
|
|
/>
|
|
<div class="min-w-[11rem] max-w-[11rem] text-base">
|
|
<DateTimePicker
|
|
v-model="start_time"
|
|
variant="subtle"
|
|
placeholder="Start Time"
|
|
label="Start Time"
|
|
:disabled="false"
|
|
/>
|
|
</div>
|
|
<div class="min-w-[11rem] max-w-[11rem] text-base">
|
|
<DateTimePicker
|
|
v-model="end_time"
|
|
variant="subtle"
|
|
placeholder="End Time"
|
|
:disabled="false"
|
|
/>
|
|
</div>
|
|
<Button
|
|
variant="solid"
|
|
theme="gray"
|
|
size="sm"
|
|
loadingText="Searching"
|
|
:loading="this.$resources.logs.loading"
|
|
iconLeft="search"
|
|
@click="this.$resources.logs.submit()"
|
|
>
|
|
Search
|
|
</Button>
|
|
</form>
|
|
|
|
<!-- Result -->
|
|
<div class="mt-5">
|
|
<div
|
|
v-if="this.$resources.logs.loading"
|
|
class="flex h-[14.5rem] w-full items-center justify-center gap-2 py-20 text-base text-gray-700"
|
|
>
|
|
<Spinner class="w-4" /> Fetching logs...
|
|
</div>
|
|
<div v-else>
|
|
<SQLResultTable
|
|
:columns="['Timestamp', 'Client IP', 'Query', 'Duration (ms)']"
|
|
:data="this.logs"
|
|
:hideIndexColumn="true"
|
|
:isTruncateText="true"
|
|
:truncateLength="70"
|
|
/>
|
|
<p class="mt-2 text-sm text-gray-700">
|
|
<span class="font-semibold">NOTE :</span> Search result will show
|
|
max 500 logs.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<ErrorMessage :message="this.$resources?.logs?.error" class="mt-2" />
|
|
</template>
|
|
</Dialog>
|
|
</template>
|
|
<script>
|
|
import { ErrorMessage, FormControl } from 'frappe-ui';
|
|
import { icon } from '../../utils/components';
|
|
import { DashboardError } from '../../utils/error';
|
|
import { DateTimePicker } from 'frappe-ui';
|
|
import SQLResultTable from '../devtools/database/SQLResultTable.vue';
|
|
import Spinner from '../Spinner.vue';
|
|
|
|
export default {
|
|
name: 'SiteDatabaseUserLogs',
|
|
props: ['name', 'db_user_name'],
|
|
$emit: ['update:modelValue', 'hide'],
|
|
components: {
|
|
FormControl,
|
|
icon,
|
|
DateTimePicker,
|
|
SQLResultTable,
|
|
ErrorMessage,
|
|
},
|
|
data() {
|
|
return {
|
|
start_time: null,
|
|
end_time: null,
|
|
search_string: '',
|
|
client_ip: '',
|
|
};
|
|
},
|
|
mounted() {
|
|
const now = new Date();
|
|
this.end_time = now.toLocaleString();
|
|
const oneHourAgo = new Date(now.getTime() - 60 * 60 * 1000);
|
|
this.start_time = oneHourAgo.toLocaleString();
|
|
|
|
this.$resources.logs.submit();
|
|
},
|
|
resources: {
|
|
logs() {
|
|
return {
|
|
url: 'press.api.client.run_doc_method',
|
|
initialData: {},
|
|
auto: false,
|
|
makeParams: () => {
|
|
return {
|
|
dt: 'Site Database User',
|
|
dn: this.name,
|
|
method: 'fetch_logs',
|
|
args: {
|
|
start_timestamp: parseInt(
|
|
new Date(this.start_time).getTime() / 1000,
|
|
),
|
|
end_timestamp: parseInt(new Date(this.end_time).getTime() / 1000),
|
|
search_string: this.search_string,
|
|
client_ip: this.client_ip,
|
|
},
|
|
};
|
|
},
|
|
validate() {
|
|
let start_time_date = new Date(this.start_time);
|
|
let end_time_date = new Date(this.end_time);
|
|
if (!(start_time_date || start_time_date == 'Invalid Date')) {
|
|
throw new DashboardError('Please choose a valid start time');
|
|
}
|
|
|
|
if (!(end_time_date || end_time_date == 'Invalid Date')) {
|
|
throw new DashboardError('Please choose a valid end time');
|
|
}
|
|
|
|
if (start_time_date >= end_time_date) {
|
|
throw new DashboardError('Start time must be before end time');
|
|
}
|
|
},
|
|
onSuccess: (data) => {
|
|
if (data?.message?.loading) {
|
|
setTimeout(this.fetchTableSchemas, 5000);
|
|
}
|
|
},
|
|
};
|
|
},
|
|
},
|
|
computed: {
|
|
showDialog: {
|
|
get() {
|
|
return this.modelValue;
|
|
},
|
|
set(value) {
|
|
this.$emit('update:modelValue', value);
|
|
if (!value) {
|
|
this.$emit('hide');
|
|
}
|
|
},
|
|
},
|
|
logs() {
|
|
if (!this.$resources?.logs?.data?.message) return [];
|
|
let data = this.$resources?.logs?.data?.message ?? [];
|
|
let result = [];
|
|
for (let log of data) {
|
|
result.push([
|
|
new Date((log.start_timestamp || 0) * 1000).toLocaleString(),
|
|
log.client_ip,
|
|
log.query,
|
|
log.duration_ms,
|
|
]);
|
|
}
|
|
return result;
|
|
},
|
|
},
|
|
methods: {},
|
|
};
|
|
</script>
|