start jobs filters + fix select maxBtnChars

* add new keys for list items to prepare filtering in python
* add jobs filters
* fix maxBtnChars condition
* some component update
* add i18n keys
This commit is contained in:
Jordan Blasenhauer 2024-06-17 21:28:06 +02:00
parent e7e0c2cfbc
commit 79e5f8c8f2
9 changed files with 3044 additions and 1170 deletions

View file

@ -56,11 +56,6 @@ const props = defineProps({
required: true,
default: {},
},
filters: {
type: Object,
required: false,
default: {},
},
containerClass: {
type: String,
required: false,
@ -86,31 +81,6 @@ const data = reactive({
});
const filters = [
{
filter: "default",
filterName: "type",
type: "select",
value: "all",
keys: ["type"],
field: {
id: uuidv4(),
value: "all",
// add 'all' as first value
values: ["all"].concat(plugin_types),
name: uuidv4(),
onlyDown: true,
label: "inp_select_plugin_type",
containerClass: "setting",
popovers: [
{
text: "inp_select_plugin_type_desc",
iconName: "info",
iconColor: "info",
},
],
columns: { pc: 3, tablet: 4, mobile: 12 },
},
},
{
filter: "settings",
filterName: "keyword",
@ -144,6 +114,31 @@ const filters = [
columns: { pc: 3, tablet: 4, mobile: 12 },
},
},
{
filter: "default",
filterName: "type",
type: "select",
value: "all",
keys: ["type"],
field: {
id: uuidv4(),
value: "all",
// add 'all' as first value
values: ["all"].concat(plugin_types),
name: uuidv4(),
onlyDown: true,
label: "inp_select_plugin_type",
containerClass: "setting",
popovers: [
{
text: "inp_select_plugin_type_desc",
iconName: "info",
iconColor: "info",
},
],
columns: { pc: 3, tablet: 4, mobile: 12 },
},
},
{
filter: "settings",
filterName: "context",
@ -220,6 +215,7 @@ const comboboxPlugin = {
disabled: false,
required: false,
onlyDown: true,
containerClass: "setting",
label: "dashboard_plugins",
popovers: [
{
@ -275,7 +271,12 @@ onUnmounted(() => {
:values="data.plugins"
@inp="data.currPlugin = $event"
/>
<Filter @filter="(v) => filter(v)" :data="data.base" :filters="filters" />
<Filter
v-if="filters.length"
@filter="(v) => filter(v)"
:data="data.base"
:filters="filters"
/>
<template v-for="plugin in data.format">
<Container
data-advanced-form-plugin

View file

@ -344,8 +344,8 @@ const emits = defineEmits(["inp"]);
>
<span :id="`${props.id}-text`" class="select-btn-name">
{{
(props.maxBtnChars && select.value) ||
props.value > +props.maxBtnChars
props.maxBtnChars &&
(select.value || props.value).length > +props.maxBtnChars
? `${
select.value.substring(0, props.maxBtnChars) ||
props.value.substring(0, props.maxBtnChars)

View file

@ -320,8 +320,8 @@ const emits = defineEmits(["inp"]);
>
<span :id="`${props.id}-text`" class="select-btn-name">
{{
(props.maxBtnChars && select.value) ||
props.value > +props.maxBtnChars
props.maxBtnChars &&
(select.value || props.value).length > +props.maxBtnChars
? `${
select.value.substring(0, props.maxBtnChars) ||
props.value.substring(0, props.maxBtnChars)

View file

@ -6,6 +6,7 @@ import Text from "@components/Widget/Text.vue";
import Icons from "@components/Widget/Icons.vue";
import Fields from "@components/Form/Fields.vue";
import Button from "@components/Widget/Button.vue";
import Filter from "@components/Widget/Filter.vue";
/**
@name Widget/Table.vue
@ -32,12 +33,41 @@ import Button from "@components/Widget/Button.vue";
],
...
],
const filters = [
{
filter: "default",
filterName: "type",
type: "select",
value: "all",
keys: ["type"],
field: {
id: uuidv4(),
value: "all",
// add 'all' as first value
values: ["all"].concat(plugin_types),
name: uuidv4(),
onlyDown: true,
label: "inp_select_plugin_type",
containerClass: "setting",
popovers: [
{
text: "inp_select_plugin_type_desc",
iconName: "info",
iconColor: "info",
},
],
columns: { pc: 3, tablet: 4, mobile: 12 },
},
},
...
}
@param {string} title - Determine the title of the table.
@param {array} header - Determine the header of the table.
@param {array} positions - Determine the position of each item in the table in a list of number based on 12 columns grid.
@param {array} items - items to render in the table. This need to be an array (row) of array (cols) with a cell being a regular widget.
@param {array} filters - Determine the filters of the table.
@param {string} [minWidth="base"] - Determine the minimum size of the table. Can be "base", "sm", "md", "lg", "xl".
@param {string} [containerClass=""] - Container additional class.
@param {string} [containerWrapClass=""] - Container wrap additional class.
@ -49,10 +79,10 @@ const props = defineProps({
type: String,
required: true,
},
filter: {
type: Boolean,
filters: {
type: Object,
required: false,
default: false,
default: {},
},
minWidth: {
type: String,
@ -102,6 +132,10 @@ const table = reactive({
title: computed(() => {
return props.title ? props.title : "dashboard_table";
}),
// base items that never change
itemsBase: JSON.parse(JSON.stringify(props.items)),
// items that can be filtered
itemsFormat: JSON.parse(JSON.stringify(props.items)),
});
function getOverflow() {
@ -127,7 +161,12 @@ onUpdated(() => {
<template>
<Container :containerClass="`${props.containerClass} table-container`">
<slot></slot>
<Filter
v-if="filters.length"
@filter="(v) => (table.itemsFormat = filterData)"
:data="table.itemsBase"
:filters="filters"
/>
<Container
:containerClass="`${props.containerWrapClass} table-container-wrap`"
>
@ -162,7 +201,7 @@ onUpdated(() => {
:aria-rowindex="rowId"
class="table-content-item"
>
<template v-for="(col, id) in props.items[rowId]">
<template v-for="(col, id) in table.itemsFormat[rowId]">
<td
role="Scell"
:class="[

View file

@ -89,7 +89,7 @@
"dashboard_advanced_mode_subtitle": "Advanced mode show settings by plugin in dedicated fields.",
"dashboard_advanced_invalid": "{plugin} {setting} is invalid",
"dashboard_advanced_required": "{plugin} {setting} is required",
"dashboard_easy_mode" : "Easy mode",
"dashboard_easy_mode": "Easy mode",
"dashboard_easy_mode_title": "Step {step} of {total} - {name}",
"dashboard_easy_mode_subtitle": "Easy mode will guide you using steps and additional information to help you configure your settings.",
"dashboard_easy_invalid": "{setting} in step {step} is invalid",
@ -119,7 +119,7 @@
"inp_select_plugin_context_desc": "Only show plugins of the chosen context.",
"inp_search_key": "search key",
"inp_search_key_desc": "Search within the settings key.",
"inp_editor_desc" : "Editor input behaving like a code editor.",
"inp_editor_desc": "Editor input behaving like a code editor.",
"inp_input_clipboard_copied": "copied to clipboard",
"inp_input_clipboard_desc": "Copy to clipboard on click.",
"icons_cross_desc": "Cross icon representing a close, delete, error or cancel state.",
@ -151,8 +151,8 @@
"action_restart": "restart {name}",
"action_upload": "upload {name}",
"action_delete_all": "delete all {name}",
"action_previous" : "previous",
"action_next" : "next",
"action_previous": "previous",
"action_next": "next",
"home_version": "version",
"home_all_features_available": "all features are available",
"home_awaiting_compliance": "awaiting compliance",
@ -180,5 +180,13 @@
"instances_status": "status",
"instances_active": "active",
"instances_inactive": "inactive",
"jobs_download_cache_file": "download cache files"
"jobs_download_cache_file": "download cache files",
"jobs_search": "search jobs",
"jobs_search_desc": "Search within job name, plugin id or last run.",
"jobs_interval": "Interval",
"jobs_interval_desc": "Choose interval between available options.",
"jobs_success": "success",
"jobs_success_desc": "Choose the job success state.",
"jobs_last_run": "last run",
"jobs_last_run_desc": "Choose the job last run state."
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,78 +1,290 @@
import json
jobs = {'anonymous-report': {'plugin_id': 'misc', 'every': 'day', 'reload': False, 'success': True, 'last_run': '2024/06/14, 01:33:11 PM', 'cache': []}, 'backup-data': {'plugin_id': 'backup', 'every': 'day', 'reload': False, 'success': True, 'last_run': '2024/06/14, 01:33:10 PM', 'cache': []}, 'blacklist-download': {'plugin_id': 'blacklist', 'every': 'hour', 'reload': True, 'success': True, 'last_run': '2024/06/14, 01:33:09 PM', 'cache': []}, 'bunkernet-data': {'plugin_id': 'bunkernet', 'every': 'day', 'reload': True, 'success': True, 'last_run': '2024/06/14, 01:33:11 PM', 'cache': []}, 'bunkernet-register': {'plugin_id': 'bunkernet', 'every': 'hour', 'reload': True, 'success': True, 'last_run': '2024/06/14, 01:33:09 PM', 'cache': []}, 'certbot-new': {'plugin_id': 'letsencrypt', 'every': 'once', 'reload': False, 'success': True, 'last_run': '2024/06/14, 01:33:08 PM', 'cache': []}, 'certbot-renew': {'plugin_id': 'letsencrypt', 'every': 'day', 'reload': True, 'success': True, 'last_run': '2024/06/14, 01:33:09 PM', 'cache': []}, 'coreruleset-nightly': {'plugin_id': 'modsecurity', 'every': 'day', 'reload': True, 'success': True, 'last_run': '2024/06/14, 01:33:09 PM', 'cache': []}, 'custom-cert': {'plugin_id': 'customcert', 'every': 'day', 'reload': True, 'success': True, 'last_run': '2024/06/14, 01:33:10 PM', 'cache': []}, 'default-server-cert': {'plugin_id': 'misc', 'every': 'once', 'reload': False, 'success': True, 'last_run': '2024/06/14, 01:33:10 PM', 'cache': [{'service_id': None, 'file_name': 'default-server-cert.pem', 'last_update': '2024/06/14, 01:33:10 PM'}, {'service_id': None, 'file_name': 'default-server-cert.key', 'last_update': '2024/06/14, 01:33:10 PM'}]}, 'download-plugins': {'plugin_id': 'misc', 'every': 'once', 'reload': False, 'success': True, 'last_run': '2024/06/14, 01:33:13 PM', 'cache': []}, 'download-pro-plugins': {'plugin_id': 'pro', 'every': 'day', 'reload': True, 'success': True, 'last_run': '2024/06/14, 01:33:10 PM', 'cache': []}, 'failover-backup': {'plugin_id': 'jobs', 'every': 'once', 'reload': False, 'success': True, 'last_run': '2024/06/14, 01:33:16 PM', 'cache': [{'service_id': None, 'file_name': 'folder:/var/tmp/bunkerweb/failover.tgz', 'last_update': '2024/06/14, 01:33:27 PM'}]}, 'greylist-download': {'plugin_id': 'greylist', 'every': 'hour', 'reload': True, 'success': True, 'last_run': '2024/06/14, 01:33:09 PM', 'cache': []}, 'mmdb-asn': {'plugin_id': 'jobs', 'every': 'day', 'reload': True, 'success': True, 'last_run': '2024/06/14, 01:33:14 PM', 'cache': [{'service_id': None, 'file_name': 'asn.mmdb', 'last_update': '2024/06/14, 01:33:13 PM'}]}, 'mmdb-country': {'plugin_id': 'jobs', 'every': 'day', 'reload': True, 'success': True, 'last_run': '2024/06/14, 01:33:12 PM', 'cache': [{'service_id': None, 'file_name': 'country.mmdb', 'last_update': '2024/06/14, 01:33:11 PM'}]}, 'realip-download': {'plugin_id': 'realip', 'every': 'hour', 'reload': True, 'success': True, 'last_run': '2024/06/14, 01:33:09 PM', 'cache': []}, 'self-signed': {'plugin_id': 'selfsigned', 'every': 'day', 'reload': True, 'success': True, 'last_run': '2024/06/14, 01:33:10 PM', 'cache': [{'service_id': 'www.example.com', 'file_name': 'cert.pem', 'last_update': '2024/06/14, 01:33:10 PM'}, {'service_id': 'www.example.com', 'file_name': 'key.pem', 'last_update': '2024/06/14, 01:33:10 PM'}]}, 'update-check': {'plugin_id': 'jobs', 'every': 'day', 'reload': False, 'success': True, 'last_run': '2024/06/14, 01:33:15 PM', 'cache': []}, 'whitelist-download': {'plugin_id': 'whitelist', 'every': 'hour', 'reload': True, 'success': True, 'last_run': '2024/06/14, 01:33:09 PM', 'cache': []}}
jobs = {
"anonymous-report": {
"plugin_id": "misc",
"every": "day",
"reload": False,
"success": True,
"last_run": "2024/06/14, 01:33:11 PM",
"cache": [],
},
"backup-data": {
"plugin_id": "backup",
"every": "day",
"reload": False,
"success": True,
"last_run": "2024/06/14, 01:33:10 PM",
"cache": [],
},
"blacklist-download": {
"plugin_id": "blacklist",
"every": "hour",
"reload": True,
"success": True,
"last_run": "2024/06/14, 01:33:09 PM",
"cache": [],
},
"bunkernet-data": {
"plugin_id": "bunkernet",
"every": "day",
"reload": True,
"success": True,
"last_run": "2024/06/14, 01:33:11 PM",
"cache": [],
},
"bunkernet-register": {
"plugin_id": "bunkernet",
"every": "hour",
"reload": True,
"success": True,
"last_run": "2024/06/14, 01:33:09 PM",
"cache": [],
},
"certbot-new": {
"plugin_id": "letsencrypt",
"every": "once",
"reload": False,
"success": True,
"last_run": "2024/06/14, 01:33:08 PM",
"cache": [],
},
"certbot-renew": {
"plugin_id": "letsencrypt",
"every": "day",
"reload": True,
"success": True,
"last_run": "2024/06/14, 01:33:09 PM",
"cache": [],
},
"coreruleset-nightly": {
"plugin_id": "modsecurity",
"every": "day",
"reload": True,
"success": True,
"last_run": "2024/06/14, 01:33:09 PM",
"cache": [],
},
"custom-cert": {
"plugin_id": "customcert",
"every": "day",
"reload": True,
"success": True,
"last_run": "2024/06/14, 01:33:10 PM",
"cache": [],
},
"default-server-cert": {
"plugin_id": "misc",
"every": "once",
"reload": False,
"success": True,
"last_run": "2024/06/14, 01:33:10 PM",
"cache": [
{
"service_id": None,
"file_name": "default-server-cert.pem",
"last_update": "2024/06/14, 01:33:10 PM",
},
{
"service_id": None,
"file_name": "default-server-cert.key",
"last_update": "2024/06/14, 01:33:10 PM",
},
],
},
"download-plugins": {
"plugin_id": "misc",
"every": "once",
"reload": False,
"success": True,
"last_run": "2024/06/14, 01:33:13 PM",
"cache": [],
},
"download-pro-plugins": {
"plugin_id": "pro",
"every": "day",
"reload": True,
"success": True,
"last_run": "2024/06/14, 01:33:10 PM",
"cache": [],
},
"failover-backup": {
"plugin_id": "jobs",
"every": "once",
"reload": False,
"success": True,
"last_run": "2024/06/14, 01:33:16 PM",
"cache": [
{
"service_id": None,
"file_name": "folder:/var/tmp/bunkerweb/failover.tgz",
"last_update": "2024/06/14, 01:33:27 PM",
}
],
},
"greylist-download": {
"plugin_id": "greylist",
"every": "hour",
"reload": True,
"success": True,
"last_run": "2024/06/14, 01:33:09 PM",
"cache": [],
},
"mmdb-asn": {
"plugin_id": "jobs",
"every": "day",
"reload": True,
"success": True,
"last_run": "2024/06/14, 01:33:14 PM",
"cache": [
{
"service_id": None,
"file_name": "asn.mmdb",
"last_update": "2024/06/14, 01:33:13 PM",
}
],
},
"mmdb-country": {
"plugin_id": "jobs",
"every": "day",
"reload": True,
"success": True,
"last_run": "2024/06/14, 01:33:12 PM",
"cache": [
{
"service_id": None,
"file_name": "country.mmdb",
"last_update": "2024/06/14, 01:33:11 PM",
}
],
},
"realip-download": {
"plugin_id": "realip",
"every": "hour",
"reload": True,
"success": True,
"last_run": "2024/06/14, 01:33:09 PM",
"cache": [],
},
"self-signed": {
"plugin_id": "selfsigned",
"every": "day",
"reload": True,
"success": True,
"last_run": "2024/06/14, 01:33:10 PM",
"cache": [
{
"service_id": "www.example.com",
"file_name": "cert.pem",
"last_update": "2024/06/14, 01:33:10 PM",
},
{
"service_id": "www.example.com",
"file_name": "key.pem",
"last_update": "2024/06/14, 01:33:10 PM",
},
],
},
"update-check": {
"plugin_id": "jobs",
"every": "day",
"reload": False,
"success": True,
"last_run": "2024/06/14, 01:33:15 PM",
"cache": [],
},
"whitelist-download": {
"plugin_id": "whitelist",
"every": "hour",
"reload": True,
"success": True,
"last_run": "2024/06/14, 01:33:09 PM",
"cache": [],
},
}
def jobs_to_list(jobs):
data = []
# loop on each dict
for key, value in jobs.items():
item = []
item.append({ 'type': 'Text', 'data': {'text' : key } })
item.append({"name": key, "type": "Text", "data": {"text": key}})
# loop on each value
for k, v in value.items():
# override widget type for some keys
if k in ('reload', 'success'):
item.append({ 'type': 'Icons', 'data': {"iconColor": "success" if v else "error", "iconName": "check" if v else "cross" } })
continue
if k in ("plugin_id", "every", "last_run"):
item.append({ 'type': 'Text', 'data': {'text' : v } })
if k in ("reload", "success"):
item.append(
{
k: "success" if v else "failed",
"type": "Icons",
"data": {
"iconColor": "success" if v else "error",
"iconName": "check" if v else "cross",
},
}
)
continue
if k in ("plugin_id", "every", "last_run"):
item.append({k: v, "type": "Text", "data": {"text": v}})
continue
if k in ("cache") and len(v) <= 0:
item.append({ 'type': 'Text', 'data': {'text' : "No cache" } })
item.append({k: v, "type": "Text", "data": {"text": ""}})
continue
if k in ("cache") and len(v) > 0:
files = ["none"]
# loop on each cache item
for cache in v:
file_name = f"{cache['service_id']}/{cache['file_name']}" if cache['service_id'] else cache['file_name']
file_name = (
f"{cache['service_id']}/{cache['file_name']}"
if cache["service_id"]
else cache["file_name"]
)
files.append(file_name)
item.append({ 'type': 'Fields', 'data': {
'setting' : {
"id": f"{key}_cache",
"label": f"{key}_cache",
"hideLabel": True,
"inpType": "select",
"name": f"{key}_cache",
"value": "none",
"values": files,
"columns": {
"pc": 12,
"tablet": 12,
"mobile": 12,
},
"overflowAttrEl" : "data-table-body",
"containerClass" : "table",
"maxBtnChars" : 12,
"popovers": [
{
"iconColor": "info",
"iconName": "info",
"text": "jobs_download_cache_file",
},
],
}
},
})
continue
item.append(
{
k: " ".join(files),
"type": "Fields",
"data": {
"setting": {
"id": f"{key}_cache",
"label": f"{key}_cache",
"hideLabel": True,
"inpType": "select",
"name": f"{key}_cache",
"value": "none",
"values": files,
"columns": {
"pc": 12,
"tablet": 12,
"mobile": 12,
},
"overflowAttrEl": "data-table-body",
"containerClass": "table",
"maxBtnChars": 12,
"popovers": [
{
"iconColor": "info",
"iconName": "info",
"text": "jobs_download_cache_file",
},
],
}
},
}
)
continue
data.append(item)
# store on a file
with open('jobs.json', 'w') as f:
# store on a file
with open("jobs.json", "w") as f:
json.dump(data, f, indent=4)
jobs_to_list(jobs)
jobs_to_list(jobs)

1217
vuejs/test4.js Normal file

File diff suppressed because it is too large Load diff