update ui-components doc

This commit is contained in:
Jordan Blasenhauer 2024-08-19 21:24:03 +02:00
parent 4886ed8e11
commit e0574b8ded
21 changed files with 571 additions and 2906 deletions

File diff suppressed because it is too large Load diff

View file

@ -3,9 +3,7 @@ const path = require("path");
// Merge all components md on this file name
const finalFile = "ui-components.md";
// Where we have all SFC components
// Where we want to output md components file
const ouputFolder = path.join(__dirname, "components");
// Format merge file
function formatMd() {

View file

@ -4,6 +4,7 @@ from subprocess import Popen, PIPE
from typing import List
from shutil import rmtree
from re import search
from traceback import format_exc
outputFilename = "ui-components.md"
# We want to get path of the folder where our components are
@ -12,6 +13,7 @@ outputFilename = "ui-components.md"
inputFolder = abspath("../src/ui/client/dashboard/components")
outputFolder = abspath("../docs/components")
outputFile = abspath("../docs")
components_path_to_exclude = ("components/Icons", "components/Forms/Error", "components/Dashboard", "components/Builder")
def run_command(command: List[str]) -> int:
@ -57,18 +59,30 @@ def vue2js():
# Create outputFolder if not exists
Path(outputFolder).mkdir(parents=True, exist_ok=True)
# Get every subfolders from the input folder
print(Path(inputFolder).rglob("*"))
for folder in Path(inputFolder).rglob("*"):
# Get only files
if folder.is_file() and folder.suffix == ".vue":
# Read the file content
data = folder.read_text()
# Get only the content between <script setup> and </script> tag
script = data.split("<script setup>")[1].split("</script>")[0]
# Create a file on the output folder with the same name but with .js extension
fileName = folder.name.replace(".vue", ".js")
dest = Path(outputFolder) / fileName
dest.write_text(script)
# Get only vue file
if not folder.is_file() or folder.suffix != ".vue":
continue
# Exclude some files
if any(folder_path in folder.as_posix() for folder_path in components_path_to_exclude):
continue
# Read the file content
data = folder.read_text()
# Get only the content between <script setup> and </script> tag
script = data.split("<script setup>")[1].split("</script>")[0]
# Get index of jsdoc comments
first_doc_index_start = script.find("/**")
first_doc_index_end = script.find("*/")
if first_doc_index_start != -1 and first_doc_index_end != -1:
# get content before first_doc_index_end
script = script[first_doc_index_start : first_doc_index_end + 2]
# Create a file on the output folder with the same name but with .js extension
fileName = folder.name.replace(".vue", ".js")
dest = Path(outputFolder) / fileName
dest.write_text(script)
def js2md():
@ -99,49 +113,55 @@ def formatMd():
files = list(Path(outputFolder).rglob("*"))
for file in files:
# Get the title from first line
data = file.read_text()
# Remove everything after a [1]: tag
data = data.split("[1]:")[0]
# Remove ### Table of contents
data = data.replace("### Table of Contents", "")
# Remove everything before the first ## tag
index = data.index("## ")
data = data[index:]
try:
# Get the title from first line
data = file.read_text()
# Remove everything after a [1]: tag
data = data.split("[1]:")[0]
# Remove ### Table of contents
data = data.replace("### Table of Contents", "")
# Remove everything before the first ## tag
if "## " in data:
index = data.index("## ")
data = data[index:]
# I want to loop on each line
lines = data.split("\n")
line_result = []
for line in lines:
# remove space (so &#x20 or &#32)
line = line.replace("&#x20", "").replace("&#32", "")
# I want to loop on each line
lines = data.split("\n")
line_result = []
for line in lines:
# remove space (so &#x20 or &#32)
line = line.replace("&#x20", "").replace("&#32", "")
if line.startswith("#") and ".vue" in line and "\.vue" in line:
line = line.replace("\.vue", ".vue")
if line.startswith("#") and ".vue" in line and "\\.vue" in line:
line = line.replace("\\.vue", ".vue")
# Case not a param, keep the line as is
if not line.startswith("*"):
line_result.append(line)
continue
# get line without first char
line = "-" + line[1:]
# remove each **[string][num]** pattern in a param by **string**
reg = r"\[\w+\]\[\d+\]"
while search(reg, line):
# get data of the pattern
pattern = search(reg, line).group()
# get content of first bracket
content = pattern.split("][")[0].replace("[", "")
line = line.replace(pattern, f"{content}")
# Case not a param, keep the line as is
if not line.startswith("*"):
line_result.append(line)
continue
# get line without first char
line = "-" + line[1:]
# remove each **[string][num]** pattern in a param by **string**
reg = r"\[\w+\]\[\d+\]"
while search(reg, line):
# get data of the pattern
pattern = search(reg, line).group()
# get content of first bracket
content = pattern.split("][")[0].replace("[", "")
line = line.replace(pattern, f"{content}")
line_result.append(line)
# I can merge the lines
data = "\n".join(line_result)
# update the file with the new content
file.write_text(data)
# I can merge the lines
data = "\n".join(line_result)
# update the file with the new content
file.write_text(data)
except BaseException:
print(format_exc(), flush=True)
print("Error while parsing file", str(file.name), flush=True)
exit(1)
def mergeMd():

View file

@ -14,18 +14,6 @@ import { useEqualStr } from "@utils/global.js";
/**
* @name Builder/Bans.vue
* @description This component is lightweight builder containing only the necessary components to create the bans page.
* @example
* [
* {
* type: "card",
* gridLayoutClass: "transparent",
* widgets: [
* { type: "Unmatch",
* data: { text: "bans_not_found" }
* },
* ],
* },
* ];
* @param {array} builder - Array of containers and widgets
*/

View file

@ -33,18 +33,6 @@ import { useEqualStr } from "@utils/global.js";
/**
* @name Builder/Bans.vue
* @description This component is lightweight builder containing only the necessary components to create the bans page.
* @example
* [
* {
* type: "card",
* gridLayoutClass: "transparent",
* widgets: [
* { type: "Unmatch",
* data: { text: "bans_not_found" }
* },
* ],
* },
* ];
* @param {array} builder - Array of containers and widgets
*/

View file

@ -14,18 +14,6 @@ import { useEqualStr } from "@utils/global.js";
/**
* @name Builder/Configs.vue
* @description This component is lightweight builder containing only the necessary components to create the configs page.
* @example
* [
* {
* type: "card",
* gridLayoutClass: "transparent",
* widgets: [
* { type: "Unmatch",
* data: { text: "bans_not_found" }
* },
* ],
* },
* ];
* @param {array} builder - Array of containers and widgets
*/

View file

@ -10,32 +10,6 @@ import { useEqualStr } from "@utils/global.js";
/**
* @name Builder/GlobalConfig.vue
* @description This component is lightweight builder containing only the necessary components to create the instances page.
* @example
* [
* {
* type: "card",
* containerColumns: { pc: 12, tablet: 12, mobile: 12 },
* widgets: [
* {
* type: "Title",
* data : {
* title: "dashboard_global_config",
* type: "card"
* },
* },
* {
* type: "Templates",
* data: {
* title: "home_version",
* subtitle: "home_all_features_available" if is_pro_version else "home_upgrade_pro",
* subtitleColor: "success" is is_pro_version else "warning",
* stat: "home_pro" if is_pro_version else "home_free",
* iconName: "crown" if is_pro_version else "core",
* },
* },
* ],
* },
* ];
* @param {array} builder - Array of containers and widgets
*/

View file

@ -8,26 +8,6 @@ import { useEqualStr } from "@utils/global.js";
/**
* @name Builder/Home.vue
* @description This component is lightweight builder containing only the necessary components to create the home page.
*@example
* [
* {
* type: "card",
* link : "https://panel.bunkerweb.io/?utm_campaign=self&utm_source=ui"
* containerColumns: { pc: 4, tablet: 6, mobile: 12 },
* widgets: [
* {
* type: "Stat",
* data: {
* title: "home_version",
* subtitle: "home_all_features_available" if is_pro_version else "home_upgrade_pro",
* subtitleColor: "success" is is_pro_version else "warning",
* stat: "home_pro" if is_pro_version else "home_free",
* iconName: "crown" if is_pro_version else "core",
* },
* },
* ],
* },
* ]
* @param {array} builder - Array of containers and widgets
*/

View file

@ -14,30 +14,7 @@ import { useEqualStr } from "@utils/global.js";
/**
* @name Builder/Instances.vue
* @description This component is lightweight builder containing only the necessary components to create the instances page.
** @example
* [
* {
* type: "Instance",
* data: {
* details: [
* { key: <instances_hostname="hostname">, value: "www.example.com" },
* { key: <instances_method="method">, value: <dashboard_ui> or <dashboard_scheduler>...},
* { key: <instances_port="port">, value: "1084" },
* { key: <instances_status="status">, value: <instances_active="active"> or <instances_inactive="inactive"> },
* ],
* status: "success",
* title: "www.example.com",
* buttons: [
* {
* text: <action_*>,
* color: "edit",
* size: "normal",
* },
* ],
* },
* },
*];
** @param {array} builder - Array of containers and widgets
* @param {array} builder - Array of containers and widgets
*/
const props = defineProps({

View file

@ -8,57 +8,8 @@ import Title from "@components/Widget/Title.vue";
import { useEqualStr } from "@utils/global.js";
/**
** @name Builder/Jobs.vue
* @name Builder/Jobs.vue
* @description This component is lightweight builder containing only the necessary components to create the jobs page.
* @example
* [
* {
* "type": "card",
* "containerColumns": {
* "pc": 4,
* "tablet": 6,
* "mobile": 12
* },
* "widgets": [
* {
* "type": "table",
* "data": {
* "title": "jobs_table_title",
* "minWidth": "lg",
* "header": [
* "jobs_table_name",
* "jobs_table_plugin_id",
* "jobs_table_interval",
* "jobs_table_last_run",
* "jobs_table_success",
* "jobs_table_last_run_date",
* "jobs_table_cache"
* ],
* "positions": [
* 2,
* 2,
* 1,
* 1,
* 1,
* 3,
* 2
* ],
* "items": [
* [
* {
* "name": "anonymous-report",
* "type": "Text",
* "data": {
* "text": "anonymous-report"
* }
* },
* ],
* ]
* }
* }
* ]
* }
* ]
* @param {array} builder - Array of containers and widgets
*/

View file

@ -8,7 +8,7 @@ import Unmatch from "@components/Message/Unmatch.vue";
import { useEqualStr } from "@utils/global.js";
/**
** @name Builder/Logs.vue
* @name Builder/Logs.vue
* @description This component is lightweight builder containing only the necessary components to create the logs page.
* @param {array} builder - Array of containers and widgets
*/

View file

@ -11,28 +11,6 @@ import { useEqualStr } from "@utils/global.js";
/**
* @name Builder/Modes.vue
* @description This component is lightweight builder containing only the necessary components to create a service mode page.
* @example
* [
* {
* type: "card",
* containerColumns: { pc: 12, tablet: 12, mobile: 12 },
* widgets: [
* {
* type: "Title",
* data : {
* title: "dashboard_global_config",
* type: "card"
* },
* },
* {
* type: "Raw",
* data: {
* template: {},
* },
* },
* ],
* },
* ];
* @param {array} builder - Array of containers and widgets
*/

View file

@ -14,38 +14,6 @@ import { useEqualStr } from "@utils/global.js";
/**
* @name Builder/PLugins.vue
* @description This component is lightweight builder containing only the necessary components to create the plugins page.
* @example
* [
* {
* type: "card",
* containerColumns: { pc: 12, tablet: 12, mobile: 12 },
* widgets: [
* {
* type: "Title",
* data : {
* title: "dashboard_plugins",
* type: "card"
* },
* },
* {
* type: "ListDetails",
* data: {
* text: "Plugin name",
* popovers: [
* {
* text: "This is a popover text",
* iconName: "info",
* },
* {
* text: "This is a popover text",
* iconName: "info",
* },
* ],
* },
* },
* ],
* },
* ];
* @param {array} builder - Array of containers and widgets
*/

View file

@ -17,8 +17,7 @@ import { useEqualStr } from "@utils/global.js";
/**
* @name Builder/Profile.vue
* @description This component is lightweight builder containing only the necessary components to create the profile page.
** @example
** @param {array} builder - Array of containers and widgets
* @param {array} builder - Array of containers and widgets
*/
const props = defineProps({

View file

@ -11,19 +11,6 @@ import { useEqualStr } from "@utils/global.js";
/**
* @name Builder/Reports.vue
* @description This component is lightweight builder containing only the necessary components to create the reports page.
* @example
* [
* {
* type: "card",
* gridLayoutClass: "transparent",
* widgets: [
* {
* type: "Unmatch",
* data: { text: "reports_not_found" }
* }
* ],
* },
* ];
* @param {array} builder - Array of containers and widgets
*/

View file

@ -10,287 +10,8 @@ import Button from "@components/Widget/Button.vue";
import { useEqualStr } from "@utils/global.js";
/**
*@name Builder/Services.vue
* @name Builder/Services.vue
* @description This component is lightweight builder containing only the necessary components to create the services page.
*@example
* [
* {
* "type": "card",
* "containerColumns": {
* "pc": 12,
* "tablet": 12,
* "mobile": 12
* },
* "widgets": [
* {
* "type": "Title",
* "data": {
* "title": "services_title"
* }
* },
* {
* "type": "Table",
* "data": {
* "title": "services_table_title",
* "minWidth": "lg",
* "header": [
* "services_table_name",
* "services_table_method",
* "services_table_settings",
* "services_table_manage",
* "services_table_is_draft",
* "services_table_delete"
* ],
* "positions": [
* 2,
* 2,
* 2,
* 2,
* 2,
* 2
* ],
* "items": [
* [
* {
* "name": "app1.example.com",
* "type": "Text",
* "data": {
* "text": "app1.example.com"
* }
* },
* {
* "method": "scheduler",
* "type": "Text",
* "data": {
* "text": "scheduler"
* }
* },
* {
* "type": "Button",
* "data": {
* "id": "open-modal-settings-0",
* "text": "settings",
* "hideText": false,
* " color": "info",
* "size": "normal",
* "iconName": "settings"
* }
* },
* {
* "type": "Button",
* "data": {
* "attrs": {
* "data-server-name": "app1.example.com"
* },
* "id": "open-modal-manage-0",
* "text": "manage",
* "hideText": false,
* " color": "green",
* "size": "normal",
* "iconName": "manage"
* }
* },
* {
* "type": "Button",
* "data": {
* "attrs": {
* "data-server-name": "app1.example.com",
* "data-is-draft": "no"
* },
* "id": "open-modal-draft-0",
* "text": "online",
* "hideText": false,
* " color": "cyan",
* "size": "normal",
* "iconName": "online"
* }
* },
* {
* "type": "Button",
* "data": {
* "attrs": {
* "data-server-name": "app1.example.com"
* },
* "id": "open-modal-delete-0",
* "text": "delete",
* "disabled": true,
* "hideText": false,
* " color": "red",
* "size": "normal",
* "iconName": "trash"
* }
* }
* ],
* [
* {
* "name": "www.example.com",
* "type": "Text",
* "data": {
* "text": "www.example.com"
* }
* },
* {
* "method": "scheduler",
* "type": "Text",
* "data": {
* "text": "scheduler"
* }
* },
* {
* "type": "Button",
* "data": {
* "id": "open-modal-settings-1",
* "text": "settings",
* "hideText": false,
* " color": "info",
* "size": "normal",
* "iconName": "settings"
* }
* },
* {
* "type": "Button",
* "data": {
* "attrs": {
* "data-server-name": "www.example.com"
* },
* "id": "open-modal-manage-1",
* "text": "manage",
* "hideText": false,
* " color": "green",
* "size": "normal",
* "iconName": "manage"
* }
* },
* {
* "type": "Button",
* "data": {
* "attrs": {
* "data-server-name": "www.example.com",
* "data-is-draft": "no"
* },
* "id": "open-modal-draft-1",
* "text": "online",
* "hideText": false,
* " color": "cyan",
* "size": "normal",
* "iconName": "online"
* }
* },
* {
* "type": "Button",
* "data": {
* "attrs": {
* "data-server-name": "www.example.com"
* },
* "id": "open-modal-delete-1",
* "text": "delete",
* "disabled": true,
* "hideText": false,
* " color": "red",
* "size": "normal",
* "iconName": "trash"
* }
* }
* ]
* ],
* "filters": [
* {
* "filter": "table",
* "filterName": "keyword",
* "type": "keyword",
* "value": "",
* "keys": [
* "name"
* ],
* "field": {
* "id": "services-keyword",
* "value": "",
* "type": "text",
* "name": "services-keyword",
* "label": "services_search",
* "placeholder": "inp_keyword",
* "isClipboard": false,
* "popovers": [
* {
* "text": "services_search_desc",
* "iconName": "info"
* }
* ],
* "columns": {
* "pc": 3,
* "tablet": 4,
* "mobile": 12
* }
* }
* },
* {
* "filter": "table",
* "filterName": "method",
* "type": "select",
* "value": "all",
* "keys": [
* "method"
* ],
* "field": {
* "id": "services-methods",
* "value": "all",
* "values": [
* "scheduler"
* ],
* "name": "services-methods",
* "onlyDown": true,
* "label": "services_methods",
* "popovers": [
* {
* "text": "services_methods_desc",
* "iconName": "info"
* }
* ],
* "columns": {
* "pc": 3,
* "tablet": 4,
* "mobile": 12
* }
* }
* },
* {
* "filter": "table",
* "filterName": "draft",
* "type": "select",
* "value": "all",
* "keys": [
* "draft"
* ],
* "field": {
* "id": "services-draft",
* "value": "all",
* "values": [
* "all",
* "online",
* "draft"
* ],
* "name": "services-draft",
* "onlyDown": true,
* "label": "services_draft",
* "popovers": [
* {
* "text": "services_draft_desc",
* "iconName": "info"
* }
* ],
* "columns": {
* "pc": 3,
* "tablet": 4,
* "mobile": 12
* }
* }
* }
* ]
* }
* }
* ]
* }
* ]
* @param {array} builder - Array of containers and widgets
*/

View file

@ -7,11 +7,7 @@ import { useEqualStr } from "@utils/global.js";
/**
* @name Builder/Setup.vue
* @description This component is lightweight builder containing only the necessary components to create the setup page.
* @example
*
*
*
*@param {array} builder - Array of containers and widgets
* @param {array} builder - Array of containers and widgets
*/
const props = defineProps({

View file

@ -14,18 +14,6 @@ import { useEqualStr } from "@utils/global.js";
/**
* @name Builder/UserManagement.vue
* @description This component is lightweight builder containing only the necessary components to create the user management page.
* @example
* [
* {
* type: "card",
* gridLayoutClass: "transparent",
* widgets: [
* { type: "Unmatch",
* data: { text: "bans_not_found" }
* },
* ],
* },
* ];
* @param {array} builder - Array of containers and widgets
*/

View file

@ -253,7 +253,7 @@ const filters = [
** @name filter
** @description Get the filter data from the <Filter /> component and store the result in the advanced store.
* After that, update some UI states like disabled state.
** @param {Object} filterData - The filter data from the <Filter /> component.
* @param {Object} filterData - The filter data from the <Filter /> component.
** @returns {void}
*/
function filter(filterData) {
@ -295,7 +295,7 @@ function setValidity() {
/**
** @name getFirstPlugin
** @description Get the first available plugin in the template.
** @param {Object} template - The template object.
* @param {Object} template - The template object.
** @returns {string} - The first plugin name.
*/
function getFirstPlugin(template) {
@ -309,7 +309,7 @@ function getFirstPlugin(template) {
/**
** @name getPluginNames
** @description Get the first available plugin in the template.
** @param {Object} template - The template object.
* @param {Object} template - The template object.
** @returns {array} - The list of plugin names.
*/
function getPluginNames(template) {

View file

@ -6,32 +6,32 @@ import Filter from "@components/Widget/Filter.vue";
import Grid from "@components/Widget/Grid.vue";
import Unmatch from "@components/Message/Unmatch.vue";
/**
* @name List/Details.vue
* @description This component is a list of items separate on two columns : one for the title, and other for a list of popovers related to the plugin (type, link...)
* @example
{
details : [{
text: "name",
disabled : false,
attrs: {
id: "id",
value: "value",
},
popovers: [
{
text: "This is a popover text",
iconName: "info",
},
{
text: "This is a popover text",
iconName: "info",
},
],
}]
* @param {string} details - List of details item that contains a text, disabled state, attrs and list of popovers. We can also add a disabled key to disable the item.
* @param {array} [filters=[]] - List of filters to apply on the list of items.
* @param {columns} [columns={"pc": "4", "tablet": "6", "mobile": "12"}] - Determine the position of the items in the grid system.
*/
* @name List/Details.vue
* @description This component is a list of items separate on two columns : one for the title, and other for a list of popovers related to the plugin (type, link...)
* @example
* {
* details : [{
* text: "name",
* disabled : false,
* attrs: {
* id: "id",
* value: "value",
* },
* popovers: [
* {
* text: "This is a popover text",
* iconName: "info",
* },
* {
* text: "This is a popover text",
* iconName: "info",
* },
* ],
* }
* @param {string} details - List of details item that contains a text, disabled state, attrs and list of popovers. We can also add a disabled key to disable the item.
* @param {array} [filters=[]] - List of filters to apply on the list of items.
* @param {columns} [columns={"pc": "4", "tablet": "6", "mobile": "12"}] - Determine the position of the items in the grid system.
*/
const props = defineProps({
details: {

View file

@ -1,52 +0,0 @@
<script setup>
import { reactive, computed, ref, onMounted, watch } from "vue";
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 ButtonGroup from "@components/Widget/ButtonGroup.vue";
import { useEqualStr } from "@utils/global.js";
/**
* @name Builder/Cell.vue
* @description This component includes all elements that can be shown in a table cell.
* @example
* {
* type : "button",
* data : {
* id: "open-modal-btn",
* text: "Open modal",
* disabled: false,
* hideText: true,
* color: "green",
* size: "normal",
* iconName: "modal",
* attrs: { data-toggle: "modal", "data-target": "#modal"},
* }
* }
* @param {String} type - The type of the cell. This needs to be a Vue component.
* @param {Object} data - The data to display in the cell. This needs to be the props of the Vue component.
*/
const props = defineProps({
type: {
type: String,
required: true,
},
data: {
type: Object,
required: true,
},
});
</script>
<template>
<Text v-if="useEqualStr(props.type, 'Text')" v-bind="props.data" />
<Icons v-if="useEqualStr(props.type, 'Icons')" v-bind="props.data" />
<Fields v-if="useEqualStr(props.type, 'Fields')" v-bind="props.data" />
<Button v-if="useEqualStr(props.type, 'Button')" v-bind="props.data" />
<ButtonGroup
v-if="useEqualStr(props.type, 'ButtonGroup')"
v-bind="props.data"
/>
</template>