Convert et2_widget_favorites to TS

This commit is contained in:
Hadi Nategh 2020-02-10 16:48:15 +01:00
parent 44ed664f7a
commit 81b12cf9ee
4 changed files with 731 additions and 372 deletions

View File

@ -377,5 +377,6 @@ var et2_dropdown_button = /** @class */ (function (_super) {
}; };
return et2_dropdown_button; return et2_dropdown_button;
}(et2_core_inputWidget_1.et2_inputWidget)); }(et2_core_inputWidget_1.et2_inputWidget));
exports.et2_dropdown_button = et2_dropdown_button;
et2_core_widget_1.et2_register_widget(et2_dropdown_button, ["dropdown_button"]); et2_core_widget_1.et2_register_widget(et2_dropdown_button, ["dropdown_button"]);
//# sourceMappingURL=et2_widget_dropdown_button.js.map //# sourceMappingURL=et2_widget_dropdown_button.js.map

View File

@ -34,7 +34,7 @@ import {ClassWithAttributes} from "./et2_core_inheritance";
* *
* @augments et2_inputWidget * @augments et2_inputWidget
*/ */
class et2_dropdown_button extends et2_inputWidget export class et2_dropdown_button extends et2_inputWidget
{ {
static readonly attributes : any = { static readonly attributes : any = {
"label": { "label": {

View File

@ -1,3 +1,4 @@
"use strict";
/** /**
* EGroupware eTemplate2 - JS Favorite widget * EGroupware eTemplate2 - JS Favorite widget
* *
@ -7,14 +8,28 @@
* @link http://www.egroupware.org * @link http://www.egroupware.org
* @author Nathan Gray * @author Nathan Gray
* @copyright Nathan Gray 2013 * @copyright Nathan Gray 2013
* @version $Id$
*/ */
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
/*egw:uses /*egw:uses
et2_dropdown_button; et2_dropdown_button;
et2_extension_nextmatch; et2_extension_nextmatch;
*/ */
var et2_core_widget_1 = require("./et2_core_widget");
var et2_widget_dropdown_button_1 = require("./et2_widget_dropdown_button");
var et2_core_inheritance_1 = require("./et2_core_inheritance");
/** /**
* Favorites widget, designed for use with a nextmatch widget * Favorites widget, designed for use with a nextmatch widget
* *
@ -42,369 +57,287 @@
* *
* @augments et2_dropdown_button * @augments et2_dropdown_button
*/ */
var et2_favorites = (function(){ "use strict"; return et2_dropdown_button.extend([et2_INextmatchHeader], var et2_favorites = /** @class */ (function (_super) {
{ __extends(et2_favorites, _super);
attributes: { /**
"default_pref": { * Constructor
"name": "Default preference key", *
"type": "string", * @memberOf et2_favorites
"description": "The preference key where default favorite is stored (not the value)" */
}, function et2_favorites(_parent, _attrs, _child) {
"sidebox_target": { var _this = _super.call(this, _parent, _attrs, et2_core_inheritance_1.ClassWithAttributes.extendAttributes(et2_favorites._attributes, _child || {})) || this;
"name": "Sidebox target", // Some convenient variables, used in closures / event handlers
"type": "string", _this.header = null;
"description": "ID of element to insert favorite list into", _this.nextmatch = null;
"default": "favorite_sidebox" _this.favSortedList = null;
}, _this.sidebox_target = null;
"app": { // If filter was set server side, we need to remember it until nm is created
"name": "Application", _this.nm_filter = false;
"type": "string", _this.sidebox_target = jQuery("#" + _this.options.sidebox_target);
"description": "Application to show favorites for" if (_this.sidebox_target.length == 0 && egw_getFramework() != null) {
}, var egw_fw = egw_getFramework();
"filters": { _this.sidebox_target = jQuery("#" + _this.options.sidebox_target, egw_fw.sidemenuDiv);
"name": "Extra filters", }
"type": "any", // Store array of sorted items
"description": "Array of extra filters to include in the saved favorite" _this.favSortedList = ['blank'];
}, var apps = egw().user('apps');
et2_favorites.is_admin = (typeof apps['admin'] != "undefined");
// These are particular to favorites _this.stored_filters = _this.load_favorites(_this.options.app);
id: {"default": "favorite"}, _this.preferred = egw.preference(_this.options.default_pref, _this.options.app);
label: {"default": ""}, if (!_this.preferred || typeof _this.stored_filters[_this.preferred] == "undefined") {
label_updates: { "default": false}, _this.preferred = "blank";
image: {"default": this.egw().image('fav_filter')}, }
statustext: {"default": "Favorite queries", "type": "string"} // It helps to have the ID properly set before we get too far
}, _this.set_id(_this.id);
_this.init_filters(_this);
// Some convenient variables, used in closures / event handlers _this.menu.addClass("favorites");
header: null, // Set the default (button) value
nextmatch: null, _this.set_value(_this.preferred, true);
favorite_prefix: "favorite_", var self = _this;
stored_filters: {}, // Add a listener on the radio buttons to set default filter
jQuery(_this.menu).on("click", "input:radio", function (event) {
// If filter was set server side, we need to remember it until nm is created // Don't do the menu
nm_filter: false, 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());
* Constructor self.preferred = jQuery(this).val();
* // Update sidebox, if there
* @memberOf et2_favorites if (self.sidebox_target.length) {
*/ self.sidebox_target.find("div.ui-icon-heart")
init: function() { .replaceWith("<div class='sideboxstar'/>");
this._super.apply(this, arguments); jQuery("li[data-id='" + self.preferred + "'] div.sideboxstar", self.sidebox_target)
this.sidebox_target = jQuery("#"+this.options.sidebox_target); .replaceWith("<div class='ui-icon ui-icon-heart'/>");
if(this.sidebox_target.length == 0 && egw_getFramework() != null) }
{ // Close the menu
var egw_fw = egw_getFramework(); self.menu.hide();
this.sidebox_target = jQuery("#"+this.options.sidebox_target,egw_fw.sidemenuDiv); // Some user feedback
} self.button.addClass("ui-state-active", 500, "swing", function () {
// Store array of sorted items self.button.removeClass("ui-state-active", 2000);
this.favSortedList = ['blank']; });
});
var apps = egw().user('apps'); //Sort DomNodes of sidebox fav. menu
this.is_admin = (typeof apps['admin'] != "undefined"); var sideBoxDOMNodeSort = function (_favSList) {
var favS = jQuery.isArray(_favSList) ? _favSList.slice(0).reverse() : [];
this.stored_filters = this.load_favorites(this.options.app); for (var i = 0; i < favS.length; i++) {
self.sidebox_target.children().find('[data-id$="' + favS[i] + '"]').prependTo(self.sidebox_target.children());
this.preferred = egw.preference(this.options.default_pref,this.options.app); }
if(!this.preferred || typeof this.stored_filters[this.preferred] == "undefined") };
{ //Add Sortable handler to nm fav. menu
this.preferred = "blank"; jQuery(_this.menu).sortable({
} items: 'li:not([data-id$="add"])',
placeholder: 'ui-fav-sortable-placeholder',
// It helps to have the ID properly set before we get too far delay: 250,
this.set_id(this.id); update: function () {
self.favSortedList = jQuery(this).sortable('toArray', { attribute: 'data-id' });
this.init_filters(this); self.egw().set_preference(self.options.app, 'fav_sort_pref', self.favSortedList);
sideBoxDOMNodeSort(self.favSortedList);
this.menu.addClass("favorites"); }
});
// Set the default (button) value // Add a listener on the delete to remove
this.set_value(this.preferred,true); _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
var self = this; app[self.options.app].delete_favorite.apply(this, arguments);
})
// Add a listener on the radio buttons to set default filter // Wrap and unwrap because jQueryUI styles use a parent, and we don't want to change the state of the menu item
jQuery(this.menu).on("click","input:radio", function(event){ // Wrap in a span instead of a div because div gets a border
// Don't do the menu .on("mouseenter", "div.ui-icon-trash", function () { jQuery(this).wrap("<span class='ui-state-active'/>"); })
event.stopImmediatePropagation(); .on("mouseleave", "div.ui-icon-trash", function () { jQuery(this).unwrap(); });
// Trigger refresh of menu options now that events are registered
// Save as default favorite - used when you click the button // to update sidebox
self.egw().set_preference(self.options.app,self.options.default_pref,jQuery(this).val()); if (_this.sidebox_target.length > 0) {
self.preferred = jQuery(this).val(); _this.init_filters(_this);
}
// Update sidebox, if there return _this;
if(self.sidebox_target.length) }
{ /**
self.sidebox_target.find("div.ui-icon-heart") * Load favorites from preferences
.replaceWith("<div class='sideboxstar'/>"); *
jQuery("li[data-id='"+self.preferred+"'] div.sideboxstar",self.sidebox_target) * @param app String Load favorites from this application
.replaceWith("<div class='ui-icon ui-icon-heart'/>"); */
} et2_favorites.prototype.load_favorites = function (app) {
// Default blank filter
// Close the menu var stored_filters = {
self.menu.hide(); 'blank': {
name: this.egw().lang("No filters"),
// Some user feedback state: {}
self.button.addClass("ui-state-active", 500,"swing",function(){ }
self.button.removeClass("ui-state-active",2000); };
}); // Load saved favorites
}); var preferences = egw.preference("*", app);
for (var pref_name in preferences) {
//Sort DomNodes of sidebox fav. menu if (pref_name.indexOf(this.favorite_prefix) == 0 && typeof preferences[pref_name] == 'object') {
var sideBoxDOMNodeSort = function (_favSList) { var name_1 = pref_name.substr(this.favorite_prefix.length);
var favS = jQuery.isArray(_favSList)?_favSList.slice(0).reverse():[]; stored_filters[name_1] = preferences[pref_name];
// Keep older favorites working - they used to store nm filters in 'filters',not state
for (var i=0; i < favS.length;i++) if (preferences[pref_name]["filters"]) {
{ stored_filters[pref_name]["state"] = preferences[pref_name]["filters"];
self.sidebox_target.children().find('[data-id$="' + favS[i] + '"]').prependTo(self.sidebox_target.children()); }
} }
}; if (pref_name == 'fav_sort_pref') {
this.favSortedList = preferences[pref_name];
//Add Sortable handler to nm fav. menu //Make sure sorted list is always an array, seems some old fav are not array
jQuery(this.menu).sortable({ if (!jQuery.isArray(this.favSortedList))
this.favSortedList = this.favSortedList.split(',');
items:'li:not([data-id$="add"])', }
placeholder:'ui-fav-sortable-placeholder', }
delay: 250, //(millisecond) delay before the sorting should start if (typeof stored_filters == "undefined" || !stored_filters) {
update: function (event, ui) stored_filters = {};
{ }
self.favSortedList = jQuery(this).sortable('toArray', {attribute:'data-id'}); else {
for (var name_2 in stored_filters) {
self.egw().set_preference(self.options.app,'fav_sort_pref',self.favSortedList); if (this.favSortedList.indexOf(name_2) < 0) {
this.favSortedList.push(name_2);
sideBoxDOMNodeSort(self.favSortedList); }
} }
}); this.egw().set_preference(this.options.app, 'fav_sort_pref', this.favSortedList);
if (this.favSortedList.length > 0) {
// Add a listener on the delete to remove var sortedListObj = {};
this.menu.on("click","div.ui-icon-trash", app[self.options.app], function() { for (var i = 0; i < this.favSortedList.length; i++) {
// App instance might not be ready yet, so don't bind directly if (typeof stored_filters[this.favSortedList[i]] != 'undefined') {
app[self.options.app].delete_favorite.apply(this,arguments); sortedListObj[this.favSortedList[i]] = stored_filters[this.favSortedList[i]];
}) }
// Wrap and unwrap because jQueryUI styles use a parent, and we don't want to change the state of the menu item else {
// Wrap in a span instead of a div because div gets a border this.favSortedList.splice(i, 1);
.on("mouseenter","div.ui-icon-trash", function() {jQuery(this).wrap("<span class='ui-state-active'/>");}) this.egw().set_preference(this.options.app, 'fav_sort_pref', this.favSortedList);
.on("mouseleave","div.ui-icon-trash", function() {jQuery(this).unwrap();}); }
}
// Trigger refresh of menu options now that events are registered stored_filters = jQuery.extend(sortedListObj, stored_filters);
// to update sidebox }
if(this.sidebox_target.length > 0) }
{ return stored_filters;
this.init_filters(this); };
} // Create & set filter options for dropdown menu
}, et2_favorites.prototype.init_filters = function (widget, filters) {
if (typeof filters == "undefined") {
/** filters = this.stored_filters;
* Load favorites from preferences }
* var options = {};
* @param app String Load favorites from this application for (var name_3 in filters) {
*/ options[name_3] = "<input type='radio' name='" + this.internal_ids.menu + "[button][favorite]' value='" + name_3 + "' title='" +
load_favorites: function(app) { this.egw().lang('Set as default') + "'/>" +
(filters[name_3].name != undefined ? filters[name_3].name : name_3) +
// Default blank filter (filters[name_3].group != false && !et2_favorites.is_admin || name_3 == 'blank' ? "" :
var stored_filters = { "<div class='ui-icon ui-icon-trash' title='" + this.egw().lang('Delete') + "'/>");
'blank': { }
name: this.egw().lang("No filters"), // Only add 'Add current' if we have a nextmatch
state: {} if (this.nextmatch) {
} options["add"] = "<img src='" + this.egw().image("new") + "'/>" + this.egw().lang('Add current');
}; }
widget.set_select_options.call(widget, options);
// Load saved favorites // Set radio to current value
var preferences = egw.preference("*",app); jQuery("input[value='" + this.preferred + "']:radio", this.menu).attr("checked", 1);
for(var pref_name in preferences) };
{ et2_favorites.prototype.set_nm_filters = function (filters) {
if(pref_name.indexOf(this.favorite_prefix) == 0 && typeof preferences[pref_name] == 'object') if (this.nextmatch) {
{ this.nextmatch.applyFilters(filters);
var name = pref_name.substr(this.favorite_prefix.length); }
stored_filters[name] = preferences[pref_name]; else {
// Keep older favorites working - they used to store nm filters in 'filters',not state console.log(filters);
if(preferences[pref_name].filters) }
{ };
stored_filters[pref_name].state = preferences[pref_name].filters; et2_favorites.prototype.onclick = function (node) {
} // Apply preferred filter - make sure it's an object, and not a reference
} if (this.preferred && this.stored_filters[this.preferred]) {
if (pref_name == 'fav_sort_pref') // 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') {
this.favSortedList = preferences[pref_name]; app[this.options.app].setState(this.stored_filters[this.preferred]);
//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(','); else {
} this.set_nm_filters(jQuery.extend({}, this.stored_filters[this.preferred].state));
} }
if(typeof stored_filters == "undefined" || !stored_filters) }
{ else {
stored_filters = {}; alert(this.egw().lang("No default set"));
} }
else };
{ // Apply the favorite when you pick from the list
for(var name in stored_filters) et2_favorites.prototype.change = function (selected_node) {
{ this.value = jQuery(selected_node).attr("data-id");
if (this.favSortedList.indexOf(name) < 0) if (this.value == "add" && this.nextmatch) {
{ // Get current filters
this.favSortedList.push(name); var current_filters = jQuery.extend({}, this.nextmatch.activeFilters);
} // Add in extras
} for (var extra in this.options.filters) {
this.egw().set_preference (this.options.app,'fav_sort_pref',this.favSortedList); // Don't overwrite what nm has, chances are nm has more up-to-date value
if (this.favSortedList.length > 0) if (typeof current_filters == 'undefined') {
{ current_filters[extra] = this.nextmatch.options.settings[extra];
var sortedListObj = {}; }
}
for (var i=0;i < this.favSortedList.length;i++) // Skip columns for now
{ delete current_filters.selcolumns;
if (typeof stored_filters[this.favSortedList[i]] != 'undefined') // Add in application's settings
{ if (this.filters != true) {
sortedListObj[this.favSortedList[i]] = stored_filters[this.favSortedList[i]]; for (var i = 0; i < this.filters.length; i++) {
} current_filters[this.options.filters[i]] = this.nextmatch.options.settings[this.options.filters[i]];
else }
{ }
this.favSortedList.splice(i,1); // Call framework
this.egw().set_preference (this.options.app,'fav_sort_pref',this.favSortedList); app[this.options.app].add_favorite(current_filters);
} // Reset value
} this.set_value(this.preferred, true);
stored_filters = jQuery.extend(sortedListObj,stored_filters); }
} else if (this.value == 'blank') {
} // Reset filters when select no filters
return stored_filters; this.set_nm_filters({});
}, }
};
// Create & set filter options for dropdown menu et2_favorites.prototype.set_value = function (filter_name, parent) {
init_filters: function(widget, filters) if (parent) {
{ return _super.prototype.set_value.call(this, filter_name);
if(typeof filters == "undefined") }
{ if (filter_name == 'add')
filters = this.stored_filters; return false;
} app[this.options.app].setState(this.stored_filters[filter_name]);
return false;
var options = {}; };
for(var name in filters) et2_favorites.prototype.getValue = function () {
{ return null;
options[name] = "<input type='radio' name='"+this.internal_ids.menu+"[button][favorite]' value='"+name+"' title='" + };
this.egw().lang('Set as default') + "'/>"+ /**
(filters[name].name != undefined ? filters[name].name : name) + * Set the nextmatch to filter
(filters[name].group != false && !this.is_admin || name == 'blank' ? "" : * From et2_INextmatchHeader interface
"<div class='ui-icon ui-icon-trash' title='" + this.egw().lang('Delete') + "'/>"); *
} * @param {et2_nextmatch} nextmatch
*/
// Only add 'Add current' if we have a nextmatch et2_favorites.prototype.setNextmatch = function (nextmatch) {
if(this.nextmatch) this.nextmatch = nextmatch;
{ if (this.nm_filter) {
options.add = "<img src='"+this.egw().image("new") +"'/>"+this.egw().lang('Add current'); this.set_value(this.nm_filter);
} this.nm_filter = false;
widget.set_select_options.call(widget,options); }
// Re-generate filter list so we can add 'Add current'
// Set radio to current value this.init_filters(this);
jQuery("input[value='"+ this.preferred +"']:radio", this.menu).attr("checked",true); };
}, et2_favorites._attributes = {
"default_pref": {
set_nm_filters: function(filters) "name": "Default preference key",
{ "type": "string",
if(this.nextmatch) "description": "The preference key where default favorite is stored (not the value)"
{ },
this.nextmatch.applyFilters(filters); "sidebox_target": {
} "name": "Sidebox target",
else "type": "string",
{ "description": "ID of element to insert favorite list into",
console.log(filters); "default": "favorite_sidebox"
} },
}, "app": {
"name": "Application",
onclick: function(node) { "type": "string",
// Apply preferred filter - make sure it's an object, and not a reference "description": "Application to show favorites for"
if(this.preferred && this.stored_filters[this.preferred]) },
{ "filters": {
// use app[appname].setState if available to allow app to overwrite it (eg. change to non-listview in calendar) "name": "Extra filters",
if (typeof app[this.options.app] != 'undefined') "type": "any",
{ "description": "Array of extra filters to include in the saved favorite"
app[this.options.app].setState(this.stored_filters[this.preferred]); },
} // These are particular to favorites
else id: { "default": "favorite" },
{ label: { "default": "" },
this.set_nm_filters(jQuery.extend({},this.stored_filters[this.preferred].state)); label_updates: { "default": false },
} image: { "default": egw().image('fav_filter') },
} statustext: { "default": "Favorite queries", "type": "string" }
else };
{ return et2_favorites;
alert(this.egw().lang("No default set")); }(et2_widget_dropdown_button_1.et2_dropdown_button));
} et2_core_widget_1.et2_register_widget(et2_favorites, ["favorites"]);
}, //# sourceMappingURL=et2_widget_favorites.js.map
// Apply the favorite when you pick from the list
change: function(selected_node) {
this.value = jQuery(selected_node).attr("data-id");
if(this.value == "add" && this.nextmatch)
{
// Get current filters
var current_filters = jQuery.extend({},this.nextmatch.activeFilters);
// Add in extras
for(var 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(var 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: function(filter_name, parent) {
if(parent)
{
return this._super.call(this, filter_name);
}
if(filter_name == 'add') return false;
app[this.options.app].setState(this.stored_filters[filter_name]);
return false;
},
getValue: function()
{
return null;
},
/**
* Set the nextmatch to filter
* From et2_INextmatchHeader interface
*
* @param {et2_nextmatch} nextmatch
*/
setNextmatch: function(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);
}
});}).call(this);
et2_register_widget(et2_favorites, ["favorites"]);

