• Welcome to WebsiteBaker Community Forum. Please log in or sign up.
Welcome, Guest
News
Support WebsiteBaker
Your donations will help to:
PayPal
  • Pay for our dedicated server
  • Pay for domain registration
  • and much more!
You can donate by clicking on the button below.

2.14

Started by crnogorac081, September 07, 2026, 12:11:21 PM  ( Read 622 times )

crnogorac081

I see 2.14 preview link https://websitebaker.org/en/home/Preview-214/ , its a refreshing! I hope things with Uwe are sorted 😁
    Web developer

    hgs

    Ja, die WebsiteBaker Welt dreht sich weiter.
    Schön dass dir die Vorschau auf die nächste Version von WebsiteBaker 2.14 gefällt.
    Wir freuen uns auch auf konstruktives Feedback, da wir ja erst am Anfang sind.

    deepl.com
    Yes, the WebsiteBaker world keeps turning.
    We're glad you like the preview of the next version of WebsiteBaker 2.14.
    We're also looking forward to receiving constructive feedback, as we're only just getting started.
      LG Harald

      "Fange nie an, aufzuhören - höre nie auf, anzufangen." Marcus Tullius Cicero (106-43 v.Chr.)

      "Never begin to stop - never stop beginning." Marcus Tullius Cicero (106-43 BC)

      crnogorac081

      Maybe its time to make Main menu multilevel. The idea is to have Addons/Modules, Templates,Languages and Admin Tools/tools list. It looks like this



      Here is how I did it, in /framework I created Backend folder and inside there is php class file BackendAdmin.php:

      ...


      /** @var Array Stores the Main Menu items */
      /* required: 1- show in menu, 0-hide in menu */
      public $aMainMenu = [

      [
      'id' => 1,
      'parent_id' => 0,
      'name'=> 'START',
      'url'=> 'start/index.php',
      'required'=> 0,
      'type'=> 'menu',
      'permission'=> 'start',
      'icon' => '<i class="bi bi-clipboard-pulse"></i>'
      ],
      [
      'id' => 2,
      'parent_id' => 0,
      'name'=> 'PAGES',
      'url'=> 'pages/index.php',
      'required'=> 1,
      'type'=> 'menu',
      'permission'=> 'pages',
      'icon' => '<i class="bi bi-window"></i>'
      ],
      [
      'id' => 3,
      'parent_id' => 0,
      'name'=> 'MEDIA',
      'url'=> 'media/index.php',
      'required'=> 1,
      'type'=> 'menu',
      'permission'=> 'media',
      'icon' => '<i class="bi bi-images"></i>'
      ],
      [
      'id' => 4,
      'parent_id' => 0,
      'name'=> 'ADDONS',
      'url'=> 'addons/index.php',
      'required'=> 1,
      'type'=> 'menu',
      'permission'=> 'addons',
      'icon' => '<i class="bi bi-plug"></i>'
      ],
      [
      'id' => 5,
      'parent_id' => 4,
      'name'=> 'MODULES',
      'url'=> 'modules/index.php',
      'required'=> 1,
      'type'=> 'menu',
      'permission'=> 'modules',
      'icon' => '<i class="bi bi-puzzle"></i>'
      ],
      [
      'id' => 6,
      'parent_id' => 4,
      'name'=> 'TEMPLATES',
      'url'=> 'templates/index.php',
      'required'=> 1,
      'type'=> 'menu',
      'permission'=> 'templates',
      'icon' => '<i class="bi bi-brush"></i>'
      ],
      [
      'id' => 7,
      'parent_id' => 4,
      'name'=> 'LANGUAGES',
      'url'=> 'languages/index.php',
      'required'=> 1,
      'type'=> 'menu',
      'permission'=> 'languages',
      'icon' => '<i class="bi bi-translate"></i>'
      ],
      [
      'id' => 8,
      'parent_id' => 0,
      'name'=> 'PREFERENCES',
      'url'=> 'preferences/index.php',
      'required'=> 1,
      'type'=> 'menu',
      'permission'=> 'preferences',
      'icon' => '<i class="bi bi-person-video2"></i>'
      ],
      [
      'id' => 9,
      'parent_id' => 0,
      'name'=> 'SETTINGS',
      'url'=> 'settings/index.php?advanced=0',
      'required'=> 1,
      'type'=> 'menu',
      'permission'=> 'settings',
      'icon' => '<i class="bi bi-gear"></i>'
      ],
      [
      'id' => 10,
      'parent_id' => 0,
      'name'=> 'ADMINTOOLS',
      'url'=> 'admintools/index.php',
      'required'=> 1,
      'type'=> 'menu',
      'permission'=> 'admintools',
      'icon' => '<i class="bi bi-screwdriver"></i>'
      ],
      [
      'id' => 11,
      'parent_id' => 0,
      'name'=> 'ACCESS',
      'url'=> 'access/index.php',
      'required'=> 1,
      'type'=> 'menu',
      'permission'=> 'access',
      'icon' => '<i class="bi bi-key"></i>'
      ],
      [
      'id' => 12,
      'parent_id' => 11,
      'name'=> 'USERS',
      'url'=> 'users/index.php',
      'required'=> 1,
      'type'=> 'menu',
      'permission'=> 'users',
      'icon' => '<i class="bi bi-person"></i>'
      ],
      [
      'id' => 13,
      'parent_id' => 11,
      'name'=> 'GROUPS',
      'url'=> 'groups/index.php',
      'required'=> 1,
      'type'=> 'menu',
      'permission'=> 'groups',
      'icon' => '<i class="bi bi-people"></i>'
      ],
      ];


      ...

      /********************************************************************************************/
      // MainMenu
      /********************************************************************************************/

         public function
      getMainMenuItems():? array
      {
      // First loop menu items and check item has to be removed
      foreach ($this->aMainMenu as $k => $aItem) {
      // No permission
      if( !$this->admin->get_permission($aItem['permission']) ){
      unset($this->aMainMenu[$k]);
      }
      // Not required in menu
      if( !$aItem['required'] ){
      unset($this->aMainMenu[$k]);
      }
      }

      // Add Additional Items From Admintools
      $sSql = 'SELECT * FROM `'.$this->oDb->sTablePrefix.'addons` WHERE `type` = \'module\' AND `function` = \'tool\' order by `name`';
             if( (
      $oRes = $this->oDb->query($sSql)) )
             {
      $iId = 14; // last item from $aMainMenu was 13, so we continue

                 while(!
      is_null($aRow = $oRes->fetchRow(MYSQLI_ASSOC)))
                 {

      if( $this->admin->get_permission($aRow['directory'], 'module' ) )
      {
      if (is_readable($this->oReg->AppPath.'/modules/' .$aRow['directory'].'/tool_icon.png'))
      {
      $sIco = '<img src="'.$this->oReg->AppUrl.'/modules/' .$aRow['directory'].'/tool_icon.png" alt="'.$aRow['name'].'" />';
      } else {
      $sIco = '<i class="bi bi-puzzle"></i>';
      }
      $this->aMainMenu[] =
      [
      'id' => $iId,
      'parent_id' => 10, // Admintool id from $aMainMenu array
      'name'=> $aRow['name'],
      'url'=> 'admintools/tool.php?tool='.$aRow['directory'],
      'required'=> 1,
      'type'=> 'tool',
      'permission'=> $aRow['directory'],
      'icon' => $sIco,
      'description' => $aRow['description']
      ];
      }
      $iId++;
                 }
             }
      return $this->aMainMenu;
      }



         
      // Method to get the parent ID path
      public function getParentPath($aArr, $iSelectedId) {
      $aPath = [];
      $visited = []; // Array to track visited IDs
      $this->findPath($aArr, $iSelectedId, $aPath, $visited);
      return array_reverse($aPath);
      }

      // Recursive helper function to find the path
      private function findPath($aArr, $currentId, &$path, &$visited) {
      // Skip if the current ID has been visited
      if (in_array($currentId, $visited)) {
      return;
      }
      // Add the current ID to the visited list
      $visited[] = $currentId;
      // Ensure the current ID exists in the array
      if (isset($aArr[$currentId])) {
      $currentItem = $aArr[$currentId];
      $path[] = $currentItem['parent_id'];
      // Recursively find the parent path, if the parent_id is not 0
      if ($currentItem['parent_id'] != 0) {
      $this->findPath($aArr, $currentItem['parent_id'], $path, $visited);
      }
      }
      }

      // Make menu nested from flat array
      public function buildTree(array $elements, $parentId = 0, $aOpts=[]):? array
      {
      $in = array_replace(array(
      'id' =>'page_id',
      'parent' =>'parent',
      'children' =>'children'
      ),(array)$aOpts);

      $branch = array();
      foreach ($elements as $element) {
      if ($element[$in['parent']] == $parentId) {
      $children = $this->buildTree($elements, $element[$in['id']], $aOpts);
      if ($children) {
      $element[$in['children']] = $children;
      }
      $branch[] = $element;
      }
      }
      return $branch;
      }



      the twig

      {% macro render_menu(aItems, aLang, parent, aAdditional) %}
      {% import _self as UIMacro %}

         {% if
      parent == 0 %}
      <ul class="navbar-top mx-auto">
         {% else %}
      <ul>
         {% endif %}
       
      {% for item in aItems %}
      <li class="{% if item.children is defined and item.children|length > 0 %}dropdown{% endif %}
      {% if item.id in aAdditional.aParents %} in_tree{% endif %}
      {% if item.id == aAdditional.iCurPageId %} active{% endif %}
      {% if item.id == 10 %} admintools{% endif %}"
      >
      <a href="{{ aAdditional.sAdminUrl ~ item.url }}" title="{% if item.id > 13 %}{{ item.name }}{% else %}{{ aLang['MENU_'~item.name] }}{% endif %}">
      <div class="d-flex overflow-auto---">
      <span class="nav-icon">{{ item.icon|raw }}</span>
      <span>
      <span class="title text-truncate">
      {% if item.id > 13 %}
      {{ item.name }}
      {% else %}
      {{ aLang['MENU_'~item.name] }}
      {% endif %}
      </span>

      </span>
      </div>
      {% if item.children is defined and item.children|length > 0 %}
      <i class="bi bi-chevron-down toggle-dropdown"></i>
      {% endif %}
      </a>
      {% if item.children is defined and item.children|length > 0 %}
      {% set parent = parent + 1 %}
      {{ UIMacro.render_menu(item.children, aLang, parent, aAdditional) }}
      {% endif %}
      </li>
      {% endfor %}
         </
      ul>
      {%
      endmacro %}

      {{ _self.render_menu(aMenu, aLang, iParent, aAdditional, '') }}

      and then call it

      $iCurPageId = 1; //default

      foreach ($aItems as $k => $aItem) {
      if( $oReg->AcpUrl.$aItem['url'] == $sUrl) {
      $iCurPageId = $aItems[$k]['id'];
      }
      }

      $aFields = [
      'id' =>'id',
      'parent' =>'parent_id',
      'children' =>'children'
      ];


      $aMenuTree = $cBackendAdmin->buildTree( $aItems, 0, $aFields );



      $aPageParents = [];

      $aPageParents = $cBackendAdmin->getParentPath($aItems, $iCurPageId);
      // Remove from parent
      $aRemoveFromParents = [0];
      $aRemoveFromParents[] = $iCurPageId;
      $aPageParents = array_diff($aPageParents, $aRemoveFromParents);

      $sMainMenu = '';
      $aAdditional = [
      'sAdminUrl' => $oReg->AcpUrl,
      'iCurPageId' => $iCurPageId,
      'aParents' => $aPageParents,
      ];

      $aPagesOut = [
      'aMenu' => $aMenuTree,
      'aAdditional' => $aAdditional,
      'iParent' => 0,
      'aLang' => $oLang->getLangArray(),
      ];


      then you can create menu vertical or horizontal, using twig, this is just my example.
        Web developer

        hgs

        As you can see on the test website, there is a toggle switch for the vertical or horizontal menu. 
          LG Harald

          "Fange nie an, aufzuhören - höre nie auf, anzufangen." Marcus Tullius Cicero (106-43 v.Chr.)

          "Never begin to stop - never stop beginning." Marcus Tullius Cicero (106-43 BC)

          dbs

          Will have a look at the dropdown. 

            dbs



            We implemented the dropdown menus using WebsiteBaker's existing menu mechanisms and Twig, keeping the solution fully integrated with WB.
            • 1
            • hgs

            crnogorac081

            brilliant  (Y)

            Can you highlignt active menu item ,and  parent in tree , like Droplets (active) , and Admin tools (as his active parent) ?
              Web developer

              dbs


              \n\n