forked from extern/egroupware
Add observer to home, delegating the update to each portlet if possible.
This commit is contained in:
parent
df76d33437
commit
daf62789a0
calendar/js
home
38
calendar/js/calendar_favorite_portlet.js
Normal file
38
calendar/js/calendar_favorite_portlet.js
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Egroupware - Calendar javascript for home favorite portlet(s)
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package calendar
|
||||
* @subpackage home
|
||||
* @link http://www.egroupware.org
|
||||
* @author Nathan Gray
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
/**
|
||||
* Custom code for calendar favorite home page portlets.
|
||||
* Since calendar doesn't use etemplate2, as well as having multiple different
|
||||
* views, we need some custom handling to detect and handle refreshes.
|
||||
*
|
||||
* Note we put the class in home.
|
||||
*/
|
||||
app.classes.home.calendar_favorite_portlet = app.classes.home.home_favorite_portlet.extend({
|
||||
|
||||
observer: function(_msg, _app, _id, _type, _msg_type, _targetapp)
|
||||
{
|
||||
if(this.portlet.getWidgetById('nm'))
|
||||
{
|
||||
// List view, we can just update it
|
||||
this.portlet.getWidgetById('nm').refresh(_id,_type);
|
||||
}
|
||||
else
|
||||
{
|
||||
// No intelligence since we don't have access to the state
|
||||
// (app.calendar.getState() is for the calendar tab, not home)
|
||||
// just refresh on every calendar or infolog change
|
||||
if(_app == 'calendar' || _app == 'infolog')
|
||||
{
|
||||
app.home.refresh(this.portlet.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
@ -266,6 +266,10 @@ class home_ui
|
||||
{
|
||||
$etemplate->setElementAttribute($id, $attr, $value);
|
||||
}
|
||||
|
||||
// Make sure custom javascript is loaded
|
||||
egw_framework::validate_file('', $classname, $context['appname'] ? $context['appname'] : 'home');
|
||||
|
||||
if($full_exec)
|
||||
{
|
||||
$content = $portlet->exec($id, $etemplate, $full_exec ? 2 : -1);
|
||||
|
192
home/js/app.js
192
home/js/app.js
@ -47,6 +47,9 @@ app.classes.home = AppJS.extend(
|
||||
HEIGHT: 1
|
||||
},
|
||||
|
||||
// List of portlets
|
||||
portlets: {},
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
@ -67,6 +70,8 @@ app.classes.home = AppJS.extend(
|
||||
delete this.et2;
|
||||
delete this.portlet_container;
|
||||
|
||||
this.portlets = {};
|
||||
|
||||
// call parent
|
||||
this._super.apply(this, arguments);
|
||||
|
||||
@ -130,6 +135,14 @@ app.classes.home = AppJS.extend(
|
||||
app.home.add_from_drop(action, [{data: ui.helper.context.dataset}])
|
||||
}
|
||||
})
|
||||
// Bind to unload to remove it from our list
|
||||
.on('clear','.et2_container[id]', jQuery.proxy(function(e) {
|
||||
if(e.target && e.target.id && this.portlets[e.target.id])
|
||||
{
|
||||
this.portlets[e.target.id].destroy();
|
||||
delete this.portlets[e.target.id];
|
||||
}
|
||||
},this));
|
||||
}
|
||||
else if (et2.uniqueId)
|
||||
{
|
||||
@ -164,6 +177,9 @@ app.classes.home = AppJS.extend(
|
||||
{
|
||||
et2.DOMContainer.id = et2.uniqueId;
|
||||
}
|
||||
|
||||
// Instanciate custom code for this portlet
|
||||
this._get_portlet_code(portlet);
|
||||
}
|
||||
|
||||
// Special handling to deal with legacy (non-et2) calendar links
|
||||
@ -177,6 +193,53 @@ app.classes.home = AppJS.extend(
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Observer method receives update notifications from all applications
|
||||
*
|
||||
* Home passes the notification off to specific code for each portlet, which
|
||||
* decide if they should be updated or not.
|
||||
*
|
||||
* @param {string} _msg message (already translated) to show, eg. 'Entry deleted'
|
||||
* @param {string} _app application name
|
||||
* @param {(string|number)} _id id of entry to refresh or null
|
||||
* @param {string} _type either 'update', 'edit', 'delete', 'add' or null
|
||||
* - update: request just modified data from given rows. Sorting is not considered,
|
||||
* so if the sort field is changed, the row will not be moved.
|
||||
* - edit: rows changed, but sorting may be affected. Requires full reload.
|
||||
* - delete: just delete the given rows clientside (no server interaction neccessary)
|
||||
* - add: requires full reload for proper sorting
|
||||
* @param {string} _msg_type 'error', 'warning' or 'success' (default)
|
||||
* @param {string} _targetapp which app's window should be refreshed, default current
|
||||
* @return {false|*} false to stop regular refresh, thought all observers are run
|
||||
*/
|
||||
observer: function(_msg, _app, _id, _type, _msg_type, _targetapp)
|
||||
{
|
||||
for(var id in this.portlets)
|
||||
{
|
||||
// App is home, refresh all portlets
|
||||
if(_app == 'home')
|
||||
{
|
||||
this.refresh(id);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ask the portlets if they're interested
|
||||
try
|
||||
{
|
||||
var code = this.portlets[id];
|
||||
if(code)
|
||||
{
|
||||
code.observer(_msg,_app,_id,_type,_msg_type,_targetapp);
|
||||
}
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
this.egw.debug("error", "Error trying to update portlet " + id,e);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a new portlet from the context menu
|
||||
*/
|
||||
@ -212,6 +275,9 @@ app.classes.home = AppJS.extend(
|
||||
this.DEFAULT.WIDTH, this.DEFAULT.HEIGHT,
|
||||
attrs.col, attrs.row
|
||||
);
|
||||
|
||||
// Instanciate custom code for this portlet
|
||||
this._get_portlet_code(portlet);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -268,6 +334,9 @@ app.classes.home = AppJS.extend(
|
||||
this.DEFAULT.WIDTH, this.DEFAULT.HEIGHT,
|
||||
attrs.col, attrs.row
|
||||
);
|
||||
|
||||
// Instanciate custom code for this portlet
|
||||
this._get_portlet_code(portlet);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -334,14 +403,40 @@ app.classes.home = AppJS.extend(
|
||||
*
|
||||
* @param {string} id
|
||||
*/
|
||||
refresh: function($id) {
|
||||
var p = this.portlet_container.getWidgetById($id);
|
||||
refresh: function(id) {
|
||||
var p = this.portlet_container.getWidgetById(id);
|
||||
if(p)
|
||||
{
|
||||
p._process_edit(et2_dialog.OK_BUTTON, '~reload~');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Determine the best fitting code to use for the given portlet, instanciate
|
||||
* it and add it to the list.
|
||||
*
|
||||
* @param {et2_portlet} portlet
|
||||
* @returns {home_portlet}
|
||||
*/
|
||||
_get_portlet_code: function(portlet) {
|
||||
var classname = portlet.class;
|
||||
// Freshly added portlets can have 'add_' prefix
|
||||
if(classname.indexOf('add_') == 0)
|
||||
{
|
||||
classname = classname.replace('add_','');
|
||||
}
|
||||
// Prefer a specific match
|
||||
var _class = app.classes.home[classname] ||
|
||||
// If it has a nextmatch, use favorite base class
|
||||
(portlet.getWidgetById('nm') ? app.classes.home.home_favorite_portlet : false) ||
|
||||
// Fall back to base class
|
||||
app.classes.home.home_portlet;
|
||||
|
||||
this.portlets[portlet.id] = new _class(portlet);
|
||||
|
||||
return this.portlets[portlet.id];
|
||||
},
|
||||
|
||||
/**
|
||||
* For link_portlet - opens the configured record when the user
|
||||
* double-clicks or chooses view from the context menu
|
||||
@ -571,7 +666,6 @@ app.classes.home = AppJS.extend(
|
||||
}
|
||||
|
||||
widget.getWidgetById('list').set_value(new_list);
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
@ -647,3 +741,95 @@ app.classes.home = AppJS.extend(
|
||||
nm.resize();
|
||||
}
|
||||
});
|
||||
|
||||
/// Base class code
|
||||
|
||||
/**
|
||||
* Base class for portlet specific javascript
|
||||
*
|
||||
* Should this maybe extend et2_portlet? It would complicate instantiation.
|
||||
*
|
||||
* @type @exp;Class@call;extend
|
||||
*/
|
||||
app.classes.home.home_portlet = Class.extend({
|
||||
portlet: null,
|
||||
|
||||
init: function(portlet) {
|
||||
this.portlet = portlet;
|
||||
},
|
||||
destroy: function() {
|
||||
this.portlet = null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle framework refresh messages to determine if the portlet needs to
|
||||
* refresh too.
|
||||
*
|
||||
* App is responsible for only reacting to "messages" it is interested in!
|
||||
*
|
||||
*/
|
||||
observer: function(_msg, _app, _id, _type, _msg_type, _targetapp)
|
||||
{
|
||||
// Not interested
|
||||
}
|
||||
});
|
||||
|
||||
app.classes.home.home_link_portlet = app.classes.home.home_portlet.extend({
|
||||
observer: function(_msg, _app, _id, _type)
|
||||
{
|
||||
if(this.portlet)
|
||||
{
|
||||
var value = this.portlet.settings.entry || {};
|
||||
if(value.app && value.app == _app && value.id && value.id == _id)
|
||||
{
|
||||
// We don't just get the updated title, in case there's a custom
|
||||
// template with more fields
|
||||
app.home.refresh(this.portlet.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
app.classes.home.home_list_portlet = app.classes.home.home_portlet.extend({
|
||||
observer: function(_msg, _app, _id, _type)
|
||||
{
|
||||
if(this.portlet && this.portlet.getWidgetById('list'))
|
||||
{
|
||||
var list = this.portlet.getWidgetById('list').options.value;
|
||||
for(var i = 0; i < list.length; i++)
|
||||
{
|
||||
if(list[i].app == _app && list[i].id == _id)
|
||||
{
|
||||
app.home.refresh(this.portlet.id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
app.classes.home.home_favorite_portlet = app.classes.home.home_portlet.extend({
|
||||
observer: function(_msg, _app, _id, _type, _msg_type, _targetapp)
|
||||
{
|
||||
if(this.portlet.class.indexOf(_app) == 0 || this.portlet.class == 'home_favorite_portlet')
|
||||
{
|
||||
this.portlet.getWidgetById('nm').refresh(_id,_type);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* An example illustrating extending the base code for a application specific code.
|
||||
* See also the calendar app, which needs custom handlers
|
||||
*
|
||||
* @type @exp;app@pro;classes@pro;home@pro;home_favorite_portlet@call;extend
|
||||
* Note we put it in home, but this code should go in addressbook/js/addressbook_favorite_portlet.js
|
||||
*
|
||||
app.classes.home.addressbook_favorite_portlet = app.classes.home.home_favorite_portlet.extend({
|
||||
|
||||
observer: function(_msg, _app, _id, _type, _msg_type, _targetapp)
|
||||
{
|
||||
// Just checking...
|
||||
debugger;
|
||||
}
|
||||
});
|
||||
*/
|
@ -127,3 +127,39 @@ div.calendar_favorite_portlet.et2_portlet.ui-widget-content > div:last-of-type {
|
||||
[class*="favorite_portlet"].et2_portlet .et2_nextmatch.header_hidden .egwGridView_outer thead:first-of-type th {
|
||||
visibility: hidden;
|
||||
}
|
||||
/**
|
||||
* Weather
|
||||
*/
|
||||
.home_weather_portlet table[id$="current"] {
|
||||
max-width: 250px;
|
||||
}
|
||||
.home_weather_portlet .temperature:after {
|
||||
content: "\00B0";
|
||||
}
|
||||
.home_weather_portlet .current {
|
||||
font-size: large;
|
||||
}
|
||||
.home_weather_portlet .forecast [id$="day"] {
|
||||
font-size: smaller;
|
||||
}
|
||||
.home_weather_portlet .forecast > div {
|
||||
display: inline-block;
|
||||
margin-bottom: 15px;
|
||||
width: 52px;
|
||||
}
|
||||
.home_weather_portlet .forecast img {
|
||||
margin: -10px -6px;
|
||||
width: 40px;
|
||||
height: auto;
|
||||
}
|
||||
.home_weather_portlet .high_low {
|
||||
padding: 3px;
|
||||
}
|
||||
.home_weather_portlet .high_low[id$="min"] {
|
||||
background-color: rgba(200, 200, 255, 0.3);
|
||||
}
|
||||
.home_weather_portlet .attribution {
|
||||
position: relative;
|
||||
bottom: 0.5em;
|
||||
font-size: smaller;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user