Skip to content

Commit

Permalink
update instances and jobs pages
Browse files Browse the repository at this point in the history
* add new list data in instances
* update jobs page adding history modal
* avoid objet key access on Title and Subtitle
* update gitignore to add logs build
  • Loading branch information
syrk4web committed Aug 7, 2024
1 parent 9d485d2 commit 9713f9b
Show file tree
Hide file tree
Showing 21 changed files with 2,266 additions and 2,322 deletions.
2 changes: 2 additions & 0 deletions src/ui/builder/instances.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ def instances_builder(instances: List[Instance]) -> str:
instance = instance_widget(
containerColumns={"pc": 6, "tablet": 6, "mobile": 12},
pairs=[
{"key": "instances_name", "value": instance.name},
{"key": "instances_type", "value": instance.type},
{"key": "instances_method", "value": instance.method},
{"key": "instances_creation_date", "value": instance.creation_date.strftime("%d-%m-%Y %H:%M:%S")},
{"key": "instances_last_seen", "value": instance.last_seen.strftime("%d-%m-%Y %H:%M:%S")},
Expand Down
96 changes: 87 additions & 9 deletions src/ui/builder/jobs.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@ def jobs_builder(jobs):
"widgets": [
title_widget("jobs_title"),
table_widget(
positions=[2, 2, 1, 1, 1, 2, 3],
positions=[3, 2, 1, 1, 1, 1, 3],
header=[
"jobs_table_name",
"jobs_table_plugin_id",
"jobs_table_interval",
"jobs_table_reload",
"jobs_table_success",
"jobs_table_last_run_date",
"jobs_table_history",
"jobs_table_cache_downloadable",
],
items=jobs_list,
Expand All @@ -46,7 +46,7 @@ def jobs_builder(jobs):
"filterName": "keyword",
"type": "keyword",
"value": "",
"keys": ["name", "plugin_id", "last_run"],
"keys": ["name", "plugin_id"],
"field": {
"id": "jobs-keyword",
"value": "",
Expand Down Expand Up @@ -150,22 +150,100 @@ def get_jobs_list(jobs):
# loop on each value
for k, v in value.items():
# override widget type for some keys
if k in ("reload", "success"):
if k in ("reload", "history"):
is_success = v if k == "reload" else v[0].get("success")
item.append(
{
k: "success" if v else "failed",
k: "success" if is_success else "failed",
"type": "Icons",
"data": {
"iconName": "check" if v else "cross",
"iconName": "check" if is_success else "cross",
},
}
)
continue

if k in ("plugin_id", "every", "last_run"):
if k not in ("history"):
continue

if k in ("plugin_id", "every"):
item.append({k: v, "type": "Text", "data": {"text": v}})
continue

if k in ("history"):
items = []
for hist in v:
items.append(
[
{
"type": "Text",
"data": {
"text": hist["start_date"],
},
},
{
"type": "Text",
"data": {
"text": hist["end_date"],
},
},
{
"type": "Icons",
"data": {
"iconName": "check" if hist["success"] else "cross",
},
},
]
)

item.append(
{
"type": "Button",
"data": {
"id": f"open-modal-history-{k}",
"text": "jobs_history",
"hideText": True,
"color": "blue",
"size": "normal",
"iconName": "document",
"iconColor": "white",
"modal": {
"widgets": [
{"type": "Title", "data": {"title": key}},
{"type": "Subtitle", "data": {"subtitle": "jobs_history_subtitle"}},
{
"type": "Table",
"data": {
"title": "jobs_history_table_title",
"minWidth": "",
"header": [
"jobs_table_start_run",
"jobs_table_end_run",
"jobs_table_success",
],
"positions": [5, 5, 2],
"items": items,
},
},
{
"type": "ButtonGroup",
"data": {
"buttons": [
{
"id": f"close-history-{k}",
"text": "action_close",
"color": "close",
"size": "normal",
"attrs": {"data-close-modal": ""},
}
]
},
},
]
},
},
}
)

if k in ("cache") and len(v) <= 0:
item.append({k: v, "type": "Text", "data": {"text": ""}})
continue
Expand Down Expand Up @@ -201,7 +279,7 @@ def get_jobs_list(jobs):
},
"overflowAttrEl": "data-table-body",
"containerClass": "table download-cache-file",
"maxBtnChars": 12,
"maxBtnChars": 16,
"popovers": [
{
"iconName": "info",
Expand Down
2 changes: 2 additions & 0 deletions src/ui/client/dashboard/.gitignore
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
# Logs
logs
!pages/logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*


node_modules
dist
dist-ssr
Expand Down
2 changes: 1 addition & 1 deletion src/ui/client/dashboard/components/Forms/Field/List.vue
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ function closeTab(e) {
/**
* @name addEntry
* @description When clicking add entry or key "Enter", will add the current input value to list.
* @param {e} e - The event object.
* @param {event} e - The event object.
* @returns {void}
*/
function addEntry(e) {
Expand Down
2 changes: 1 addition & 1 deletion src/ui/client/dashboard/components/Widget/Subtitle.vue
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ const subtitleEl = ref(null);
onMounted(() => {
subtitle.class =
props.subtitleClass || subtitleEl.value.closest("[data-is]")
props.subtitleClass || subtitleEl?.value?.closest("[data-is]")
? `subtitle-${subtitleEl.value
.closest("[data-is]")
.getAttribute("data-is")}`
Expand Down
3 changes: 2 additions & 1 deletion src/ui/client/dashboard/components/Widget/Title.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<script setup>
import { computed, onMounted, reactive, ref } from "vue";
/**
* @name Widget/Title.vue
* @description This component is a general title wrapper.
Expand Down Expand Up @@ -83,7 +84,7 @@ onMounted(() => {
!nextSibling || !nextSibling.hasAttribute("data-subtitle") ? false : true;
title.class =
props.titleClass || titleEl.value.closest("[data-is]")
props.titleClass || titleEl?.value?.closest("[data-is]")
? `title-${titleEl.value.closest("[data-is]").getAttribute("data-is")}`
: "title-card";
});
Expand Down
6 changes: 5 additions & 1 deletion src/ui/client/dashboard/lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -213,9 +213,13 @@
"jobs_table_plugin_id": "Plugin id",
"jobs_table_interval": "Interval",
"jobs_table_reload": "Reload",
"jobs_table_history": "History",
"jobs_table_success": "Success",
"jobs_table_last_run_date": "Last run date",
"jobs_table_start_run": "Start run date",
"jobs_table_end_run": "End run date",
"jobs_table_cache_downloadable": "Cache (downloadable)",
"jobs_history_subtitle": "Job history details.",
"jobs_history_table_title": "Job history list with start run date, end run date and success state.",
"plugins_pro_plugin_desc": "Pro plugin",
"plugins_core_plugin_desc": "Core plugin",
"plugins_external_plugin_desc": "External plugin",
Expand Down
2 changes: 1 addition & 1 deletion src/ui/client/dashboard/pages/jobs/index.html

Large diffs are not rendered by default.

66 changes: 66 additions & 0 deletions src/ui/client/dashboard/pages/logs/Logs.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<script setup>
import { reactive, onBeforeMount, onMounted } from "vue";
import DashboardLayout from "@components/Dashboard/Layout.vue";
import BuilderLogs from "@components/Builder/Logs.vue";
import { useGlobal } from "@utils/global";
/**
* @name Page/Logs.vue
* @description This component is the logd page.
This page allow to choose log files and view the logs.
*/
const logs = reactive({
builder: "",
});
onBeforeMount(() => {
// Get builder data
const dataAtt = "data-server-builder";
const dataEl = document.querySelector(`[${dataAtt}]`);
const data =
dataEl && !dataEl.getAttribute(dataAtt).includes(dataAtt)
? JSON.parse(atob(dataEl.getAttribute(dataAtt)))
: {};
logs.builder = data;
});
/**
* @name getLogContent
* @description Redirect to the same page but with log name as query parameter to get the content of the log.
* @returns {void}
*/
function getLogContent() {
window.addEventListener(
"click",
(e) => {
// Case not wanted element
if (!e.target.hasAttribute("data-setting-value")) return;
if (
!e.target.closest("[data-field-container]").querySelector("[data-log]")
)
return;
const value = e.target.getAttribute("data-setting-value");
const url = `${location.href}/logs?file=${value}`;
// go to url
location.href = url;
},
true
);
}
onMounted(() => {
// Set the page title
useGlobal();
getLogContent();
});
</script>

<template>
<DashboardLayout>
<div class="col-span-12 grid grid-cols-12 card">
<BuilderLogs v-if="logs.builder" :builder="logs.builder" />
</div>
</DashboardLayout>
</template>
24 changes: 24 additions & 0 deletions src/ui/client/dashboard/pages/logs/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/x-icon" href="/img/favicon.ico" />
<link rel="stylesheet" href="/css/style.css" />
<link rel="stylesheet" href="/css/flag-icons.min.css" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>BunkerWeb | Logs</title>
</head>
<body>
<div class="hidden" data-server-global='{"username" : "admin"}'></div>
<div
class="hidden"
data-server-flash='[{"type" : "success", "title" : "title", "message" : "Success feedback"}, {"type" : "error", "title" : "title", "message" : "Error feedback"}, {"type" : "warning", "title" : "title", "message" : "Warning feedback"}, {"type" : "info", "title" : "title", "message" : "Info feedback"}]'
></div>
<div
class="hidden"
data-server-builder="W3sidHlwZSI6ICJjYXJkIiwgImNvbnRhaW5lckNvbHVtbnMiOiB7InBjIjogMTIsICJ0YWJsZXQiOiAxMiwgIm1vYmlsZSI6IDEyfSwgIndpZGdldHMiOiBbeyJ0eXBlIjogIlRpdGxlIiwgImRhdGEiOiB7InRpdGxlIjogImxvZ3NfdGl0bGUifX0sIHsidHlwZSI6ICJGaWVsZHMiLCAiZGF0YSI6IHsic2V0dGluZyI6IHsiaWQiOiAibG9ncy1zZWxlY3QtZmlsZSIsICJsYWJlbCI6ICJsb2dzX3NlbGVjdF9maWxlIiwgImlucFR5cGUiOiAic2VsZWN0IiwgIm5hbWUiOiAibG9ncy1zZWxlY3QtZmlsZSIsICJvbmx5RG93biI6IHRydWUsICJ2YWx1ZSI6ICIiLCAidmFsdWVzIjogWyJmaWxlMSIsICJmaWxlMiJdLCAiY29sdW1ucyI6IHsicGMiOiA0LCAidGFibGV0IjogNiwgIm1vYmlsZSI6IDEyfSwgIm1heEJ0bkNoYXJzIjogMjAsICJhdHRycyI6IHsiZGF0YS1sb2ciOiAidHJ1ZSJ9LCAicG9wb3ZlcnMiOiBbeyJpY29uTmFtZSI6ICJpbmZvIiwgInRleHQiOiAibG9nc19zZWxlY3RfZmlsZV9pbmZvIn1dfX19LCB7InR5cGUiOiAiRmllbGRzIiwgImRhdGEiOiB7InNldHRpbmciOiB7ImNvbnRhaW5lckNsYXNzIjogIm10LTQiLCAiaWQiOiAibG9ncy1maWxlLWNvbnRlbnQiLCAibGFiZWwiOiAibG9nc19maWxlX2NvbnRlbnQiLCAiaW5wVHlwZSI6ICJlZGl0b3IiLCAibmFtZSI6ICJsb2dzLWZpbGUtY29udGVudCIsICJ2YWx1ZSI6ICJnZWZlc2Zlc2ZzZWZlcyIsICJjb2x1bW5zIjogeyJwYyI6IDEyLCAidGFibGV0IjogMTIsICJtb2JpbGUiOiAxMn19fX1dfV0"
></div>
<div id="app"></div>
<script type="module" src="logs.js"></script>
</body>
</html>
11 changes: 11 additions & 0 deletions src/ui/client/dashboard/pages/logs/logs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { createApp } from "vue";
import { createPinia } from "pinia";
import { getI18n } from "@utils/lang.js";
import Logs from "./Logs.vue";

const pinia = createPinia();

createApp(Logs)
.use(pinia)
.use(getI18n(["dashboard", "action", "inp", "icons", "logs"]))
.mount("#app");
2 changes: 1 addition & 1 deletion src/ui/client/dashboard/utils/global.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ function useEqualStr(type, compare) {
* @name useDataLinkAttr
* @description Check from event if the target has a data-link attribute. Case it is, it will be used to redirect the user to the define link.
* This is useful to avoid using the <a> tag and use a <div> or <button> instead.
* @param {e} event - The event to attach the function logic
* @param {event} e - The event to attach the function logic
* @returns {void}
*/
function useDataLinkAttr(e) {
Expand Down
4 changes: 4 additions & 0 deletions src/ui/client/input.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/ui/client/public/css/style.css

Large diffs are not rendered by default.

22 changes: 12 additions & 10 deletions src/ui/client/tests/builder/instances.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from .utils.widgets import instance_widget


def instances_builder(instances: list) -> str:
def instances_builder(instances: List[Instance]) -> str:
"""
It returns the needed format from data to render the instances page in JSON format for the Vue.js builder
"""
Expand All @@ -11,18 +11,18 @@ def instances_builder(instances: list) -> str:
# setup actions buttons
actions = (
["restart", "stop"]
if instance._type == "local" and instance.health
if instance.hostname in ("localhost", "127.0.0.1") and instance.status == "up"
else (
["reload", "stop"]
if not instance._type == "local" and instance.health
else ["start"] if instance._type == "local" and not instance.health else []
if instance.hostname not in ("localhost", "127.0.0.1") and instance.status == "up"
else ["start"] if instance.hostname in ("localhost", "127.0.0.1") and instance.status != "up" else []
)
)

buttons = [
{
"attrs": {
"data-submit-form": f"""{{"INSTANCE_ID" : "{instance._id}", "operation" : "{action}" }}""",
"data-submit-form": f"""{{"INSTANCE_ID" : "{instance.hostname}", "operation" : "{action}" }}""",
},
"text": f"action_{action}",
"color": "success" if action == "start" else "error" if action == "stop" else "warning",
Expand All @@ -33,12 +33,14 @@ def instances_builder(instances: list) -> str:
instance = instance_widget(
containerColumns={"pc": 6, "tablet": 6, "mobile": 12},
pairs=[
{"key": "instances_hostname", "value": instance.hostname},
{"key": "instances_type", "value": instance._type},
{"key": "instances_status", "value": "instances_active" if instance.health else "instances_inactive"},
{"key": "instances_name", "value": instance.name},
{"key": "instances_type", "value": instance.type},
{"key": "instances_method", "value": instance.method},
{"key": "instances_creation_date", "value": instance.creation_date.strftime("%d-%m-%Y %H:%M:%S")},
{"key": "instances_last_seen", "value": instance.last_seen.strftime("%d-%m-%Y %H:%M:%S")},
],
status="success" if instance.health else "error",
title=instance.name,
status="success" if instance.status == "up" else "error",
title=instance.hostname,
buttons=buttons,
)

Expand Down
Loading

0 comments on commit 9713f9b

Please sign in to comment.