* Calendar: Activate links in location & description in event tooltip

This commit is contained in:
nathan 2021-08-12 08:57:15 -06:00
parent 50f620e075
commit 1d0772a064

View File

@ -20,7 +20,7 @@ import {et2_action_object_impl, et2_DOMWidget} from "../../api/js/etemplate/et2_
import {et2_calendar_daycol} from "./et2_widget_daycol"; import {et2_calendar_daycol} from "./et2_widget_daycol";
import {et2_calendar_planner_row} from "./et2_widget_planner_row"; import {et2_calendar_planner_row} from "./et2_widget_planner_row";
import {et2_IDetachedDOM} from "../../api/js/etemplate/et2_core_interfaces"; import {et2_IDetachedDOM} from "../../api/js/etemplate/et2_core_interfaces";
import {et2_no_init} from "../../api/js/etemplate/et2_core_common"; import {et2_activateLinks, et2_insertLinkText, et2_no_init} from "../../api/js/etemplate/et2_core_common";
import {egw_getAppObjectManager, egwActionObject} from '../../api/js/egw_action/egw_action.js'; import {egw_getAppObjectManager, egwActionObject} from '../../api/js/egw_action/egw_action.js';
import {egw} from "../../api/js/jsapi/egw_global"; import {egw} from "../../api/js/jsapi/egw_global";
import {et2_selectbox} from "../../api/js/etemplate/et2_widget_selectbox"; import {et2_selectbox} from "../../api/js/etemplate/et2_widget_selectbox";
@ -88,7 +88,8 @@ export class et2_calendar_event extends et2_valueWidget implements et2_IDetached
.addClass("calendar_calEvent") .addClass("calendar_calEvent")
.addClass(this.options.class) .addClass(this.options.class)
.css('width', this.options.width) .css('width', this.options.width)
.on('mouseenter', function() { .on('mouseenter', function ()
{
// Bind actions on first mouseover for faster creation // Bind actions on first mouseover for faster creation
if (event._need_actions_linked) if (event._need_actions_linked)
{ {
@ -105,16 +106,20 @@ export class et2_calendar_event extends et2_valueWidget implements et2_IDetached
} }
} }
// Hacky to remove egw's tooltip border and let the mouse in // Hacky to remove egw's tooltip border and let the mouse in
window.setTimeout(function() { window.setTimeout(function ()
{
jQuery('body .egw_tooltip') jQuery('body .egw_tooltip')
.css('border', 'none') .css('border', 'none')
.on('mouseenter', function() { .on('mouseenter', function ()
{
event.div.off('mouseleave.tooltip'); event.div.off('mouseleave.tooltip');
jQuery('body.egw_tooltip').remove(); jQuery('body.egw_tooltip').remove();
jQuery('body').append(this); jQuery('body').append(this);
jQuery(this).stop(true).fadeTo(400, 1) jQuery(this).stop(true).fadeTo(400, 1)
.on('mouseleave', function() { .on('mouseleave', function ()
jQuery(this).fadeOut('400', function() { {
jQuery(this).fadeOut('400', function ()
{
jQuery(this).remove(); jQuery(this).remove();
// Set up to work again // Set up to work again
event.set_statustext(event._tooltip()); event.set_statustext(event._tooltip());
@ -289,7 +294,10 @@ export class et2_calendar_event extends et2_valueWidget implements et2_IDetached
const im = this.getInstanceManager(); const im = this.getInstanceManager();
et2_selectbox.cat_options({ et2_selectbox.cat_options({
_type: 'select-cat', _type: 'select-cat',
getInstanceManager: function() {return im;} getInstanceManager: function ()
{
return im;
}
}, },
{application: event.app || 'calendar'} {application: event.app || 'calendar'}
); );
@ -328,11 +336,13 @@ export class et2_calendar_event extends et2_valueWidget implements et2_IDetached
.attr("tabindex", 0) .attr("tabindex", 0)
.attr("aria-label", tooltip) .attr("aria-label", tooltip)
// Remove any category classes // Remove any category classes
.removeClass(function(index, css) { .removeClass(function (index, css)
{
return (css.match(/(^|\s)cat_\S+/g) || []).join(' '); return (css.match(/(^|\s)cat_\S+/g) || []).join(' ');
}) })
// Remove any status classes // Remove any status classes
.removeClass(function(index, css) { .removeClass(function (index, css)
{
return (css.match(/calendar_calEvent\S+/g) || []).join(' '); return (css.match(/calendar_calEvent\S+/g) || []).join(' ');
}) })
.removeClass('calendar_calEventSmall') .removeClass('calendar_calEventSmall')
@ -530,7 +540,8 @@ export class et2_calendar_event extends et2_valueWidget implements et2_IDetached
cat_label = this.options.value.category.indexOf(',') <= 0 ? cat.span.text() : []; cat_label = this.options.value.category.indexOf(',') <= 0 ? cat.span.text() : [];
if (typeof cat_label != 'string') if (typeof cat_label != 'string')
{ {
cat.span.children().each(function() { cat.span.children().each(function ()
{
(<string[]>cat_label).push(jQuery(this).text()); (<string[]>cat_label).push(jQuery(this).text());
}); });
cat_label = cat_label.join(', '); cat_label = cat_label.join(', ');
@ -538,12 +549,25 @@ export class et2_calendar_event extends et2_valueWidget implements et2_IDetached
cat.destroy(); cat.destroy();
} }
// Activate links in description
let description_node = document.createElement("p");
description_node.className = "calendar_calEvent_description";
et2_insertLinkText(
et2_activateLinks(egw.htmlspecialchars(this.options.value.description)), description_node, '_blank'
);
// Location + Videoconference // Location + Videoconference
let location = ''; let location = '';
if (this.options.value.location || this.options.value['##videoconference']) if (this.options.value.location || this.options.value['##videoconference'])
{ {
location += '<p><span class="calendar_calEventLabel">' + this.egw().lang('Location') + '</span>:' + location = '<p>';
egw.htmlspecialchars(this.options.value.location); let location_node = document.createElement("span");
location_node.className = "calendar_calEventLabel";
et2_insertLinkText(et2_activateLinks(
this.egw().lang('Location') + ':' +
egw.htmlspecialchars(this.options.value.location)), location_node, '_blank');
location += location_node.outerHTML;
if (this.options.value['##videoconference']) if (this.options.value['##videoconference'])
{ {
// Click handler is set in _bind_videoconference() // Click handler is set in _bind_videoconference()
@ -580,8 +604,8 @@ export class et2_calendar_event extends et2_valueWidget implements et2_IDetached
this.icons[0].outerHTML + this.icons[0].outerHTML +
'</div>' + '</div>' +
'<div class="calendar_calEventBody">' + '<div class="calendar_calEventBody">' +
'<h1 class="calendar_calEventTitle">'+egw.htmlspecialchars(this.options.value.title)+'</h1><br><p>'+ '<h1 class="calendar_calEventTitle">' + egw.htmlspecialchars(this.options.value.title) + '</h1><br>' +
egw.htmlspecialchars(this.options.value.description)+'</p>'+ description_node.outerHTML +
'<p style="margin: 2px 0px;">' + times + '</p>' + '<p style="margin: 2px 0px;">' + times + '</p>' +
location + location +
(cat_label ? '<p><h2 class="calendar_calEventLabel">' + this.egw().lang('Category') + ':</h2>' + cat_label + '</p>' : '') + (cat_label ? '<p><h2 class="calendar_calEventLabel">' + this.egw().lang('Category') + ':</h2>' + cat_label + '</p>' : '') +
@ -718,11 +742,13 @@ export class et2_calendar_event extends et2_valueWidget implements et2_IDetached
{ {
let vc_event = 'click.calendar_videoconference'; let vc_event = 'click.calendar_videoconference';
jQuery('body').off(vc_event) jQuery('body').off(vc_event)
.on(vc_event, '[data-videoconference]',function(event) { .on(vc_event, '[data-videoconference]', function (event)
{
let data = egw.dataGetUIDdata("calendar::" + this.dataset.id); let data = egw.dataGetUIDdata("calendar::" + this.dataset.id);
app.calendar.joinVideoConference(this.dataset.videoconference, data.data || this.dataset); app.calendar.joinVideoConference(this.dataset.videoconference, data.data || this.dataset);
}); });
} }
/** /**
* Get a text representation of the timespan of the event. Either start * Get a text representation of the timespan of the event. Either start
* - end, or 'all day' * - end, or 'all day'
@ -1113,10 +1139,13 @@ export class et2_calendar_event extends et2_valueWidget implements et2_IDetached
{ {
action_parent = action_parent.getParent(); action_parent = action_parent.getParent();
} }
try { try
{
this._link_actions(action_parent.options.actions || {}); this._link_actions(action_parent.options.actions || {});
this._need_actions_linked = false; this._need_actions_linked = false;
} catch (e) { }
catch (e)
{
// something went wrong, but keep quiet about it // something went wrong, but keep quiet about it
} }
} }
@ -1137,7 +1166,8 @@ export class et2_calendar_event extends et2_valueWidget implements et2_IDetached
this._actionObject = objectManager.getObjectById('calendar::' + this.options.value.row_id); this._actionObject = objectManager.getObjectById('calendar::' + this.options.value.row_id);
} }
if (this._actionObject == null) { if (this._actionObject == null)
{
// Add a new container to the object manager which will hold the widget // Add a new container to the object manager which will hold the widget
// objects // objects
this._actionObject = objectManager.insertObject(false, new egwActionObject( this._actionObject = objectManager.insertObject(false, new egwActionObject(
@ -1234,7 +1264,10 @@ export class et2_calendar_event extends et2_valueWidget implements et2_IDetached
// we need the list - pull it from sidebox owner // we need the list - pull it from sidebox owner
if ((isNaN(parent_owner[i]) || parent_owner[i] < 0) && options && typeof options.find == "function") if ((isNaN(parent_owner[i]) || parent_owner[i] < 0) && options && typeof options.find == "function")
{ {
var resource = options.find(function(element) {return element.id == parent_owner[i];}) || {}; var resource = options.find(function (element)
{
return element.id == parent_owner[i];
}) || {};
if (resource && resource.resources) if (resource && resource.resources)
{ {
parent_owner.splice(i, 1); parent_owner.splice(i, 1);
@ -1253,14 +1286,18 @@ export class et2_calendar_event extends et2_valueWidget implements et2_IDetached
{ {
// Add in groups, if we can get them from options, great // Add in groups, if we can get them from options, great
var resource; var resource;
if(options && options.find && (resource = options.find(function(element) {return element.id === id;})) && resource.resources) if (options && options.find && (resource = options.find(function (element)
{
return element.id === id;
})) && resource.resources)
{ {
participants = participants.concat(resource.resources); participants = participants.concat(resource.resources);
} }
else else
{ {
// Add in groups, if we can get them (this is asynchronous) // Add in groups, if we can get them (this is asynchronous)
egw.accountData(id,'account_id',true,function(members) { egw.accountData(id, 'account_id', true, function (members)
{
participants = participants.concat(Object.keys(members)); participants = participants.concat(Object.keys(members));
}, this); }, this);
} }
@ -1325,7 +1362,8 @@ export class et2_calendar_event extends et2_valueWidget implements et2_IDetached
{ {
egw = this.egw ? (typeof this.egw == 'function' ? this.egw() : this.egw) : window.opener && typeof window.opener.egw != 'undefined' ? window.opener.egw('calendar') : window.egw('calendar'); egw = this.egw ? (typeof this.egw == 'function' ? this.egw() : this.egw) : window.opener && typeof window.opener.egw != 'undefined' ? window.opener.egw('calendar') : window.egw('calendar');
} }
catch(e){ catch (e)
{
egw = window.egw('calendar'); egw = window.egw('calendar');
} }
@ -1361,7 +1399,10 @@ export class et2_calendar_event extends et2_valueWidget implements et2_IDetached
{text: egw.lang("Cancel"), id: "cancel"} {text: egw.lang("Cancel"), id: "cancel"}
]; ];
et2_dialog.show_dialog( et2_dialog.show_dialog(
function(button_id) {callback.call(that, button_id, event_data);}, function (button_id)
{
callback.call(that, button_id, event_data);
},
(!event_data.is_private ? event_data['title'] : egw.lang('private')) + "\n" + (!event_data.is_private ? event_data['title'] : egw.lang('private')) + "\n" +
egw.lang("Do you want to edit this event as an exception or the whole series?"), egw.lang("Do you want to edit this event as an exception or the whole series?"),
egw.lang("This event is part of a series"), {}, buttons, et2_dialog.QUESTION_MESSAGE egw.lang("This event is part of a series"), {}, buttons, et2_dialog.QUESTION_MESSAGE
@ -1395,10 +1436,12 @@ export class et2_calendar_event extends et2_valueWidget implements et2_IDetached
let egw; let egw;
// seems window.opener somehow in certian conditions could be from different origin // seems window.opener somehow in certian conditions could be from different origin
// we try to catch the exception and in this case retrieve the egw object from current window. // we try to catch the exception and in this case retrieve the egw object from current window.
try { try
{
egw = this.egw ? (typeof this.egw == 'function' ? this.egw() : this.egw) : window.opener && typeof window.opener.egw != 'undefined' ? window.opener.egw('calendar') : window.egw('calendar'); egw = this.egw ? (typeof this.egw == 'function' ? this.egw() : this.egw) : window.opener && typeof window.opener.egw != 'undefined' ? window.opener.egw('calendar') : window.egw('calendar');
} }
catch(e){ catch (e)
{
egw = window.egw('calendar'); egw = window.egw('calendar');
} }
@ -1417,7 +1460,10 @@ export class et2_calendar_event extends et2_valueWidget implements et2_IDetached
if (parseInt(event_data.recur_type)) if (parseInt(event_data.recur_type))
{ {
et2_dialog.show_dialog( et2_dialog.show_dialog(
function(button_id) {callback.call(that, button_id, event_data);}, function (button_id)
{
callback.call(that, button_id, event_data);
},
(!event_data.is_private ? event_data['title'] : egw.lang('private')) + "\n" + (!event_data.is_private ? event_data['title'] : egw.lang('private')) + "\n" +
egw.lang("Do you really want to change the start of this series? If you do, the original series will be terminated as of %1 and a new series for the future reflecting your changes will be created.", termination_date), egw.lang("Do you really want to change the start of this series? If you do, the original series will be terminated as of %1 and a new series for the future reflecting your changes will be created.", termination_date),
egw.lang("This event is part of a series"), {}, et2_dialog.BUTTONS_OK_CANCEL, et2_dialog.WARNING_MESSAGE egw.lang("This event is part of a series"), {}, et2_dialog.BUTTONS_OK_CANCEL, et2_dialog.WARNING_MESSAGE
@ -1478,10 +1524,12 @@ export class et2_calendar_event extends et2_valueWidget implements et2_IDetached
// _outerCall may be used to determine, whether the state change has been // _outerCall may be used to determine, whether the state change has been
// evoked from the outside and the stateChangeCallback has to be called // evoked from the outside and the stateChangeCallback has to be called
// or not. // or not.
aoi.doSetState = function(_state, _outerCall) { aoi.doSetState = function (_state, _outerCall)
{
}; };
return aoi; return aoi;
} }
} }
et2_register_widget(et2_calendar_event, ["calendar-event"]); et2_register_widget(et2_calendar_event, ["calendar-event"]);