forked from extern/egroupware
Switch calendar owner to web component
This commit is contained in:
parent
5dc1c74167
commit
c6ef3b3a8d
@ -148,25 +148,31 @@ class calendar_owner_etemplate_widget extends Etemplate\Widget\Taglist
|
|||||||
Api\Json\Response::get()->data($label);
|
Api\Json\Response::get()->data($label);
|
||||||
return $label;
|
return $label;
|
||||||
}
|
}
|
||||||
else if($id && is_array($id))
|
else
|
||||||
{
|
{
|
||||||
$labels = Array();
|
if($id && is_array($id))
|
||||||
foreach($id as $index => $_id)
|
|
||||||
{
|
{
|
||||||
$labels[$_id] = self::format_owner($_id, self::get_owner_label($_id));
|
$labels = array();
|
||||||
|
foreach($id as $index => $_id)
|
||||||
|
{
|
||||||
|
$labels[$_id] = self::format_owner($_id, self::get_owner_label($_id));
|
||||||
|
}
|
||||||
|
Api\Json\Response::get()->data($labels);
|
||||||
|
return $labels;
|
||||||
}
|
}
|
||||||
Api\Json\Response::get()->data($labels);
|
|
||||||
return $labels;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function ajax_search($search_text, $search_options = [])
|
||||||
|
{
|
||||||
|
|
||||||
$bo = new calendar_bo();
|
$bo = new calendar_bo();
|
||||||
$query = $_REQUEST['query'];
|
|
||||||
|
|
||||||
// Arbitrarily limited to 50 / resource
|
// Arbitrarily limited to 50 / resource
|
||||||
$options = array('start' => 0, 'num_rows' => 50,
|
$options = array('start' => 0, 'num_rows' => 50,
|
||||||
// Filter accounts out of addressbook
|
// Filter accounts out of addressbook
|
||||||
'filter' => array('account_id' => null)) +
|
'filter' => array('account_id' => null)) +
|
||||||
array_diff_key($_REQUEST, array_flip(array('menuaction','query')));
|
$search_options;
|
||||||
$results = array();
|
$results = array();
|
||||||
|
|
||||||
// Contacts matching accounts the user does not have permission for cause
|
// Contacts matching accounts the user does not have permission for cause
|
||||||
@ -174,7 +180,7 @@ class calendar_owner_etemplate_widget extends Etemplate\Widget\Taglist
|
|||||||
// we remove those contacts
|
// we remove those contacts
|
||||||
$remove_contacts = array();
|
$remove_contacts = array();
|
||||||
|
|
||||||
$resources = array_merge(array('' => $bo->resources['']),$bo->resources);
|
$resources = array_merge(array('' => $bo->resources['']), $bo->resources);
|
||||||
$contacts_obj = new Api\Contacts();
|
$contacts_obj = new Api\Contacts();
|
||||||
foreach($resources as $type => $data)
|
foreach($resources as $type => $data)
|
||||||
{
|
{
|
||||||
@ -187,7 +193,7 @@ class calendar_owner_etemplate_widget extends Etemplate\Widget\Taglist
|
|||||||
$owngroup_options = $options+array('account_type'=>'owngroups');
|
$owngroup_options = $options+array('account_type'=>'owngroups');
|
||||||
$own_groups = Api\Accounts::link_query('',$owngroup_options);
|
$own_groups = Api\Accounts::link_query('',$owngroup_options);
|
||||||
$account_options = $options + array('account_type' => 'both');
|
$account_options = $options + array('account_type' => 'both');
|
||||||
$_results += $remove_contacts = Api\Accounts::link_query($query, $account_options);
|
$_results += $remove_contacts = Api\Accounts::link_query($search_text, $account_options);
|
||||||
if (!empty($_REQUEST['checkgrants']))
|
if (!empty($_REQUEST['checkgrants']))
|
||||||
{
|
{
|
||||||
$grants = (array)$GLOBALS['egw']->acl->get_grants('calendar') + $own_groups;
|
$grants = (array)$GLOBALS['egw']->acl->get_grants('calendar') + $own_groups;
|
||||||
@ -197,12 +203,12 @@ class calendar_owner_etemplate_widget extends Etemplate\Widget\Taglist
|
|||||||
// App provides a custom search function
|
// App provides a custom search function
|
||||||
else if ($data['app'] && $data['search'])
|
else if ($data['app'] && $data['search'])
|
||||||
{
|
{
|
||||||
$_results = call_user_func_array($data['search'], array($query, $options));
|
$_results = call_user_func_array($data['search'], array($search_text, $options));
|
||||||
}
|
}
|
||||||
// Use standard link registry
|
// Use standard link registry
|
||||||
else if ($data['app'] && Link::get_registry($data['app'], 'query'))
|
else if ($data['app'] && Link::get_registry($data['app'], 'query'))
|
||||||
{
|
{
|
||||||
$_results = Link::query($data['app'], $query,$options);
|
$_results = Link::query($data['app'], $search_text, $options);
|
||||||
}
|
}
|
||||||
|
|
||||||
// There are always special cases
|
// There are always special cases
|
||||||
@ -212,10 +218,11 @@ class calendar_owner_etemplate_widget extends Etemplate\Widget\Taglist
|
|||||||
// Include mailing lists, but not account groups
|
// Include mailing lists, but not account groups
|
||||||
$lists = array_filter(
|
$lists = array_filter(
|
||||||
$contacts_obj->get_lists(Api\Acl::READ),
|
$contacts_obj->get_lists(Api\Acl::READ),
|
||||||
function($element, $index) use($query) {
|
function ($element, $index) use ($search_text)
|
||||||
return $index > 0 && (stripos($element, $query) !== false);
|
{
|
||||||
|
return $index > 0 && (stripos($element, $search_text) !== false);
|
||||||
},
|
},
|
||||||
ARRAY_FILTER_USE_BOTH
|
ARRAY_FILTER_USE_BOTH
|
||||||
);
|
);
|
||||||
foreach($lists as $list_id => $list)
|
foreach($lists as $list_id => $list)
|
||||||
{
|
{
|
||||||
@ -244,12 +251,7 @@ class calendar_owner_etemplate_widget extends Etemplate\Widget\Taglist
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// switch regular JSON response handling off
|
Api\Json\Response::get()->data($results);
|
||||||
Api\Json\Request::isJSONRequest(false);
|
|
||||||
|
|
||||||
header('Content-Type: application/json; charset=utf-8');
|
|
||||||
echo json_encode($results);
|
|
||||||
exit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -280,12 +282,10 @@ class calendar_owner_etemplate_widget extends Etemplate\Widget\Taglist
|
|||||||
}
|
}
|
||||||
$type = $data['type'];
|
$type = $data['type'];
|
||||||
|
|
||||||
// Magicsuggest uses id, not value.
|
|
||||||
$value = array(
|
$value = array(
|
||||||
'id' => $type.$id,
|
'value' => $id,
|
||||||
'value'=> $type.$id,
|
|
||||||
'label' => $title,
|
'label' => $title,
|
||||||
'app' => lang($data['app'])
|
'app' => lang($data['app'])
|
||||||
);
|
);
|
||||||
if(is_array($value['label']))
|
if(is_array($value['label']))
|
||||||
{
|
{
|
||||||
@ -338,8 +338,10 @@ class calendar_owner_etemplate_widget extends Etemplate\Widget\Taglist
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$label = Link::title('api-accounts',$id) ?: Api\Accounts::username($id);
|
$label = Link::title('api-accounts', $id) ?: Api\Accounts::username($id);
|
||||||
}
|
}
|
||||||
return $label;
|
return $label;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Etemplate\Widget::registerWidget(__NAMESPACE__ . '\\calendar_owner_etemplate_widget', array('calendar-owner'));
|
92
calendar/js/CalendarOwner.ts
Normal file
92
calendar/js/CalendarOwner.ts
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* Calendar owner widget
|
||||||
|
*
|
||||||
|
* @license https://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||||
|
* @package calendar
|
||||||
|
* @subpackage etemplate
|
||||||
|
* @link https://www.egroupware.org
|
||||||
|
* @author Nathan Gray
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {Et2Select} from "../../api/js/etemplate/Et2Select/Et2Select";
|
||||||
|
import {css} from "@lion/core";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select widget customised for calendar owner, which can be a user
|
||||||
|
* account or group, or an entry from almost any app, or an email address
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export class CalendarOwner extends Et2Select
|
||||||
|
{
|
||||||
|
|
||||||
|
static get styles()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
...super.styles,
|
||||||
|
css`
|
||||||
|
/* Larger maximum height before scroll*/
|
||||||
|
.select__tags {
|
||||||
|
max-height: 10em;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(...args : any[])
|
||||||
|
{
|
||||||
|
super(...args);
|
||||||
|
this.searchUrl = "calendar_owner_etemplate_widget::ajax_search";
|
||||||
|
this.multiple = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override parent to handle our special additional data types (c#,r#,etc.) when they
|
||||||
|
* are not available client side.
|
||||||
|
*
|
||||||
|
* @param {string|string[]} _value array of selected owners, which can be a number,
|
||||||
|
* or a number prefixed with one character indicating the resource type.
|
||||||
|
*/
|
||||||
|
set_value(_value)
|
||||||
|
{
|
||||||
|
super.set_value(_value);
|
||||||
|
|
||||||
|
// If parent didn't find a label, label will be the same as ID so we
|
||||||
|
// can find them that way
|
||||||
|
let missing_labels = [];
|
||||||
|
for(var i = 0; i < this.value.length; i++)
|
||||||
|
{
|
||||||
|
if(!this.menuItems.find(o => o.value == this.value[i]))
|
||||||
|
{
|
||||||
|
missing_labels.push(this.value[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(Object.keys(missing_labels).length > 0)
|
||||||
|
{
|
||||||
|
// Proper label was not found by parent - ask directly
|
||||||
|
this.egw().json('calendar_owner_etemplate_widget::ajax_owner', [missing_labels], function(data)
|
||||||
|
{
|
||||||
|
for(let owner in data)
|
||||||
|
{
|
||||||
|
if(!owner || typeof owner == "undefined")
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Put it in the list of options
|
||||||
|
let index = this.select_options.findIndex(o => o.value == owner);
|
||||||
|
if(index !== -1)
|
||||||
|
{
|
||||||
|
this.select_options[index] = data[owner];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.select_options.push(data[owner]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.requestUpdate("select_options");
|
||||||
|
this.updateComplete.then(() => {this.syncItemsFromValue();});
|
||||||
|
}, this, true, this).sendRequest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define("calendar-owner", CalendarOwner);
|
@ -23,7 +23,6 @@ import {EgwApp, PushData} from "../../api/js/jsapi/egw_app";
|
|||||||
import {etemplate2} from "../../api/js/etemplate/etemplate2";
|
import {etemplate2} from "../../api/js/etemplate/etemplate2";
|
||||||
import {et2_container} from "../../api/js/etemplate/et2_core_baseWidget";
|
import {et2_container} from "../../api/js/etemplate/et2_core_baseWidget";
|
||||||
import {et2_date} from "../../api/js/etemplate/et2_widget_date";
|
import {et2_date} from "../../api/js/etemplate/et2_widget_date";
|
||||||
import {et2_calendar_owner} from "./et2_widget_owner";
|
|
||||||
import {day, day4, listview, month, planner, week, weekN} from "./View";
|
import {day, day4, listview, month, planner, week, weekN} from "./View";
|
||||||
import {et2_calendar_view} from "./et2_widget_view";
|
import {et2_calendar_view} from "./et2_widget_view";
|
||||||
import {et2_calendar_timegrid} from "./et2_widget_timegrid";
|
import {et2_calendar_timegrid} from "./et2_widget_timegrid";
|
||||||
@ -56,6 +55,7 @@ import {nm_action} from "../../api/js/etemplate/et2_extension_nextmatch_actions"
|
|||||||
import flatpickr from "flatpickr";
|
import flatpickr from "flatpickr";
|
||||||
import Sortable from 'sortablejs/modular/sortable.complete.esm.js';
|
import Sortable from 'sortablejs/modular/sortable.complete.esm.js';
|
||||||
import {tapAndSwipe} from "../../api/js/tapandswipe";
|
import {tapAndSwipe} from "../../api/js/tapandswipe";
|
||||||
|
import {CalendarOwner} from "./CalendarOwner";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UI for calendar
|
* UI for calendar
|
||||||
@ -263,7 +263,7 @@ export class CalendarApp extends EgwApp
|
|||||||
if(sidebox.length == 0 && egw_getFramework() != null)
|
if(sidebox.length == 0 && egw_getFramework() != null)
|
||||||
{
|
{
|
||||||
// Force rollup to load owner widget, it leaves it out otherwise
|
// Force rollup to load owner widget, it leaves it out otherwise
|
||||||
new et2_calendar_owner(_et2.widgetContainer, {});
|
new CalendarOwner();
|
||||||
// Force rollup to load planner widget, it leaves it out otherwise
|
// Force rollup to load planner widget, it leaves it out otherwise
|
||||||
new et2_calendar_planner(_et2.widgetContainer, {});
|
new et2_calendar_planner(_et2.widgetContainer, {});
|
||||||
|
|
||||||
@ -1482,17 +1482,25 @@ export class CalendarApp extends EgwApp
|
|||||||
*/
|
*/
|
||||||
edit_update_participant(input, widget?)
|
edit_update_participant(input, widget?)
|
||||||
{
|
{
|
||||||
if(typeof widget === 'undefined') widget = input;
|
if(typeof widget === 'undefined')
|
||||||
|
{
|
||||||
|
widget = input;
|
||||||
|
}
|
||||||
var content = widget.getInstanceManager().getValues(widget.getRoot());
|
var content = widget.getInstanceManager().getValues(widget.getRoot());
|
||||||
var participant = widget.getRoot().getWidgetById('participant');
|
var participant = <CalendarOwner>widget.getRoot().getWidgetById('participant');
|
||||||
if(!participant) return;
|
if(!participant)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
participant.set_autocomplete_params({exec:{
|
participant.searchOptions = {
|
||||||
start: content.start,
|
exec: {
|
||||||
end: content.end,
|
start: content.start,
|
||||||
duration: content.duration,
|
end: content.end,
|
||||||
whole_day: content.whole_day,
|
duration: content.duration,
|
||||||
}});
|
whole_day: content.whole_day,
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1618,12 +1626,12 @@ export class CalendarApp extends EgwApp
|
|||||||
*/
|
*/
|
||||||
participantOnChange()
|
participantOnChange()
|
||||||
{
|
{
|
||||||
var add = <et2_button> this.et2.getWidgetById('add');
|
var add = <et2_button>this.et2.getWidgetById('add');
|
||||||
var quantity = <et2_number> this.et2.getWidgetById('quantity');
|
var quantity = <et2_number>this.et2.getWidgetById('quantity');
|
||||||
var participant = <et2_calendar_owner> this.et2.getWidgetById('participant');
|
var participant = <Et2CalendarOwner>this.et2.getWidgetById('participant');
|
||||||
|
|
||||||
// array of participants
|
// array of participants
|
||||||
var value = participant.get_value();
|
let value = participant.value;
|
||||||
|
|
||||||
add.set_readonly(value.length <= 0);
|
add.set_readonly(value.length <= 0);
|
||||||
|
|
||||||
@ -3700,27 +3708,27 @@ export class CalendarApp extends EgwApp
|
|||||||
{
|
{
|
||||||
var found = false;
|
var found = false;
|
||||||
var option = data.rows.sel_options[field][i];
|
var option = data.rows.sel_options[field][i];
|
||||||
for(var j in widget.options.select_options)
|
for(var j in widget.select_options)
|
||||||
{
|
{
|
||||||
if(option.value == widget.options.select_options[j].value)
|
if(option.value == widget.select_options[j].value)
|
||||||
{
|
{
|
||||||
widget.options.select_options[j].label = option.label;
|
widget.select_options[j].label = option.label;
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!found)
|
if(!found)
|
||||||
{
|
{
|
||||||
if(!widget.options.select_options.push)
|
if(!widget.select_options.push)
|
||||||
{
|
{
|
||||||
widget.options.select_options = [];
|
widget.select_options = [];
|
||||||
}
|
}
|
||||||
widget.options.select_options.push(option);
|
widget.select_options.push(option);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var in_progress = app.calendar.state_update_in_progress;
|
var in_progress = app.calendar.state_update_in_progress;
|
||||||
app.calendar.state_update_in_progress = true;
|
app.calendar.state_update_in_progress = true;
|
||||||
widget.set_select_options(widget.options.select_options);
|
widget.set_select_options(widget.select_options);
|
||||||
widget.set_value(widget.getValue());
|
widget.set_value(widget.getValue());
|
||||||
|
|
||||||
app.calendar.state_update_in_progress = in_progress;
|
app.calendar.state_update_in_progress = in_progress;
|
||||||
@ -4173,17 +4181,6 @@ export class CalendarApp extends EgwApp
|
|||||||
button.parent().css('margin-right',button.outerWidth(true)+2);
|
button.parent().css('margin-right',button.outerWidth(true)+2);
|
||||||
button.parent().parent().css('white-space','nowrap');
|
button.parent().parent().css('white-space','nowrap');
|
||||||
}
|
}
|
||||||
jQuery(window).on('resize.calendar-owner', function() {
|
|
||||||
var preferred_width = jQuery('#calendar-et2_target').children().first().outerWidth()||0;
|
|
||||||
if(app.calendar && app.calendar.sidebox_et2)
|
|
||||||
{
|
|
||||||
var owner = app.calendar.sidebox_et2.getWidgetById('owner');
|
|
||||||
if(preferred_width && owner.input.hasClass("chzn-done"))
|
|
||||||
{
|
|
||||||
owner.input.next().css('width',preferred_width);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -961,13 +961,13 @@ export class et2_calendar_event extends et2_valueWidget implements et2_IDetached
|
|||||||
let options: any = null;
|
let options: any = null;
|
||||||
if (app.calendar && app.calendar.sidebox_et2 && app.calendar.sidebox_et2.getWidgetById('owner'))
|
if (app.calendar && app.calendar.sidebox_et2 && app.calendar.sidebox_et2.getWidgetById('owner'))
|
||||||
{
|
{
|
||||||
options = app.calendar.sidebox_et2.getWidgetById('owner').taglist.getSelection();
|
options = app.calendar.sidebox_et2.getWidgetById('owner').select_options
|
||||||
}
|
}
|
||||||
if ((isNaN(parseInt(owner)) || parseInt(owner) < 0) && options && typeof options.find == "function")
|
if ((isNaN(parseInt(owner)) || parseInt(owner) < 0) && options && typeof options.find == "function")
|
||||||
{
|
{
|
||||||
let resource = options.find(function (element)
|
let resource = options.find(function (element)
|
||||||
{
|
{
|
||||||
return element.id == owner;
|
return element.value == owner;
|
||||||
}) || {};
|
}) || {};
|
||||||
let matching_participant = typeof resource.resources == "undefined" ?
|
let matching_participant = typeof resource.resources == "undefined" ?
|
||||||
resource :
|
resource :
|
||||||
@ -1201,7 +1201,7 @@ export class et2_calendar_event extends et2_valueWidget implements et2_IDetached
|
|||||||
let options: any = null;
|
let options: any = null;
|
||||||
if (app.calendar && app.calendar.sidebox_et2 && app.calendar.sidebox_et2.getWidgetById('owner'))
|
if (app.calendar && app.calendar.sidebox_et2 && app.calendar.sidebox_et2.getWidgetById('owner'))
|
||||||
{
|
{
|
||||||
options = app.calendar.sidebox_et2.getWidgetById('owner').taglist.getSelection();
|
options = app.calendar.sidebox_et2.getWidgetById('owner').select_options;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1227,7 +1227,7 @@ export class et2_calendar_event extends et2_valueWidget implements et2_IDetached
|
|||||||
{
|
{
|
||||||
var resource = options.find(function(element)
|
var resource = options.find(function(element)
|
||||||
{
|
{
|
||||||
return element.id == parent_owner[i];
|
return element.value == parent_owner[i];
|
||||||
}) || {};
|
}) || {};
|
||||||
if(resource && resource.resources)
|
if(resource && resource.resources)
|
||||||
{
|
{
|
||||||
@ -1249,7 +1249,7 @@ export class et2_calendar_event extends et2_valueWidget implements et2_IDetached
|
|||||||
var resource;
|
var resource;
|
||||||
if (options && options.find && (resource = options.find(function (element)
|
if (options && options.find && (resource = options.find(function (element)
|
||||||
{
|
{
|
||||||
return element.id === id;
|
return element.value === id;
|
||||||
})) && resource.resources)
|
})) && resource.resources)
|
||||||
{
|
{
|
||||||
participants = participants.concat(resource.resources);
|
participants = participants.concat(resource.resources);
|
||||||
|
@ -1,152 +0,0 @@
|
|||||||
/*
|
|
||||||
* Egroupware
|
|
||||||
*
|
|
||||||
* @license https://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
|
||||||
* @package calendar
|
|
||||||
* @subpackage etemplate
|
|
||||||
* @link https://www.egroupware.org
|
|
||||||
* @author Nathan Gray
|
|
||||||
*/
|
|
||||||
|
|
||||||
import {et2_register_widget} from "../../api/js/etemplate/et2_core_widget.ts";
|
|
||||||
import {et2_taglist_email} from "../../api/js/etemplate/et2_widget_taglist";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tag list widget customised for calendar owner, which can be a user
|
|
||||||
* account or group, or an entry from almost any app, or an email address
|
|
||||||
*
|
|
||||||
* A cross between auto complete, selectbox and chosen multiselect
|
|
||||||
*
|
|
||||||
* Uses MagicSuggest library
|
|
||||||
* @see http://nicolasbize.github.io/magicsuggest/
|
|
||||||
* @augments et2_taglist_email
|
|
||||||
*/
|
|
||||||
export class et2_calendar_owner extends et2_taglist_email
|
|
||||||
{
|
|
||||||
static readonly _attributes = {
|
|
||||||
"autocomplete_url": {
|
|
||||||
"default": "calendar_owner_etemplate_widget::ajax_owner"
|
|
||||||
},
|
|
||||||
"autocomplete_params": {
|
|
||||||
"name": "Autocomplete parameters",
|
|
||||||
"type": "any",
|
|
||||||
"default": {},
|
|
||||||
"description": "Extra parameters passed to autocomplete URL. It should be a stringified JSON object."
|
|
||||||
},
|
|
||||||
allowFreeEntries: {
|
|
||||||
"default": false,
|
|
||||||
ignore: true
|
|
||||||
},
|
|
||||||
select_options: {
|
|
||||||
"type": "any",
|
|
||||||
"name": "Select options",
|
|
||||||
// Set to empty object to use selectbox's option finding
|
|
||||||
"default": {},
|
|
||||||
"description": "Internally used to hold the select options."
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Allows sub-widgets to override options to the library
|
|
||||||
lib_options = {
|
|
||||||
autoSelect: false,
|
|
||||||
groupBy: 'app',
|
|
||||||
minChars: 2,
|
|
||||||
selectFirst: true,
|
|
||||||
// This option will also expand when the selection is changed
|
|
||||||
// via code, which we do not want
|
|
||||||
//expandOnFocus: true
|
|
||||||
toggleOnClick: true
|
|
||||||
};
|
|
||||||
|
|
||||||
doLoadingFinished()
|
|
||||||
{
|
|
||||||
super.doLoadingFinished();
|
|
||||||
|
|
||||||
var widget = this;
|
|
||||||
// onChange fired when losing focus, which is different from normal
|
|
||||||
this._oldValue = this.taglist.getValue();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
selectionRenderer(item)
|
|
||||||
{
|
|
||||||
if(this && this.options && this.options.allowFreeEntries)
|
|
||||||
{
|
|
||||||
return super.selectionRenderer(item);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var label = jQuery('<span>').text(item.label);
|
|
||||||
if (item.class) label.addClass(item.class);
|
|
||||||
if (typeof item.title != 'undefined') label.attr('title', item.title);
|
|
||||||
if (typeof item.data != 'undefined') label.attr('data', item.data);
|
|
||||||
if (typeof item.icon != 'undefined')
|
|
||||||
{
|
|
||||||
var wrapper = jQuery('<div>').addClass('et2_taglist_tags_icon_wrapper');
|
|
||||||
jQuery('<span/>')
|
|
||||||
.addClass('et2_taglist_tags_icon')
|
|
||||||
.css({"background-image": "url("+(item.icon.match(/^(http|https|\/)/) ? item.icon : egw.image(item.icon, item.app))+")"})
|
|
||||||
.appendTo(wrapper);
|
|
||||||
label.appendTo(wrapper);
|
|
||||||
return wrapper;
|
|
||||||
}
|
|
||||||
return label;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getValue()
|
|
||||||
{
|
|
||||||
if(this.taglist == null) return null;
|
|
||||||
return this.taglist.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Override parent to handle our special additional data types (c#,r#,etc.) when they
|
|
||||||
* are not available client side.
|
|
||||||
*
|
|
||||||
* @param {string|string[]} _value array of selected owners, which can be a number,
|
|
||||||
* or a number prefixed with one character indicating the resource type.
|
|
||||||
*/
|
|
||||||
set_value(_value)
|
|
||||||
{
|
|
||||||
super.set_value(_value);
|
|
||||||
|
|
||||||
// If parent didn't find a label, label will be the same as ID so we
|
|
||||||
// can find them that way
|
|
||||||
let missing_labels = [];
|
|
||||||
for(var i = 0; i < this.options.value.length; i++)
|
|
||||||
{
|
|
||||||
var value = this.options.value[i];
|
|
||||||
if(value.id == value.label)
|
|
||||||
{
|
|
||||||
missing_labels.push(value.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(Object.keys(missing_labels).length > 0)
|
|
||||||
{
|
|
||||||
// Proper label was not found by parent - ask directly
|
|
||||||
egw.json('calendar_owner_etemplate_widget::ajax_owner',[missing_labels],function(data) {
|
|
||||||
for(let owner in data)
|
|
||||||
{
|
|
||||||
if(!owner || typeof owner == "undefined") continue;
|
|
||||||
let idx = this.options.value.find(element => element.id == owner);
|
|
||||||
if(idx)
|
|
||||||
{
|
|
||||||
idx = jQuery.extend(idx, data[owner]);
|
|
||||||
}
|
|
||||||
// Put it in the list of options for next time
|
|
||||||
this.options.select_options.push(data[owner]);
|
|
||||||
}
|
|
||||||
this.set_value(this.options.value);
|
|
||||||
}, this,true,this).sendRequest();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(this.taglist)
|
|
||||||
{
|
|
||||||
this.taglist.clear(true);
|
|
||||||
this.taglist.addToSelection(this.options.value,true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
et2_register_widget(et2_calendar_owner, ["calendar-owner"]);
|
|
@ -408,11 +408,11 @@ export class et2_calendar_planner extends et2_calendar_view implements et2_IDeta
|
|||||||
row_labels: function() {
|
row_labels: function() {
|
||||||
var labels = [];
|
var labels = [];
|
||||||
var already_added = [];
|
var already_added = [];
|
||||||
var options = false;
|
var options = [];
|
||||||
var resource = null;
|
var resource = null;
|
||||||
if(app.calendar && app.calendar.sidebox_et2 && app.calendar.sidebox_et2.getWidgetById('owner'))
|
if(app.calendar && app.calendar.sidebox_et2 && app.calendar.sidebox_et2.getWidgetById('owner'))
|
||||||
{
|
{
|
||||||
options = app.calendar.sidebox_et2.getWidgetById('owner').taglist.getSelection();
|
options = app.calendar.sidebox_et2.getWidgetById('owner').select_options;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -424,14 +424,14 @@ export class et2_calendar_planner extends et2_calendar_view implements et2_IDeta
|
|||||||
// Handle grouped resources like mailing lists - pull it from sidebox owner
|
// Handle grouped resources like mailing lists - pull it from sidebox owner
|
||||||
// and expand to their contents
|
// and expand to their contents
|
||||||
if(options && options.find &&
|
if(options && options.find &&
|
||||||
((resource = options.find(function(element) {return element.id == user;}) || {}) || isNaN(user)))
|
((resource = options.find(function(element) {return element.value == user;}) || {}) || isNaN(user)))
|
||||||
{
|
{
|
||||||
if(resource && resource.resources)
|
if(resource && resource.resources)
|
||||||
{
|
{
|
||||||
for(var j = 0; j < resource.resources.length; j++)
|
for(var j = 0; j < resource.resources.length; j++)
|
||||||
{
|
{
|
||||||
var id = resource.resources[j];
|
var id = resource.resources[j];
|
||||||
if(already_added.indexOf(''+id) < 0)
|
if(already_added.indexOf('' + id) < 0)
|
||||||
{
|
{
|
||||||
labels.push({
|
labels.push({
|
||||||
id: id,
|
id: id,
|
||||||
@ -2128,7 +2128,7 @@ export class et2_calendar_planner extends et2_calendar_view implements et2_IDeta
|
|||||||
|
|
||||||
if(app.calendar && app.calendar.sidebox_et2 && app.calendar.sidebox_et2.getWidgetById('owner'))
|
if(app.calendar && app.calendar.sidebox_et2 && app.calendar.sidebox_et2.getWidgetById('owner'))
|
||||||
{
|
{
|
||||||
options = app.calendar.sidebox_et2.getWidgetById('owner').taglist.getSelection();
|
options = app.calendar.sidebox_et2.getWidgetById('owner').select_options;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -2143,7 +2143,7 @@ export class et2_calendar_planner extends et2_calendar_view implements et2_IDeta
|
|||||||
if(options.find &&
|
if(options.find &&
|
||||||
((resource = options.find(function (element)
|
((resource = options.find(function (element)
|
||||||
{
|
{
|
||||||
return element.id == user;
|
return element.value == user;
|
||||||
}))))
|
}))))
|
||||||
{
|
{
|
||||||
// Members found
|
// Members found
|
||||||
|
@ -440,7 +440,7 @@ export class et2_calendar_view extends et2_valueWidget
|
|||||||
let options = false;
|
let options = false;
|
||||||
if(app.calendar && app.calendar.sidebox_et2 && app.calendar.sidebox_et2.getWidgetById('owner'))
|
if(app.calendar && app.calendar.sidebox_et2 && app.calendar.sidebox_et2.getWidgetById('owner'))
|
||||||
{
|
{
|
||||||
options = app.calendar.sidebox_et2.getWidgetById('owner').taglist.getSelection();
|
options = app.calendar.sidebox_et2.getWidgetById('owner').select_options;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -448,7 +448,7 @@ export class et2_calendar_view extends et2_valueWidget
|
|||||||
}
|
}
|
||||||
if(options && options.find)
|
if(options && options.find)
|
||||||
{
|
{
|
||||||
var found = options.find(function(element) {return element.id == user;}) || {};
|
var found = options.find(function(element) {return element.value == user;}) || {};
|
||||||
if(found && found.label && found.label !== user)
|
if(found && found.label && found.label !== user)
|
||||||
{
|
{
|
||||||
label = found.label;
|
label = found.label;
|
||||||
|
@ -70,13 +70,6 @@
|
|||||||
#calendar-et2_target > div {
|
#calendar-et2_target > div {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
#calendar-sidebox_owner {
|
|
||||||
width: 90%;
|
|
||||||
}
|
|
||||||
#calendar-sidebox_owner ~ * {
|
|
||||||
vertical-align: top;
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
#calendar-sidebox_cat_id {
|
#calendar-sidebox_cat_id {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
@ -120,10 +113,6 @@
|
|||||||
#calendar-sidebox_date .calendar_calHoliday {
|
#calendar-sidebox_date .calendar_calHoliday {
|
||||||
background-color: rgba(103, 159, 210, 0.5);
|
background-color: rgba(103, 159, 210, 0.5);
|
||||||
}
|
}
|
||||||
#calendar-sidebox_owner .ms-helper {
|
|
||||||
padding: 2px;
|
|
||||||
background-color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
#calendar-sidebox_date .flatpickr-months {
|
#calendar-sidebox_date .flatpickr-months {
|
||||||
gap: 0;
|
gap: 0;
|
||||||
|
@ -57,13 +57,18 @@
|
|||||||
<select label="Notify externals" id="notify_externals" span="all" align="right"/>
|
<select label="Notify externals" id="notify_externals" span="all" align="right"/>
|
||||||
</row>
|
</row>
|
||||||
<row disabled="@no_add" height="60" class="et2_toolbar">
|
<row disabled="@no_add" height="60" class="et2_toolbar">
|
||||||
<calendar-owner id="participant" allowFreeEntries="true" span="4" empty_label="Add new participants or resource" onchange="app.calendar.participantOnChange"/>
|
<calendar-owner id="participant" allowFreeEntries="true" span="4"
|
||||||
<hbox width="100%">
|
empty_label="Add new participants or resource"
|
||||||
<textbox type="integer" id="quantity" min="1" size="3" statustext="Number of resources to be booked"/>
|
onchange="app.calendar.participantOnChange"/>
|
||||||
<select class="selectRole" id="role"/>
|
<hbox width="100%">
|
||||||
<button id="add" align="right" image="add" novalidate="1" statustext="Please first select participants on the left and then use plus button to add them" background_image="1" readonly="true" ro_image="add"/>
|
<textbox type="integer" id="quantity" min="1" size="3"
|
||||||
</hbox>
|
statustext="Number of resources to be booked"/>
|
||||||
</row>
|
<select class="selectRole" id="role"/>
|
||||||
|
<button id="add" align="right" image="add" novalidate="1"
|
||||||
|
statustext="Please first select participants on the left and then use plus button to add them"
|
||||||
|
background_image="1" readonly="true" ro_image="add"/>
|
||||||
|
</hbox>
|
||||||
|
</row>
|
||||||
<row class="th thb">
|
<row class="th thb">
|
||||||
<description value="Type"/>
|
<description value="Type"/>
|
||||||
<description value="Participants"/>
|
<description value="Participants"/>
|
||||||
|
@ -91,13 +91,6 @@
|
|||||||
#calendar-et2_target > div {
|
#calendar-et2_target > div {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
#calendar-sidebox_owner {
|
|
||||||
width: 90%;
|
|
||||||
}
|
|
||||||
#calendar-sidebox_owner ~ * {
|
|
||||||
vertical-align: top;
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
#calendar-sidebox_cat_id {
|
#calendar-sidebox_cat_id {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
@ -140,10 +133,6 @@
|
|||||||
#calendar-sidebox_date .calendar_calHoliday {
|
#calendar-sidebox_date .calendar_calHoliday {
|
||||||
background-color: rgba(103, 159, 210, 0.5);
|
background-color: rgba(103, 159, 210, 0.5);
|
||||||
}
|
}
|
||||||
#calendar-sidebox_owner .ms-helper {
|
|
||||||
padding: 2px;
|
|
||||||
background-color: white;
|
|
||||||
}
|
|
||||||
#calendar-sidebox_date .flatpickr-months {
|
#calendar-sidebox_date .flatpickr-months {
|
||||||
gap: 0;
|
gap: 0;
|
||||||
background-color: initial;
|
background-color: initial;
|
||||||
|
@ -79,13 +79,6 @@
|
|||||||
#calendar-et2_target > div {
|
#calendar-et2_target > div {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
#calendar-sidebox_owner {
|
|
||||||
width: 90%;
|
|
||||||
}
|
|
||||||
#calendar-sidebox_owner ~ * {
|
|
||||||
vertical-align: top;
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
#calendar-sidebox_cat_id {
|
#calendar-sidebox_cat_id {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
@ -128,10 +121,6 @@
|
|||||||
#calendar-sidebox_date .calendar_calHoliday {
|
#calendar-sidebox_date .calendar_calHoliday {
|
||||||
background-color: rgba(103, 159, 210, 0.5);
|
background-color: rgba(103, 159, 210, 0.5);
|
||||||
}
|
}
|
||||||
#calendar-sidebox_owner .ms-helper {
|
|
||||||
padding: 2px;
|
|
||||||
background-color: white;
|
|
||||||
}
|
|
||||||
#calendar-sidebox_date .flatpickr-months {
|
#calendar-sidebox_date .flatpickr-months {
|
||||||
gap: 0;
|
gap: 0;
|
||||||
background-color: initial;
|
background-color: initial;
|
||||||
|
Loading…
Reference in New Issue
Block a user