import { MelEnumerable } from '../../../mel_metapage/js/lib/classes/enum.js';
import { EMPTY_STRING } from '../../../mel_metapage/js/lib/constants/constants.js';
import { MelObject } from '../../../mel_metapage/js/lib/mel_object.js';
export { FavoriteLoader };
/**
* Contient les classes utiles pour la récupération et gestion des resources favorites
* @module Resources/Favorites/Loaders
* @local FavoriteData
* @local FavoriteLoader
* @local FavoriteLoaderWrapper
*/
/**
* @typedef FavoriteData
* @property {string} date
* @property {import('./resource_base.js').ResourceData[]} data
*
*/
/**
* @class
* @classdesc Récupère les données favorites. Récupère les favoris depuis le stockage local. Chaque jour, les données sont récupérés depuis le serveur avant d'être stocké en local.
* @extends {MelObject}
*/
class FavoriteLoader extends MelObject {
/**
* Constructeur de la classe.
*
* Un loader existe par type de ressource.
* @param {string} type Type de ressource. (flex office etc....)
*/
constructor(type) {
super(type);
}
/**
* Fonction principale de la classe
* @private
* @param {string} type Type de ressource. (flex office etc....)
* @override
*/
main(type) {
super.main(type);
this._type = type;
this.key = EMPTY_STRING;
Object.defineProperties(this, {
key: {
value: `favorite-${this._type}`,
enumerable: true,
writable: false,
configurable: false,
},
});
}
/**
* Sauvegarde des favoris en local
* @param {import('./resource_base.js').ResourceData[]} favs Favoris à sauvegarder
* @returns {FavoriteLoader} Chaînage
*/
save_favorites(favs) {
let loaded = this._set_date(moment().startOf('day'));
loaded.data = favs;
this.save(this.key, loaded);
return this;
}
/**
* Ajoute des favoris au stockage local
* @param {...import('./resource_base.js').ResourceData} favs Favoris à ajouter
* @returns {FavoriteLoader} chaînage
*/
add_favorites(...favs) {
let loaded = this._get_data_saved();
for (const iterator of favs) {
if (!loaded.data.filter((x) => x.email === iterator.email).length) {
loaded.data.push(iterator);
}
}
return this.save_favorites(loaded.data);
}
/**
* Supprime des favoris. Se base sur les emails qui sont uniques.
* @param {...string} emails Favoris à supprimer
* @returns {FavoriteLoader} Chaînage
*/
remove_favorites(...emails) {
let loaded = this._get_data_saved();
loaded.data = MelEnumerable.from(loaded.data)
.where((x) => !emails.includes(x.email))
.toArray();
return this.save_favorites(loaded.data);
}
clear() {
this._cleared = true;
return this._set_date(moment().startOf('day').substract(1, 'd'));
}
/**
* Vérifie si les données sont obsolète ou non
* @param {?FavoriteData} [loaded=null] Données déjà chargés. Si ce n'est pas le cas, les récupère depuis lo stockage local. Evite les chargements multiples.
* @returns {boolean} Si vrai : pas obsolète, sinon obsolète.
*/
is_same_date(loaded = null) {
return (
(loaded?.date ?? this._get_data_saved().date) ===
moment().startOf('day').format()
);
}
/**
* Force la récupèration des données, sans passer par la récupération serveur.
* @returns {import('./resource_base.js').ResourceData[]}
*/
force_load_favorites() {
return this._get_data_saved().data;
}
/**
* Récupère les favoris, si les favoris local sont obsolète, les récupères depuis la bdd.
* @returns {Promise<import('./resource_base.js').ResourceData[]}
* @async
*/
async load_favorites() {
const loaded = this._get_data_saved();
if (this._cleared || !this.is_same_date(loaded)) {
const busy = rcmail.set_busy(true, 'loading');
this._cleared = false;
await this.http_internal_post({
task: 'mel_cal_resources',
action: 'load_favorites',
on_success: (rcs) => {
if (typeof rcs === 'string') rcs = JSON.parse(rcs);
this.save_favorites(rcs || []);
},
}).always(() => {
rcmail.set_busy(false, 'loading', busy);
});
return await this.load_favorites();
} else return loaded.data;
}
/**
* Met le jour en cours en données local.
* @private
* @param {external:moment} date
* @returns {FavoriteData}
*/
_set_date(date) {
let loaded = this._get_data_saved();
loaded.date = date.format();
return loaded;
}
/**
* Récupère les données locales
* @private
* @returns {FavoriteData}
*/
_get_data_saved() {
return this.load(this.key, { date: moment().format(), data: [] });
}
/**
* Sauvegarde les favoris dans le stockage local
* @param {string} type Type de resource (flex office etc....)
* @param {import('./resource_base.js').ResourceData[]} favs Favoris à sauvegarder
* @returns {FavoriteLoader} Instance
* @static
*/
static Save(type, favs) {
return this._Get(type).save_favorites(favs);
}
/**
* Ajoute des favoris au stockage local
* @param {string} type Type de resource (flex office etc....)
* @param {...import('./resource_base.js').ResourceData} favs Favoris à sauvegarder
* @returns {FavoriteLoader} Instance
* @static
*/
static Add(type, ...favs) {
return this._Get(type).add_favorites(...favs);
}
/**
* Supprime des favoris. Se base sur les emails qui sont uniques.
* @param {string} type Type de resource (flex office etc....)
* @param {...string} emails Favoris à supprimer
* @returns {FavoriteLoader} Chaînage
* @static
*/
static Remove(type, ...emails) {
return this._Get(type).remove_favorites(...emails);
}
/**
* Vérifie si les données sont obsolète ou non
* @param {string} type Type de resource (flex office etc....)
* @returns {boolean} Si vrai : pas obsolète, sinon obsolète.
* @static
*/
static IsSameDate(type) {
return this._Get(type).is_same_date();
}
/**
* Le prochain chargement de favoris sera depuis la bdd.
* @param {?string} [type=null]
* @returns {FavoriteData | typeof FavoriteLoader}
*/
static Clear(type = null) {
if (type) return this._Get(type).clear();
else {
const keys = Object.keys(
JSON.parse(
localStorage.getItem(mel_metapage.Storage._getDataStore().name),
),
);
for (const iterator of MelEnumerable.from(keys).where((x) =>
x.includes('favorite-'),
)) {
mel_metapage.Storage.remove(iterator);
}
return this;
}
}
/**
* Force la récupèration des données, sans passer par la récupération serveur.
* @param {string} type Type de resource (flex office etc....)
* @returns {import('./resource_base.js').ResourceData[]}
* @static
*/
static Force_Load(type) {
return this._Get(type).force_load_favorites();
}
/**
* Récupère les favoris, si les favoris local sont obsolète, les récupères depuis la bdd.
* @param {string} type Type de resource (flex office etc....)
* @returns {Promise<import('./resource_base.js').ResourceData[]}
* @async
* @static
*/
static async Load(type) {
let instance = this._Get(type);
if (instance._promise) {
let data = await instance._promise;
instance._promise = null;
return data;
} else return await this._Get(type).load_favorites();
}
/**
* Commence à récupèrer les favoris depuis la base
* @param {string} type Type de resource (flex office etc....)
* @returns {typeof FavoriteLoader}
* @static
*/
static StartLoading(type) {
if (!this.IsSameDate(type)) {
this._Get(type)._promise = this.Load(type);
}
return this;
}
/**
* Récupère une instance de FavoriteLoader en fonction du type.
*
* Les instances sont détruites au bout de 5 minutes.
* @private
* @param {string} type Type de resource (flex office etc....)
* @returns {FavoriteLoader} Instance
*/
static _Get(type) {
if (!instances[type]) {
instances[type] = {
timeout: null,
loader: new FavoriteLoader(type),
};
if (instances[type].timeout) clearTimeout(instances[type].timeout);
instances[type].timeout = setTimeout(
() => {
instances[type] = null;
},
5 * 60 * 60 * 1000,
);
}
return instances[type].loader;
}
}
/**
* @typedef FavoriteLoaderWrapper
* @property {?number} timeout Id du timeout
* @property {FavoriteLoader} loader Instance du loader
*/
/**
* Instances de FavoritesLoaders
* @package
* @type {Object<string, FavoriteLoaderWrapper>}
* @frommodule Resources/Favorites/Loaders {@linkto FavoriteLoaderWrapper}
*/
let instances = {};