/** * 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 { et2_register_widget } from "./et2_core_widget"; import { et2_dropdown_button } from "./et2_widget_dropdown_button"; import { ClassWithAttributes } from "./et2_core_inheritance"; import { egw, egw_getFramework } from "../jsapi/egw_global"; /** * 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 { /** * Constructor * * @memberOf et2_favorites */ constructor(_parent, _attrs, _child) { super(_parent, _attrs, ClassWithAttributes.extendAttributes(et2_favorites._attributes, _child || {})); // Some convenient variables, used in closures / event handlers this.header = null; this.nextmatch = null; this.favSortedList = null; this.sidebox_target = null; // If filter was set server side, we need to remember it until nm is created this.nm_filter = false; 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()); } }; //Add Sortable handler to nm fav. menu jQuery(this.menu).sortable({ items: 'li:not([data-id$="add"])', placeholder: 'ui-fav-sortable-placeholder', delay: 250, update: function () { self.favSortedList = jQuery(this).sortable('toArray', { attribute: 'data-id' }); 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 = { 'blank': { name: this.egw().lang("No filters"), state: {} } }; // Load saved favorites let preferences = 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) { 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); } } et2_favorites._attributes = { "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" } }; et2_favorites.PREFIX = "favorite_"; et2_register_widget(et2_favorites, ["favorites"]); //# sourceMappingURL=et2_widget_favorites.js.map