From abc332923d7edcd49a79b0483e47adc2ad57a67e Mon Sep 17 00:00:00 2001 From: Volker Schukai <volker.schukai@schukai.com> Date: Wed, 31 Jul 2024 11:35:06 +0200 Subject: [PATCH] fix: improvement of the tree menu to avoid recursion. #230 --- .idea/misc.xml | 2 +- CHANGELOG.md | 3 +- development/config/import.mjs | 4 +- development/issues/closed/230.html | 52 + development/issues/closed/230.mjs | 19 + development/issues/open/229.html | 24 + development/issues/open/229.mjs | 15 + development/mock/issue-230.js | 1285 +++++++++++++++++++ development/mockoon/issues.json | 85 ++ flake.lock | 6 +- nix/config/release.nix | 2 +- nix/scripts/go-task.nix | 12 + nix/scripts/start-server.nix | 3 +- package.json | 3 +- source/components/datatable/save-button.mjs | 526 ++++---- source/components/form/button.mjs | 1 - source/components/form/select.mjs | 116 +- source/components/tree-menu/tree-menu.mjs | 4 +- source/data/buildtree.mjs | 121 +- source/types/node.mjs | 278 ++-- test/cases/data/buildtree.mjs | 49 + test/cases/dom/resource/data.mjs | 2 +- test/cases/dom/resource/link.mjs | 2 +- test/cases/dom/resource/link/stylesheet.mjs | 2 +- test/cases/dom/resource/script.mjs | 2 +- 25 files changed, 2064 insertions(+), 554 deletions(-) create mode 100644 development/issues/closed/230.html create mode 100644 development/issues/closed/230.mjs create mode 100644 development/issues/open/229.html create mode 100644 development/issues/open/229.mjs create mode 100644 development/mock/issue-230.js create mode 100644 development/mockoon/issues.json diff --git a/.idea/misc.xml b/.idea/misc.xml index 4ff1fd4bd..0b42db999 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <project version="4"> - <component name="ProjectRootManager"> + <component name="ProjectRootManager" version="2" languageLevel="JDK_22" project-jdk-name="17 (2)" project-jdk-type="JavaSDK"> <output url="file://$PROJECT_DIR$/out" /> </component> <component name="accountSettings"> diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a63cf5f9..51b25a2f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,11 @@ # Changelog - ## [3.73.5] - 2024-07-02 ### Bug Fixes -- originValues in the savebutton is now reset. +- originValues in the save button is now reset. ## [3.73.4] - 2024-07-02 diff --git a/development/config/import.mjs b/development/config/import.mjs index ebf1f2425..8de0f078e 100644 --- a/development/config/import.mjs +++ b/development/config/import.mjs @@ -1,8 +1,8 @@ export const projectRoot = "/home/vs/workspaces/oss/monster/monster"; export const sourcePath = "/home/vs/workspaces/oss/monster/monster/source"; export const developmentPath = "/home/vs/workspaces/oss/monster/monster/development"; -export const pnpxBin = "/nix/store/r9h39llf5vwzmyj2mdqdx790ssggwlzb-pnpm-8.15.5/bin/pnpx"; -export const nodeBin = "/nix/store/6ridy27nr6drh8qqpsm2fj3879xr6yib-nodejs-20.12.2/bin/node"; +export const pnpxBin = "/nix/store/p77wj35xjj2ay96bsg4s916lyaa6jxrv-pnpm-8.15.5/bin/pnpx"; +export const nodeBin = "/nix/store/9cwyl546mzksfbvk6gdpjddc7z7m6ixv-nodejs-20.15.1/bin/node"; export const license = "/**" + "\n" + " * Copyright © schukai GmbH and all contributing authors, {{copyRightYear}}. All rights reserved." + "\n" + " * Node module: @schukai/monster" + "\n" + diff --git a/development/issues/closed/230.html b/development/issues/closed/230.html new file mode 100644 index 000000000..253319aa2 --- /dev/null +++ b/development/issues/closed/230.html @@ -0,0 +1,52 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>optimize tree-menu #230</title> + <script src="./230.mjs" type="module"></script> +</head> +<body> + <h1>optimize tree-menu #230</h1> + <p>The tree menu is displaying an error in the blueprint. This should be investigated and optimized if necessary.</p> + <ul> + <li><a href="https://gitlab.schukai.com/oss/libraries/javascript/monster/-/issues/230">Issue #230</a></li> + <li><a href="/">Back to overview</a></li> + </ul> + <main> + + <monster-datasource-rest id="menu-rest" data-monster-option-read-path="dataset" data-monster-option-features-autoinit="true" data-monster-option-read-url="/issue-230.json"> + </monster-datasource-rest> + + <monster-tree-menu id="main-menu" data-monster-option-mapping-idtemplate="id" data-monster-option-mapping-parentkey="parent_id" data-monster-option-mapping-labeltemplate="${title}" data-monster-option-mapping-valuetemplate="${path:url | tostring}" data-monster-option-mapping-icontemplate="${path:icon | default:default}" data-monster-option-datasource-selector="#menu-rest" value=""> + + <svg xmlns="http://www.w3.org/2000/svg" style="display: none;"> + <symbol id="box" viewBox="0 0 16 16"> + <path d="M6 9a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 0 1h-3A.5.5 0 0 1 6 9M3.854 4.146a.5.5 0 1 0-.708.708L4.793 6.5 3.146 8.146a.5.5 0 1 0 .708.708l2-2a.5.5 0 0 0 0-.708z"></path> + <path d="M2 1a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V3a2 2 0 0 0-2-2zm12 1a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1V3a1 1 0 0 1 1-1z"></path> + </symbol> + + <symbol id="default" viewBox="0 0 16 16"> + <path d="M11 2a3 3 0 0 1 3 3v6a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V5a3 3 0 0 1 3-3zM5 1a4 4 0 0 0-4 4v6a4 4 0 0 0 4 4h6a4 4 0 0 0 4-4V5a4 4 0 0 0-4-4z"></path> + </symbol> + + <symbol id="balloon" viewBox="0 0 16 16"> + <path d="M8 9.984C10.403 9.506 12 7.48 12 5a4 4 0 0 0-8 0c0 2.48 1.597 4.506 4 4.984M13 5c0 2.837-1.789 5.227-4.52 5.901l.244.487a.25.25 0 1 1-.448.224l-.008-.017c.008.11.02.202.037.29.054.27.161.488.419 1.003.288.578.235 1.15.076 1.629-.157.469-.422.867-.588 1.115l-.004.007a.25.25 0 1 1-.416-.278c.168-.252.4-.6.533-1.003.133-.396.163-.824-.049-1.246l-.013-.028c-.24-.48-.38-.758-.448-1.102a3 3 0 0 1-.052-.45l-.04.08a.25.25 0 1 1-.447-.224l.244-.487C4.789 10.227 3 7.837 3 5a5 5 0 0 1 10 0m-6.938-.495a2 2 0 0 1 1.443-1.443C7.773 2.994 8 2.776 8 2.5s-.226-.504-.498-.459a3 3 0 0 0-2.46 2.461c-.046.272.182.498.458.498s.494-.227.562-.495"></path> + </symbol> + + <symbol id="cart" viewBox="0 0 16 16"> + <path d="M8 1a2.5 2.5 0 0 1 2.5 2.5V4h-5v-.5A2.5 2.5 0 0 1 8 1m3.5 3v-.5a3.5 3.5 0 1 0-7 0V4H1v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V4zM2 5h12v9a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1z"></path> + </symbol> + + <symbol id="box2" viewBox="0 0 16 16"> + <path d="M8 7.982C9.664 6.309 13.825 9.236 8 13 2.175 9.236 6.336 6.31 8 7.982"></path> + <path d="M3.75 0a1 1 0 0 0-.8.4L.1 4.2a.5.5 0 0 0-.1.3V15a1 1 0 0 0 1 1h14a1 1 0 0 0 1-1V4.5a.5.5 0 0 0-.1-.3L13.05.4a1 1 0 0 0-.8-.4zm0 1H7.5v3h-6zM8.5 4V1h3.75l2.25 3zM15 5v10H1V5z"></path> + </symbol> + + + </svg> + </monster-tree-menu> + + </main> +</body> +</html> diff --git a/development/issues/closed/230.mjs b/development/issues/closed/230.mjs new file mode 100644 index 000000000..4ac5fea91 --- /dev/null +++ b/development/issues/closed/230.mjs @@ -0,0 +1,19 @@ +/** +* @file development/issues/open/230.mjs +* @url https://gitlab.schukai.com/oss/libraries/javascript/monster/-/issues/230 +* @description optimize tree-menu +* @issue 230 +*/ + +import "../../../source/components/style/property.pcss"; +import "../../../source/components/style/link.pcss"; +import "../../../source/components/style/color.pcss"; +import "../../../source/components/style/theme.pcss"; +import "../../../source/components/style/normalize.pcss"; +import "../../../source/components/style/typography.pcss"; +import "../../../source/components/tree-menu/tree-menu.mjs"; +import "../../../source/components/layout/split-panel.mjs"; +import "../../../source/components/layout/panel.mjs"; +import "../../../source/components/datatable/datasource/dom.mjs"; +import "../../../source/components/datatable/datasource/rest.mjs"; + diff --git a/development/issues/open/229.html b/development/issues/open/229.html new file mode 100644 index 000000000..374f881f5 --- /dev/null +++ b/development/issues/open/229.html @@ -0,0 +1,24 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>select's performance seems to be slow for many entries #229</title> + <script src="./229.mjs" type="module"></script> +</head> +<body> + <h1>select's performance seems to be slow for many entries #229</h1> + <p></p> + <ul> + <li><a href="https://gitlab.schukai.com/oss/libraries/javascript/monster/-/issues/229">Issue #229</a></li> + <li><a href="/">Back to overview</a></li> + </ul> + <main> + + <monster-select> + <monster-option value="1">Option 1</monster-option> + </monster-select> + + </main> +</body> +</html> diff --git a/development/issues/open/229.mjs b/development/issues/open/229.mjs new file mode 100644 index 000000000..534a76530 --- /dev/null +++ b/development/issues/open/229.mjs @@ -0,0 +1,15 @@ +/** +* @file development/issues/open/229.mjs +* @url https://gitlab.schukai.com/oss/libraries/javascript/monster/-/issues/229 +* @description select's performance seems to be slow for many entries +* @issue 229 +*/ + +import "../../../source/components/style/property.pcss"; +import "../../../source/components/style/link.pcss"; +import "../../../source/components/style/color.pcss"; +import "../../../source/components/style/theme.pcss"; +import "../../../source/components/style/normalize.pcss"; +import "../../../source/components/style/typography.pcss"; +import "../../../source/components/form/select.mjs"; + diff --git a/development/mock/issue-230.js b/development/mock/issue-230.js new file mode 100644 index 000000000..76714826b --- /dev/null +++ b/development/mock/issue-230.js @@ -0,0 +1,1285 @@ +const json = + `{ + "dataset": [ + { + "id": 100001, + "parent_id": 200001, + "title": "eBay", + "url": "/", + "weight": 1, + "css_styles": "", + "css_classes": "" + }, + { + "id": 100001, + "parent_id": 200001, + "title": "alvineconsole", + "url": "", + "weight": 1, + "css_styles": "", + "css_classes": "" + }, + { + "id": 100466, + "parent_id": 200466, + "title": "countries", + "url": "/alvine/?cmd=466", + "weight": 1, + "css_styles": "", + "css_classes": "" + }, + { + "id": 101023, + "parent_id": 201023, + "title": "itemlist", + "url": "/alvine/?cmd=1023", + "weight": 1, + "css_styles": "", + "css_classes": "" + }, + { + "id": 101100, + "parent_id": 205111, + "title": "published", + "url": "/alvine/?cmd=1100", + "weight": 1, + "css_styles": "", + "css_classes": "" + }, + { + "id": 101400, + "parent_id": 201400, + "title": "album", + "url": "/alvine/?cmd=1400", + "weight": 1, + "css_styles": "", + "css_classes": "" + }, + { + "id": 105059, + "parent_id": 205059, + "title": "pluginlocale", + "url": "/alvine/?cmd=5059", + "weight": 1, + "css_styles": "", + "css_classes": "" + }, + { + "id": 105064, + "parent_id": 205064, + "title": "pluginlocale", + "url": "/alvine/?cmd=5064", + "weight": 1, + "css_styles": "", + "css_classes": "" + }, + { + "id": 105111, + "parent_id": 205111, + "title": "pages", + "url": "/", + "weight": 1, + "css_styles": "", + "css_classes": "" + }, + { + "id": 108019, + "parent_id": 208019, + "title": "datev", + "url": "/alvine/?cmd=8019", + "weight": 1, + "css_styles": "", + "css_classes": "" + }, + { + "id": 108023, + "parent_id": 308023, + "title": "deliveries", + "url": "/alvine/?cmd=8023", + "weight": 1, + "css_styles": "", + "css_classes": "" + }, + { + "id": 108113, + "parent_id": 208124, + "title": "brands", + "url": "/alvine/?cmd=8113", + "weight": 1, + "css_styles": "", + "css_classes": "" + }, + { + "id": 109211, + "parent_id": 209211, + "title": "avises", + "url": "/alvine/?cmd=9211", + "weight": 1, + "css_styles": "", + "css_classes": "" + }, + { + "id": 109221, + "parent_id": 209221, + "title": "retoure", + "url": "/alvine/?cmd=9221", + "weight": 1, + "css_styles": "", + "css_classes": "" + }, + { + "id": 109231, + "parent_id": 209231, + "title": "partner", + "url": "/alvine/?cmd=9231", + "weight": 1, + "css_styles": "", + "css_classes": "" + }, + { + "id": 126012, + "parent_id": 226012, + "title": "productexport", + "url": "/alvine/?cmd=26012", + "weight": 1, + "css_styles": "", + "css_classes": "" + }, + { + "id": 126036, + "parent_id": 226036, + "title": "productimport", + "url": "/alvine/?cmd=26036", + "weight": 1, + "css_styles": "", + "css_classes": "" + }, + { + "id": 128006, + "parent_id": 228006, + "title": "salesstatistic", + "url": "/alvine/?cmd=28006", + "weight": 1, + "css_styles": "", + "css_classes": "" + }, + { + "id": 140017, + "parent_id": 226036, + "title": "importfilter", + "url": "/alvine/?cmd=40017", + "weight": 1, + "css_styles": "", + "css_classes": "" + }, + { + "id": 141024, + "parent_id": 241024, + "title": "dailystatementaction", + "url": "/alvine/?cmd=41024", + "weight": 1, + "css_styles": "", + "css_classes": "" + }, + { + "id": 151001, + "parent_id": 251001, + "title": "dunning", + "url": "/alvine/?cmd=51001", + "weight": 1, + "css_styles": "", + "css_classes": "" + }, + { + "id": 200001, + "parent_id": 200000, + "title": "developer", + "url": "", + "weight": 1, + "css_styles": "", + "css_classes": "" + }, + { + "id": 208124, + "parent_id": 201023, + "title": "catalog", + "url": "/", + "weight": 1, + "css_styles": "", + "css_classes": "" + }, + { + "id": 209221, + "parent_id": 209211, + "title": "retoure", + "url": "/", + "weight": 1, + "css_styles": "", + "css_classes": "" + }, + { + "id": 226036, + "parent_id": 2026036, + "title": "import", + "url": "/", + "weight": 1, + "css_styles": "", + "css_classes": "" + }, + { + "id": 241024, + "parent_id": 208023, + "title": "dailystatement", + "url": "", + "weight": 1, + "css_styles": "", + "css_classes": "" + }, + { + "id": 300001, + "parent_id": 200466, + "title": "taskstream", + "url": "/apps/commerce/task-stream", + "weight": 1, + "css_styles": "", + "css_classes": "" + }, + { + "id": 308023, + "parent_id": 208023, + "title": "deliveries", + "url": "/apps/commerce/delivery-list", + "weight": 1, + "css_styles": "", + "css_classes": "" + }, + { + "id": 50039, + "parent_id": 226036, + "title": "userimport", + "url": "/alvine/?cmd=50039", + "weight": 2, + "css_styles": "", + "css_classes": "" + }, + { + "id": 100002, + "parent_id": 200001, + "title": "Amazon", + "url": "/", + "weight": 2, + "css_styles": "", + "css_classes": "" + }, + { + "id": 100002, + "parent_id": 200001, + "title": "alvineframework", + "url": "", + "weight": 2, + "css_styles": "", + "css_classes": "" + }, + { + "id": 100220, + "parent_id": 300125, + "title": "tickets", + "url": "/alvine/?cmd=220", + "weight": 2, + "css_styles": "", + "css_classes": "" + }, + { + "id": 101053, + "parent_id": 201400, + "title": "article", + "url": "/alvine/?cmd=1053", + "weight": 2, + "css_styles": "", + "css_classes": "" + }, + { + "id": 105075, + "parent_id": 205059, + "title": "systemlocale", + "url": "/alvine/?cmd=5075", + "weight": 2, + "css_styles": "", + "css_classes": "" + }, + { + "id": 105076, + "parent_id": 205064, + "title": "systemlocale", + "url": "/alvine/?cmd=5076", + "weight": 2, + "css_styles": "", + "css_classes": "" + }, + { + "id": 105077, + "parent_id": 205111, + "title": "clearcache", + "url": "/alvine/?cmd=5077", + "weight": 2, + "css_styles": "", + "css_classes": "" + }, + { + "id": 108003, + "parent_id": 308004, + "title": "Orders search", + "url": "/alvine/?cmd=8003", + "weight": 2, + "css_styles": "", + "css_classes": "" + }, + { + "id": 108004, + "parent_id": 308004, + "title": "orders", + "url": "/alvine/?cmd=8004", + "weight": 2, + "css_styles": "", + "css_classes": "" + }, + { + "id": 108047, + "parent_id": 308023, + "title": "deliveryresubmission", + "url": "/alvine/?cmd=8047", + "weight": 2, + "css_styles": "", + "css_classes": "" + }, + { + "id": 108064, + "parent_id": 209211, + "title": "avisescan", + "url": "/alvine/?cmd=8064", + "weight": 2, + "css_styles": "", + "css_classes": "" + }, + { + "id": 109010, + "parent_id": 208124, + "title": "department", + "url": "/alvine/?cmd=9010", + "weight": 2, + "css_styles": "", + "css_classes": "" + }, + { + "id": 109037, + "parent_id": 209221, + "title": "retouredailystatementaction", + "url": "/alvine/?cmd=9037", + "weight": 2, + "css_styles": "", + "css_classes": "" + }, + { + "id": 109101, + "parent_id": 228006, + "title": "itemsalesstatistic", + "url": "/alvine/?cmd=9101", + "weight": 2, + "css_styles": "", + "css_classes": "" + }, + { + "id": 109700, + "parent_id": 308004, + "title": "visual check", + "url": "/alvine/?cmd=9700", + "weight": 2, + "css_styles": "", + "css_classes": "" + }, + { + "id": 122002, + "parent_id": 209231, + "title": "voucher", + "url": "/alvine/?cmd=22002", + "weight": 2, + "css_styles": "", + "css_classes": "" + }, + { + "id": 126001, + "parent_id": 200466, + "title": "payments", + "url": "/alvine/?cmd=26001", + "weight": 2, + "css_styles": "", + "css_classes": "" + }, + { + "id": 131531, + "parent_id": 201023, + "title": "storageposition", + "url": "/alvine/?cmd=31531", + "weight": 2, + "css_styles": "", + "css_classes": "" + }, + { + "id": 141002, + "parent_id": 241024, + "title": "importdhlpaketfile", + "url": "/alvine/?cmd=41024", + "weight": 2, + "css_styles": "", + "css_classes": "" + }, + { + "id": 150038, + "parent_id": 226012, + "title": "userexport", + "url": "/alvine/?cmd=50039", + "weight": 2, + "css_styles": "", + "css_classes": "" + }, + { + "id": 151023, + "parent_id": 208019, + "title": "datevopos", + "url": "/alvine/?cmd=51023", + "weight": 2, + "css_styles": "", + "css_classes": "" + }, + { + "id": 208019, + "parent_id": 251001, + "title": "datev", + "url": "/", + "weight": 2, + "css_styles": "", + "css_classes": "" + }, + { + "id": 226012, + "parent_id": 2026036, + "title": "export", + "url": "/", + "weight": 2, + "css_styles": "", + "css_classes": "" + }, + { + "id": 301053, + "parent_id": 201400, + "title": "article", + "url": "/apps/commerce/article-list", + "weight": 2, + "css_styles": "", + "css_classes": "" + }, + { + "id": 308004, + "parent_id": 0, + "title": "orders", + "url": "/apps/commerce/order-list", + "weight": 2, + "css_styles": "", + "css_classes": "" + }, + { + "id": 100003, + "parent_id": 200001, + "title": "alvinebootstrap", + "url": "", + "weight": 3, + "css_styles": "", + "css_classes": "" + }, + { + "id": 100125, + "parent_id": 300125, + "title": "customers", + "url": "/alvine/?cmd=125", + "weight": 3, + "css_styles": "", + "css_classes": "" + }, + { + "id": 100600, + "parent_id": 209231, + "title": "serialletter", + "url": "/alvine/?cmd=600", + "weight": 3, + "css_styles": "", + "css_classes": "" + }, + { + "id": 101073, + "parent_id": 201400, + "title": "listofdates", + "url": "/alvine/?cmd=1073", + "weight": 3, + "css_styles": "", + "css_classes": "" + }, + { + "id": 105049, + "parent_id": 205111, + "title": "textandimages", + "url": "/alvine/?cmd=5049", + "weight": 3, + "css_styles": "", + "css_classes": "" + }, + { + "id": 108007, + "parent_id": 308004, + "title": "Orders backtemplate", + "url": "/alvine/?cmd=8007", + "weight": 3, + "css_styles": "", + "css_classes": "" + }, + { + "id": 108124, + "parent_id": 208124, + "title": "colors", + "url": "/alvine/?cmd=8124", + "weight": 3, + "css_styles": "", + "css_classes": "" + }, + { + "id": 108210, + "parent_id": 308023, + "title": "picklists", + "url": "/alvine/?cmd=8210", + "weight": 3, + "css_styles": "", + "css_classes": "" + }, + { + "id": 109076, + "parent_id": 226012, + "title": "categoryexport", + "url": "/alvine/?cmd=9076", + "weight": 3, + "css_styles": "", + "css_classes": "" + }, + { + "id": 109077, + "parent_id": 226036, + "title": "categoryimport", + "url": "/alvine/?cmd=9077", + "weight": 3, + "css_styles": "", + "css_classes": "" + }, + { + "id": 109201, + "parent_id": 209211, + "title": "deliveries", + "url": "/alvine/?cmd=9201", + "weight": 3, + "css_styles": "", + "css_classes": "" + }, + { + "id": 124013, + "parent_id": 300125, + "title": "customerblacklist", + "url": "/alvine/?cmd=24013", + "weight": 3, + "css_styles": "", + "css_classes": "" + }, + { + "id": 128003, + "parent_id": 228006, + "title": "transactions", + "url": "/alvine/?cmd=28003", + "weight": 3, + "css_styles": "", + "css_classes": "" + }, + { + "id": 141006, + "parent_id": 200466, + "title": "deliveryconditions", + "url": "/alvine/?cmd=41006", + "weight": 3, + "css_styles": "", + "css_classes": "" + }, + { + "id": 201400, + "parent_id": 205111, + "title": "contenttypes", + "url": "/", + "weight": 3, + "css_styles": "", + "css_classes": "" + }, + { + "id": 300125, + "parent_id": 0, + "title": "customers", + "url": "/apps/commerce/user-list", + "weight": 3, + "css_styles": "", + "css_classes": "" + }, + { + "id": 100004, + "parent_id": 200001, + "title": "alvinejQuery", + "url": "", + "weight": 4, + "css_styles": "", + "css_classes": "" + }, + { + "id": 100117, + "parent_id": 300125, + "title": "groups", + "url": "/alvine/?cmd=117", + "weight": 4, + "css_styles": "", + "css_classes": "" + }, + { + "id": 100320, + "parent_id": 209231, + "title": "blacklist", + "url": "/alvine/?cmd=320", + "weight": 4, + "css_styles": "", + "css_classes": "" + }, + { + "id": 100487, + "parent_id": 205111, + "title": "mailtemplates", + "url": "/alvine/?cmd=487", + "weight": 4, + "css_styles": "", + "css_classes": "" + }, + { + "id": 101153, + "parent_id": 201400, + "title": "yellowpages", + "url": "/alvine/?cmd=1153", + "weight": 4, + "css_styles": "", + "css_classes": "" + }, + { + "id": 108073, + "parent_id": 308004, + "title": "Incoming Payment", + "url": "/alvine/?cmd=8073", + "weight": 4, + "css_styles": "", + "css_classes": "" + }, + { + "id": 108135, + "parent_id": 200466, + "title": "ordercondition", + "url": "/alvine/?cmd=8135", + "weight": 4, + "css_styles": "", + "css_classes": "" + }, + { + "id": 108157, + "parent_id": 201023, + "title": "billofmaterial", + "url": "/alvine/?cmd=8157", + "weight": 4, + "css_styles": "", + "css_classes": "" + }, + { + "id": 108218, + "parent_id": 208023, + "title": "scanpicklist", + "url": "/alvine/?cmd=8218", + "weight": 4, + "css_styles": "", + "css_classes": "" + }, + { + "id": 108218, + "parent_id": 308023, + "title": "scanpicklist", + "url": "/alvine/?cmd=8218", + "weight": 4, + "css_styles": "", + "css_classes": "" + }, + { + "id": 109076, + "parent_id": 226012, + "title": "colorexport", + "url": "/alvine/?cmd=9076", + "weight": 4, + "css_styles": "", + "css_classes": "" + }, + { + "id": 109077, + "parent_id": 226036, + "title": "colorimport", + "url": "/alvine/?cmd=9077", + "weight": 4, + "css_styles": "", + "css_classes": "" + }, + { + "id": 109102, + "parent_id": 228006, + "title": "salesperpassword", + "url": "/alvine/?cmd=9102", + "weight": 4, + "css_styles": "", + "css_classes": "" + }, + { + "id": 109119, + "parent_id": 208124, + "title": "raster", + "url": "/alvine/?cmd=9119", + "weight": 4, + "css_styles": "", + "css_classes": "" + }, + { + "id": 141005, + "parent_id": 241024, + "title": "importglspaketfile", + "url": "/alvine/?cmd=41005", + "weight": 4, + "css_styles": "", + "css_classes": "" + }, + { + "id": 209231, + "parent_id": 0, + "title": "marketing", + "url": "/alvine/?cmd=209231", + "weight": 4, + "css_styles": "", + "css_classes": "" + }, + { + "id": 101185, + "parent_id": 201400, + "title": "files", + "url": "/alvine/?cmd=1185", + "weight": 5, + "css_styles": "", + "css_classes": "" + }, + { + "id": 105022, + "parent_id": 205111, + "title": "templateversion", + "url": "/alvine/?cmd=5022", + "weight": 5, + "css_styles": "", + "css_classes": "" + }, + { + "id": 105141, + "parent_id": 205111, + "title": "metadata", + "url": "/alvine/?cmd=5141", + "weight": 5, + "css_styles": "", + "css_classes": "" + }, + { + "id": 109025, + "parent_id": 201023, + "title": "variants", + "url": "/alvine/?cmd=9025", + "weight": 5, + "css_styles": "", + "css_classes": "" + }, + { + "id": 109056, + "parent_id": 228006, + "title": "inventorylist", + "url": "/alvine/?cmd=9056", + "weight": 5, + "css_styles": "", + "css_classes": "" + }, + { + "id": 109076, + "parent_id": 226012, + "title": "stylesexport", + "url": "/alvine/?cmd=9076", + "weight": 5, + "css_styles": "", + "css_classes": "" + }, + { + "id": 109077, + "parent_id": 226036, + "title": "stylesimport", + "url": "/alvine/?cmd=9077", + "weight": 5, + "css_styles": "", + "css_classes": "" + }, + { + "id": 109081, + "parent_id": 208124, + "title": "style", + "url": "/alvine/?cmd=9081", + "weight": 5, + "css_styles": "", + "css_classes": "" + }, + { + "id": 110000, + "parent_id": 200466, + "title": "shoppingcartconditions", + "url": "/alvine/?cmd=10000", + "weight": 5, + "css_styles": "", + "css_classes": "" + }, + { + "id": 114000, + "parent_id": 308004, + "title": "offers", + "url": "/alvine/?cmd=14000", + "weight": 5, + "css_styles": "", + "css_classes": "" + }, + { + "id": 126038, + "parent_id": 300125, + "title": "customerrating", + "url": "/alvine/?cmd=26038", + "weight": 5, + "css_styles": "", + "css_classes": "" + }, + { + "id": 150040, + "parent_id": 209231, + "title": "campaign", + "url": "/alvine/?cmd=50040", + "weight": 5, + "css_styles": "", + "css_classes": "" + }, + { + "id": 200001, + "parent_id": 0, + "title": "distributionchannels", + "url": "/", + "weight": 5, + "css_styles": "", + "css_classes": "" + }, + { + "id": 100113, + "parent_id": 205111, + "title": "calendar", + "url": "/alvine/?cmd=113", + "weight": 6, + "css_styles": "", + "css_classes": "" + }, + { + "id": 100330, + "parent_id": 209231, + "title": "marketingaddresses", + "url": "/alvine/?cmd=330", + "weight": 6, + "css_styles": "", + "css_classes": "" + }, + { + "id": 101142, + "parent_id": 201400, + "title": "faq", + "url": "/alvine/?cmd=1142", + "weight": 6, + "css_styles": "", + "css_classes": "" + }, + { + "id": 108181, + "parent_id": 300125, + "title": "favouriteslist", + "url": "/alvine/?cmd=8181", + "weight": 6, + "css_styles": "", + "css_classes": "" + }, + { + "id": 109050, + "parent_id": 228006, + "title": "inventoryreport", + "url": "/alvine/?cmd=9050", + "weight": 6, + "css_styles": "", + "css_classes": "" + }, + { + "id": 109130, + "parent_id": 208124, + "title": "material", + "url": "/alvine/?cmd=9130", + "weight": 6, + "css_styles": "", + "css_classes": "" + }, + { + "id": 131500, + "parent_id": 200466, + "title": "storeposition", + "url": "/alvine/?cmd=31500", + "weight": 6, + "css_styles": "", + "css_classes": "" + }, + { + "id": 131600, + "parent_id": 308004, + "title": "orderrulesets", + "url": "/alvine/?cmd=31600", + "weight": 6, + "css_styles": "", + "css_classes": "" + }, + { + "id": 141028, + "parent_id": 241024, + "title": "importdpdpaketfile", + "url": "/alvine/?cmd=41028", + "weight": 6, + "css_styles": "", + "css_classes": "" + }, + { + "id": 150053, + "parent_id": 226012, + "title": "marketingadressexport", + "url": "/alvine/?cmd=50053", + "weight": 6, + "css_styles": "", + "css_classes": "" + }, + { + "id": 150054, + "parent_id": 226036, + "title": "marketingadressimport", + "url": "/alvine/?cmd=50054", + "weight": 6, + "css_styles": "", + "css_classes": "" + }, + { + "id": 201023, + "parent_id": 0, + "title": "products", + "url": "/", + "weight": 6, + "css_styles": "", + "css_classes": "" + }, + { + "id": 101131, + "parent_id": 200466, + "title": "objecttargets", + "url": "/alvine/?cmd=1131", + "weight": 7, + "css_styles": "", + "css_classes": "" + }, + { + "id": 101174, + "parent_id": 201400, + "title": "jobadvertisements", + "url": "/alvine/?cmd=1174", + "weight": 7, + "css_styles": "", + "css_classes": "" + }, + { + "id": 108053, + "parent_id": 208124, + "title": "collection", + "url": "/alvine/?cmd=8053", + "weight": 7, + "css_styles": "", + "css_classes": "" + }, + { + "id": 109058, + "parent_id": 201023, + "title": "categories", + "url": "/alvine/?cmd=9058", + "weight": 7, + "css_styles": "", + "css_classes": "" + }, + { + "id": 205059, + "parent_id": 226012, + "title": "localeexport", + "url": "/", + "weight": 7, + "css_styles": "", + "css_classes": "" + }, + { + "id": 205064, + "parent_id": 226036, + "title": "localeimport", + "url": "/", + "weight": 7, + "css_styles": "", + "css_classes": "" + }, + { + "id": 208023, + "parent_id": 0, + "title": "outgoinggoods", + "url": "", + "weight": 7, + "css_styles": "", + "css_classes": "" + }, + { + "id": 126013, + "parent_id": 208124, + "title": "season", + "url": "/alvine/?cmd=26013", + "weight": 8, + "css_styles": "", + "css_classes": "" + }, + { + "id": 126035, + "parent_id": 201023, + "title": "bulkactions", + "url": "/alvine/?cmd=26035", + "weight": 8, + "css_styles": "", + "css_classes": "" + }, + { + "id": 131520, + "parent_id": 200466, + "title": "storelocations", + "url": "/alvine/?cmd=31520", + "weight": 8, + "css_styles": "", + "css_classes": "" + }, + { + "id": 209211, + "parent_id": 0, + "title": "incominggoods", + "url": "/", + "weight": 8, + "css_styles": "", + "css_classes": "" + }, + { + "id": 100386, + "parent_id": 200466, + "title": "client", + "url": "/alvine/?cmd=386", + "weight": 9, + "css_styles": "", + "css_classes": "" + }, + { + "id": 109258, + "parent_id": 208124, + "title": "assignment1", + "url": "/alvine/?cmd=9258", + "weight": 9, + "css_styles": "", + "css_classes": "" + }, + { + "id": 110000, + "parent_id": 201023, + "title": "conditions", + "url": "/alvine/?cmd=10000", + "weight": 9, + "css_styles": "", + "css_classes": "" + }, + { + "id": 251001, + "parent_id": 0, + "title": "finances", + "url": "/", + "weight": 9, + "css_styles": "", + "css_classes": "" + }, + { + "id": 109269, + "parent_id": 208124, + "title": "assignment2", + "url": "/alvine/?cmd=9269", + "weight": 10, + "css_styles": "", + "css_classes": "" + }, + { + "id": 109310, + "parent_id": 208124, + "title": "assignment3", + "url": "/alvine/?cmd=9310", + "weight": 10, + "css_styles": "", + "css_classes": "" + }, + { + "id": 120008, + "parent_id": 200466, + "title": "pricelists", + "url": "/alvine/?cmd=20008", + "weight": 10, + "css_styles": "", + "css_classes": "" + }, + { + "id": 228006, + "parent_id": 0, + "title": "reports", + "url": "/", + "weight": 10, + "css_styles": "", + "css_classes": "" + }, + { + "id": 100350, + "parent_id": 200466, + "title": "objectproperties", + "url": "/alvine/?cmd=350", + "weight": 11, + "css_styles": "", + "css_classes": "" + }, + { + "id": 205111, + "parent_id": 0, + "title": "contentmanagement", + "url": "/", + "weight": 11, + "css_styles": "", + "css_classes": "" + }, + { + "id": 2026036, + "parent_id": 0, + "title": "importexport", + "url": "/", + "weight": 12, + "css_styles": "", + "css_classes": "" + }, + { + "id": 200466, + "parent_id": 0, + "title": "settings", + "url": "/", + "weight": 13, + "css_styles": "", + "css_classes": "" + }, + { + "id": 200000, + "parent_id": 0, + "title": "documentation", + "url": "", + "weight": 14, + "css_styles": "", + "css_classes": "" + } + ], + "sys": { + "code": 200, + "result": {}, + "api_version": "1" + } +}`; + + +// check if json is valid +JSON.parse(json) + +const json400Error=`[ + { + "sys": { + "type": "Error", + "message": "Invalid request" + } + } + ]` + +// check if json is valid +JSON.parse(json400Error) + + +const json200Error=`[ + { + "sys": { + "type": "Error", + "message": "Invalid request" + } + } + ]` + +// check if json is valid +JSON.parse(json200Error) + +export default [ + { + url: '/issue-230.json', + method: 'get', + rawResponse: async (req, res) => { + res.setHeader('Content-Type', 'application/json') + res.statusCode = 200 + + setTimeout(function() { + res.end(json) + }, 10); + }, + }, + + { + url: '/issue-230', + method: 'post', + rawResponse: async (req, res) => { + res.setHeader('Content-Type', 'application/json') + res.statusCode = 400 + + setTimeout(function() { + res.end(json400Error) + }, 10); + }, + } + + + +]; \ No newline at end of file diff --git a/development/mockoon/issues.json b/development/mockoon/issues.json new file mode 100644 index 000000000..f256f2a09 --- /dev/null +++ b/development/mockoon/issues.json @@ -0,0 +1,85 @@ +{ + "uuid": "66fb8768-0d50-484e-a3bc-1a251bb1fb59", + "lastMigration": 32, + "name": "Issues", + "endpointPrefix": "", + "latency": 0, + "port": 3000, + "hostname": "", + "folders": [], + "routes": [ + { + "uuid": "d9f0436c-e07a-4967-bf5a-7d15ef2f5f74", + "type": "http", + "documentation": "", + "method": "get", + "endpoint": "navigation", + "responses": [ + { + "uuid": "bcdb940b-184c-4ba5-a6ab-bf082d1f4c99", + "body": "{\n \"dataset\": [\n {\n \"id\": 100001,\n \"parent_id\": 200001,\n \"title\": \"eBay\",\n \"url\": \"/\",\n \"weight\": 1,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 100001,\n \"parent_id\": 200001,\n \"title\": \"alvineconsole\",\n \"url\": \"\",\n \"weight\": 1,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 100466,\n \"parent_id\": 200466,\n \"title\": \"countries\",\n \"url\": \"/alvine/?cmd=466\",\n \"weight\": 1,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 101023,\n \"parent_id\": 201023,\n \"title\": \"itemlist\",\n \"url\": \"/alvine/?cmd=1023\",\n \"weight\": 1,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 101100,\n \"parent_id\": 205111,\n \"title\": \"published\",\n \"url\": \"/alvine/?cmd=1100\",\n \"weight\": 1,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 101400,\n \"parent_id\": 201400,\n \"title\": \"album\",\n \"url\": \"/alvine/?cmd=1400\",\n \"weight\": 1,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 105059,\n \"parent_id\": 205059,\n \"title\": \"pluginlocale\",\n \"url\": \"/alvine/?cmd=5059\",\n \"weight\": 1,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 105064,\n \"parent_id\": 205064,\n \"title\": \"pluginlocale\",\n \"url\": \"/alvine/?cmd=5064\",\n \"weight\": 1,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 105111,\n \"parent_id\": 205111,\n \"title\": \"pages\",\n \"url\": \"/\",\n \"weight\": 1,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 108019,\n \"parent_id\": 208019,\n \"title\": \"datev\",\n \"url\": \"/alvine/?cmd=8019\",\n \"weight\": 1,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 108023,\n \"parent_id\": 308023,\n \"title\": \"deliveries\",\n \"url\": \"/alvine/?cmd=8023\",\n \"weight\": 1,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 108113,\n \"parent_id\": 208124,\n \"title\": \"brands\",\n \"url\": \"/alvine/?cmd=8113\",\n \"weight\": 1,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 109211,\n \"parent_id\": 209211,\n \"title\": \"avises\",\n \"url\": \"/alvine/?cmd=9211\",\n \"weight\": 1,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 109221,\n \"parent_id\": 209221,\n \"title\": \"retoure\",\n \"url\": \"/alvine/?cmd=9221\",\n \"weight\": 1,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 109231,\n \"parent_id\": 209231,\n \"title\": \"partner\",\n \"url\": \"/alvine/?cmd=9231\",\n \"weight\": 1,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 126012,\n \"parent_id\": 226012,\n \"title\": \"productexport\",\n \"url\": \"/alvine/?cmd=26012\",\n \"weight\": 1,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 126036,\n \"parent_id\": 226036,\n \"title\": \"productimport\",\n \"url\": \"/alvine/?cmd=26036\",\n \"weight\": 1,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 128006,\n \"parent_id\": 228006,\n \"title\": \"salesstatistic\",\n \"url\": \"/alvine/?cmd=28006\",\n \"weight\": 1,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 140017,\n \"parent_id\": 226036,\n \"title\": \"importfilter\",\n \"url\": \"/alvine/?cmd=40017\",\n \"weight\": 1,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 141024,\n \"parent_id\": 241024,\n \"title\": \"dailystatementaction\",\n \"url\": \"/alvine/?cmd=41024\",\n \"weight\": 1,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 151001,\n \"parent_id\": 251001,\n \"title\": \"dunning\",\n \"url\": \"/alvine/?cmd=51001\",\n \"weight\": 1,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 200001,\n \"parent_id\": 200000,\n \"title\": \"developer\",\n \"url\": \"\",\n \"weight\": 1,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 208124,\n \"parent_id\": 201023,\n \"title\": \"catalog\",\n \"url\": \"/\",\n \"weight\": 1,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 209221,\n \"parent_id\": 209211,\n \"title\": \"retoure\",\n \"url\": \"/\",\n \"weight\": 1,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 226036,\n \"parent_id\": 2026036,\n \"title\": \"import\",\n \"url\": \"/\",\n \"weight\": 1,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 241024,\n \"parent_id\": 208023,\n \"title\": \"dailystatement\",\n \"url\": \"\",\n \"weight\": 1,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 300001,\n \"parent_id\": 200466,\n \"title\": \"taskstream\",\n \"url\": \"/apps/commerce/task-stream\",\n \"weight\": 1,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 308023,\n \"parent_id\": 208023,\n \"title\": \"deliveries\",\n \"url\": \"/apps/commerce/delivery-list\",\n \"weight\": 1,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 0,\n \"parent_id\": 0,\n \"title\": \"Yes\",\n \"url\": \"/apps/test\",\n \"weight\": 2,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 50039,\n \"parent_id\": 226036,\n \"title\": \"userimport\",\n \"url\": \"/alvine/?cmd=50039\",\n \"weight\": 2,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 100002,\n \"parent_id\": 200001,\n \"title\": \"Amazon\",\n \"url\": \"/\",\n \"weight\": 2,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 100002,\n \"parent_id\": 200001,\n \"title\": \"alvineframework\",\n \"url\": \"\",\n \"weight\": 2,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 100220,\n \"parent_id\": 300125,\n \"title\": \"tickets\",\n \"url\": \"/alvine/?cmd=220\",\n \"weight\": 2,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 101053,\n \"parent_id\": 201400,\n \"title\": \"article\",\n \"url\": \"/alvine/?cmd=1053\",\n \"weight\": 2,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 105075,\n \"parent_id\": 205059,\n \"title\": \"systemlocale\",\n \"url\": \"/alvine/?cmd=5075\",\n \"weight\": 2,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 105076,\n \"parent_id\": 205064,\n \"title\": \"systemlocale\",\n \"url\": \"/alvine/?cmd=5076\",\n \"weight\": 2,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 105077,\n \"parent_id\": 205111,\n \"title\": \"clearcache\",\n \"url\": \"/alvine/?cmd=5077\",\n \"weight\": 2,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 108003,\n \"parent_id\": 308004,\n \"title\": \"Orders search\",\n \"url\": \"/alvine/?cmd=8003\",\n \"weight\": 2,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 108004,\n \"parent_id\": 308004,\n \"title\": \"orders\",\n \"url\": \"/alvine/?cmd=8004\",\n \"weight\": 2,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 108047,\n \"parent_id\": 308023,\n \"title\": \"deliveryresubmission\",\n \"url\": \"/alvine/?cmd=8047\",\n \"weight\": 2,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 108064,\n \"parent_id\": 209211,\n \"title\": \"avisescan\",\n \"url\": \"/alvine/?cmd=8064\",\n \"weight\": 2,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 109010,\n \"parent_id\": 208124,\n \"title\": \"department\",\n \"url\": \"/alvine/?cmd=9010\",\n \"weight\": 2,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 109037,\n \"parent_id\": 209221,\n \"title\": \"retouredailystatementaction\",\n \"url\": \"/alvine/?cmd=9037\",\n \"weight\": 2,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 109101,\n \"parent_id\": 228006,\n \"title\": \"itemsalesstatistic\",\n \"url\": \"/alvine/?cmd=9101\",\n \"weight\": 2,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 109700,\n \"parent_id\": 308004,\n \"title\": \"visual check\",\n \"url\": \"/alvine/?cmd=9700\",\n \"weight\": 2,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 122002,\n \"parent_id\": 209231,\n \"title\": \"voucher\",\n \"url\": \"/alvine/?cmd=22002\",\n \"weight\": 2,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 126001,\n \"parent_id\": 200466,\n \"title\": \"payments\",\n \"url\": \"/alvine/?cmd=26001\",\n \"weight\": 2,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 131531,\n \"parent_id\": 201023,\n \"title\": \"storageposition\",\n \"url\": \"/alvine/?cmd=31531\",\n \"weight\": 2,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 141002,\n \"parent_id\": 241024,\n \"title\": \"importdhlpaketfile\",\n \"url\": \"/alvine/?cmd=41024\",\n \"weight\": 2,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 150038,\n \"parent_id\": 226012,\n \"title\": \"userexport\",\n \"url\": \"/alvine/?cmd=50039\",\n \"weight\": 2,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 151023,\n \"parent_id\": 208019,\n \"title\": \"datevopos\",\n \"url\": \"/alvine/?cmd=51023\",\n \"weight\": 2,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 208019,\n \"parent_id\": 251001,\n \"title\": \"datev\",\n \"url\": \"/\",\n \"weight\": 2,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 226012,\n \"parent_id\": 2026036,\n \"title\": \"export\",\n \"url\": \"/\",\n \"weight\": 2,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 301053,\n \"parent_id\": 201400,\n \"title\": \"article\",\n \"url\": \"/apps/commerce/article-list\",\n \"weight\": 2,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 308004,\n \"parent_id\": 0,\n \"title\": \"orders\",\n \"url\": \"/apps/commerce/order-list\",\n \"weight\": 2,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 100003,\n \"parent_id\": 200001,\n \"title\": \"alvinebootstrap\",\n \"url\": \"\",\n \"weight\": 3,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 100125,\n \"parent_id\": 300125,\n \"title\": \"customers\",\n \"url\": \"/alvine/?cmd=125\",\n \"weight\": 3,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 100600,\n \"parent_id\": 209231,\n \"title\": \"serialletter\",\n \"url\": \"/alvine/?cmd=600\",\n \"weight\": 3,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 101073,\n \"parent_id\": 201400,\n \"title\": \"listofdates\",\n \"url\": \"/alvine/?cmd=1073\",\n \"weight\": 3,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 105049,\n \"parent_id\": 205111,\n \"title\": \"textandimages\",\n \"url\": \"/alvine/?cmd=5049\",\n \"weight\": 3,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 108007,\n \"parent_id\": 308004,\n \"title\": \"Orders backtemplate\",\n \"url\": \"/alvine/?cmd=8007\",\n \"weight\": 3,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 108124,\n \"parent_id\": 208124,\n \"title\": \"colors\",\n \"url\": \"/alvine/?cmd=8124\",\n \"weight\": 3,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 108210,\n \"parent_id\": 308023,\n \"title\": \"picklists\",\n \"url\": \"/alvine/?cmd=8210\",\n \"weight\": 3,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 109076,\n \"parent_id\": 226012,\n \"title\": \"categoryexport\",\n \"url\": \"/alvine/?cmd=9076\",\n \"weight\": 3,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 109077,\n \"parent_id\": 226036,\n \"title\": \"categoryimport\",\n \"url\": \"/alvine/?cmd=9077\",\n \"weight\": 3,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 109201,\n \"parent_id\": 209211,\n \"title\": \"deliveries\",\n \"url\": \"/alvine/?cmd=9201\",\n \"weight\": 3,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 124013,\n \"parent_id\": 300125,\n \"title\": \"customerblacklist\",\n \"url\": \"/alvine/?cmd=24013\",\n \"weight\": 3,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 128003,\n \"parent_id\": 228006,\n \"title\": \"transactions\",\n \"url\": \"/alvine/?cmd=28003\",\n \"weight\": 3,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 141006,\n \"parent_id\": 200466,\n \"title\": \"deliveryconditions\",\n \"url\": \"/alvine/?cmd=41006\",\n \"weight\": 3,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 201400,\n \"parent_id\": 205111,\n \"title\": \"contenttypes\",\n \"url\": \"/\",\n \"weight\": 3,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 300125,\n \"parent_id\": 0,\n \"title\": \"customers\",\n \"url\": \"/apps/commerce/user-list\",\n \"weight\": 3,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 100004,\n \"parent_id\": 200001,\n \"title\": \"alvinejQuery\",\n \"url\": \"\",\n \"weight\": 4,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 100117,\n \"parent_id\": 300125,\n \"title\": \"groups\",\n \"url\": \"/alvine/?cmd=117\",\n \"weight\": 4,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 100320,\n \"parent_id\": 209231,\n \"title\": \"blacklist\",\n \"url\": \"/alvine/?cmd=320\",\n \"weight\": 4,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 100487,\n \"parent_id\": 205111,\n \"title\": \"mailtemplates\",\n \"url\": \"/alvine/?cmd=487\",\n \"weight\": 4,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 101153,\n \"parent_id\": 201400,\n \"title\": \"yellowpages\",\n \"url\": \"/alvine/?cmd=1153\",\n \"weight\": 4,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 108073,\n \"parent_id\": 308004,\n \"title\": \"Incoming Payment\",\n \"url\": \"/alvine/?cmd=8073\",\n \"weight\": 4,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 108135,\n \"parent_id\": 200466,\n \"title\": \"ordercondition\",\n \"url\": \"/alvine/?cmd=8135\",\n \"weight\": 4,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 108157,\n \"parent_id\": 201023,\n \"title\": \"billofmaterial\",\n \"url\": \"/alvine/?cmd=8157\",\n \"weight\": 4,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 108218,\n \"parent_id\": 208023,\n \"title\": \"scanpicklist\",\n \"url\": \"/alvine/?cmd=8218\",\n \"weight\": 4,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 108218,\n \"parent_id\": 308023,\n \"title\": \"scanpicklist\",\n \"url\": \"/alvine/?cmd=8218\",\n \"weight\": 4,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 109076,\n \"parent_id\": 226012,\n \"title\": \"colorexport\",\n \"url\": \"/alvine/?cmd=9076\",\n \"weight\": 4,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 109077,\n \"parent_id\": 226036,\n \"title\": \"colorimport\",\n \"url\": \"/alvine/?cmd=9077\",\n \"weight\": 4,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 109102,\n \"parent_id\": 228006,\n \"title\": \"salesperpassword\",\n \"url\": \"/alvine/?cmd=9102\",\n \"weight\": 4,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 109119,\n \"parent_id\": 208124,\n \"title\": \"raster\",\n \"url\": \"/alvine/?cmd=9119\",\n \"weight\": 4,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 141005,\n \"parent_id\": 241024,\n \"title\": \"importglspaketfile\",\n \"url\": \"/alvine/?cmd=41005\",\n \"weight\": 4,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 209231,\n \"parent_id\": 0,\n \"title\": \"marketing\",\n \"url\": \"/alvine/?cmd=209231\",\n \"weight\": 4,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 101185,\n \"parent_id\": 201400,\n \"title\": \"files\",\n \"url\": \"/alvine/?cmd=1185\",\n \"weight\": 5,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 105022,\n \"parent_id\": 205111,\n \"title\": \"templateversion\",\n \"url\": \"/alvine/?cmd=5022\",\n \"weight\": 5,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 105141,\n \"parent_id\": 205111,\n \"title\": \"metadata\",\n \"url\": \"/alvine/?cmd=5141\",\n \"weight\": 5,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 109025,\n \"parent_id\": 201023,\n \"title\": \"variants\",\n \"url\": \"/alvine/?cmd=9025\",\n \"weight\": 5,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 109056,\n \"parent_id\": 228006,\n \"title\": \"inventorylist\",\n \"url\": \"/alvine/?cmd=9056\",\n \"weight\": 5,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 109076,\n \"parent_id\": 226012,\n \"title\": \"stylesexport\",\n \"url\": \"/alvine/?cmd=9076\",\n \"weight\": 5,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 109077,\n \"parent_id\": 226036,\n \"title\": \"stylesimport\",\n \"url\": \"/alvine/?cmd=9077\",\n \"weight\": 5,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 109081,\n \"parent_id\": 208124,\n \"title\": \"style\",\n \"url\": \"/alvine/?cmd=9081\",\n \"weight\": 5,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 110000,\n \"parent_id\": 200466,\n \"title\": \"shoppingcartconditions\",\n \"url\": \"/alvine/?cmd=10000\",\n \"weight\": 5,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 114000,\n \"parent_id\": 308004,\n \"title\": \"offers\",\n \"url\": \"/alvine/?cmd=14000\",\n \"weight\": 5,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 126038,\n \"parent_id\": 300125,\n \"title\": \"customerrating\",\n \"url\": \"/alvine/?cmd=26038\",\n \"weight\": 5,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 150040,\n \"parent_id\": 209231,\n \"title\": \"campaign\",\n \"url\": \"/alvine/?cmd=50040\",\n \"weight\": 5,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 200001,\n \"parent_id\": 0,\n \"title\": \"distributionchannels\",\n \"url\": \"/\",\n \"weight\": 5,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 100113,\n \"parent_id\": 205111,\n \"title\": \"calendar\",\n \"url\": \"/alvine/?cmd=113\",\n \"weight\": 6,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 100330,\n \"parent_id\": 209231,\n \"title\": \"marketingaddresses\",\n \"url\": \"/alvine/?cmd=330\",\n \"weight\": 6,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 101142,\n \"parent_id\": 201400,\n \"title\": \"faq\",\n \"url\": \"/alvine/?cmd=1142\",\n \"weight\": 6,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 108181,\n \"parent_id\": 300125,\n \"title\": \"favouriteslist\",\n \"url\": \"/alvine/?cmd=8181\",\n \"weight\": 6,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 109050,\n \"parent_id\": 228006,\n \"title\": \"inventoryreport\",\n \"url\": \"/alvine/?cmd=9050\",\n \"weight\": 6,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 109130,\n \"parent_id\": 208124,\n \"title\": \"material\",\n \"url\": \"/alvine/?cmd=9130\",\n \"weight\": 6,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 131500,\n \"parent_id\": 200466,\n \"title\": \"storeposition\",\n \"url\": \"/alvine/?cmd=31500\",\n \"weight\": 6,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 131600,\n \"parent_id\": 308004,\n \"title\": \"orderrulesets\",\n \"url\": \"/alvine/?cmd=31600\",\n \"weight\": 6,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 141028,\n \"parent_id\": 241024,\n \"title\": \"importdpdpaketfile\",\n \"url\": \"/alvine/?cmd=41028\",\n \"weight\": 6,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 150053,\n \"parent_id\": 226012,\n \"title\": \"marketingadressexport\",\n \"url\": \"/alvine/?cmd=50053\",\n \"weight\": 6,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 150054,\n \"parent_id\": 226036,\n \"title\": \"marketingadressimport\",\n \"url\": \"/alvine/?cmd=50054\",\n \"weight\": 6,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 201023,\n \"parent_id\": 0,\n \"title\": \"products\",\n \"url\": \"/\",\n \"weight\": 6,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 101131,\n \"parent_id\": 200466,\n \"title\": \"objecttargets\",\n \"url\": \"/alvine/?cmd=1131\",\n \"weight\": 7,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 101174,\n \"parent_id\": 201400,\n \"title\": \"jobadvertisements\",\n \"url\": \"/alvine/?cmd=1174\",\n \"weight\": 7,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 108053,\n \"parent_id\": 208124,\n \"title\": \"collection\",\n \"url\": \"/alvine/?cmd=8053\",\n \"weight\": 7,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 109058,\n \"parent_id\": 201023,\n \"title\": \"categories\",\n \"url\": \"/alvine/?cmd=9058\",\n \"weight\": 7,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 205059,\n \"parent_id\": 226012,\n \"title\": \"localeexport\",\n \"url\": \"/\",\n \"weight\": 7,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 205064,\n \"parent_id\": 226036,\n \"title\": \"localeimport\",\n \"url\": \"/\",\n \"weight\": 7,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 208023,\n \"parent_id\": 0,\n \"title\": \"outgoinggoods\",\n \"url\": \"\",\n \"weight\": 7,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 126013,\n \"parent_id\": 208124,\n \"title\": \"season\",\n \"url\": \"/alvine/?cmd=26013\",\n \"weight\": 8,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 126035,\n \"parent_id\": 201023,\n \"title\": \"bulkactions\",\n \"url\": \"/alvine/?cmd=26035\",\n \"weight\": 8,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 131520,\n \"parent_id\": 200466,\n \"title\": \"storelocations\",\n \"url\": \"/alvine/?cmd=31520\",\n \"weight\": 8,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 209211,\n \"parent_id\": 0,\n \"title\": \"incominggoods\",\n \"url\": \"/\",\n \"weight\": 8,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 100386,\n \"parent_id\": 200466,\n \"title\": \"client\",\n \"url\": \"/alvine/?cmd=386\",\n \"weight\": 9,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 109258,\n \"parent_id\": 208124,\n \"title\": \"assignment1\",\n \"url\": \"/alvine/?cmd=9258\",\n \"weight\": 9,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 110000,\n \"parent_id\": 201023,\n \"title\": \"conditions\",\n \"url\": \"/alvine/?cmd=10000\",\n \"weight\": 9,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 251001,\n \"parent_id\": 0,\n \"title\": \"finances\",\n \"url\": \"/\",\n \"weight\": 9,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 109269,\n \"parent_id\": 208124,\n \"title\": \"assignment2\",\n \"url\": \"/alvine/?cmd=9269\",\n \"weight\": 10,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 109310,\n \"parent_id\": 208124,\n \"title\": \"assignment3\",\n \"url\": \"/alvine/?cmd=9310\",\n \"weight\": 10,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 120008,\n \"parent_id\": 200466,\n \"title\": \"pricelists\",\n \"url\": \"/alvine/?cmd=20008\",\n \"weight\": 10,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 228006,\n \"parent_id\": 0,\n \"title\": \"reports\",\n \"url\": \"/\",\n \"weight\": 10,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 100350,\n \"parent_id\": 200466,\n \"title\": \"objectproperties\",\n \"url\": \"/alvine/?cmd=350\",\n \"weight\": 11,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 205111,\n \"parent_id\": 0,\n \"title\": \"contentmanagement\",\n \"url\": \"/\",\n \"weight\": 11,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 2026036,\n \"parent_id\": 0,\n \"title\": \"importexport\",\n \"url\": \"/\",\n \"weight\": 12,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 200466,\n \"parent_id\": 0,\n \"title\": \"settings\",\n \"url\": \"/\",\n \"weight\": 13,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n },\n {\n \"id\": 200000,\n \"parent_id\": 0,\n \"title\": \"documentation\",\n \"url\": \"\",\n \"weight\": 14,\n \"css_styles\": \"\",\n \"css_classes\": \"\"\n }\n ],\n \"sys\": {\n \"code\": 200,\n \"result\": {},\n \"api_version\": \"1\"\n }\n}", + "latency": 0, + "statusCode": 200, + "label": "", + "headers": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "bodyType": "INLINE", + "filePath": "", + "databucketID": "", + "sendFileAsBody": false, + "rules": [], + "rulesOperator": "OR", + "disableTemplating": false, + "fallbackTo404": false, + "default": true, + "crudKey": "id", + "callbacks": [] + } + ], + "responseMode": null + } + ], + "rootChildren": [ + { + "type": "route", + "uuid": "d9f0436c-e07a-4967-bf5a-7d15ef2f5f74" + } + ], + "proxyMode": false, + "proxyHost": "", + "proxyRemovePrefix": false, + "tlsOptions": { + "enabled": false, + "type": "CERT", + "pfxPath": "", + "certPath": "", + "keyPath": "", + "caPath": "", + "passphrase": "" + }, + "cors": true, + "headers": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "proxyReqHeaders": [ + { + "key": "", + "value": "" + } + ], + "proxyResHeaders": [ + { + "key": "", + "value": "" + } + ], + "data": [], + "callbacks": [] +} \ No newline at end of file diff --git a/flake.lock b/flake.lock index 8e1a71f7f..beb5a08ce 100644 --- a/flake.lock +++ b/flake.lock @@ -55,11 +55,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1719426051, - "narHash": "sha256-yJL9VYQhaRM7xs0M867ZFxwaONB9T2Q4LnGo1WovuR4=", + "lastModified": 1722221733, + "narHash": "sha256-sga9SrrPb+pQJxG1ttJfMPheZvDOxApFfwXCFO0H9xw=", "owner": "nixos", "repo": "nixpkgs", - "rev": "89c49874fb15f4124bf71ca5f42a04f2ee5825fd", + "rev": "12bf09802d77264e441f48e25459c10c93eada2e", "type": "github" }, "original": { diff --git a/nix/config/release.nix b/nix/config/release.nix index c369d979b..fcbc8670b 100644 --- a/nix/config/release.nix +++ b/nix/config/release.nix @@ -3,4 +3,4 @@ commit = "efa3cf498dd40ccbb114cb0074409c1adf2bf6a7"; name = "Monster"; mnemonic = "monster"; -} \ No newline at end of file +} diff --git a/nix/scripts/go-task.nix b/nix/scripts/go-task.nix index aff37a699..ef7fc566d 100644 --- a/nix/scripts/go-task.nix +++ b/nix/scripts/go-task.nix @@ -159,6 +159,18 @@ silent: true aliases: - r + + + tool-mockoon: + desc: Run example + aliases: + - m + - mockoon + cmds: + - ${pkgs'.mockoon}/bin/mockoon + silent: true + env: + USER_WORKING_DIR: "{{.USER_WORKING_DIR}}" ''; diff --git a/nix/scripts/start-server.nix b/nix/scripts/start-server.nix index 1032c2e31..763d3bc95 100644 --- a/nix/scripts/start-server.nix +++ b/nix/scripts/start-server.nix @@ -49,7 +49,8 @@ in exit 1 fi - if ! ${pkgs'.nodePackages.pnpm}/bin/pnpx vite --config "./config/vite.config.mjs"; then + ## --inspect-brk (debug flag) + if ! ${pkgs'.nodejs_22}/bin/node "$WORKING_DIR/node_modules/vite/bin/vite.js" --config "./config/vite.config.mjs"; then echo_fail "Vite build failed, check your JS!" exit 1 fi diff --git a/package.json b/package.json index 6201ce53c..684b5793f 100644 --- a/package.json +++ b/package.json @@ -96,5 +96,6 @@ "vite-plugin-mock": "^3.0.2", "vite-plugin-terminal": "^1.2.0", "ws": "^8.17.1" - } + }, + "packageManager": "pnpm@9.4.0+sha256.b6fd0bfda555e7e584ad7e56b30c68b01d5a04f9ee93989f4b93ca8473c49c74" } diff --git a/source/components/datatable/save-button.mjs b/source/components/datatable/save-button.mjs index 83a347c1b..646a496aa 100644 --- a/source/components/datatable/save-button.mjs +++ b/source/components/datatable/save-button.mjs @@ -12,33 +12,33 @@ * SPDX-License-Identifier: AGPL-3.0 */ -import {instanceSymbol, internalSymbol} from "../../constants.mjs"; -import {diff} from "../../data/diff.mjs"; -import {addAttributeToken} from "../../dom/attributes.mjs"; -import {ATTRIBUTE_ERRORMESSAGE} from "../../dom/constants.mjs"; +import { instanceSymbol, internalSymbol } from "../../constants.mjs"; +import { diff } from "../../data/diff.mjs"; +import { addAttributeToken } from "../../dom/attributes.mjs"; +import { ATTRIBUTE_ERRORMESSAGE } from "../../dom/constants.mjs"; import { - assembleMethodSymbol, - CustomElement, - attributeObserverSymbol, - registerCustomElement, + assembleMethodSymbol, + CustomElement, + attributeObserverSymbol, + registerCustomElement, } from "../../dom/customelement.mjs"; -import {findElementWithSelectorUpwards} from "../../dom/util.mjs"; -import {isString, isArray} from "../../types/is.mjs"; -import {Observer} from "../../types/observer.mjs"; -import {TokenList} from "../../types/tokenlist.mjs"; -import {clone} from "../../util/clone.mjs"; -import {State} from "../form/types/state.mjs"; -import {ATTRIBUTE_DATASOURCE_SELECTOR} from "./constants.mjs"; -import {Datasource} from "./datasource.mjs"; -import {BadgeStyleSheet} from "../stylesheet/badge.mjs"; -import {SaveButtonStyleSheet} from "./stylesheet/save-button.mjs"; +import { findElementWithSelectorUpwards } from "../../dom/util.mjs"; +import { isString, isArray } from "../../types/is.mjs"; +import { Observer } from "../../types/observer.mjs"; +import { TokenList } from "../../types/tokenlist.mjs"; +import { clone } from "../../util/clone.mjs"; +import { State } from "../form/types/state.mjs"; +import { ATTRIBUTE_DATASOURCE_SELECTOR } from "./constants.mjs"; +import { Datasource } from "./datasource.mjs"; +import { BadgeStyleSheet } from "../stylesheet/badge.mjs"; +import { SaveButtonStyleSheet } from "./stylesheet/save-button.mjs"; import { - handleDataSourceChanges, - datasourceLinkedElementSymbol, + handleDataSourceChanges, + datasourceLinkedElementSymbol, } from "./util.mjs"; -export {SaveButton}; +export { SaveButton }; /** * @private @@ -59,185 +59,187 @@ const originValuesSymbol = Symbol("originValues"); const badgeElementSymbol = Symbol("badgeElement"); class SaveButton extends CustomElement { - /** - * This method is called by the `instanceof` operator. - * @returns {symbol} - */ - static get [instanceSymbol]() { - return Symbol.for( - "@schukai/monster/components/datasource/save-button@@instance", - ); - } - - /** - * To set the options via the html tag the attribute `data-monster-options` must be used. - * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control} - * - * The individual configuration values can be found in the table. - * - * @property {Object} templates Template definitions - * @property {string} templates.main Main template - * @property {object} datasource The datasource - * @property {string} datasource.selector The selector of the datasource - * @property {string} labels.button The button label - * @property {Object} classes The classes - * @property {string} classes.bar The bar class - * @property {string} classes.badge The badge class - * @property {Array} ignoreChanges The ignore changes (regex) - * @property {Array} data The data - * @return {Object} - */ - get defaults() { - const obj = Object.assign({}, super.defaults, { - templates: { - main: getTemplate(), - }, - - labels: { - button: "save", - }, - - classes: { - bar: "monster-button-primary", - badge: "monster-badge-secondary hidden", - }, - - datasource: { - selector: null, - }, - - changes: "0", - - ignoreChanges: [], - - data: {}, - - disabled: false, - }); - - updateOptionsFromArguments.call(this, obj); - return obj; - } - - /** - * - * @return {string} - */ - static getTag() { - return "monster-datasource-save-button"; - } - - /** - * This method is responsible for assembling the component. - * - * It calls the parent's assemble method first, then initializes control references and event handlers. - * If the `datasource.selector` option is provided and is a string, it searches for the corresponding - * element in the DOM using that selector. - * - * If the selector matches exactly one element, it checks if the element is an instance of the `Datasource` class. - * - * If it is, the component's `datasourceLinkedElementSymbol` property is set to the element, and the component - * attaches an observer to the datasource's changes. - * - * The observer is a function that calls the `handleDataSourceChanges` method in the context of the component. - * Additionally, the component attaches an observer to itself, which also calls the `handleDataSourceChanges` - * method in the component's context. - */ - [assembleMethodSymbol]() { - super[assembleMethodSymbol](); - const self = this; - - initControlReferences.call(this); - initEventHandler.call(this); - - const selector = this.getOption("datasource.selector"); - - if (isString(selector)) { - const element = findElementWithSelectorUpwards(this, selector); - if (element === null) { - throw new Error("the selector must match exactly one element"); - } - - if (!(element instanceof Datasource)) { - throw new TypeError("the element must be a datasource"); - } - - this[datasourceLinkedElementSymbol] = element; - element.datasource.attachObserver( - new Observer(handleDataSourceChanges.bind(this)), - ); - - self[originValuesSymbol] = null; - - element.datasource.attachObserver( - new Observer(function () { - if (!self[originValuesSymbol]) { - self[originValuesSymbol] = clone(self[datasourceLinkedElementSymbol].data); - } - - const currentValues = this.getRealSubject(); - const ignoreChanges = self.getOption("ignoreChanges"); - - const result = diff(self[originValuesSymbol], currentValues); - if (isArray(ignoreChanges) && ignoreChanges.length > 0) { - const itemsToRemove = []; - for (const item of result) { - for (const ignorePattern of ignoreChanges) { - const p = new RegExp(ignorePattern); - if (p.test(item.path)) { - itemsToRemove.push(item); - break; - } - } - } - - for (const itemToRemove of itemsToRemove) { - const index = result.indexOf(itemToRemove); - if (index > -1) { - result.splice(index, 1); - } - } - } - - if (isArray(result) && result.length > 0) { - self[stateButtonElementSymbol].setState("changed"); - self[stateButtonElementSymbol].setOption("disabled", false); - self.setOption("changes", result.length); - self.setOption( - "classes.badge", - new TokenList(self.getOption("classes.badge")) - .remove("hidden") - .toString(), - ); - } else { - self[stateButtonElementSymbol].removeState(); - self[stateButtonElementSymbol].setOption("disabled", true); - self.setOption("changes", 0); - self.setOption( - "classes.badge", - new TokenList(self.getOption("classes.badge")) - .add("hidden") - .toString(), - ); - } - }), - ); - } - - this.attachObserver( - new Observer(() => { - handleDataSourceChanges.call(this); - }), - ); - } - - /** - * - * @return [CSSStyleSheet] - */ - static getCSSStyleSheet() { - return [SaveButtonStyleSheet, BadgeStyleSheet]; - } + /** + * This method is called by the `instanceof` operator. + * @returns {symbol} + */ + static get [instanceSymbol]() { + return Symbol.for( + "@schukai/monster/components/datasource/save-button@@instance", + ); + } + + /** + * To set the options via the html tag the attribute `data-monster-options` must be used. + * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control} + * + * The individual configuration values can be found in the table. + * + * @property {Object} templates Template definitions + * @property {string} templates.main Main template + * @property {object} datasource The datasource + * @property {string} datasource.selector The selector of the datasource + * @property {string} labels.button The button label + * @property {Object} classes The classes + * @property {string} classes.bar The bar class + * @property {string} classes.badge The badge class + * @property {Array} ignoreChanges The ignore changes (regex) + * @property {Array} data The data + * @return {Object} + */ + get defaults() { + const obj = Object.assign({}, super.defaults, { + templates: { + main: getTemplate(), + }, + + labels: { + button: "save", + }, + + classes: { + bar: "monster-button-primary", + badge: "monster-badge-secondary hidden", + }, + + datasource: { + selector: null, + }, + + changes: "0", + + ignoreChanges: [], + + data: {}, + + disabled: false, + }); + + updateOptionsFromArguments.call(this, obj); + return obj; + } + + /** + * + * @return {string} + */ + static getTag() { + return "monster-datasource-save-button"; + } + + /** + * This method is responsible for assembling the component. + * + * It calls the parent's assemble method first, then initializes control references and event handlers. + * If the `datasource.selector` option is provided and is a string, it searches for the corresponding + * element in the DOM using that selector. + * + * If the selector matches exactly one element, it checks if the element is an instance of the `Datasource` class. + * + * If it is, the component's `datasourceLinkedElementSymbol` property is set to the element, and the component + * attaches an observer to the datasource's changes. + * + * The observer is a function that calls the `handleDataSourceChanges` method in the context of the component. + * Additionally, the component attaches an observer to itself, which also calls the `handleDataSourceChanges` + * method in the component's context. + */ + [assembleMethodSymbol]() { + super[assembleMethodSymbol](); + const self = this; + + initControlReferences.call(this); + initEventHandler.call(this); + + const selector = this.getOption("datasource.selector"); + + if (isString(selector)) { + const element = findElementWithSelectorUpwards(this, selector); + if (element === null) { + throw new Error("the selector must match exactly one element"); + } + + if (!(element instanceof Datasource)) { + throw new TypeError("the element must be a datasource"); + } + + this[datasourceLinkedElementSymbol] = element; + element.datasource.attachObserver( + new Observer(handleDataSourceChanges.bind(this)), + ); + + self[originValuesSymbol] = null; + + element.datasource.attachObserver( + new Observer(function () { + if (!self[originValuesSymbol]) { + self[originValuesSymbol] = clone( + self[datasourceLinkedElementSymbol].data, + ); + } + + const currentValues = this.getRealSubject(); + const ignoreChanges = self.getOption("ignoreChanges"); + + const result = diff(self[originValuesSymbol], currentValues); + if (isArray(ignoreChanges) && ignoreChanges.length > 0) { + const itemsToRemove = []; + for (const item of result) { + for (const ignorePattern of ignoreChanges) { + const p = new RegExp(ignorePattern); + if (p.test(item.path)) { + itemsToRemove.push(item); + break; + } + } + } + + for (const itemToRemove of itemsToRemove) { + const index = result.indexOf(itemToRemove); + if (index > -1) { + result.splice(index, 1); + } + } + } + + if (isArray(result) && result.length > 0) { + self[stateButtonElementSymbol].setState("changed"); + self[stateButtonElementSymbol].setOption("disabled", false); + self.setOption("changes", result.length); + self.setOption( + "classes.badge", + new TokenList(self.getOption("classes.badge")) + .remove("hidden") + .toString(), + ); + } else { + self[stateButtonElementSymbol].removeState(); + self[stateButtonElementSymbol].setOption("disabled", true); + self.setOption("changes", 0); + self.setOption( + "classes.badge", + new TokenList(self.getOption("classes.badge")) + .add("hidden") + .toString(), + ); + } + }), + ); + } + + this.attachObserver( + new Observer(() => { + handleDataSourceChanges.call(this); + }), + ); + } + + /** + * + * @return [CSSStyleSheet] + */ + static getCSSStyleSheet() { + return [SaveButtonStyleSheet, BadgeStyleSheet]; + } } /** @@ -245,78 +247,78 @@ class SaveButton extends CustomElement { * @return {Monster.Components.Datatable.Form} */ function initControlReferences() { - if (!this.shadowRoot) { - throw new Error("no shadow-root is defined"); - } - - this[stateButtonElementSymbol] = this.shadowRoot.querySelector( - "[data-monster-role=state-button]", - ); - - this[badgeElementSymbol] = this.shadowRoot.querySelector( - "[data-monster-role=badge]", - ); - - if (this[stateButtonElementSymbol]) { - setTimeout(() => { - const states = { - changed: new State( - "changed", - '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-cloud-arrow-up" viewBox="0 0 16 16">\n' + - ' <path fill-rule="evenodd" d="M7.646 5.146a.5.5 0 0 1 .708 0l2 2a.5.5 0 0 1-.708.708L8.5 6.707V10.5a.5.5 0 0 1-1 0V6.707L6.354 7.854a.5.5 0 1 1-.708-.708z"/>\n' + - ' <path d="M4.406 3.342A5.53 5.53 0 0 1 8 2c2.69 0 4.923 2 5.166 4.579C14.758 6.804 16 8.137 16 9.773 16 11.569 14.502 13 12.687 13H3.781C1.708 13 0 11.366 0 9.318c0-1.763 1.266-3.223 2.942-3.593.143-.863.698-1.723 1.464-2.383m.653.757c-.757.653-1.153 1.44-1.153 2.056v.448l-.445.049C2.064 6.805 1 7.952 1 9.318 1 10.785 2.23 12 3.781 12h8.906C13.98 12 15 10.988 15 9.773c0-1.216-1.02-2.228-2.313-2.228h-.5v-.5C12.188 4.825 10.328 3 8 3a4.53 4.53 0 0 0-2.941 1.1z"/>\n' + - "</svg>", - ), - }; - - this[stateButtonElementSymbol].removeState(); - this[stateButtonElementSymbol].setOption("disabled", "disabled"); - this[stateButtonElementSymbol].setOption("states", states); - this[stateButtonElementSymbol].setOption( - "labels.button", - this.getOption("labels.button"), - ); - }, 1); - } - - return this; + if (!this.shadowRoot) { + throw new Error("no shadow-root is defined"); + } + + this[stateButtonElementSymbol] = this.shadowRoot.querySelector( + "[data-monster-role=state-button]", + ); + + this[badgeElementSymbol] = this.shadowRoot.querySelector( + "[data-monster-role=badge]", + ); + + if (this[stateButtonElementSymbol]) { + setTimeout(() => { + const states = { + changed: new State( + "changed", + '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-cloud-arrow-up" viewBox="0 0 16 16">\n' + + ' <path fill-rule="evenodd" d="M7.646 5.146a.5.5 0 0 1 .708 0l2 2a.5.5 0 0 1-.708.708L8.5 6.707V10.5a.5.5 0 0 1-1 0V6.707L6.354 7.854a.5.5 0 1 1-.708-.708z"/>\n' + + ' <path d="M4.406 3.342A5.53 5.53 0 0 1 8 2c2.69 0 4.923 2 5.166 4.579C14.758 6.804 16 8.137 16 9.773 16 11.569 14.502 13 12.687 13H3.781C1.708 13 0 11.366 0 9.318c0-1.763 1.266-3.223 2.942-3.593.143-.863.698-1.723 1.464-2.383m.653.757c-.757.653-1.153 1.44-1.153 2.056v.448l-.445.049C2.064 6.805 1 7.952 1 9.318 1 10.785 2.23 12 3.781 12h8.906C13.98 12 15 10.988 15 9.773c0-1.216-1.02-2.228-2.313-2.228h-.5v-.5C12.188 4.825 10.328 3 8 3a4.53 4.53 0 0 0-2.941 1.1z"/>\n' + + "</svg>", + ), + }; + + this[stateButtonElementSymbol].removeState(); + this[stateButtonElementSymbol].setOption("disabled", "disabled"); + this[stateButtonElementSymbol].setOption("states", states); + this[stateButtonElementSymbol].setOption( + "labels.button", + this.getOption("labels.button"), + ); + }, 1); + } + + return this; } /** * @private */ function initEventHandler() { - setTimeout(() => { - this[stateButtonElementSymbol].setOption("actions.click", () => { - this[datasourceLinkedElementSymbol] - .write() - .then(() => { - this[originValuesSymbol] = null; - this[stateButtonElementSymbol].removeState(); - this[stateButtonElementSymbol].setOption("disabled", true); - this.setOption("changes", 0); - this.setOption( - "classes.badge", - new TokenList(this.getOption("classes.badge")) - .add("hidden") - .toString(), - ); - }) - .catch((error) => { - addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, error.toString()); - }); - }); - }, 1); + setTimeout(() => { + this[stateButtonElementSymbol].setOption("actions.click", () => { + this[datasourceLinkedElementSymbol] + .write() + .then(() => { + this[originValuesSymbol] = null; + this[stateButtonElementSymbol].removeState(); + this[stateButtonElementSymbol].setOption("disabled", true); + this.setOption("changes", 0); + this.setOption( + "classes.badge", + new TokenList(this.getOption("classes.badge")) + .add("hidden") + .toString(), + ); + }) + .catch((error) => { + addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, error.toString()); + }); + }); + }, 1); } /** * @param {Object} options */ function updateOptionsFromArguments(options) { - const selector = this.getAttribute(ATTRIBUTE_DATASOURCE_SELECTOR); - if (selector) { - options.datasource.selector = selector; - } + const selector = this.getAttribute(ATTRIBUTE_DATASOURCE_SELECTOR); + if (selector) { + options.datasource.selector = selector; + } } /** @@ -324,8 +326,8 @@ function updateOptionsFromArguments(options) { * @return {string} */ function getTemplate() { - // language=HTML - return ` + // language=HTML + return ` <div data-monster-role="control" part="control" data-monster-attributes="disabled path:disabled | if:true"> <monster-state-button data-monster-role="state-button">save</monster-state-button> diff --git a/source/components/form/button.mjs b/source/components/form/button.mjs index 887244577..c7626242b 100644 --- a/source/components/form/button.mjs +++ b/source/components/form/button.mjs @@ -51,7 +51,6 @@ export const buttonElementSymbol = Symbol("buttonElement"); * @copyright schukai GmbH * @summary A beautiful button that can make your life easier and also looks good. * @fires monster-button-clicked this event is triggered when the button is clicked. It contains the field {button} with the button instance. - * */ class Button extends CustomControl { /** diff --git a/source/components/form/select.mjs b/source/components/form/select.mjs index 44ae5a2d4..b109d8da8 100644 --- a/source/components/form/select.mjs +++ b/source/components/form/select.mjs @@ -32,7 +32,6 @@ import { assembleMethodSymbol, getSlottedElements, registerCustomElement, - updaterTransformerMethodsSymbol, } from "../../dom/customelement.mjs"; import { findTargetElementFromEvent, @@ -84,120 +83,120 @@ const clickToLoadOptionsMessage = "Click to load options."; /** * @private - * @type {symbol} + * @type {Symbol} */ const timerCallbackSymbol = Symbol("timerCallback"); /** * @private - * @type {symbol} + * @type {Symbol} */ const keyFilterEventSymbol = Symbol("keyFilterEvent"); /** * @private - * @type {symbol} + * @type {Symbol} */ const lazyLoadDoneSymbol = Symbol("lazyLoadDone"); /** * @private - * @type {symbol} + * @type {Symbol} */ const isLoadingSymbol = Symbol("isLoading"); /** * local symbol * @private - * @type {symbol} + * @type {Symbol} */ const closeEventHandler = Symbol("closeEventHandler"); /** * local symbol * @private - * @type {symbol} + * @type {Symbol} */ const clearOptionEventHandler = Symbol("clearOptionEventHandler"); /** * local symbol * @private - * @type {symbol} + * @type {Symbol} */ const resizeObserverSymbol = Symbol("resizeObserver"); /** * local symbol * @private - * @type {symbol} + * @type {Symbol} */ const keyEventHandler = Symbol("keyEventHandler"); /** * local symbol * @private - * @type {symbol} + * @type {Symbol} */ const lastFetchedDataSymbol = Symbol("lastFetchedData"); /** * local symbol * @private - * @type {symbol} + * @type {Symbol} */ const inputEventHandler = Symbol("inputEventHandler"); /** * local symbol * @private - * @type {symbol} + * @type {Symbol} */ const changeEventHandler = Symbol("changeEventHandler"); /** * local symbol * @private - * @type {symbol} + * @type {Symbol} */ const controlElementSymbol = Symbol("controlElement"); /** * local symbol * @private - * @type {symbol} + * @type {Symbol} */ const selectionElementSymbol = Symbol("selectionElement"); /** * local symbol * @private - * @type {symbol} + * @type {Symbol} */ const containerElementSymbol = Symbol("containerElement"); /** * local symbol * @private - * @type {symbol} + * @type {Symbol} */ const popperElementSymbol = Symbol("popperElement"); /** * local symbol * @private - * @type {symbol} + * @type {Symbol} */ const inlineFilterElementSymbol = Symbol("inlineFilterElement"); /** * local symbol * @private - * @type {symbol} + * @type {Symbol} */ const popperFilterElementSymbol = Symbol("popperFilterElement"); /** * local symbol * @private - * @type {symbol} + * @type {Symbol} */ const popperFilterContainerElementSymbol = Symbol( "popperFilterContainerElement", @@ -206,27 +205,27 @@ const popperFilterContainerElementSymbol = Symbol( /** * local symbol * @private - * @type {symbol} + * @type {Symbol} */ const optionsElementSymbol = Symbol("optionsElement"); /** * local symbol * @private - * @type {symbol} + * @type {Symbol} */ const noOptionsAvailableElementSymbol = Symbol("noOptionsAvailableElement"); /** * local symbol * @private - * @type {symbol} + * @type {Symbol} */ const statusOrRemoveBadgesElementSymbol = Symbol("statusOrRemoveBadgesElement"); /** * @private - * @type {symbol} + * @type {Symbol} */ const areOptionsAvailableAndInitSymbol = Symbol("@@areOptionsAvailableAndInit"); @@ -271,69 +270,20 @@ const FILTER_POSITION_POPPER = "popper"; const FILTER_POSITION_INLINE = "inline"; /** - * @typedef {Object} Selection - * @property {*} value - * @property {String} label - * @memberOf Monster.Components.Form - * @since 1.2.0 - */ - -/** - * This CustomControl creates a select element with a variety of options. - * It supports filtering, local and remote, multiple selection and has a - * template system for displaying the options. - * - * <img src="./images/select.png"> + * A select control that can be used to select one or more options from a list. * - * Dependencies: the system uses functions of the [monsterjs](https://monsterjs.org/) library - * as well as [pooperjs](https://popper.js.org/docs/v2/). + * @fragments /fragments/components/form/select/ * - * You can create this control either by specifying the HTML tag `<monster-select />` directly in the HTML or using - * Javascript via the `document.createElement('monster-select');` method. - * - * ```html - * <monster-select></monster-select> - * ``` - * - * Or you can create this CustomControl directly in Javascript: - * - * ```js - * import {Select} from '@schukai/component-form/source/select.js'; - * document.createElement('monster-select'); - * ``` - * - * ## Events - * - * The event `monster-change` is sent as soon as someone has clicked on a input control. - * `monster-changed` is sent as soon as the control has processed this input. - * The `monster-changed` event is sent when setting a selection. If the options have been set, the `monster-options-set` event is sent. - * - * The CustomEvent has the property [`detail`](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/detail). - * - * ``` - * node.addEventListener('monster-change',(e)=>console.log(e.detail)) - * node.addEventListener('monster-changed',(e)=>console.log(e.detail)) - * node.addEventListener('monster-selected',(e)=>console.log(e.detail)) - * node.addEventListener('monster-options-set',(e)=>console.log(e.detail)) - * ``` - * - * @externalExample ../../../example/components/form/select.mjs - * @startuml select.png - * skinparam monochrome true - * skinparam shadowing false - * HTMLElement <|-- CustomElement - * CustomElement <|-- CustomControl - * CustomControl <|-- Select - * @enduml + * @example /examples/components/form/select-simple + * @example /examples/components/form/select-with-options * * @since 1.0.0 * @copyright schukai GmbH - * @memberOf Monster.Components.Form - * @summary A highly configurable select control - * @fires Monster.Components.Form.event:monster-options-set - * @fires Monster.Components.Form.event:monster-selected - * @fires Monster.Components.Form.event:monster-change - * @fires Monster.Components.Form.event:monster-changed + * @summary A beautiful select control that can make your life easier and also looks good. + * @fires monster-options-set + * @fires monster-selected + * @fires monster-change + * @fires monster-changed */ class Select extends CustomControl { /** @@ -346,7 +296,7 @@ class Select extends CustomControl { /** * This method is called by the `instanceof` operator. - * @returns {symbol} + * @returns {Symbol} * @since 2.1.0 */ static get [instanceSymbol]() { @@ -540,7 +490,7 @@ class Select extends CustomControl { } /** - * @return {Monster.Components.Form.Select} + * @return {Select} */ [assembleMethodSymbol]() { const self = this; diff --git a/source/components/tree-menu/tree-menu.mjs b/source/components/tree-menu/tree-menu.mjs index 914c32f7d..6b91af5d6 100644 --- a/source/components/tree-menu/tree-menu.mjs +++ b/source/components/tree-menu/tree-menu.mjs @@ -431,7 +431,7 @@ function initEventHandler() { } return this; -} +} /** * @private @@ -469,6 +469,7 @@ function importEntries() { }); } catch (error) { addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, String(error)); + return this; } const options = []; @@ -500,7 +501,6 @@ function importEntries() { } this.setOption("entries", options); - return this; } diff --git a/source/data/buildtree.mjs b/source/data/buildtree.mjs index ae67c1326..c88d2d590 100644 --- a/source/data/buildtree.mjs +++ b/source/data/buildtree.mjs @@ -12,13 +12,14 @@ * SPDX-License-Identifier: AGPL-3.0 */ -import { isArray, isObject } from "../types/is.mjs"; -import { Node } from "../types/node.mjs"; -import { NodeList } from "../types/nodelist.mjs"; -import { assembleParts } from "./buildmap.mjs"; -import { extend } from "./extend.mjs"; +import {isArray, isObject} from "../types/is.mjs"; +import {Node} from "../types/node.mjs"; +import {NodeList} from "../types/nodelist.mjs"; +import {clone} from "../util/clone.mjs"; +import {assembleParts} from "./buildmap.mjs"; +import {extend} from "./extend.mjs"; -export { buildTree }; +export {buildTree}; /** * @private @@ -139,63 +140,69 @@ const rootSymbol = Symbol("root"); * @since 1.26.0 */ function buildTree(subject, selector, idKey, parentIDKey, options) { - const nodes = new Map(); - - if (!isObject(options)) { - options = {}; - } - - options = extend( - {}, - { - rootReferences: [null, undefined], - filter: undefined, - }, - options, - ); - - const filter = options?.filter; - let rootReferences = options.rootReferences; - if (!isArray(rootReferences)) { - rootReferences = [rootReferences]; - } - - const childMap = assembleParts(subject, selector, filter, function (o, k, m) { - const key = o?.[idKey]; - let ref = o?.[parentIDKey]; - if (rootReferences.indexOf(ref) !== -1) ref = rootSymbol; - - if (key === undefined) { - throw new Error("the object has no value for the specified id"); - } - - o[parentSymbol] = ref; - - const node = new Node(o); - this.has(ref) - ? this.get(ref).add(node) - : this.set(ref, new NodeList().add(node)); - nodes.set(key, node); - }); - - nodes.forEach((node) => { + const nodes = new Map(); + + const maxDepth = 100; + + if (!isObject(options)) { + options = {}; + } + + options = extend( + {}, + { + rootReferences: [null, undefined], + filter: undefined, + }, + options, + ); + + const filter = options?.filter; + let rootReferences = options.rootReferences; + if (!isArray(rootReferences)) { + rootReferences = [rootReferences]; + } + + const childMap = assembleParts(subject, selector, filter, function (o, k, m) { + const key = o?.[idKey]; + let ref = o?.[parentIDKey]; + if (rootReferences.indexOf(ref) !== -1) ref = rootSymbol; + + if (key === undefined) { + throw new Error("the object has no value for the specified id"); + } + + o[parentSymbol] = ref; + + const node = new Node(o); + this.has(ref) + ? this.get(ref).add(node) + : this.set(ref, new NodeList().add(node)); + nodes.set(key, node); + }); + + nodes.forEach((node) => { const id = node?.["value"]?.[idKey]; + if (id === undefined) { + throw new Error("the object has no value for the specified id"); + } + if (childMap.has(id)) { - node.childNodes = childMap.get(id); - childMap.delete(id); + node.childNodes = childMap.get(id); + childMap.delete(id); } }); - const list = new NodeList(); + const list = new NodeList(); - childMap.forEach((s) => { - if (s instanceof Set) { - s.forEach((n) => { - list.add(n); - }); - } - }); + childMap.forEach((s) => { + if (s instanceof Set) { + s.forEach((n) => { + list.add(n); + }); + } + }); - return list; + return list; } diff --git a/source/types/node.mjs b/source/types/node.mjs index e7265ecab..216035bbd 100644 --- a/source/types/node.mjs +++ b/source/types/node.mjs @@ -12,13 +12,13 @@ * SPDX-License-Identifier: AGPL-3.0 */ -import { Base } from "./base.mjs"; -import { isPrimitive } from "./is.mjs"; -import { NodeList } from "./nodelist.mjs"; -import { validateInstance } from "./validate.mjs"; -import { instanceSymbol } from "../constants.mjs"; +import {Base} from "./base.mjs"; +import {isPrimitive} from "./is.mjs"; +import {NodeList} from "./nodelist.mjs"; +import {validateInstance} from "./validate.mjs"; +import {instanceSymbol} from "../constants.mjs"; -export { Node }; +export {Node}; /** * @private @@ -43,120 +43,120 @@ const treeStructureSymbol = Symbol("treeStructure"); * @see https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Iteration_protocols */ class Node extends Base { - /** - * @param {*} [value] - */ - constructor(value) { - super(); - this[internalValueSymbol] = value; - - this[treeStructureSymbol] = { - parent: null, - childNodes: new NodeList(), - level: 0, - }; - } - - /** - * This method is called by the `instanceof` operator. - * @returns {symbol} - * @since 2.1.0 - */ - static get [instanceSymbol]() { - return Symbol.for("@schukai/monster/types/node"); - } - - /** - * @property {*} - */ - get value() { - return this[internalValueSymbol]; - } - - /** - * @property {*} - */ - set value(value) { - this[internalValueSymbol] = value; - } - - /** - * @property {Monster.Types.Node|null} - */ - get parent() { - return this[treeStructureSymbol].parent; - } - - /** - * @property {integer} - */ - get level() { - return this[treeStructureSymbol].level; - } - - /** - * - * @property {NodeList} - */ - get childNodes() { - return this[treeStructureSymbol].childNodes; - } - - /** - * - * @property {NodeList} - */ - set childNodes(childNodes) { - this[treeStructureSymbol].childNodes = validateInstance( - childNodes, - NodeList, - ); - setChildLevelAndParent.call(this, this, 1); - } - - /** - * @return {Monster.Types.Node} - * @param {Node} node - */ - appendChild(node) { - this[treeStructureSymbol].childNodes.add(validateInstance(node, Node)); - node[treeStructureSymbol].parent = this; - - node[treeStructureSymbol].level = this.level + 1; - setChildLevelAndParent.call(this, node, 1); - return this; - } - - /** - * @return {Monster.Types.Node} - * @param {Node} node - */ - removeChild(node) { - this[treeStructureSymbol].childNodes.remove(validateInstance(node, Node)); - node[treeStructureSymbol].parent = null; - - node[treeStructureSymbol].level = 0; - setChildLevelAndParent.call(this, node, -1); - return this; - } - - /** - * - * @return {boolean} - */ - hasChildNodes() { - return this[treeStructureSymbol].childNodes.length > 0; - } - - /** - * @return {Monster.Types.Node} - * @param {Node} node - */ - hasChild(node) { - return this[treeStructureSymbol].childNodes.has( - validateInstance(node, Node), - ); - } + /** + * @param {*} [value] + */ + constructor(value) { + super(); + this[internalValueSymbol] = value; + + this[treeStructureSymbol] = { + parent: null, + childNodes: new NodeList(), + level: 0, + }; + } + + /** + * This method is called by the `instanceof` operator. + * @returns {symbol} + * @since 2.1.0 + */ + static get [instanceSymbol]() { + return Symbol.for("@schukai/monster/types/node"); + } + + /** + * @property {*} + */ + get value() { + return this[internalValueSymbol]; + } + + /** + * @property {*} + */ + set value(value) { + this[internalValueSymbol] = value; + } + + /** + * @property {Monster.Types.Node|null} + */ + get parent() { + return this[treeStructureSymbol].parent; + } + + /** + * @property {integer} + */ + get level() { + return this[treeStructureSymbol].level; + } + + /** + * + * @property {NodeList} + */ + get childNodes() { + return this[treeStructureSymbol].childNodes; + } + + /** + * + * @property {NodeList} + */ + set childNodes(childNodes) { + this[treeStructureSymbol].childNodes = validateInstance( + childNodes, + NodeList, + ); + setChildLevelAndParent.call(this, this, 1, new Set()); + } + + /** + * @return {Monster.Types.Node} + * @param {Node} node + */ + appendChild(node) { + this[treeStructureSymbol].childNodes.add(validateInstance(node, Node)); + node[treeStructureSymbol].parent = this; + + node[treeStructureSymbol].level = this.level + 1; + setChildLevelAndParent.call(this, node, 1, new Set()); + return this; + } + + /** + * @return {Monster.Types.Node} + * @param {Node} node + */ + removeChild(node) { + this[treeStructureSymbol].childNodes.remove(validateInstance(node, Node)); + node[treeStructureSymbol].parent = null; + + node[treeStructureSymbol].level = 0; + setChildLevelAndParent.call(this, node, -1, new Set()); + return this; + } + + /** + * + * @return {boolean} + */ + hasChildNodes() { + return this[treeStructureSymbol].childNodes.length > 0; + } + + /** + * @return {Monster.Types.Node} + * @param {Node} node + */ + hasChild(node) { + return this[treeStructureSymbol].childNodes.has( + validateInstance(node, Node), + ); + } /** * @since 1.28.0 @@ -192,24 +192,34 @@ class Node extends Base { } } + /** * @private * @param {Node} node * @param {int} operand + * @param {Set} visitedNodes * @return {setChildLevelAndParent} */ -function setChildLevelAndParent(node, operand) { - const self = this; - - if (node !== this) { - node[treeStructureSymbol].parent = this; - } - - node[treeStructureSymbol].childNodes.forEach(function (child) { - child[treeStructureSymbol].parent = node; - child[treeStructureSymbol].level = - node[treeStructureSymbol].level + operand; - setChildLevelAndParent.call(self, child, operand); - }); - return this; +function setChildLevelAndParent(node, operand, visitedNodes) { + const self = this; + + if (visitedNodes.has(node)) { + throw new Error( + "the node has already been visited and cannot be traversed again", + ) + } + + visitedNodes.add(node); + + if (node !== this) { + node[treeStructureSymbol].parent = this; + } + + node[treeStructureSymbol].childNodes.forEach(function (child) { + child[treeStructureSymbol].parent = node; + child[treeStructureSymbol].level = + node[treeStructureSymbol].level + operand; + setChildLevelAndParent.call(self, child, operand, visitedNodes); + }); + return this; } diff --git a/test/cases/data/buildtree.mjs b/test/cases/data/buildtree.mjs index e6ff5aa19..e066daaf0 100644 --- a/test/cases/data/buildtree.mjs +++ b/test/cases/data/buildtree.mjs @@ -7,6 +7,52 @@ import {NodeList} from "../../../source/types/nodelist.mjs"; describe('buildTree', function () { + + describe('legacy navigation example (issue #230)', function () { + + it('should run example', function () { + + const objects = JSON.parse(`{ + "dataset": [ + { + "id": 100001, + "parent_id": 200001, + "title": "eBay", + "url": "/", + "weight": 1, + "css_styles": "", + "css_classes": "" + }, + { + "id": 200001, + "parent_id": 200001, + "title": "alvineconsole", + "url": "", + "weight": 1, + "css_styles": "", + "css_classes": "" + } + ], + "sys": { + "code": 200, + "result": {}, + "api_version": "1" + } +}`); + + try { + buildTree(objects, 'dataset.*', 'id', 'parent_id'); + } catch (error) { + expect(error).to.be.instanceOf(Error); + } + + + + + }) + }) + + describe('example', function () { it('should run example', function () { @@ -207,6 +253,9 @@ describe('buildTree', function () { }); + + + }); diff --git a/test/cases/dom/resource/data.mjs b/test/cases/dom/resource/data.mjs index 1d11b3066..a54286b06 100644 --- a/test/cases/dom/resource/data.mjs +++ b/test/cases/dom/resource/data.mjs @@ -76,7 +76,7 @@ describe('Data', function () { describe('External Data', () => { let id = new ID('data').toString(); - let server, data, url = 'https://monsterjs.org/assets/empty.js?' + id; + let server, data, url = 'data:text/javascript;base64,SGVsbG8sIFdvcmxkIQo='; beforeEach(() => { diff --git a/test/cases/dom/resource/link.mjs b/test/cases/dom/resource/link.mjs index 781a44b51..c7790a5ce 100644 --- a/test/cases/dom/resource/link.mjs +++ b/test/cases/dom/resource/link.mjs @@ -51,7 +51,7 @@ describe('Link', function () { this.timeout(5000); let id = new ID('link').toString(); - let link, url = 'https://monsterjs.org/assets/empty.css?' + id; + let link, url = 'data:text/css;base64,SGVsbG8sIFdvcmxkIQo='; beforeEach(() => { diff --git a/test/cases/dom/resource/link/stylesheet.mjs b/test/cases/dom/resource/link/stylesheet.mjs index 9499b93f8..95c699744 100644 --- a/test/cases/dom/resource/link/stylesheet.mjs +++ b/test/cases/dom/resource/link/stylesheet.mjs @@ -54,7 +54,7 @@ describe('Stylesheet', function () { describe('External Stylesheet', () => { let id = new ID('Stylesheet').toString(); - let stylesheet, url = 'https://monsterjs.org/assets/empty.css?' + id; + let stylesheet, url = 'data:text/css;base64,SGVsbG8sIFdvcmxkIQo='; beforeEach(() => { diff --git a/test/cases/dom/resource/script.mjs b/test/cases/dom/resource/script.mjs index 4ca53e800..a5b8332f7 100644 --- a/test/cases/dom/resource/script.mjs +++ b/test/cases/dom/resource/script.mjs @@ -60,7 +60,7 @@ describe('Script', function () { describe('External JS', () => { let id = new ID('script').toString(); - let server, script, url = 'https://monsterjs.org/assets/empty.js?' + id; + let server, script, url = 'data:text/javascript;base64,SGVsbG8sIFdvcmxkIQo='; beforeEach(() => { -- GitLab