Skip to content

Commit

Permalink
add new jobs page + better JSdoc
Browse files Browse the repository at this point in the history
* add JSdoc to client components/pages functions
* add jobs to vite build
* created table and title widget to builder.py
* add jobs_builder to builder.py and update route
* Jobs client page now retrieve real data
* update input components to handle props.attrs + use this to create the download cache file url
  • Loading branch information
syrk4web committed Jul 24, 2024
1 parent 809d0d9 commit 7bb2824
Show file tree
Hide file tree
Showing 36 changed files with 990 additions and 1,680 deletions.
232 changes: 232 additions & 0 deletions src/ui/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,27 @@
from typing import Union


def title_widget(title):
return {
"type": "Title",
"data": {"title": title},
}


def table_widget(positions, header, items, filters, minWidth, title):
return {
"type": "Table",
"data": {
"title": title,
"minWidth": minWidth,
"header": header,
"positions": positions,
"items": items,
"filters": filters,
},
}


def stat_widget(
link: str, containerColums: dict, title: Union[str, int], subtitle: Union[str, int], subtitle_color: str, stat: Union[str, int], icon_name: str
) -> dict:
Expand Down Expand Up @@ -604,3 +625,214 @@ def global_config_builder(plugins: list, settings: dict) -> str:
}
]
return base64.b64encode(bytes(json.dumps(builder), "utf-8")).decode("ascii")


