diff --git a/api/js/etemplate/et2_extension_nextmatch_actions.js b/api/js/etemplate/et2_extension_nextmatch_actions.js
index ec81cd6cd1..2096ff908d 100644
--- a/api/js/etemplate/et2_extension_nextmatch_actions.js
+++ b/api/js/etemplate/et2_extension_nextmatch_actions.js
@@ -234,7 +234,7 @@ export function nm_action(_action, _senders, _target, _ids)
 				// Fake a getValue() function
 				var old_value = nextmatch.getValue;
 				var value = nextmatch.getValue();
-				jQuery.extend(value, _action.data, this.activeFilters, {
+				jQuery.extend(value, _action.data, nextmatch.activeFilters, {
 					"selected": idsArr,
 					"select_all": _ids.all,
 					"checkboxes": checkbox_values
@@ -474,7 +474,7 @@ export function nm_open_popup(_action, _selected)
 				dialog_parent.append(dialog);
 			};
 			jQuery('button:visible',popup).each(function(index) {
-				var but = jQuery(this);
+				var but = jQuery(window);
 				if(but.attr("id"))
 				{
 					// Find the associated widget
@@ -485,13 +485,13 @@ export function nm_open_popup(_action, _selected)
 					text: but.text(),
 					id: widget_id,
 					click: button && button.onclick ? function(e) {
-						jQuery(this).dialog("close");
+						jQuery(window).dialog("close");
 						nm_popup_action = action;
 						nm_popup_ids = selected;
 						button.onclick.apply(button, e.currentTarget);
 						close_function();
 					} : function(e) {
-						jQuery(this).dialog("close");
+						jQuery(window).dialog("close");
 						nm_popup_action = null;
 						close_function();
 					}
diff --git a/api/js/etemplate/etemplate2.ts b/api/js/etemplate/etemplate2.ts
index 09f022b743..6f7f878602 100644
--- a/api/js/etemplate/etemplate2.ts
+++ b/api/js/etemplate/etemplate2.ts
@@ -507,9 +507,6 @@ export class etemplate2
 		if (Array.isArray(_data.langRequire)) {
 			promisses.push(egw(currentapp, window).langRequire(window, _data.langRequire));
 		}
-		if (appname) {
-			promisses.push(egw(currentapp, window).includeJS('/'+appname+'/js/app.js', undefined, undefined, egw.webserverUrl));
-		}
 		return Promise.all(promisses).catch((err) => {
 			console.log("et2.load(): error loading lang-files and app.js: "+err.message);
 		}).then(() => {
diff --git a/api/js/framework/fw_ui.js b/api/js/framework/fw_ui.js
index 7f647864b5..a77b3693a2 100644
--- a/api/js/framework/fw_ui.js
+++ b/api/js/framework/fw_ui.js
@@ -17,6 +17,7 @@ import "../../../vendor/bower-asset/jquery/dist/jquery.min.js";
 import "../jquery/jquery.noconflict.js";
 import "../../../vendor/bower-asset/jquery-ui/jquery-ui.js";
 import '../jsapi/egw_inheritance.js';
+import {EGW_KEY_ENTER, EGW_KEY_SPACE} from '../egw_action/egw_action_constants.js';
 
 /**
  * ui siemenu entry class
diff --git a/api/js/jsapi/egw.js b/api/js/jsapi/egw.js
index b236f414a6..74d12beb85 100644
--- a/api/js/jsapi/egw.js
+++ b/api/js/jsapi/egw.js
@@ -78,7 +78,7 @@ window.app = {classes: {}};
 	window.egw_appName = egw_script.getAttribute('data-app');
 
 	// split includes in legacy js and modules
-	const legacy_js_regexp = /do_not_match_anything/;
+	const legacy_js_regexp = /\/dhtmlx/;
 
 	// check if egw object was injected by window open
 	if (typeof window.egw == 'undefined')
diff --git a/api/js/jsapi/egw_json.js b/api/js/jsapi/egw_json.js
index fdbd9ca0ec..a442d2ff96 100644
--- a/api/js/jsapi/egw_json.js
+++ b/api/js/jsapi/egw_json.js
@@ -293,7 +293,8 @@ egw.extend('json', egw.MODULE_WND_LOCAL, function(_app, _wnd)
 			if(js_files.length > 0)
 			{
 				var start_time = (new Date).getTime();
-				this.egw.includeJS(js_files, function() {
+				// for some reason using this.includeJS() does NOT work / app.classes does not get set, before the Promise resolves
+				Promise.all(js_files.map((file) => import(file))).then(() => {
 					var end_time = (new Date).getTime();
 					this.handleResponse(data);
 					if (egw.preference('show_generation_time', 'common', false) == "1")
@@ -304,7 +305,7 @@ egw.extend('json', egw.MODULE_WND_LOCAL, function(_app, _wnd)
 							gen_time_div.append('<span class="asyncIncludeTime"></span>').find('.asyncIncludeTime');
 						gen_time_async.text(egw.lang('async includes took %1s', (end_time-start_time)/1000));
 					}
-				}, this);
+				});
 				return;
 			}
 
diff --git a/api/src/Framework.php b/api/src/Framework.php
index 7d0fa28d02..980de1fd2a 100644
--- a/api/src/Framework.php
+++ b/api/src/Framework.php
@@ -14,6 +14,7 @@
 namespace EGroupware\Api;
 
 use EGroupware\Api\Framework\Bundle;
+use EGroupware\Api\Framework\IncludeMgr;
 use EGroupware\Api\Header\ContentSecurityPolicy;
 
 /**
@@ -1071,21 +1072,29 @@ abstract class Framework extends Framework\Extra
 				'etag' => md5(json_encode($GLOBALS['egw_info']['user']['preferences']['common']).
 					$GLOBALS['egw']->accounts->json($GLOBALS['egw_info']['user']['account_id'])),
 			));
+			// manually load old dhtmlx stuff via script tag
+			self::includeJS('/api/js/dhtmlxtree/codebase/dhtmlxcommon.js');
+			self::includeJS('/api/js/dhtmlxMenu/sources/dhtmlxmenu.js');
+			self::includeJS('/api/js/dhtmlxMenu/sources/ext/dhtmlxmenu_ext.js');
+			self::includeJS('/api/js/dhtmlxtree/sources/dhtmlxtree.js');
+			self::includeJS('/api/js/dhtmlxtree/sources/ext/dhtmlxtree_json.js');
 		}
 
 		$extra['url'] = $GLOBALS['egw_info']['server']['webserver_url'];
 		$map = null;
 		$extra['include'] = array_map(static function($str){
 			return substr($str,1);
-		}, self::get_script_links(true, false, $map), array(1));
+		}, self::get_script_links(true, false, $map));
 		$extra['app'] = $GLOBALS['egw_info']['flags']['currentapp'];
 
 		// Static things we want to make sure are loaded first
 //$java_script .='<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.0.0-beta.44/dist/themes/base.css">
 //<script type="module" src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.0.0-beta.44/dist/shoelace.js"></script>';
-		// load our clientside entrypoint egw.js
+
+		// load our clientside entrypoint egw.min.js with a cache-buster
 		$java_script .= '<script type="module" src="'.$GLOBALS['egw_info']['server']['webserver_url'].
-				'/api/js/jsapi/egw.min.js" id="egw_script_id"';
+			'/api/js/jsapi/egw.min.js?'.filemtime(EGW_SERVER_ROOT.'/api/js/jsapi/egw.min.js').
+			'" id="egw_script_id"';
 
 		// add values of extra parameter and class var as data attributes to script tag of egw.js
 		foreach($extra+self::$extra as $name => $value)
@@ -1460,6 +1469,8 @@ abstract class Framework extends Framework\Extra
 
 	/**
 	 * The include manager manages including js files and their dependencies
+	 *
+	 * @var IncludeMgr
 	 */
 	protected static $js_include_mgr;
 
diff --git a/api/src/Framework/Bundle.php b/api/src/Framework/Bundle.php
index d45555767e..7436310cb0 100644
--- a/api/src/Framework/Bundle.php
+++ b/api/src/Framework/Bundle.php
@@ -79,7 +79,7 @@ class Bundle
 		$query = null;
 		foreach($js_includes as $file)
 		{
-			if ($file == '/api/js/jsapi/egw.js') continue;	// loaded via own tag, and we must not load it twice!
+			if (in_array($file, ['/api/js/jsapi/egw.js','/api/js/jsapi/egw.min.js'])) continue;	// loaded via own tag, and we must not load it twice!
 
 			if (!isset($to_include[$file]))
 			{
@@ -118,8 +118,15 @@ class Bundle
 						$path = $min_path;
 						$mod  = $min_mod;
 					}
-					// skip timestamp $to_include[$file] = $path.'?'.$mod.($query ? '&'.$query : '');
-					$to_include[$file] = $path.($query ? '?'.$query : '');
+					// use cache-buster only for entry-points / app.js, as the have no hash
+					if (preg_match('#/js/app(\.min)?\.js$#', $file))
+					{
+						$to_include[$file] = $path.'?'.$mod.($query ? '&'.$query : '');
+					}
+					else
+					{
+						$to_include[$file] = $path.($query ? '?'.$query : '');
+					}
 				}
 			}
 		}