merge newui branch
This commit is contained in:
276
ui/src/logs/logPreviewModal.js
Normal file
276
ui/src/logs/logPreviewModal.js
Normal file
@@ -0,0 +1,276 @@
|
||||
import { logLevel } from "./logLevel";
|
||||
|
||||
window.app = window.app || {};
|
||||
window.app.modals = window.app.modals || {};
|
||||
|
||||
window.app.modals.openLogPreview = function(logIdOrModel, settings = {
|
||||
onbeforeopen: null,
|
||||
onafteropen: null,
|
||||
onbeforeclose: null,
|
||||
onafterclose: null,
|
||||
}) {
|
||||
const modal = logPreviewModal(logIdOrModel, settings);
|
||||
if (!modal) {
|
||||
return;
|
||||
}
|
||||
|
||||
document.body.appendChild(modal);
|
||||
|
||||
app.modals.open(modal);
|
||||
};
|
||||
|
||||
const priotizedKeys = [
|
||||
"execTime",
|
||||
"type",
|
||||
"auth",
|
||||
"authId",
|
||||
"status",
|
||||
"method",
|
||||
"url",
|
||||
"referer",
|
||||
"remoteIP",
|
||||
"userIP",
|
||||
"userAgent",
|
||||
"error",
|
||||
"details",
|
||||
];
|
||||
|
||||
function downloadJSON(log) {
|
||||
app.utils.downloadJSON(log, "log_" + log.created.replaceAll(/[-:\. ]/gi, "") + ".json");
|
||||
}
|
||||
|
||||
function copyJSON(log) {
|
||||
app.utils.copyToClipboard(JSON.stringify(log, null, 2));
|
||||
app.toasts.success("Log copied to clipboard!");
|
||||
}
|
||||
|
||||
function logPreviewModal(logIdOrModel, settings) {
|
||||
let modal;
|
||||
|
||||
const data = store({
|
||||
isLoading: false,
|
||||
log: null,
|
||||
get isRequest() {
|
||||
return data.log?.data?.type == "request";
|
||||
},
|
||||
get orderedDataKeys() {
|
||||
const result = new Set();
|
||||
|
||||
if (!data.log?.data) {
|
||||
return result;
|
||||
}
|
||||
|
||||
for (let key of priotizedKeys) {
|
||||
if (typeof data.log.data[key] != "undefined") {
|
||||
result.add(key);
|
||||
}
|
||||
}
|
||||
|
||||
for (let key in data.log.data) {
|
||||
result.add(key);
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
});
|
||||
|
||||
async function load() {
|
||||
data.isLoading = true;
|
||||
|
||||
try {
|
||||
if (app.utils.isObject(logIdOrModel)) {
|
||||
data.log = JSON.parse(JSON.stringify(logIdOrModel));
|
||||
} else {
|
||||
data.log = await app.pb.logs.getOne(logIdOrModel, {
|
||||
requestKey: "log_preview",
|
||||
});
|
||||
}
|
||||
|
||||
data.isLoading = false;
|
||||
} catch (err) {
|
||||
if (!err.isAbort) {
|
||||
data.isLoading = false;
|
||||
app.checkApiError(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
modal = t.div(
|
||||
{
|
||||
pbEvent: "logPreviewModal",
|
||||
className: "modal log-preview-modal",
|
||||
onbeforeopen: (el) => {
|
||||
load();
|
||||
return settings.onbeforeopen?.(el);
|
||||
},
|
||||
onafteropen: (el) => {
|
||||
settings.onafteropen?.(el);
|
||||
},
|
||||
onbeforeclose: (el) => {
|
||||
return settings.onbeforeclose?.(el);
|
||||
},
|
||||
onafterclose: (el) => {
|
||||
settings.onafterclose?.(el);
|
||||
el?.remove();
|
||||
},
|
||||
},
|
||||
t.header(
|
||||
{ className: "modal-header" },
|
||||
t.h5(null, "Log details"),
|
||||
t.button(
|
||||
{
|
||||
"className": "btn sm circle transparent m-l-auto",
|
||||
"html-popovertarget": "log-meta-dropdown",
|
||||
},
|
||||
t.i({ className: "ri-more-line" }),
|
||||
),
|
||||
t.div({ id: "log-meta-dropdown", className: "dropdown", popover: "auto" }, (el) => {
|
||||
return t.button(
|
||||
{
|
||||
className: "dropdown-item",
|
||||
onclick: () => {
|
||||
copyJSON(data.log);
|
||||
el.hidePopover();
|
||||
},
|
||||
},
|
||||
t.i({ className: "ri-braces-line" }),
|
||||
t.span({ className: "txt" }, "Copy JSON"),
|
||||
);
|
||||
}),
|
||||
),
|
||||
t.div({ className: "modal-content" }, () => {
|
||||
if (!data.log || data.isLoading) {
|
||||
return t.div({ className: "block txt-center" }, t.span({ className: "loader" }));
|
||||
}
|
||||
|
||||
return t.table(
|
||||
{
|
||||
pbEvent: "logPreviewTable",
|
||||
className: "log-view-table responsive-table",
|
||||
},
|
||||
t.tbody(
|
||||
null,
|
||||
t.tr(
|
||||
null,
|
||||
t.th({ className: "col-field-name-id p-r-0" }, "id"),
|
||||
t.td(null, () => data.log.id),
|
||||
t.td({ className: "col-copy min-width" }, app.components.copyButton(data.log.id)),
|
||||
),
|
||||
t.tr(
|
||||
null,
|
||||
t.th({ className: "col-field-name-level p-r-0" }, "level"),
|
||||
t.td(null, () => logLevel(data.log)),
|
||||
t.td({ className: "col-copy min-width" }, app.components.copyButton(data.log.level)),
|
||||
),
|
||||
t.tr(
|
||||
null,
|
||||
t.th({ className: "col-field-name-created p-r-0" }, "created"),
|
||||
t.td(
|
||||
null,
|
||||
app.components.formattedDate({
|
||||
value: () => data.log.created,
|
||||
short: false,
|
||||
}),
|
||||
),
|
||||
t.td({ className: "col-copy min-width" }, app.components.copyButton(data.log.created)),
|
||||
),
|
||||
() => {
|
||||
if (!data.isRequest) {
|
||||
return t.tr(
|
||||
null,
|
||||
t.th({ className: "col-field-name-message p-r-0" }, "message"),
|
||||
t.td(null, () => app.utils.truncate(data.log.message, 1000)),
|
||||
t.td(
|
||||
{ className: "col-copy min-width" },
|
||||
app.components.copyButton(data.log.message),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
() => {
|
||||
const rows = [];
|
||||
for (let key of data.orderedDataKeys) {
|
||||
let value = data.log.data?.[key];
|
||||
|
||||
if (app.utils.logDataFormatters[key]) {
|
||||
value = app.utils.logDataFormatters[key](data.log);
|
||||
}
|
||||
|
||||
const isEmpty = app.utils.isEmpty(value);
|
||||
const isJSON = !isEmpty && app.utils.isObject(value);
|
||||
if (isJSON) {
|
||||
value = JSON.stringify(value, null, 2);
|
||||
}
|
||||
|
||||
rows.push(
|
||||
t.tr(
|
||||
{
|
||||
rid: "log_data_" + data.log.id + "_" + key,
|
||||
},
|
||||
t.th({ className: "min-width p-r-0" }, "data." + key),
|
||||
t.td(null, () => {
|
||||
if (isEmpty) {
|
||||
return t.span({
|
||||
className: "txt txt-hint",
|
||||
textContent: "N/A",
|
||||
});
|
||||
}
|
||||
|
||||
if (key === "error") {
|
||||
return t.span({
|
||||
className: `label danger log-error-label ${isJSON ? "txt-code" : ""}`,
|
||||
textContent: value,
|
||||
});
|
||||
}
|
||||
|
||||
if (key == "details") {
|
||||
return t.span({
|
||||
className: `label warning log-details-label ${
|
||||
isJSON ? "txt-code" : ""
|
||||
}`,
|
||||
textContent: value,
|
||||
});
|
||||
}
|
||||
|
||||
if (isJSON) {
|
||||
return app.components.codeBlock({ value });
|
||||
}
|
||||
|
||||
return t.span({
|
||||
className: "txt",
|
||||
textContent: app.utils.stringifyValue(value, "N/A", 1000),
|
||||
});
|
||||
}),
|
||||
t.td({ className: "col-copy min-width" }, app.components.copyButton(value)),
|
||||
),
|
||||
);
|
||||
}
|
||||
return rows;
|
||||
},
|
||||
),
|
||||
);
|
||||
}),
|
||||
t.footer(
|
||||
{ className: "modal-footer" },
|
||||
t.button(
|
||||
{
|
||||
type: "button",
|
||||
className: "btn transparent m-r-auto",
|
||||
onclick: () => app.modals.close(modal),
|
||||
},
|
||||
t.span({ className: "txt" }, "Close"),
|
||||
),
|
||||
t.button(
|
||||
{
|
||||
type: "button",
|
||||
className: "btn",
|
||||
onclick: () => downloadJSON(data.log),
|
||||
},
|
||||
t.i({ className: "ri-download-line" }),
|
||||
t.span({ className: "txt" }, "Download JSON"),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return modal;
|
||||
}
|
||||
Reference in New Issue
Block a user