import { EventView } from '../../../mel_metapage/js/lib/calendar/event/event_view.js';
import { GuestsPart } from '../../../mel_metapage/js/lib/calendar/event/parts/guestspart.js';
import {
AExternalLocationPart,
LocationPartManager,
} from '../../../mel_metapage/js/lib/calendar/event/parts/location_part.js';
import { BnumLog } from '../../../mel_metapage/js/lib/classes/bnum_log.js';
import {
BnumMessage,
eMessageType,
} from '../../../mel_metapage/js/lib/classes/bnum_message.js';
import { MelEnumerable } from '../../../mel_metapage/js/lib/classes/enum.js';
import { Tuple } from '../../../mel_metapage/js/lib/classes/tuple.js';
import { EMPTY_STRING } from '../../../mel_metapage/js/lib/constants/constants.js';
import { MelHtml } from '../../../mel_metapage/js/lib/html/JsHtml/MelHtml.js';
import { BnumEvent } from '../../../mel_metapage/js/lib/mel_events.js';
import { MelObject } from '../../../mel_metapage/js/lib/mel_object.js';
import { Mel_Promise } from '../../../mel_metapage/js/lib/mel_promise.js';
import { ResourceDialogPage } from '../../skins/mel_elastic/js_template/resource_location.js';
export { ResourceLocation };
/**
* Ajoute une location à la liste de location d'un évènement
* @module Resources/Location
* @local ResourceLocation
*/
/**
* @class
* @classdesc Location d'un évènement pour une ressource.
* @extends AExternalLocationPart
* @frommodule EventView/Parts/Location
*/
class ResourceLocation extends AExternalLocationPart {
/**
* Constructeur de la classe
* @param {*} attendee Participant du plugin `Calendar`
* @param {number} index Id de la location
*/
constructor(attendee, index) {
super(EMPTY_STRING, index);
/**
* Participant du plugin `Calendar`
* @private
*/
this._attendee = attendee;
/**
* Html de la location
* @private
* @type {external:jQuery}
*/
this._$page = null;
/**
* Données de la location
* @private
* @type {ResourceDialogPage}
*/
this._page = null;
/**
* Action à faire après avoir cliquer sur le bouton de la localisation
* @type {BnumEvent<EventClickCallback>}
*/
this.onclickafter = new BnumEvent();
}
/**
* Met en forme le bouton et les participants
* @async
* @private
* @returns {Promise}
*/
async _load_attendee_data() {
BnumMessage.SetBusyLoading();
await MelObject.Empty().http_internal_post({
task: 'mel_cal_resources',
action: 'load_custom',
params: {
_resources: [this._attendee.email],
},
on_success: (data) => {
if (typeof data === 'string') data = JSON.parse(data);
if (data && data.length && this._$page && this._$page.length) {
const current_resource = data[0];
this.location = `${current_resource.name} - ${current_resource.street} ${current_resource.postalcode} ${current_resource.locality}`;
this.update_and_remove_same_location();
this.onchange.call();
this._$page
.find('button')
.html(
$('<span>')
.css('vertical-align', 'super')
.text(
`${current_resource.name} - ${current_resource.street} ${current_resource.postalcode} ${current_resource.locality}`,
),
)
.prepend(
MelHtml.start
.icon('ads_click')
.css('color', 'var(--mel-button-text-color)')
.css('margin-right', '5px')
.end()
.generate(),
)
.attr('resource', current_resource.email)
.removeAttr('disabled')
.removeClass('disabled');
if (!window.selected_resources) window.selected_resources = {};
window.selected_resources[this.id] = current_resource;
}
},
});
BnumMessage.StopBusyLoading();
}
/**
* Met à jours le participant de type flex office associé à cette localisation pour qu'il est la bonne mise en forme.
* @private
* @async
* @return {Promise}
*/
async _update_old_attendees() {
await ResourceLocation.SetAttendeeMechanics(this._attendee.email);
}
_get_email() {
return this._attendee?.email || this._$page.find('button').attr('resource');
}
/**
* Génère la location et l'ajoute au parent
* @override
* @param {external:jQuery} $parent
* @returns {ResourceLocation} Chaîne
*/
generate($parent) {
super.generate($parent);
this.page = new ResourceDialogPage(
this._attendee,
this,
this?.resource_type?.(),
);
this.page.onclickafter.push(this.onclickafter.call.bind(this.onclickafter));
this._$page = this.page.get().generate().appendTo($parent);
if (this._attendee) {
this._update_old_attendees();
this._load_attendee_data();
}
EventView.INSTANCE.parts.recurrence._$fakeField
.val(EMPTY_STRING)
.attr('disabled', 'disabled')
.addClass('disabled')
.change();
return this;
}
changed_to_this() {
if (!window.start_planify) this.force_click();
}
/**
* Supprime les localisations de type "Emplacement" qui ont la même valeur que cette localisation
*/
update_and_remove_same_location() {
const objs = EventView.INSTANCE.parts.location.locations;
for (const key in objs) {
if (Object.hasOwnProperty.call(objs, key)) {
const element = objs[key];
if (element.location === this.location) {
EventView.INSTANCE.parts.location.remove(element.id);
break;
}
}
}
}
hide_attendee() {
return $(`.mel-attendee[data-email="${this._get_email()}"]`)
.addClass('not-here')
.css('display', 'none');
}
show_attendee() {
return $(`.mel-attendee[data-email="${this._get_email()}"]`)
.removeClass('not-here')
.css('display', EMPTY_STRING);
}
/**
* Force le click sur le bouton générer par cette classe
*/
force_click() {
this._$page.find('button').first().click();
}
/**
* Si la localisation est valide et correspond à ce que l'on attend
*
* Un emplacement est TOUJOURS valide.
* @returns {boolean}
* @override
*/
is_valid() {
return !!this._$page.find('button').attr('resource');
}
/**
* Action à faire si la localisation n'est pas valide
* @override
*/
invalid_action() {
BnumMessage.DisplayMessage(
'Please select a resource for this event.',
eMessageType.Error,
);
this._$page.find('button').focus();
}
/**
* Libère les données en mémoire.
* @override
*/
destroy() {
if (!EventView.INSTANCE.dialog_closed && window.selected_resources) {
$(
`.mel-attendee[data-email="${window.selected_resources[this.id].email}"] .close-button`,
).click();
}
if (window.selected_resources && window.selected_resources[this.id])
delete window.selected_resources[this.id];
if (this.page.dialog) {
try {
this.page.dialog.destroy();
} catch (error) {
BnumLog.warning('ResourceLocation/destory', 'Already deleted');
}
this.page.dialog = null;
}
if (this.page) this.page.onclickafter.clear();
if (
MelEnumerable.from(EventView.INSTANCE.parts.location.locations)
.select((x) => x.value.option_value())
.where((x) => x === 'flex-office')
.count() -
1 >
0
) {
EventView.INSTANCE.parts.recurrence._$fakeField
.val(EMPTY_STRING)
.attr('disabled', 'disabled')
.addClass('disabled')
.change();
} else {
EventView.INSTANCE.parts.recurrence._$fakeField
.removeAttr('disabled')
.removeClass('disabled');
}
}
/**
* Met à jours le participant de type flex office associé à cette localisation pour qu'il est la bonne mise en forme.
* @static
* @param {string} email Participant associé
* @returns {Promise}
*/
static async SetAttendeeMechanics(email) {
await Mel_Promise.wait(
() => $(`.mel-attendee[data-email="${email}"]`).length,
);
$(`.mel-attendee[data-email="${email}"]`)
.attr('draggable', false)
.css('cursor', 'not-allowed')
.find('.close-button')
.css('display', 'none');
}
/**
* Génère les différentes localisations
* @override
* @static
* @param {*} event Event du plugin calendar
* @returns {Array<Tuple<typeof AExternalLocationPart, *>>}
*/
static Instantiate(event) {
if (event.attendees && event.attendees.length) {
return MelEnumerable.from(event.attendees)
.where((a) => a.cutype === GuestsPart.ROLES.resource)
.select((x) => new Tuple(ResourceLocation, x))
.toArray();
} else return [];
}
/**
* Vérifie si la localisation est de ce type
* @static
* @override
* @param {*} event — Event du plugin calendar
*/
static Has(event) {
return (
event.attendees &&
event.attendees.length &&
MelEnumerable.from(event.attendees).any(
(a) => a.cutype === GuestsPart.ROLES.resource,
)
);
}
/**
* Nombre maximum de cette classe qui peut être utilisé
* @override
* @returns {number} Nombre maximum de ressources
* @default Number.POSITIVE_INFINITY
* @static
*/
static Max() {
return Number.POSITIVE_INFINITY;
}
/**
* Valeur de l'option qui désigne cette classe
* @returns {string}
* @default 'resource'
* @static
*/
static OptionValue() {
return 'resource';
}
/**
* Nom du plugin utiliser pour récupèrer le nom inscrit dans le select
* @static
* @returns {string}
* @default 'mel_cal_resources'
*/
static PluginName() {
return 'mel_cal_resources';
}
/**
* Génère les ResourceLocations individuels.
*
* Elles sont de type `ResourceLocations<T>` ou `T` est le type de la ressource.
* @static
*/
static GenerateUniqueResources() {
var renameFunction = function (name, fn) {
return eval(`
(() => {
${(fn + EMPTY_STRING).replaceAll(fn.name, name)}
return ${name};
})();
`);
};
const resources = rcmail.env.cal_resources;
let tmp;
for (const key in resources.resources) {
if (Object.hasOwnProperty.call(resources.resources, key)) {
const iterator = resources.resources[key];
if (iterator.is_option) {
tmp = renameFunction(
`ResourceLocation_${key.replaceAll('-', '_').replaceAll(' ', '_')}`,
ResourceLocation,
);
tmp.resource_type = key;
tmp.OptionValue = function () {
return this.resource_type;
}.bind(tmp);
tmp.Has = function (event) {
return (
ResourceLocation.Has(event) &&
MelEnumerable.from(event.attendees).any(
(x) =>
x.resource_type === `X-${this.resource_type.toUpperCase()}`,
)
);
}.bind(tmp);
tmp.Instantiate = function (event) {
if (event.attendees && event.attendees.length) {
return MelEnumerable.from(event.attendees)
.where((a) => a.cutype === GuestsPart.ROLES.resource)
.where(
(x) =>
x.resource_type === `X-${this.resource_type.toUpperCase()}`,
)
.select((x) => new Tuple(this, x))
.toArray();
} else return [];
}.bind(tmp);
tmp.Max = ResourceLocation.Max.bind(tmp);
eval(`tmp.prototype.resource_type = () => '${key}'`);
LocationPartManager.AddExtraLocationType(tmp);
}
}
}
}
}
if (!window.mel_cal_resource_loaded) {
if (rcmail.env.cal_resources.enable_all)
//Ajoute les resources au select
LocationPartManager.AddExtraLocationType(ResourceLocation);
ResourceLocation.GenerateUniqueResources();
rcmail.addEventListener('location.changed', (args) => {
const { new: new_loc, last } = args;
if (last.constructor.name.includes(ResourceLocation.name)) {
last.hide_attendee();
} else if (new_loc.constructor.name.includes(ResourceLocation.name)) {
new_loc.show_attendee();
}
if (
MelEnumerable.from(EventView.INSTANCE.parts.location.locations)
.select((x) => x.value.option_value())
.where((x) => x === 'flex-office')
.any()
) {
EventView.INSTANCE.parts.recurrence._$fakeField
.val(EMPTY_STRING)
.attr('disabled', 'disabled')
.addClass('disabled')
.change();
} else {
EventView.INSTANCE.parts.recurrence._$fakeField
.removeAttr('disabled')
.removeClass('disabled');
}
});
rcmail.addEventListener('calendar.save_event.before', () => {
for (const iterator of $('.mel-attendee.not-here')) {
$(iterator).find('button').click();
}
});
//Signifie que les données de ce plugin sont chargés
window.mel_cal_resource_loaded = true;
}