UNPKG

@publidata/utils-mapper

Version:

Collection of methods to extract data from publidata

1,417 lines (1,263 loc) 41 kB
import React from "react"; import dayjs from "dayjs"; import customParseFormat from "dayjs/plugin/customParseFormat"; import isSameOrAfter from "dayjs/plugin/isSameOrAfter"; dayjs.extend(customParseFormat); dayjs.extend(isSameOrAfter); import i18next from "i18next"; import isEmpty from "lodash/isEmpty"; import { removeHTML } from "@publidata/utils-core"; import { sortByStartDate, sortObjectByNumber } from "@publidata/utils-sorts"; import { translateModel, poiColorTranslation } from "@publidata/utils-translation"; import { cleanTimezone } from "@publidata/utils-dates"; import kebabCase from "lodash/kebabCase"; import iconsTypes from "./icons-types.json"; import colorsTypes from "./colors-types.json"; import i18n from "./i18n"; i18n.init(); /** Extract Object custom Breadcum object * @param : object (usually object page) * @return : arrayOf<Object> [{url: ..., name: ..., position: ...}] */ export const getBreadcumb = object => { if (!object) return null; if (object.jsonLd) { const breadCumbObject = object.jsonLd.find( item => item["@type"] === "BreadcrumbList" ); if (breadCumbObject && breadCumbObject.itemListElement) { const result = breadCumbObject.itemListElement.reduce( (acc, curr) => [ ...acc, { url: curr.item["@id"], name: curr.item.name, position: curr.position } ], [] ); return result.sort(sortObjectByNumber("position", false)); } return null; } return null; }; /** Extract Object data from an object * @param : object * @return : object */ export const getData = object => { if (!object) return null; if (object._source) return object._source; if (object.data && object.data.content) { return { ...object.data, ...object.data.content, page: object }; } else if (object && object.content) { return { ...object.content, page: object }; } return object; }; /** * Extract object's blurb * @param : object (usually object page.content.blurb) * @return : String */ export const getBlurb = object => { if (!object) return null; const data = getData(object); if (data && data.blurb) return removeHTML(data.blurb || ""); if (data && data.pageable) return removeHTML(data.pageable.body || ""); return null; }; /** * Extract object's tags * @param : object (usually object page.content.tags) * @return : arrayOf<Object> [{ ... }] Tags */ export const getTags = object => { if (!object) return null; const data = getData(object); const relicat = /(slug|layout-|www-|sortir-|projet-|color-)/g; if (data && data.tags) { if (typeof data.tags === "string") { return data.tags.split(",").map(name => ({ name })); } else if (data.tags.length) { return data.tags.filter(tag => { if (relicat.test(tag.name)) return null; return tag; }); } } return []; }; /** * Extract Object id * @param : object * @return : arrayOf<Object> [{...}] Data of linked object */ export const getId = object => { if (!object) return null; const data = getData(object); return data.id; }; /** Extract Object name from an object * @param : object * @return : string , (Example: "Machin") */ export const getName = object => { if (!object) return null; const data = getData(object); if (data.name) return data.name; else if (data.person_id) return `${data.civility} ${data.first_name} ${data.last_name}`; return null; }; /** Extract Object date from an object * @param : object * @return : string , (Example: "03/07/2017") */ export const getDate = object => { if (!object) return null; const data = getData(object); if (data.date) return dayjs(data.date); else if (data.release_raw_date) return dayjs(cleanTimezone(data.release_raw_date), "YYYY-MM-DD"); else if (data.raw_start_date) return dayjs(cleanTimezone(data.raw_start_date), "YYYY-MM-DD"); return null; }; /** Extract Object geoShape from an object * @param : object * @param : options, added option to shape (such as onClick or popup) * @return : array of geo shapes, (Example: "[{type: "Polygon", ...}]") */ export const getGeoShape = (object, options = {}) => { if (!object) return null; let shapesList = []; const shape = getData(object).geo_shape; if (shape && Object.keys(shape).length) { if (shape.geometries) shapesList = shape.geometries; else shapesList = [shape]; return shapesList.map(data => ({ data, context: object, ...options })); } return []; }; /** Extract Object logo from an object * @param : object * @param : size, small - medium - large * @return : string , (Example: "Machin") */ export const getLogo = (object, size = "large") => { if (!object) return null; if (getData(object).profile_picture) { const url = getData(object).profile_picture[size]; const dimensions = getData(object).profile_picture[`${size}_dimensions`]; if (dimensions === "x") return ""; return url; } return null; }; /** Extract Object opening hours from an object * @param : object * @return : string , (Example: "Machin") */ export const getOpeningHours = object => { if (!object) return null; const data = getData(object); if (data.opening_hours) return data.opening_hours; if (data.schedules && data.schedules.all) return data.schedules.all; return null; }; /** Return the best url ever of an object depending of the current instance * @param : object * @param : instance * @return : string , (Example: "http://...") */ export const getPage = (object, instance) => { if (!object) return null; const data = getData(object); let url = null; if (typeof data.page === "object") { /* eslint-disable prefer-destructuring */ url = data.page.url; if (!url && data.page.page) url = data.page.page.url; /* eslint-enable prefer-destructuring */ } if (!url || !data.pages || data.pages.length === 0) { url = data.url || null; } if (url) return url; else if (data.pages && data.pages.length) { if (instance) { const matchedPage = data.pages .filter(page => page != null) .find(page => { const { name, id, slug } = page.instance; if ( (name !== undefined && name === instance.name) || (id !== undefined && id === instance.id) || (slug !== undefined && slug === instance.slug) ) return true; return false; }); url = matchedPage ? matchedPage.url : data.pages[0].url; } else if ( (!instance || url === null) && data.pages !== undefined && data.pages[0] ) { [{ url }] = data.pages; } else url = null; } else if (object.url) return object.url; return url; }; /** Extract Object model from an object * @param : object * @return : string , (Example: "Facility" or "Event") */ export const getModel = (object, plural = false, lower = true) => { if (!object) return null; const data = getData(object); if (data.model) return data.model; if (data._info && data._info.type) return plural ? data._info.plural : data._info.type; if (typeof data.type === "string") return lower ? data.type.toLowerCase() : data.type; // ES case return null; }; /** Return page uuid * @param : object * @return : string */ export const getPageUuid = object => { if (!object) return null; if (getModel(object) === "page" || object.template) { return object.uuid || object.id; } else if (object.pages && object.pages[0]) { return object.pages[0].uuid || object.pages[0].id; } return null; }; /** Extract Object nav from a Section * @param : section object * @param : type, nav type (Example: "footer_pages_nav") * @return : object */ export const getNav = (settings, type = "instance_nav") => { if (!type || !settings.navs) return null; return settings.navs.find(item => item.type === type); }; /** Extract Object main type from an object * @param : object * @return : string , (Example: "event") */ export const getType = (object, getSubType = true) => { if (!object) return null; const data = getData(object); const model = getModel(data) ? getModel(data).toLowerCase() : null; if (getSubType) { if (data[`${model}_types`] && data[`${model}_types`].length) return data[`${model}_types`]; if (data[`${model}_type`]) return data[`${model}_type`].name; if (data.type) { if (data.type.name) return data.type.name; } } return model; }; /** Extract Object sub Type from an object * @param : object * @return : string , (Example: "Piscine") */ export const getSubType = object => { if (!object) return null; const data = getData(object); const model = getModel(object) ? getModel(object).toLowerCase() : null; if (data[`${model}_types`] && data[`${model}_types`].length) return data[`${model}_types`]; if (data.type) { if (data.type.name) return data.type.name; } return translateModel(getType(object)); }; /** * Extract Object linked objects * @param : object (usually object page.content.linked_objects) * @param : filters (list of model you want to filter linked objects with) * @return : arrayOf<Object> [{...}] Data of linked object */ export const getLinkedObjects = (object, filters = []) => { if (!object) return null; const result = []; const data = getData(object); for (const type in data.linked_objects) { if (data.linked_objects[type].length > 0) { result.push(...data.linked_objects[type]); } } if (filters.length) { return result.filter(item => filters.indexOf(getModel(item, true)) !== -1); } return result; }; /** Extract Object type from an object * @param : object * @return : array of object types */ export const getObjectTypes = object => { if (!object) return null; const data = getData(object); const model = getModel(object) ? getModel(object).toLowerCase() : null; if (data[`${model}_type`]) return [data[`${model}_type`]]; else if (data[`${model}_types`]) return data[`${model}_types`]; else if (data[`${model}_type_and_ancestors`]) return data[`${model}_type_and_ancestors`]; return model; }; /** Extract Object cover image from an object * @param : object * @param : size (optionnal) - prefer size of image * @return : string , (Example: "http://... .png") */ export const getCover = (object, size = "large") => { if (!object) return null; const data = getData(object); let image = ""; let imageObject = object; if (data.cover_picture) imageObject = data.cover_picture; else if (data.profile_picture) imageObject = data.profile_picture; if (imageObject) { if (imageObject.large) image = imageObject[size]; if ( imageObject.image_urls_as_json && imageObject.image_urls_as_json[`image_${size}_url`] ) { image = imageObject.image_urls_as_json[`image_${size}_url`]; } if (imageObject[`image_${size}_url`]) { image = imageObject[`image_${size}_url`]; } if (imageObject[`image_${size}`]) { image = imageObject[`image_${size}`]; } } return image.replace("-dev", "-prod"); }; /** Extract Object location from an object * @param : object * @param : postalAddress, do you want geocode or postal address * @param : checkMultiples, do you want to check for multiples positions ? * @return : object, ex : {lat: 48.6294167, lng: 2.4293747} */ export const getLocation = ( object, postalAddress = false, checkMultiples = false, facilityName = false ) => { if (!object) return null; let defaultIndex = 0; if (typeof object.index === "number") defaultIndex = object.index; const data = getData(object); if (postalAddress) { if (data.address) return data.address; else if (data.locations && data.locations[defaultIndex]) { if (checkMultiples) return data.locations.map(address => address.address); return data.locations[defaultIndex].address; } else if (object.event_dates) { if (checkMultiples) return object.event_dates.map(address => address.address); return object.event_dates[defaultIndex].address; } else if (object.linked_objects && object.linked_objects.cities) { const addresses = []; let address = ""; object.linked_objects.cities.forEach((city, index) => { if (index) addresses.push(`${address}, ${city.name}`); else addresses.push(city.name); address = ""; }); if (checkMultiples) return addresses[defaultIndex]; return addresses.join(); } return null; } if (facilityName) { if (data.locations && data.locations[defaultIndex]) { if (checkMultiples) return data.locations.map(address => address.name); return data.locations[defaultIndex].name !== data.locations[defaultIndex].address ? data.locations[defaultIndex].name : null; } } if (data.locations && data.locations[0]) { if (checkMultiples) return data.locations.map(address => address.location); return data.locations[0].location; } if (getGeoShape(object).length > 0) { const coords = { lat: getGeoShape(object)[0].data.coordinates[0][0][1], lon: getGeoShape(object)[0].data.coordinates[0][0][0] }; if (checkMultiples) return [coords]; return coords; } if (!data.geocode) return null; const coords = { lat: data.geocode.lat, lon: data.geocode.lng }; if (checkMultiples) return [coords]; return coords; }; /** Extract Object address from an object * @param : object * @return : string , (Example: "6 rue de lagny") */ export const getAddress = object => getLocation(object, true); /** Extract the name of an address from an object * @param : object * @return : string , (Example: "La P'tite criée" or "6 rue de lagny") */ export const getAddressName = object => getLocation(object, false, false, true); /** return font awesome icon from social name * @param : social * @return : string , (Example: "fas fa-facebook-f") */ export const getSocialIcon = social => { switch (social) { case "allocine": return "fas fa-ticket-alt"; case "dailymotion": return "fas fa-video"; case "facebook": return "fab fa-facebook-f"; case "flickr": return "fab fa-flickr"; case "googleplus": return "fab fa-google-plus-g"; case "instagram": return "fab fa-instagram"; case "linkedin": return "fab fa-linkedin-in"; case "medium": return "fab fa-medium-m"; case "messenger": return "fab fa-facebook-messenger"; case "rss": return "fas fa-rss"; case "snapcode_svg": return "fab fa-snapchat-ghost"; case "twitter": return "fab fa-twitter"; case "video": return "fas fa-video"; case "viadeo": return "fab fa-viadeo"; case "vimeo": return "fab fa-vimeo-v"; case "youtube": return "fab fa-youtube"; default: { return "fas fa-share-alt"; } } }; /** return font awesome icon from contact object * @param : string: "phone" * @return : string , (Example: "fas fa-facebook-f") */ export const getContactIcon = contact => { if (!contact) return ""; const cleanedContact = contact.toLowerCase(); switch (cleanedContact) { case "phone": return "fas fa-phone"; case "email": return "fas fa-envelope"; case "website": return "fas fa-globe"; case "phonenumber": return "fas fa-phone"; case "tollfreephonenumber": return "fas fa-phone"; case "toll_free_phone_number": return "fas fa-phone"; case "form": return "fas fa-link"; case "document": return "fas fa-file-alt"; case "fax": return "fas fa-fax"; default: { return ""; } } }; /** return font awesome icon from social name * @param : social * @return : string , (Example: "fas fa-facebook-f") */ export const getTypeIcon = (type, icons) => { const matchIcon = str => { if (icons) { const matchedIcon = Object.keys(icons).filter(icon => icon === str); if (matchedIcon.length && icons[matchedIcon[0]]) return icons[matchedIcon[0]]; return null; } return null; }; const sanitizedType = type ? type.toLowerCase() : ""; if (matchIcon(sanitizedType)) { return matchIcon(sanitizedType); } // Get type's associated icons in the icons-types.json file return iconsTypes[sanitizedType] || ""; }; /** * * @param {string} garbageType - The type of garbage (e.g., "glass", "plastic") * @param {object} instanceColors - An object containing custom colors for different garbage types * @returns {string} - The color associated with the garbage type, either from instanceColors or colorsTypes */ export const getGarbageTypeColorFromInstance = ( garbageType, instanceColors ) => { return ( instanceColors[garbageType] ?? colorsTypes[garbageType] ?? "var(--primary)" ); }; /** * Get the color associated to a type * @param {string} type - The type * @param {object} colors - The custom_settings.colors object * @returns {string} - The color */ export const getTypeColor = (facilityType, colors) => { const { name, id } = facilityType; // if a translation is configured in utils-translation, use it const translation = poiColorTranslation(name, ""); if (translation.length) return translation; // else, if a color is configured in the instance's custom_settings, // use the kebabCase of the type name as the color const customSettingsHasTypeNameColor = colors && colors[kebabCase(name)]; if (customSettingsHasTypeNameColor) return `var(--${kebabCase(name)})`; // else, if a color is configured in the instance's custom_settings, // use the kebabCase of the type id as the color const customSettingsHasIdColor = colors && colors[id]; if (customSettingsHasIdColor) return `var(--${id})`; return "var(--primary)"; }; /** return correct JSX template according to istance data * @param {object} instance : instance object * @param {string} icon : icon string * @param {array} iconType : iconType array of strings * @param {string} image : image string * @param {string} color : color string * @return {JSX} : JSX template => <i className={icons[item]} /> */ export const getIconFromInstance = ( icons, icon, iconType, image, color, className ) => { if (icon) return ( <i style={{ color }} className={`${className}__icon-custom ${icon}`} /> ); if (icons && !image) { if (iconType.length === 1) { const item = Object.keys(icons).filter(el => el === iconType[0])[0]; if (icons[item] && icons[item].includes("http")) { return ( <div className={`${className}__svg u-bg-cover`} style={{ backgroundImage: `url(${icons[item]})` }} /> ); } return ( <i className={`${className}__icon ${icons[item]} u-color-white`} /> ); } return ( <i className={`${className}__icon-fallback fas fa-plus u-color-white`} /> ); } return <i className={`${className}__icon ${iconType[0]} u-color-white`} />; }; /** Extract Themes from an object * @param : object * @return : Array of objects , (Example: [{id: 1, name: "Culture"}]) */ export const getThemes = object => { if (!object) return null; const data = getData(object); if (data.themes) return data.themes; else if (data.thematics) return data.thematics; return null; }; /** Extract Punchline from an object * @param { 0bject } object - object * @return { String } - content */ export const getPunchline = object => { if (!object) return null; const data = getData(object); if (data.punchline) return data.punchline; else if (data.blurb) return getBlurb(object); return null; }; /** return most upcoming event object * @param : array of events * @return : object , Example: { event : id: 90571, date: "14-12-2018" raw_start_date : "2019-02-03T14:30:00.000+00:00" raw_end_date: "2019-02-03T14:30:00.000+00:00" } */ export const getUpComingEvent = events => { if (!events) return null; let upComingEvent; if (events.length === 1) [upComingEvent] = events; else { const eventDates = Array.from(events); const sortedEvents = eventDates.sort((a, b) => sortByStartDate(a, b)); const today = dayjs(); upComingEvent = sortedEvents.find(event => dayjs( event.raw_start_date ? event.raw_start_date : event.start_date ).isSameOrAfter(today) ) || sortedEvents[sortedEvents.length - 1]; } return { event: upComingEvent, raw_start_date: upComingEvent.raw_start_date ? cleanTimezone(upComingEvent.raw_start_date) : cleanTimezone(upComingEvent.start_date), raw_end_date: upComingEvent.raw_end_date ? cleanTimezone(upComingEvent.raw_end_date) : cleanTimezone(upComingEvent.end_date) }; }; export const getSocialAuthor = post => { if (!post) return null; if (post.type) { if (post.type === "facebook" && post.from) return post.from.name; else if (post.type === "twitter" && post.user) return post.user.name; else if (post.type === "instagram" && post.user) return post.user.full_name; } return null; }; export const getSocialImage = post => { if (!post) return null; if (post.type) { if (post.type === "facebook") return post.full_picture; else if (post.type === "twitter") { if (post.entities && post.entities.media && post.entities.media.length) { return post.entities.media[0].media_url_https; } else if ( post.retweeted_status && post.retweeted_status.entities && post.retweeted_status.entities.media && post.retweeted_status.entities.media.length ) { return post.retweeted_status.entities.media[0].media_url_https; } } else if (post.type === "instagram") return post.images.standard_resolution.url; } return null; }; export const getSocialText = post => { if (!post) return null; if (post.type) { if (post.type === "facebook") return post.message || post.description; else if (post.type === "twitter") return post.full_text; else if (post.type === "instagram") return post.caption.text; } return null; }; export const getSocialUrl = post => { if (!post) return null; if (post.type) { if (post.type === "facebook") return post.link; else if (post.type === "twitter") { if ( post.retweeted_status && post.retweeted_status.entities && post.retweeted_status.entities.media && post.retweeted_status.entities.media[0] && post.retweeted_status.entities.media[0].expanded_url ) { return post.retweeted_status.entities.media[0].expanded_url.replace( "/photo/1", "" ); } return `https://twitter.com/${post.user.screen_name}/status/${post.id_str}`; } else if (post.type === "instagram") return post.link; } return null; }; /** return city of an address from Publidata api * @param {string} address : "20 Rue d'Alsace, 67140 Barr, France" * @return {object} : { group, postalCode, city } getCity(address).group => "67140 Barr" getCity(address).postalCode => "67140" getCity(address).city => "Barr" */ export const getCity = address => { if (!address) return null; if (address.split(" ").length === 1) return address; const postalCodeRegexFr = /[0-9]{5}/; const postalCodeRegexCa = /[A-Z]\d[A-Z] \d[A-Z]\d/; const cityNameRegex = /[^,]+/; const regexFr = new RegExp( `(${postalCodeRegexFr.source}) (${cityNameRegex.source})` ); const regexCa = new RegExp( `(${cityNameRegex.source}) (${postalCodeRegexCa.source})` ); // FR Format let match = address.match(regexFr); if (match) { const [group, postalCode, city] = match; return { group, postalCode, city: city.trim() }; } match = address.match(regexCa); if (match) { const [_, city, postalCode] = match; return { group: `${postalCode} ${city?.trim()}`, postalCode, city: city?.trim() }; } const splittedAddress = address.split(", "); return { city: splittedAddress.reverse()[1]?.trim() }; }; /** return street name of an address from Publidata api * @param {string} address : "20 Rue d'Alsace, 67140 Barr, France" * @return {string} : String => "20 Rue d'Alsace" */ export const getStreet = address => { if (!address) return null; const postalCodeRegexFr = /[0-9]{5}/; const postalCodeRegexCa = /[A-Z]\d[A-Z] \d[A-Z]\d/; const postalCodeRegex = new RegExp( `(${postalCodeRegexFr.source})|(${postalCodeRegexCa.source})` ); const matchedAddress = address.match(postalCodeRegex); if (matchedAddress) { const postalCode = matchedAddress[0]; const splittedAddress = address.split(postalCode); const street = splittedAddress[0]; return street.replace(/,/g, "")?.trim(); } const splittedAddress = address.split(", "); return splittedAddress[0]?.trim() || address; }; /** * Extract info from meta * @param { Object } object : Object * @param { String } key : Key wanted * @return { Boolean } */ export const getInfoFromMeta = (object, key) => { if (!object) return null; const data = getData(object); if (!data.metas) return null; return data.metas[key]; }; /** * Extract Facility secured access * @param { Object } object : Facility object * @return { Boolean } */ export const getSecuredAccess = object => getInfoFromMeta(object, "secured_access"); /** * Extract Facility delivery date * @param { Object } : Facility object * @return { Boolean } */ export const getDeliveryDate = object => getInfoFromMeta(object, "delivery_date"); /** * Extract website value * @param { Object } : Facility object * @return { Boolean } */ export const getWebsite = object => { if (!object) return null; const data = getData(object); if (!data.contacts) return null; const website = data.contacts.find(({ type }) => type === "Website"); if (!website) return null; return getInfoFromMeta(website, "value"); }; /** * Extract Housing type id * @param { Object } : Housing object * @return { Integer } */ export const getHousingTypeId = object => { if (!object) return null; const data = getData(object); if (!data.facility_type_and_ancestors) return null; const housingTypes = [356, 450, 93]; const housingType = data.facility_type_and_ancestors.find(type => housingTypes.includes(type.id) ); if (!housingType) return null; return housingType.id; }; /** * Getter for Housing Icon * @param { Integer } : Housing type id * @return { String } */ export const getHousingIcon = id => { switch (id) { case 93: return "far fa-graduation-cap"; case 356: return "fal fa-home-heart"; case 450: default: return "far fa-home"; } }; export const arrayReducer = (array, key) => { if (!array) return null; return array.reduce((object, current) => { const newObject = object; newObject[current[key]] = current; return newObject; }, {}); }; export const getMaintainers = object => { if (!object) return null; const data = getData(object); const { maintainers } = data; if (maintainers) return maintainers; return null; }; export const getSource = (object, account, slug) => { if (!object || !account) return null; const source = {}; const data = getData(object); const maintainers = getMaintainers(data); const owner = maintainers.find(maintainer => maintainer.role === "owner"); source.name = owner.name; if (owner.name === account) source.url = data.pages.find(page => page.instance.slug === slug).url; else source.url = data.pages[0].url; return source; }; /** Get an icon (font awesome or image href) from an "icons" dictionnary based on wastecollection objects properties such as collection_mode / garbage_types * @Param Object, object is the wastecollection object * @Param Object, icons is the icon dictionnary (icons objet comes from the instance) * @Return String, a font awesome class or an image href */ export const getIconFromWasteCollection = (object, icons) => { if (!object || !icons) return "fas fa-plus"; if (object.parent && icons[object.parent.id]) return icons[object.parent.id]; if (object.id && icons[object.id]) return icons[object.id]; const { icon } = object.facility; if (icon) return icon; const { collectionMode, garbageTypes } = object; if (collectionMode === "mobile" && garbageTypes.length === 1) return icons[garbageTypes[0]]; if ( (collectionMode === "mobile" && garbageTypes.length > 1) || (collectionMode === "recycling_center" && garbageTypes.length !== 1) ) return icons[collectionMode]; if (garbageTypes && !isEmpty(garbageTypes)) { return icons[garbageTypes[0]]; } return "fas fa-plus"; }; /** Get the color variable associated to a wastecollection object * @Param Object, object is the wastecollection object * @Param Object, colors optional param of a color dictionnary to allow hexa returning value (colors object comes from instance object) * @Return String, a string containing the css variable of a color (ex: var(--primary)), can also be an hexa if you use the optionnal colors param */ export const getColorFromWasteCollection = ( wasteCollection, colors = undefined ) => { const { garbageTypes, collectionMode, facility, id, instance } = wasteCollection; const isMultiFlow = (collectionMode === "truck" || collectionMode === "recycling_bin") && garbageTypes.length > 1; const fallback = "#A0A0A0"; if (isMultiFlow) return instance.colors && instance.colors[id] ? instance.colors[id] : "var(--primary)"; if (!collectionMode && !garbageTypes) return fallback; if (!colors && facility.color) return facility.color; const firstGarbageCollectionModeColor = () => { if (garbageTypes && garbageTypes.length) { if (colors) return colors[`${garbageTypes[0]}`]; return `var(--${garbageTypes[0]})`; } return fallback; }; // If we collecte only one waste type then we use this collection mode color if (garbageTypes && garbageTypes.length === 1) return firstGarbageCollectionModeColor(); // Otherwise we use fallbacks because we can't choose a predominant waste collection mode if (collectionMode === "recycling_center") { if (colors) return colors.facility; return "var(--facility)"; } else if (collectionMode === "mobile") { if (colors) return colors.mobile; return "var(--mobile)"; } // Out of despair, let's at least returning something (ultime fallback) return firstGarbageCollectionModeColor(); }; export const getTranslationFromMenuAndInstance = (menu, instance) => { if (!menu || !instance) return null; const { translationDictionary } = instance; if ( translationDictionary && translationDictionary.fr && translationDictionary.fr.translation && translationDictionary.fr.translation.canteenMenuName ) { const { canteenMenuName } = translationDictionary.fr.translation; return canteenMenuName[menu.id]; } return null; }; /** return the string of the collection_mode key in a collect object * @param { Object } type : { collect } * @return { String } : String => "recycling_bin" */ export const getCollectionMode = object => getInfoFromMeta(object, "collection_mode"); /** return an array of the accepted_waste key in a collect object * @param { Object } type : { collect } * @return { Array } : Array => ["Pneus", "Piles", "..."] */ export const getAcceptedWastes = object => getInfoFromMeta(object, "accepted_waste"); /** return an array of the rejected_waste key in a collect object * @param { Object } type : { collect } * @return { Array } : Array => ["Pneus", "Piles", "..."] */ export const getRejectedWastes = object => getInfoFromMeta(object, "rejected_waste"); /** return the array of the garbage_types key in a collect object * @param { Object } type : { collect } * @return { Array } : Array => ["text", "emb", "omr"] */ export const getGarbageTypes = object => { const garbageTypes = getInfoFromMeta(object, "garbage_types"); if (!garbageTypes) return []; return garbageTypes; }; /** * * @param {Object} object - The waste collection object * @param {Object} metas - The metas object containing garbage types details * @param {*} instanceSettings - The instance settings containing icons, colors, and translation dictionary * @returns {Array} - An array of formatted garbage types details, each containing type, icon, color, translation, and additional metas. */ export const getGarbageTypesDetails = (object, metas, instanceSettings) => { const { icons, colors, translationDictionary } = instanceSettings || {}; const { wasteCollection } = translationDictionary?.fr?.translation || {}; const garbageTypes = getGarbageTypes(object); const formatGarbageTypes = garbageTypes.map(type => { const icon = getTypeIcon(type, icons); const color = getGarbageTypeColorFromInstance(type, colors); return { type, icon, color, translation: wasteCollection?.[type] ?? i18next.t(`wasteCollection:${type}`) ?? type, ...(metas?.[type] ?? {}) }; }); return formatGarbageTypes; }; export const getWasteBlurb = object => getInfoFromMeta(object, "waste_blurb"); export const getObjectBlurb = collect => { if (!collect || isEmpty(collect)) return null; const data = getData(collect); if (data) { const { blurb } = data; if (blurb) return blurb; } return null; }; export const getCollectionModeIcon = object => { if (!object) return null; const { collectionMode } = object; const icon = getTypeIcon(collectionMode); return icon; }; export const getTranslationFromWastecollectionAndInstance = ( wastecollection, instance, facility ) => { if (!wastecollection || !instance) return null; const { metas } = wastecollection; const { collection_mode } = metas; const { translationDictionary } = instance; if ( translationDictionary && translationDictionary.fr && translationDictionary.fr.translation && translationDictionary.fr.translation.wastecollectionName ) { const { wastecollectionName } = translationDictionary.fr.translation; if (wastecollectionName[wastecollection.id]) { return wastecollectionName[wastecollection.id]; } else if ( wastecollection.parent && wastecollectionName[wastecollection.parent.id] ) { return wastecollectionName[wastecollection.parent.id]; } } if (!isEmpty(facility)) { if (collection_mode === "recycling_bin") { if (facility.facilityTypeIdTranslation) return facility.facilityTypeIdTranslation; } if ( collection_mode === "reuse" || collection_mode === "mobile" || collection_mode === "recycling_center" ) { return facility.name; } } const garbageTypes = getGarbageTypes(wastecollection); if (garbageTypes && garbageTypes[0]) return i18next.t(`wasteCollection:${garbageTypes[0]}`); return null; }; export const getRedirection = object => { if (!object) return null; const redirect = getInfoFromMeta(object, "redirect_to"); const { contacts, documents } = object._source; const reducedContacts = arrayReducer(contacts, "type"); if (redirect === "website" && reducedContacts.Website) { return { url: reducedContacts.Website.metas.value, text: i18next.t("see_on_the_website"), icon: "fas fa-external-link" }; } if (redirect === "website" && reducedContacts.Form) { return { url: reducedContacts.Form.metas.value, text: i18next.t("see_on_the_website"), icon: "fas fa-external-link" }; } if (redirect === "email" && reducedContacts.Email) { return { url: `mailto:${reducedContacts.Email.metas.value}`, text: i18next.t("send_an_email"), icon: "fas fa-envelope" }; } if (redirect === "media" && !isEmpty(documents)) { return { url: documents[0].url, text: `${i18next.t("download_the")} ${i18next.t( "wasteCollection:collects_calendar" )}`, icon: "fas fa-download" }; } if (redirect === "phone" && reducedContacts.PhoneNumber) { return { url: `tel:${reducedContacts.PhoneNumber.metas.value}`, text: reducedContacts.PhoneNumber.metas.value, icon: "fas fa-phone" }; } return null; }; export const getFacilityTypeIdTranslation = (facilityTypeId, instance) => { if (!facilityTypeId || !instance) return null; const { translationDictionary } = instance; if ( translationDictionary && translationDictionary.fr && translationDictionary.fr.translation && translationDictionary.fr.translation.wastecollectionName ) { const { wastecollectionName } = translationDictionary.fr.translation; if (wastecollectionName[`${facilityTypeId}`]) return wastecollectionName[`${facilityTypeId}`]; return i18next.t(`wasteCollection:${facilityTypeId}`); } return i18next.t(`wasteCollection:${facilityTypeId}`); }; export const getAllTheFacilityTypeIdTranslation = ( facilityTypeId, instance ) => { if (!facilityTypeId || !instance) return null; const { translationDictionary } = instance; if ( translationDictionary && translationDictionary.fr && translationDictionary.fr.translation && translationDictionary.fr.translation.wastecollectionName ) { const { wastecollectionName } = translationDictionary.fr.translation; if (wastecollectionName[`all_the_${facilityTypeId}`]) return wastecollectionName[`all_the_${facilityTypeId}`]; return i18next.t(`wasteCollection:all_the_${facilityTypeId}`); } return i18next.t(`wasteCollection:all_the_${facilityTypeId}`); }; export const getFacilityTypeIdPluralTranslation = ( facilityTypeId, instance ) => { if (!facilityTypeId || !instance) return null; const { translationDictionary } = instance; if ( translationDictionary && translationDictionary.fr && translationDictionary.fr.translation && translationDictionary.fr.translation.wastecollectionName ) { const { wastecollectionName } = translationDictionary.fr.translation; if (wastecollectionName[`${facilityTypeId}_plural`]) return wastecollectionName[`${facilityTypeId}_plural`]; return i18next.t(`wasteCollection:${facilityTypeId}_plural`); } return i18next.t(`wasteCollection:${facilityTypeId}_plural`); }; export const getFacilityTypeIdTranslationShort = (facilityTypeId, instance) => { if (!facilityTypeId || !instance) return null; const { translationDictionary } = instance; if ( translationDictionary && translationDictionary.fr && translationDictionary.fr.translation && translationDictionary.fr.translation.wastecollectionName ) { const { wastecollectionName } = translationDictionary.fr.translation; if (wastecollectionName[`${facilityTypeId}_short`]) return wastecollectionName[`${facilityTypeId}_short`]; return i18next.t(`wasteCollection:${facilityTypeId}_short`); } return i18next.t(`wasteCollection:${facilityTypeId}_short`); }; export const getWasteCollectionDisplayDistance = ( wasteCollection, instance ) => { const defaultValue = 100000; if (!instance.wasteCollectionDisplayDistances) return defaultValue; return ( instance.wasteCollectionDisplayDistances[wasteCollection?.id] || instance.wasteCollectionDisplayDistances[wasteCollection?.parent?.id] || instance.wasteCollectionDisplayDistances[wasteCollection?.collectionMode] || defaultValue ); }; export default { getPage, getUrl: getPage, getBreadcumb, getData, getBlurb, getTags, getId, getName, getDate, getGeoShape, getLogo, getOpeningHours, getModel, getPageUuid, getNav, getType, getSubType, getLinkedObjects, getObjectTypes, getCover, getLocation, getAddress, getAddressName, getSocialIcon, getContactIcon, getTypeIcon, getTypeColor, getIconFromInstance, getThemes, getPunchline, getUpComingEvent, getSocialAuthor, getSocialImage, getSocialText, getSocialUrl, getCity, getStreet, getInfoFromMeta, getSecuredAccess, getDeliveryDate, getWebsite, getHousingTypeId, getHousingIcon, arrayReducer, getMaintainers, getSource, getIconFromWasteCollection, getColorFromWasteCollection, getTranslationFromMenuAndInstance, getCollectionMode, getAcceptedWastes, getRejectedWastes, getGarbageTypes, getWasteBlurb, getObjectBlurb, getCollectionModeIcon, getTranslationFromWastecollectionAndInstance, getRedirection, getFacilityTypeIdTranslation, getAllTheFacilityTypeIdTranslation, getFacilityTypeIdPluralTranslation, getFacilityTypeIdTranslationShort, getWasteCollectionDisplayDistance };