View File

@ -0,0 +1,425 @@
/**
* EGroupware eTemplate2 - JS Favorite widget
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package etemplate
* @subpackage api
* @link http://www.egroupware.org
* @author Nathan Gray
* @copyright Nathan Gray 2013
*/
/*egw:uses
et2_dropdown_button;
et2_extension_nextmatch;
*/
import {et2_register_widget, 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";
/**
* 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'=>'<span id="favorite_sidebox"/>',
* '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_<name>. The favorite favorite used for clicking on
* the filter button is stored in nextmatch-<columnselection_pref>-favorite.
*
* @augments et2_dropdown_button
*/
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;
favorite_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");
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)
{
self.sidebox_target.find("div.ui-icon-heart")
.replaceWith("<div class='sideboxstar'/>");
jQuery("li[data-id='"+self.preferred+"'] div.sideboxstar",self.sidebox_target)
.replaceWith("<div class='ui-icon ui-icon-heart'/>");
}
// 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, //(millisecond) delay before the sorting should start
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("<span class='ui-state-active'/>");})
.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(this.favorite_prefix) == 0 && typeof preferences[pref_name] == 'object')
{
let name = pref_name.substr(this.favorite_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] = "<input type='radio' name='"+this.internal_ids.menu+"[button][favorite]' value='"+name+"' title='" +
this.egw().lang('Set as default') + "'/>"+
(filters[name].name != undefined ? filters[name].name : name) +
(filters[name].group != false && !et2_favorites.is_admin || name == 'blank' ? "" :
"<div class='ui-icon ui-icon-trash' title='" + this.egw().lang('Delete') + "'/>");
}
// Only add 'Add current' if we have a nextmatch
if(this.nextmatch)
{
options["add"] = "<img src='"+this.egw().image("new") +"'/>"+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);
}
}
et2_register_widget(et2_favorites, ["favorites"]);