diff --git a/api/etemplate.php b/api/etemplate.php
index 4d14a87848..9e3dfd4b20 100644
--- a/api/etemplate.php
+++ b/api/etemplate.php
@@ -270,7 +270,7 @@ function send_template()
$str = preg_replace('#]+)(/|> #', ' ', $str);
// fix <(button|buttononly|timestamper).../> -->
- $str = preg_replace_callback('#<(button|buttononly|timestamper|button-timestamp)\s(.*?)(/|>(button|buttononly|timestamper|button-timestamp))>#s', function ($matches) use ($name)
+ $str = preg_replace_callback('#<(button|buttononly|timestamper|button-timestamp|dropdown_button)\s(.*?)(/|>(button|buttononly|timestamper|button-timestamp|dropdown_button))>#s', function ($matches) use ($name)
{
$tag = 'et2-button';
$attrs = parseAttrs($matches[2]);
@@ -284,6 +284,9 @@ function send_template()
$tag .= '-timestamp';
$attrs['background_image'] = 'true';
break;
+ case 'dropdown_button':
+ $tag = 'et2-dropdown-button';
+ break;
}
// novalidation --> noValidation
if (!empty($attrs['novalidation']) && in_array($attrs['novalidation'], ['true', '1'], true))
diff --git a/api/js/etemplate/et2_widget_dropdown_button.ts b/api/js/etemplate/et2_widget_dropdown_button.ts
deleted file mode 100644
index d38a67e271..0000000000
--- a/api/js/etemplate/et2_widget_dropdown_button.ts
+++ /dev/null
@@ -1,439 +0,0 @@
-/**
- * EGroupware eTemplate2 - JS Dropdown Button object
- *
- * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
- * @package etemplate
- * @subpackage api
- * @link https://www.egroupware.org
- * @author Nathan Gray
- * @copyright Nathan Gray 2013
- */
-
-/*egw:uses
- /vendor/bower-asset/jquery/dist/jquery.js;
- et2_baseWidget;
-*/
-
-import {et2_inputWidget} from './et2_core_inputWidget';
-import {WidgetConfig, et2_register_widget} from "./et2_core_widget";
-import {ClassWithAttributes} from "./et2_core_inheritance";
-import {et2_no_init} from "./et2_core_common";
-import {egw} from "../jsapi/egw_global";
-
-/**
- * A split button - a button with a dropdown list
- *
- * There are several parts to the button UI:
- * - Container: This is what is percieved as the dropdown button, the whole package together
- * - Button: The part on the left that can be clicked
- * - Arrow: The button to display the choices
- * - Menu: The list of choices
- *
- * Menu options are passed via the select_options. They are normally ID => Title pairs,
- * as for a select box, but the title can also be full HTML if needed.
- *
- * @augments et2_inputWidget
- */
-export class et2_dropdown_button extends et2_inputWidget
-{
- static readonly attributes : any = {
- "label": {
- "name": "caption",
- "type": "string",
- "description": "Label of the button",
- "translate": true,
- "default": "Select..."
- },
- "label_updates": {
- "name": "Label updates",
- "type": "boolean",
- "description": "Button label updates when an option is selected from the menu",
- "default": true
- },
- "image": {
- "name": "Icon",
- "type": "string",
- "description": "Add an icon"
- },
- "ro_image": {
- "name": "Read-only Icon",
- "type": "string",
- "description": "Use this icon instead of hiding for read-only"
- },
- "onclick": {
- "description": "JS code which gets executed when the button is clicked"
- },
- "select_options": {
- "type": "any",
- "name": "Select options",
- "default": {},
- "description": "Select options for dropdown. Can be a simple key => value list, or value can be full HTML",
- // Skip normal initialization for this one
- "ignore": true
- },
- "accesskey": {
- "name": "Access Key",
- "type": "string",
- "default": et2_no_init,
- "description": "Alt + activates widget"
- },
- "tabindex": {
- "name": "Tab index",
- "type": "integer",
- "default": et2_no_init,
- "description": "Specifies the tab order of a widget when the 'tab' button is used for navigating."
- },
- // No such thing as a required button
- "required": {
- "ignore": true
- }
- };
-
- internal_ids : any = {
- div: "",
- button: "",
- menu: ""
- };
-
- div : JQuery = null;
- buttons : JQuery = null;
- button : JQuery = null;
- arrow : JQuery = null;
- menu : JQuery = null;
- image : JQuery = null;
- clicked : boolean = false;
- label_updates : boolean = true;
- value : any = null;
- /**
- * Default menu, so there is something for the widget browser / editor to show
- */
- readonly default_menu : string = '';
-
- /**
- * Constructor
- *
- * @memberOf et2_dropdown_button
- */
- constructor(_parent?, _attrs? : WidgetConfig, _child? : object) {
- super(_parent, _attrs, ClassWithAttributes.extendAttributes(et2_dropdown_button._attributes, _child || {}));
-
- this.clicked = false;
-
- let self = this;
-
- // Create the individual UI elements
-
- // Menu is a UL
- this.menu = jQuery(this.default_menu).attr("id",this.internal_ids.menu)
- .hide()
- .menu({
- select: function(event,ui) {
- self.onselect.call(self,event,ui.item);
- }
- });
-
- this.buttons = jQuery(document.createElement("div"))
- .addClass("et2_dropdown");
-
- // Main "wrapper" div
- this.div = jQuery(document.createElement("div"))
- .attr("id", this.internal_ids.div)
- .append(this.buttons)
- .append(this.menu);
-
- // Left side - activates click action
- this.button = jQuery(document.createElement("button"))
- .attr("id", this.internal_ids.button)
- .attr("type", "button")
- .addClass("ui-widget ui-corner-left").removeClass("ui-corner-all")
- .appendTo(this.buttons);
-
- // Right side - shows dropdown
- this.arrow = jQuery(document.createElement("button"))
- .addClass("ui-widget ui-corner-right").removeClass("ui-corner-all")
- .attr("type", "button")
- .click(function() {
- // ignore click on readonly button
- if (self.options.readonly) return false;
- // Clicking it again hides menu
- if(self.menu.is(":visible"))
- {
- self.menu.hide();
- return false;
- }
- // Show menu dropdown
- var menu = self.menu.show().position({
- my: "left top",
- at: "left bottom",
- of: self.buttons
- });
- // Hide menu if clicked elsewhere
- jQuery( document ).one( "click", function() {
- menu.hide();
- });
- return false;
- })
- // This is the actual down arrow icon
- .append("
")
- .appendTo(this.buttons);
-
- // Common button UI
- this.buttons.children("button")
- .addClass("ui-state-default")
- .hover(
- function() {jQuery(this).addClass("ui-state-hover");},
- function() {jQuery(this).removeClass("ui-state-hover");}
- );
-
- // Icon
- this.image = jQuery(document.createElement("img"));
-
- this.setDOMNode(this.div[0]);
- }
-
- destroy() {
- // Destroy widget
- if(this.menu && this.menu.data('ui-menu')) this.menu.menu("destroy");
-
- // Null children
- this.image = null;
- this.button = null;
- this.arrow = null;
- this.buttons = null;
- this.menu = null;
-
- // Remove
- this.div.empty().remove();
- }
-
- set_id(_id) {
- super.set_id(_id);
-
- // Update internal IDs - not really needed since we refer by internal
- // javascript reference, but good to keep up to date
- this.internal_ids = {
- div: this.dom_id + "_wrapper",
- button: this.dom_id,
- menu: this.dom_id + "_menu"
- };
- for(let key in this.internal_ids)
- {
- if(this[key] == null) continue;
- this[key].attr("id", this.internal_ids[key]);
- }
- }
-
- /**
- * Set if the button label changes to match the selected option
- *
- * @param updates boolean Turn updating on or off
- */
- set_label_updates(updates)
- {
- this.label_updates = updates;
- }
-
- set_accesskey(key)
- {
- jQuery(this.node).attr("accesskey", key);
- }
-
- set_ro_image(_image)
- {
- if(this.options.readonly)
- {
- this.set_image(_image);
- }
- }
-
- set_image(_image)
- {
- if(!this.isInTree() || this.image == null) return;
- if(!_image.trim())
- {
- this.image.hide();
- }
- else
- {
- this.image.show();
- }
-
- let src = this.egw().image(_image);
- if(src)
- {
- this.image.attr("src", src);
- }
- // allow url's too
- else if (_image[0] == '/' || _image.substr(0,4) == 'http')
- {
- this.image.attr('src', _image);
- }
- else
- {
- this.image.hide();
- }
- }
-
- /**
- * Overwritten to maintain an internal clicked attribute
- *
- * @param _ev
- * @returns {Boolean}
- */
- click(_ev)
- {
- // ignore click on readonly button
- if (this.options.readonly) return false;
-
- this.clicked = true;
-
- if (!super.click(_ev))
- {
- this.clicked = false;
- return false;
- }
- this.clicked = false;
- return true;
- }
-
- onselect(event, selected_node)
- {
- this.set_value(selected_node.attr("data-id"));
- this.change(selected_node);
- }
-
- attachToDOM()
- {
- let res = super.attachToDOM();
-
- // Move the parent's handler to the button, or we can't tell the difference between the clicks
- jQuery(this.node).unbind("click.et2_baseWidget");
- this.button.off().bind("click.et2_baseWidget", this, function(e) {
- return e.data.click.call(e.data, this);
- });
- return res;
- }
-
- set_label(_value)
- {
- if (this.button)
- {
- this.label = _value;
-
- this.button.text(_value)
- .prepend(this.image);
- }
- }
-
- /**
- * Set the options for the dropdown
- *
- * @param options Object ID => Label pairs
- */
- set_select_options(options) {
- this.menu.first().empty();
-
- // Allow more complicated content, if passed
- if(typeof options == "string")
- {
- this.menu.append(options);
- }
- else
- {
- let add_complex = function(node, options)
- {
- for(let key in options)
- {
- let item;
- if(typeof options[key] == "string")
- {
- item = jQuery(""+options[key]+" ");
- }
- else if (options[key]["label"])
- {
- item =jQuery(""+options[key]["label"]+" ");
- }
- // Optgroup
- else
- {
- item = jQuery(""+key+" ");
- add_complex(node.append(""), options[key]);
- }
- node.append(item);
- if(item && options[key].icon)
- {
- // we supply a applicable class for item images
- jQuery('a',item).prepend(' ');
- }
- }
- }
- add_complex(this.menu.first(), options);
- }
- this.menu.menu("refresh");
- }
-
- /**
- * Set tab index
- */
- set_tabindex(index)
- {
- jQuery(this.button).attr("tabindex", index);
- }
-
- set_value(new_value)
- {
- let menu_item = jQuery("[data-id='"+new_value+"']",this.menu);
- if(menu_item.length)
- {
- this.value = new_value;
- if(this.label_updates)
- {
- this.set_label(menu_item.text());
- }
- }
- else
- {
- this.value = null;
- if(this.label_updates)
- {
- this.set_label(this.options.label);
- }
- }
- }
-
- getValue()
- {
- return this.value;
- }
-
- /**
- * Set options.readonly
- *
- * @param {boolean} _ro
- */
- set_readonly(_ro : boolean)
- {
- if (_ro != this.options.readonly)
- {
- this.options.readonly = _ro;
-
- // don't make readonly dropdown buttons clickable
- if (this.buttons)
- {
- this.buttons.find('button')
- .toggleClass('et2_clickable', !_ro)
- .toggleClass('et2_button_ro', _ro)
- .css('cursor', _ro ? 'default' : 'pointer');
- }
- }
- }
-}
-et2_register_widget(et2_dropdown_button, ["dropdown_button"]);
\ No newline at end of file
diff --git a/api/js/etemplate/et2_widget_favorites.ts b/api/js/etemplate/et2_widget_favorites.ts
deleted file mode 100644
index 5f61e3c785..0000000000
--- a/api/js/etemplate/et2_widget_favorites.ts
+++ /dev/null
@@ -1,433 +0,0 @@
-/**
- * EGroupware eTemplate2 - JS Favorite widget
- *
- * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
- * @package etemplate
- * @subpackage api
- * @link https://www.egroupware.org
- * @author Nathan Gray
- * @copyright Nathan Gray 2013
- */
-
-/*egw:uses
- et2_dropdown_button;
- et2_extension_nextmatch;
-*/
-
-import {WidgetConfig} from "./et2_core_widget";
-import {et2_INextmatchHeader} from "./et2_extension_nextmatch";
-import {et2_dropdown_button} from "./et2_widget_dropdown_button";
-import {ClassWithAttributes} from "./et2_core_inheritance";
-import {egw, egw_getFramework} from "../jsapi/egw_global";
-import Sortable from 'sortablejs/modular/sortable.complete.esm.js';
-
-/**
- * Favorites widget, designed for use with a nextmatch widget
- *
- * The primary control is a split/dropdown button. Clicking on the left side of the button filters the
- * nextmatch list by the user's default filter. The right side of the button gives a list of
- * saved filters, pulled from preferences. Clicking a filter from the dropdown list sets the
- * filters as saved.
- *
- * Favorites can also automatically be shown in the sidebox, using the special ID favorite_sidebox.
- * Use the following code to generate the sidebox section:
- * display_sidebox($appname,lang('Favorites'),array(
- * array(
- * 'no_lang' => true,
- * 'text'=>' ',
- * 'link'=>false,
- * 'icon' => false
- * )
- * ));
- * This sidebox list will be automatically generated and kept up to date.
- *
- *
- * Favorites are implemented by saving the values for [column] filters. Filters are stored
- * in preferences, with the name favorite_. The favorite favorite used for clicking on
- * the filter button is stored in nextmatch--favorite.
- *
- * @augments et2_dropdown_button
- */
-export class et2_favorites extends et2_dropdown_button implements et2_INextmatchHeader
-{
- static readonly _attributes : any = {
- "default_pref": {
- "name": "Default preference key",
- "type": "string",
- "description": "The preference key where default favorite is stored (not the value)"
- },
- "sidebox_target": {
- "name": "Sidebox target",
- "type": "string",
- "description": "ID of element to insert favorite list into",
- "default": "favorite_sidebox"
- },
- "app": {
- "name": "Application",
- "type": "string",
- "description": "Application to show favorites for"
- },
- "filters": {
- "name": "Extra filters",
- "type": "any",
- "description": "Array of extra filters to include in the saved favorite"
- },
-
- // These are particular to favorites
- id: {"default": "favorite"},
- label: {"default": ""},
- label_updates: { "default": false},
- image: {"default": egw().image('fav_filter')},
- statustext: {"default": "Favorite queries", "type": "string"}
- };
-
- // Some convenient variables, used in closures / event handlers
- header = null;
- nextmatch = null;
- public static readonly PREFIX = "favorite_";
- private stored_filters: {};
- private favSortedList : any = null;
- private sidebox_target : JQuery = null;
- private preferred;
- static is_admin : boolean;
- private filters : any;
-
- // If filter was set server side, we need to remember it until nm is created
- nm_filter = false;
-
- /**
- * Constructor
- *
- * @memberOf et2_favorites
- */
- constructor(_parent?, _attrs? : WidgetConfig, _child? : object)
- {
- super(_parent, _attrs, ClassWithAttributes.extendAttributes(et2_favorites._attributes, _child || {}));
- this.sidebox_target = jQuery("#"+this.options.sidebox_target);
- if(this.sidebox_target.length == 0 && egw_getFramework() != null)
- {
- let egw_fw = egw_getFramework();
- this.sidebox_target = jQuery("#"+this.options.sidebox_target,egw_fw.sidemenuDiv);
- }
- // Store array of sorted items
- this.favSortedList = ['blank'];
-
- let apps = egw().user('apps');
- et2_favorites.is_admin = (typeof apps['admin'] != "undefined");
-
- // Make sure we have an app
- if(!this.options.app)
- {
- this.options.app = this.getInstanceManager().app;
- }
-
- this.stored_filters = this.load_favorites(this.options.app);
-
- this.preferred = egw.preference(this.options.default_pref,this.options.app);
- if(!this.preferred || typeof this.stored_filters[this.preferred] == "undefined")
- {
- this.preferred = "blank";
- }
-
- // It helps to have the ID properly set before we get too far
- this.set_id(this.id);
-
- this.init_filters(this);
-
- this.menu.addClass("favorites");
-
- // Set the default (button) value
- this.set_value(this.preferred,true);
-
- let self = this;
-
- // Add a listener on the radio buttons to set default filter
- jQuery(this.menu).on("click","input:radio", function(event){
- // Don't do the menu
- event.stopImmediatePropagation();
-
- // Save as default favorite - used when you click the button
- self.egw().set_preference(self.options.app,self.options.default_pref,jQuery(this).val());
- self.preferred = jQuery(this).val();
-
- // Update sidebox, if there
- if(self.sidebox_target.length)
- {
- jQuery("div.ui-icon-heart", self.sidebox_target)
- .replaceWith("
");
- jQuery("li[data-id='"+self.preferred+"'] div.sideboxstar",self.sidebox_target)
- .replaceWith("
");
- }
-
- // Close the menu
- self.menu.hide();
-
- // Some user feedback
- self.button.addClass("ui-state-active", 500,"swing",function(){
- self.button.removeClass("ui-state-active",2000);
- });
- });
-
- //Sort DomNodes of sidebox fav. menu
- let sideBoxDOMNodeSort = function (_favSList) {
- let favS = jQuery.isArray(_favSList)?_favSList.slice(0).reverse():[];
-
- for (let i=0; i < favS.length;i++)
- {
- self.sidebox_target.children().find('[data-id$="' + favS[i] + '"]').prependTo(self.sidebox_target.children());
- }
- };
-
- /**
- * todo (@todo-jquery-ui): the sorting does not work at the moment becuase of jquery-ui menu being used in order to create dropdown
- * buttons menu. Once we replace the et2_widget_dropdown_button with web component this should be adapted
- * and working again.
- **/
- let sortablejs = Sortable.create(this.menu[0], {
- ghostClass: 'ui-fav-sortable-placeholder',
- draggable: 'li:not([data-id$="add"])',
- delay: 25,
- dataIdAttr:'data-id',
- onSort: function(event){
- self.favSortedList = sortablejs.toArray();
- self.egw.set_preference(self.options.app,'fav_sort_pref', self.favSortedList );
- sideBoxDOMNodeSort(self.favSortedList);
- }
- });
-
- // Add a listener on the delete to remove
- this.menu.on("click","div.ui-icon-trash", app[self.options.app], function() {
- // App instance might not be ready yet, so don't bind directly
- app[self.options.app].delete_favorite.apply(this,arguments);
- })
- // Wrap and unwrap because jQueryUI styles use a parent, and we don't want to change the state of the menu item
- // Wrap in a span instead of a div because div gets a border
- .on("mouseenter","div.ui-icon-trash", function() {jQuery(this).wrap(" ");})
- .on("mouseleave","div.ui-icon-trash", function() {jQuery(this).unwrap();});
-
- // Trigger refresh of menu options now that events are registered
- // to update sidebox
- if(this.sidebox_target.length > 0)
- {
- this.init_filters(this);
- }
- }
-
- /**
- * Load favorites from preferences
- *
- * @param app String Load favorites from this application
- */
- load_favorites(app)
- {
-
- // Default blank filter
- let stored_filters : any = {
- 'blank': {
- name: this.egw().lang("No filters"),
- state: {}
- }
- };
-
- // Load saved favorites
- let preferences : any = egw.preference("*",app);
- for(let pref_name in preferences)
- {
- if(pref_name.indexOf(et2_favorites.PREFIX) == 0 && typeof preferences[pref_name] == 'object')
- {
- let name = pref_name.substr(et2_favorites.PREFIX.length);
- stored_filters[name] = preferences[pref_name];
- // Keep older favorites working - they used to store nm filters in 'filters',not state
- if(preferences[pref_name]["filters"])
- {
- stored_filters[pref_name]["state"] = preferences[pref_name]["filters"];
- }
- }
- if (pref_name == 'fav_sort_pref')
- {
- this.favSortedList = preferences[pref_name];
- //Make sure sorted list is always an array, seems some old fav are not array
- if (!jQuery.isArray(this.favSortedList)) this.favSortedList = this.favSortedList.split(',');
- }
- }
- if(typeof stored_filters == "undefined" || !stored_filters)
- {
- stored_filters = {};
- }
- else
- {
- for(let name in stored_filters)
- {
- if (this.favSortedList.indexOf(name) < 0)
- {
- this.favSortedList.push(name);
- }
- }
- this.egw().set_preference (this.options.app,'fav_sort_pref',this.favSortedList);
- if (this.favSortedList.length > 0)
- {
- let sortedListObj = {};
-
- for (let i=0; i < this.favSortedList.length; i++)
- {
- if (typeof stored_filters[this.favSortedList[i]] != 'undefined')
- {
- sortedListObj[this.favSortedList[i]] = stored_filters[this.favSortedList[i]];
- }
- else
- {
- this.favSortedList.splice(i,1);
- this.egw().set_preference (this.options.app,'fav_sort_pref',this.favSortedList);
- }
- }
- stored_filters = jQuery.extend(sortedListObj,stored_filters);
- }
- }
- return stored_filters;
- }
-
- // Create & set filter options for dropdown menu
- init_filters(widget, filters?)
- {
- if(typeof filters == "undefined")
- {
- filters = this.stored_filters;
- }
-
- let options = {};
- for(let name in filters)
- {
- options[name] = " "+
- (filters[name].name != undefined ? filters[name].name : name) +
- (filters[name].group != false && !et2_favorites.is_admin || name == 'blank' ? "" :
- "
");
- }
-
- // Only add 'Add current' if we have a nextmatch
- if(this.nextmatch)
- {
- options["add"] = " "+this.egw().lang('Add current');
- }
- widget.set_select_options.call(widget,options);
-
- // Set radio to current value
- jQuery("input[value='"+ this.preferred +"']:radio", this.menu).attr("checked",1);
- }
-
- set_nm_filters(filters)
- {
- if(this.nextmatch)
- {
- this.nextmatch.applyFilters(filters);
- }
- else
- {
- console.log(filters);
- }
- }
-
- onclick(node)
- {
- // Apply preferred filter - make sure it's an object, and not a reference
- if(this.preferred && this.stored_filters[this.preferred])
- {
- // use app[appname].setState if available to allow app to overwrite it (eg. change to non-listview in calendar)
- if (typeof app[this.options.app] != 'undefined')
- {
- app[this.options.app].setState(this.stored_filters[this.preferred]);
- }
- else
- {
- this.set_nm_filters(jQuery.extend({},this.stored_filters[this.preferred].state));
- }
- }
- else
- {
- alert(this.egw().lang("No default set"));
- }
- }
-
- // Apply the favorite when you pick from the list
- change(selected_node)
- {
- this.value = jQuery(selected_node).attr("data-id");
- if(this.value == "add" && this.nextmatch)
- {
- // Get current filters
- let current_filters = jQuery.extend({},this.nextmatch.activeFilters);
-
- // Add in extras
- for(let extra in this.options.filters)
- {
- // Don't overwrite what nm has, chances are nm has more up-to-date value
- if(typeof current_filters == 'undefined')
- {
- current_filters[extra] = this.nextmatch.options.settings[extra];
- }
- }
-
- // Skip columns for now
- delete current_filters.selcolumns;
-
- // Add in application's settings
- if(this.filters != true)
- {
- for(let i = 0; i < this.filters.length; i++)
- {
- current_filters[this.options.filters[i]] = this.nextmatch.options.settings[this.options.filters[i]];
- }
- }
-
- // Call framework
- app[this.options.app].add_favorite(current_filters);
-
- // Reset value
- this.set_value(this.preferred,true);
- }
- else if (this.value == 'blank')
- {
- // Reset filters when select no filters
- this.set_nm_filters({});
- }
- }
-
- set_value(filter_name, parent? : boolean) : void | boolean
- {
- if(parent)
- {
- return super.set_value(filter_name);
- }
-
- if(filter_name == 'add') return false;
-
- app[this.options.app].setState(this.stored_filters[filter_name]);
- return false;
- }
-
- getValue()
- {
- return null;
- }
-
- /**
- * Set the nextmatch to filter
- * From et2_INextmatchHeader interface
- *
- * @param {et2_nextmatch} nextmatch
- */
- setNextmatch(nextmatch)
- {
- this.nextmatch = nextmatch;
-
- if(this.nm_filter)
- {
- this.set_value(this.nm_filter);
- this.nm_filter = false;
- }
-
- // Re-generate filter list so we can add 'Add current'
- this.init_filters(this);
- }
-}
-
diff --git a/api/js/etemplate/etemplate2.ts b/api/js/etemplate/etemplate2.ts
index 2082e0bea7..3f79328276 100644
--- a/api/js/etemplate/etemplate2.ts
+++ b/api/js/etemplate/etemplate2.ts
@@ -112,9 +112,7 @@ import './et2_widget_radiobox';
import './et2_widget_date';
import './et2_widget_dialog';
import './et2_widget_diff';
-import './et2_widget_dropdown_button';
import './et2_widget_styles';
-import './et2_widget_favorites';
import './et2_widget_html';
import './et2_widget_htmlarea';
import './et2_widget_taglist';
diff --git a/api/js/jsapi/app_base.js b/api/js/jsapi/app_base.js
index cf53a281dd..b411ae8415 100644
--- a/api/js/jsapi/app_base.js
+++ b/api/js/jsapi/app_base.js
@@ -8,19 +8,15 @@
* @author Nathan Gray
*/
-/*egw:uses
- egw_inheritance;
- /api/js/es6-promise.min.js;
-*/
import {EgwApp} from "./egw_app";
import './egw_inheritance.js';
import {etemplate2} from "../etemplate/etemplate2";
import {et2_createWidget} from "../etemplate/et2_core_widget";
import {Et2Dialog} from "../etemplate/Et2Dialog/Et2Dialog";
import {et2_nextmatch} from "../etemplate/et2_extension_nextmatch";
-import {et2_favorites} from "../etemplate/et2_widget_favorites";
import {EGW_KEY_ENTER} from "../egw_action/egw_action_constants";
import "sortablejs/Sortable.min.js";
+import {Et2Favorites} from "../etemplate/Et2Favorites/Et2Favorites";
/**
* Common base class for application javascript
@@ -736,7 +732,7 @@ export const AppJS = (function(){ "use strict"; return Class.extend(
et2[i].widgetContainer.iterateOver(function(_widget) {
_widget.stored_filters = _widget.load_favorites(self.appname);
_widget.init_filters(_widget);
- }, self, et2_favorites);
+ }, self, Et2Favorites);
}
}
else
diff --git a/api/js/jsapi/egw_app.ts b/api/js/jsapi/egw_app.ts
index f61563e57c..4184bdbb23 100644
--- a/api/js/jsapi/egw_app.ts
+++ b/api/js/jsapi/egw_app.ts
@@ -14,13 +14,13 @@ import {etemplate2} from "../etemplate/etemplate2";
import type {et2_container} from "../etemplate/et2_core_baseWidget";
import {et2_nextmatch} from "../etemplate/et2_extension_nextmatch";
import {et2_createWidget} from "../etemplate/et2_core_widget";
-import {et2_favorites} from "../etemplate/et2_widget_favorites";
import type {IegwAppLocal} from "./egw_global";
import Sortable from 'sortablejs/modular/sortable.complete.esm.js';
import {et2_valueWidget} from "../etemplate/et2_core_valueWidget";
import {nm_action} from "../etemplate/et2_extension_nextmatch_actions";
import {Et2Dialog} from "../etemplate/Et2Dialog/Et2Dialog";
import {EGW_KEY_ENTER} from "../egw_action/egw_action_constants";
+import {Et2Favorites} from "../etemplate/Et2Favorites/Et2Favorites";
/**
* Type for push-message
@@ -973,7 +973,7 @@ export abstract class EgwApp
{
_widget.stored_filters = _widget.load_favorites(self.appname);
_widget.init_filters(_widget);
- }, self, et2_favorites);
+ }, self, Et2Favorites);
}
}
else
diff --git a/filemanager/templates/default/index.xet b/filemanager/templates/default/index.xet
index a74acde798..d066dc588b 100644
--- a/filemanager/templates/default/index.xet
+++ b/filemanager/templates/default/index.xet
@@ -57,7 +57,7 @@