def get_jobs_list(jobs):
data = []
# loop on each dict
for key, value in jobs.items():
item = []
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(
{
k: "success" if v else "failed",
"type": "Icons",
"data": {
"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({k: v, "type": "Text", "data": {"text": ""}})
continue

if k in ("cache") and len(v) > 0:
files = []
# loop on each cache item
for cache in v:
file_name = f"{cache['file_name']} [{cache['service_id']}]" if cache["service_id"] else f"{cache['file_name']}"
files.append(file_name)

item.append(
{
k: " ".join(files),
"type": "Fields",
"data": {
"setting": {
"attrs": {
"data-plugin-id": value.get("plugin_id", ""),
"data-job-name": key,
},
"id": f"{key}_cache",
"label": f"{key}_cache",
"hideLabel": True,
"inpType": "select",
"name": f"{key}_cache",
"value": "download file",
"values": files,
"columns": {
"pc": 12,
"tablet": 12,
"mobile": 12,
},
"overflowAttrEl": "data-table-body",
"containerClass": "table download-cache-file",
"maxBtnChars": 12,
"popovers": [
{
"iconName": "info",
"text": "jobs_download_cache_file",
},
],
}
},
}
)
continue

data.append(item)

return data


def jobs_builder(jobs):

jobs_list = get_jobs_list(jobs)

intervals = ["all"]

# loop on each job
for job in jobs_list:
# loop on each item
for item in job:
# get the interval if not already in intervals
if item.get("every") and item.get("every") not in intervals:
intervals.append(item.get("every"))

builder = [
{
"type": "card",
"containerColumns": {"pc": 12, "tablet": 12, "mobile": 12},
"widgets": [
title_widget("jobs_title"),
table_widget(
positions=[2, 2, 1, 1, 1, 2, 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_cache_downloadable",
],
items=jobs_list,
filters=[
{
"filter": "table",
"filterName": "keyword",
"type": "keyword",
"value": "",
"keys": ["name", "plugin_id", "last_run"],
"field": {
"id": "jobs-keyword",
"value": "",
"type": "text",
"name": "jobs-keyword",
"label": "jobs_search",
"placeholder": "inp_keyword",
"isClipboard": False,
"popovers": [
{
"text": "jobs_search_desc",
"iconName": "info",
},
],
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
},
},
{
"filter": "table",
"filterName": "every",
"type": "select",
"value": "all",
"keys": ["every"],
"field": {
"id": "jobs-every",
"value": "all",
"values": intervals,
"name": "jobs-every",
"onlyDown": True,
"label": "jobs_interval",
"popovers": [
{
"text": "jobs_interval_desc",
"iconName": "info",
},
],
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
},
},
{
"filter": "table",
"filterName": "reload",
"type": "select",
"value": "all",
"keys": ["reload"],
"field": {
"id": "jobs-last-run",
"value": "all",
"values": ["all", "success", "failed"],
"name": "jobs-last-run",
"onlyDown": True,
"label": "jobs_reload",
"popovers": [
{
"text": "jobs_reload_desc",
"iconName": "info",
},
],
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
},
},
{
"filter": "table",
"filterName": "success",
"type": "select",
"value": "all",
"keys": ["success"],
"field": {
"id": "jobs-success",
"value": "all",
"values": ["all", "success", "failed"],
"name": "jobs-success",
"onlyDown": True,
"label": "jobs_success",
"popovers": [
{
"text": "jobs_success_desc",
"iconName": "info",
},
],
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
},
},
],
minWidth="lg",
title="jobs_table_title",
),
],
}
]

return base64.b64encode(bytes(json.dumps(builder), "utf-8")).decode("ascii")
2 changes: 1 addition & 1 deletion src/ui/client/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ async def move_template_file(root, file, target_folder):
</body>
</html>"""

if "global-config" in root:
if "global-config" in root or "jobs" in root:
base_html = base_html.replace("data_server_builder[1:-1]", "data_server_builder")

file_path = os.path.join(root, file)
Expand Down
41 changes: 33 additions & 8 deletions src/ui/client/dashboard/components/Dashboard/Banner.vue
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,11 @@ const banner = reactive({
}),
});
// I want to replace the content class content by banner-item-text
/**
@name setupBanner
@description This function will try to retrieve banner news from the local storage, and in case it is not available or older than one hour, it will fetch the news from the api.
@returns {void}
*/
function setupBanner() {
// Check if data, and if case, that data is not older than one hour
// Case it is, refetch
Expand Down Expand Up @@ -94,7 +97,11 @@ function setupBanner() {
});
}
// Banner animation effect
/**
@name runBanner
@description Run the banner animation to display all news at a regular interval.
@returns {void}
*/
function runBanner() {
const nextDelay = 8000;
const transDuration = 1000;
Expand Down Expand Up @@ -129,8 +136,12 @@ function runBanner() {
runBanner();
}, nextDelay);
}
// Observe banner and set is visible or not to
// Update float button and menu position
/**
@name observeBanner
@description Check if the banner is visible in the viewport and set the state in the global bannerStore to update related components.
@returns {void}
*/
function observeBanner() {
const options = {
root: null,
Expand All @@ -148,13 +159,23 @@ function observeBanner() {
observer.observe(document.getElementById("banner"));
}
/**
@name noTabindex
@description Stop highlighting a banner item that was focused with tabindex.
@returns {void}
*/
function noTabindex() {
const bannerItems = document.querySelectorAll(".banner-item");
bannerItems.forEach((item) => {
item.classList.remove("banner-tabindex-highlight", "banner-tabindex-hide");
});
}
/**
@name isTabindex
@description Highlighting a banner item that is focused with tabindex.
@returns {void}
*/
function isTabindex() {
const activeElement = document.activeElement;
const bannerItems = document.querySelectorAll(".banner-item");
Expand All @@ -171,9 +192,13 @@ function isTabindex() {
.classList.remove("banner-tabindex-hide");
}
// Focus with tabindex break banner animation
// When a banner is focused, we need to add in front of the current banner the focus element
// And remove it when the focus is lost
/**
@name isTabindex
@description Focus with tabindex break banner animation.
When a banner is focused, we need to add in front of the current banner the focus element.
And remove it when the focus is lost.
@returns {void}
*/
function handleTabIndex() {
// Get the active element after tabindex click
document.addEventListener("keyup", (e) => {
Expand Down
7 changes: 7 additions & 0 deletions src/ui/client/dashboard/components/Dashboard/LangSwitch.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ const lang = reactive({
curr: "",
});
/**
@name updateLangStorage
@description This function will update the language in the session storage and reload the page.
On reload, we will retrieve the language from the session storage and set it.
@param {string} lang - The language to set.
@returns {void}
*/
function updateLangStorage(lang) {
sessionStorage.setItem("lang", lang);
document.location.reload();
Expand Down
5 changes: 5 additions & 0 deletions src/ui/client/dashboard/components/Dashboard/Loader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ const loader = reactive({
const logo = ref();
const logoContainer = ref();
/**
@name loading
@description This function will toggle the loading animation.
@returns {void}
*/
function loading() {
// delay before stopping the loading
setTimeout(() => {
Expand Down
Loading

0 comments on commit 7bb2824

Please sign in to comment.