From d8287c936de252ab27348ad26ffb38ab5d9078bd Mon Sep 17 00:00:00 2001 From: KyMAN <0kyman0@gmail.com> Date: Wed, 22 Jul 2026 07:23:56 +0200 Subject: [PATCH] #wip: Map connection. --- Public/ecma/Application/Attributes.ecma.js | 98 ++++++++++++++++++++ Public/ecma/Application/Components.ecma.js | 49 +++++++++- Python/AnP/Controllers/SessionsController.py | 24 +++-- Python/AnP/Managers/SessionsManager.py | 1 + 4 files changed, 164 insertions(+), 8 deletions(-) create mode 100644 Public/ecma/Application/Attributes.ecma.js diff --git a/Public/ecma/Application/Attributes.ecma.js b/Public/ecma/Application/Attributes.ecma.js new file mode 100644 index 0000000..acef8be --- /dev/null +++ b/Public/ecma/Application/Attributes.ecma.js @@ -0,0 +1,98 @@ +"use strict"; + +/** + * @typedef {import("./AnP.ecma.js").AnP} AnP + */ + +import {Common} from "../Utils/Common.ecma.js"; +import {Check} from "../Utils/Checks.ecma.js"; + +export const Attributes = (function(){ + + /** + * @callback attributes_special_callback + * @param {?any} data + * @returns {[string, string]} + */ + + const Attributes = function(anp){ + + const self = this, + standard = [ + "div", "span", "p", "a", "img", "button", "input", "form", "label", + "ul", "ol", "li", "table", "thead", "tbody", "tr", "th", "td", + "header", "footer", "section", "article", "nav", "main", "i", "del", + "h1", "h2", "h3", "h4", "h5", "h6", "br", "hr", "iframe", "canvas", + "svg", "video", "audio", "source", "data", "details", "summary", + "dialog", "meter", "progress", "time", "abbr", "address", "b", "bdi", + "bdo", "cite", "code", "dfn", "em", "i", "kbd", "mark", "q", "rp", + "rt", "ruby", "s", "samp", "small", "strong", "sub", "sup", "u", + "var", "wbr", "pre", "blockquote", "dl", "dt", "dd", "figure", + "fieldset", "legend", "textarea", "select", "option", "optgroup", + "datalist", "keygen", "output" + ]; + + const constructor = () => {}; + + /** @type {Object.} */ + const special = { + permissions : data => ["data-permissions", Common.data_encode(data)], + toggle : data => ["data-toggle", data ? "true" : "false"] + }; + + this.set_standards = (inputs, callback = null) => { + if(Check.is_array(inputs)){ + if(inputs.every(item => Check.is_string(item) && /^[a-z0-9\-]+$/.test(item))){ + inputs.forEach(item => { + standard.includes(item) || standard.push(item); + }); + Common.execute(callback); + return; + }; + Common.execute_array(inputs, (item, next) => { + anp.files.load_json(item, results => { + self.set_standards(results, next); + }); + }, callback); + }else if(Check.is_string(inputs)) + self.set_standards([inputs], callback); + else + Common.execute_callback(callback); + }; + + this.set = (item, attributes, excluded = [], only = []) => { + Object.entries(attributes).forEach(([key, raw_value]) => { + if(( + (excluded.length && excluded.includes(key)) || + (only.length && !only.includes(key)) + )) + return; + + let name, value; + + if(special[key]) + [name, value] = special[key](raw_value); + else{ + [name, value] = [Common.to_kebab(key).toLowerCase(), raw_value]; + if(name.slice(0, 2) == "on") + name = name.replace(/[^a-z]+/g, ""); + else if(!["data-", "aria-"].includes(name.slice(0, 5)) && !standard.includes(name)) + name = "data-" + name; + }; + + if(name.slice(0, 2) == "on" && Check.is_function(value)) + item.addEventListener(name, event => { + value(item, event); + }); + else if(value !== null) + item.setAttribute(name, value); + + }); + }; + + constructor(); + + }; + + return Attributes; +})(); \ No newline at end of file diff --git a/Public/ecma/Application/Components.ecma.js b/Public/ecma/Application/Components.ecma.js index 6796d16..33bede0 100644 --- a/Public/ecma/Application/Components.ecma.js +++ b/Public/ecma/Application/Components.ecma.js @@ -83,6 +83,53 @@ export const Components = (function(){ }; + /** + * @param {...(HTMLElement|string|Array.)} inputs + * @returns {Array.} + * @access public + * @static + */ + this.set = (...inputs) => { + + /** @type {DocumentFragment} */ + const fragment = new DocumentFragment(), + /** @type {HTMLElement|null} */ + master = ( + Check.is_html_item(inputs[0]) ? inputs[0] : + Check.is_string(inputs[0]) ? document.querySelector(inputs[0]) : + null), + items = []; + + (master ? inputs.slice(1) : inputs).forEach(subinputs => { + if(Check.is_html_item(subinputs)) + fragment.appendChild(subinputs); + else if(Check.is_string(subinputs)) + fragment.appendChild(document.createTextNode(subinputs)); + else if(Check.is_array(subinputs)){ + + /** @type {[string, Object.|null, any|null]} */ + const [tag, attributes, children] = subinputs.concat([null, null]).slice(0, 3), + /** @type {HTMLElement} */ + item = document.createElement(tag); + + Check.is_dictionary(attributes) && anp.attributes.set(item, attributes); + + if(Check.is_array(children)) + self.set(...children).forEach(child => item.appendChild(child)); + else if(Check.is_string(children)) + item.innerHTML += children; + + fragment.appendChild(item); + + }; + }); + + items.push(...fragment.childNodes); + master && master.appendChild(fragment); + + return items; + } + /** * @returns {void} * @access private @@ -214,7 +261,7 @@ export const Components = (function(){ } } : has_action ? {on_click : action} : - {}), + {}), }, [ self.icon(name), self.i18n(name) diff --git a/Python/AnP/Controllers/SessionsController.py b/Python/AnP/Controllers/SessionsController.py index 91ca5f5..9ff0f90 100644 --- a/Python/AnP/Controllers/SessionsController.py +++ b/Python/AnP/Controllers/SessionsController.py @@ -1,26 +1,36 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -from typing import Self +from typing import Self, Any, Optional, Sequence +from AnP.Interfaces.Application.AnPInterface import AnPInterface from AnP.Abstracts.ControllerAbstract import ControllerAbstract from AnP.Models.RequestModel import RequestModel +from AnP.Utils.Common import Common class SessionsController(ControllerAbstract): + def __init__(self:Self, anp:AnPInterface, inputs:Optional[dict[str, Any|None]|Sequence[Any|None]] = None) -> None: + super().__init__(anp, inputs) + + self.__via:str = Common.get_value("via", inputs, "sqlserver") + + def __query(self:Self, query:str, request:RequestModel) -> None: + self.anp.dispatches.execute(self.__via, "session", query, request) + def get_guest(self:Self, request:RequestModel) -> None: - pass + self.__query("get_guest", request) def login(self:Self, request:RequestModel) -> None: - pass + self.__query("login", request) def logout(self:Self, request:RequestModel) -> None: - pass + self.__query("logout", request) def update(self:Self, request:RequestModel) -> None: - pass + self.__query("update", request) def register(self:Self, request:RequestModel) -> None: - pass + self.__query("register", request) def change_password(self:Self, request:RequestModel) -> None: - pass \ No newline at end of file + self.__query("change_password", request) \ No newline at end of file diff --git a/Python/AnP/Managers/SessionsManager.py b/Python/AnP/Managers/SessionsManager.py index 6fce40d..fa71f70 100644 --- a/Python/AnP/Managers/SessionsManager.py +++ b/Python/AnP/Managers/SessionsManager.py @@ -69,6 +69,7 @@ class SessionsManager: def remove(self:Self, id:str) -> bool: if id in self.__sessions: self.__sessions[id].remove() + self.anp.unique_keys.remove(id) del self.__sessions[id] return True return False \ No newline at end of file