/* * Tine 2.0 * * @license http://www.gnu.org/licenses/agpl.html AGPL Version 3 * @author Cornelius Weiss * @copyright Copyright (c) 2015 Metaways Infosystems GmbH (http://www.metaways.de) */ Tine.Calendar.EventContextAttendeesItem = Ext.extend(Ext.menu.Item, { event: null, datetime: null, initComponent: function() { this.app = Tine.Tinebase.appMgr.get('Calendar'); this.text = this.app.i18n._('Attendee/Resources') this.hidden = this.app.getMainScreen().getCenterPanel().isActiveView('Grid') || ! ( this.event && this.event.get('editGrant') && Tine.Tinebase.appMgr.get('Calendar').featureEnabled('featureExtendedEventContextActions') ); this.menu = []; this.view = this.app.getMainScreen().getCenterPanel().getCalendarPanel(this.app.getMainScreen().getCenterPanel().activeView).getView(); var attendeeFilter = Ext.state.Manager.get('calendar-attendee-filter-grid'), explicitAttendee = attendeeFilter && Ext.isArray(attendeeFilter.explicitAttendee) ? attendeeFilter.explicitAttendee : [], currentAttendee = Tine.Calendar.Model.Attender.getAttendeeStore(this.event ? this.event.get('attendee') : []); currentAttendee.each(function(r) { this.menu.push(Object.assign({ record: r, checked: true, handleClick: this.handleClick }, this.renderAttender(r))); }, this); Ext.each(explicitAttendee, function(attendeeData) { // memberOf is a filter only type and can't be an event attendee if (attendeeData.user_type === 'memberOf') return; var r = new Tine.Calendar.Model.Attender(attendeeData, 'new-' + Ext.id()), isCurrent = Tine.Calendar.Model.Attender.getAttendeeStore.getAttenderRecord(currentAttendee, r); if (! isCurrent) { this.menu.push(Object.assign({ record: r, checked: false, handleClick: this.handleClick }, this.renderAttender(r))); } }, this); var other = new Ext.Action({ text: this.app.i18n._('Additional Attendees...'), handler: this.onOtherClick, scope: this }); this.menu.push(other); Tine.Calendar.EventContextAttendeesItem.superclass.initComponent.call(this); this.menu.on('hide', this.onMenuHide, this); // NOTE: the submenu is rendered lazily on hover - async names (HTMLProxy) would never be replaced in the DOM this.menu.items.each(function(item) { if (item.namePromise) { item.namePromise.then((name) => { if (!item.isDestroyed) { item.setText(item.typeHtml + Ext.util.Format.htmlEncode(name)); } }); } }, this); }, /** * returns menu item config (text) for given attender * attendee names might be rendered async (e.g. contact title templates). In this case the name gets * resolved and set later, see initComponent * * @param {Tine.Calendar.Model.Attender} attender * @return {Object} {text, typeHtml, namePromise} */ renderAttender: function(attender) { const proto = Tine.Calendar.AttendeeGridPanel.prototype; const iconStyle = 'display: inline-block; vertical-align: middle; width: 16px; height: 16px; margin: 0 5px 0 0;'; // resources: use the specific resource type icon instead of the generic type icon + icon in name const resourceIcon = attender.get('user_type') === 'resource' ? proto.renderAttenderResourceIcon.call(proto, attender.get('user_id')) : ''; const name = proto.renderAttenderName.call(proto, attender.get('user_id'), resourceIcon ? {noIcon: true} : false, attender); // NOTE: String.prototype has asString too - plain strings are already html const isAsync = !!name?.isHTMLProxy; const typeHtml = resourceIcon ? resourceIcon.replace('