Created
April 15, 2019 14:11
-
-
Save tischsoic/55ce295d492300e1fbd15a626289ae5f to your computer and use it in GitHub Desktop.
eZ - LP
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function(global, doc, eZ, React, ReactDOM, Translator) { | |
const SELECTOR_LOCATION_PICKER_BUTTON = '.ez-location-picker__btn'; | |
const SELECTOR_LOCATION_PICKER_LIST = '.ez-location-picker__list'; | |
const SELECTOR_EZ_TAG = '.ez-tag'; | |
const IDS_SEPARATOR = ','; | |
const token = doc.querySelector('meta[name="CSRF-Token"]').content; | |
const siteaccess = doc.querySelector('meta[name="SiteAccess"]').content; | |
const udwContainer = doc.getElementById('react-udw'); | |
class LocationPicker { | |
constructor(config) { | |
this.container = config.container; | |
this.tagTemplate = config.tagTemplate || this.container.dataset.tagTemplate; | |
this.udwConfig = config.udwConfig; | |
this.onSelectionChanged = config.onSelectionChanged || (() => {}); | |
this.isMultipleSelect = config.multiple || false; | |
this.isContentSelect = config.contentSelect || false; | |
this.showOnlyContentName = config.showOnlyContentName || false; | |
this.selectedIds = null; | |
this.attachTagEventHandlers = this.attachTagEventHandlers.bind(this); | |
this.getLocationPathArray = this.getLocationPathArray.bind(this); | |
this.handleUdwConfirm = this.handleUdwConfirm.bind(this); | |
this.openUDW = this.openUDW.bind(this); | |
} | |
findLocationsByIdList(pathArraysWithoutRoot, callback) { | |
const bulkOperations = this.getBulkOperations(pathArraysWithoutRoot); | |
const request = new Request('/api/ezp/v2/bulk', { | |
method: 'POST', | |
headers: { | |
Accept: 'application/vnd.ez.api.BulkOperationResponse+json', | |
'Content-Type': 'application/vnd.ez.api.BulkOperation+json', | |
'X-Siteaccess': siteaccess, | |
'X-CSRF-Token': token, | |
}, | |
body: JSON.stringify({ | |
bulkOperations: { | |
operations: bulkOperations, | |
}, | |
}), | |
mode: 'same-origin', | |
credentials: 'same-origin', | |
}); | |
const errorMessage = Translator.trans( | |
/*@Desc("Failed to fetch content names")*/ 'limitation.pick.error', | |
{}, | |
'universal_discovery_widget' | |
); | |
fetch(request) | |
.then(eZ.helpers.request.getJsonFromResponse) | |
.then(callback) | |
.catch(() => eZ.helpers.notification.showErrorNotification(errorMessage)); | |
} | |
getBulkOperations(pathArraysWithoutRoot) { | |
return pathArraysWithoutRoot.reduce((operations, pathArray) => { | |
const locationId = pathArray[pathArray.length - 1]; | |
operations[locationId] = { | |
uri: '/api/ezp/v2/views', | |
method: 'POST', | |
headers: { | |
Accept: 'application/vnd.ez.api.View+json; version=1.1', | |
'Content-Type': 'application/vnd.ez.api.ViewInput+json; version=1.1', | |
'X-Requested-With': 'XMLHttpRequest', | |
}, | |
content: JSON.stringify({ | |
ViewInput: { | |
identifier: `udw-locations-by-path-string-${pathArray.join('-')}`, | |
public: false, | |
LocationQuery: { | |
Criteria: {}, | |
FacetBuilders: {}, | |
SortClauses: { SectionIdentifier: 'ascending' }, | |
Filter: { LocationIdCriterion: pathArray.join(IDS_SEPARATOR) }, | |
limit: 50, | |
offset: 0, | |
}, | |
}, | |
}), | |
}; | |
return operations; | |
}, {}); | |
} | |
removeRootLocation(pathArray) { | |
return pathArray.slice(1); | |
} | |
pathStringToPathArray(pathString) { | |
return pathString | |
.split('/') | |
.filter((el) => el) | |
.map((id) => parseInt(id, 10)); | |
} | |
buildContentBreadcrumbs(viewData) { | |
const searchHitList = viewData.View.Result.searchHits.searchHit; | |
return searchHitList.map((searchHit) => searchHit.value.Location.ContentInfo.Content.Name).join(' / '); | |
} | |
addLocationSingleTag(newlySelectedItem) { | |
const selectLocationsBtn = this.container.querySelector(SELECTOR_LOCATION_PICKER_BUTTON); | |
const renderedItem = this.tagTemplate | |
.replace('{{ id }}', this.isContentSelect ? newlySelectedItem.ContentInfo.Content._id : newlySelectedItem.id) | |
.replace('{{ content_name }}', newlySelectedItem.ContentInfo.Content.Name); | |
selectLocationsBtn.insertAdjacentHTML('afterend', renderedItem); | |
const tagNode = this.container.querySelector(SELECTOR_EZ_TAG); | |
this.attachTagEventHandlers(tagNode); | |
if (!this.showOnlyContentName) { | |
this.setTagsBreadcrumbs([newlySelectedItem]); | |
} | |
} | |
addLocationsTags(newlySelectedItems) { | |
const fragment = doc.createDocumentFragment(); | |
newlySelectedItems.forEach((location) => { | |
const id =this.isContentSelect ? location.ContentInfo.Content._id : location.id ; | |
const container = doc.createElement('ul'); | |
const renderedItem = this.tagTemplate | |
.replace('{{ id }}', id) | |
.replace('{{ content_name }}', location.ContentInfo.Content.Name); | |
container.insertAdjacentHTML('beforeend', renderedItem); | |
const listItemNode = container.querySelector('li'); | |
const tagNode = listItemNode.querySelector(SELECTOR_EZ_TAG); | |
this.attachTagEventHandlers(tagNode); | |
fragment.append(listItemNode); | |
}); | |
const tagsList = this.container.querySelector(SELECTOR_LOCATION_PICKER_LIST); | |
tagsList.append(fragment); | |
if (!this.showOnlyContentName) { | |
this.setTagsBreadcrumbs(newlySelectedItems); | |
} | |
} | |
setTagsBreadcrumbs(newlySelectedItems) { | |
const pathArraysWithoutRoot = newlySelectedItems.map(this.getLocationPathArray); | |
this.findLocationsByIdList(pathArraysWithoutRoot, (response) => { | |
const { operations } = response.BulkOperationResponse; | |
Object.entries(operations).forEach(([locationId, { content }]) => { | |
const viewData = JSON.parse(content); | |
const id =this.isContentSelect ? location.ContentInfo.Content._id : location.id ; | |
const tag = this.container.querySelector(`[data-id="${id}"]`); | |
const tagContent = tag.querySelector('.ez-tag__content'); | |
const tagSpinner = tag.querySelector('.ez-tag__spinner'); | |
tagContent.innerText = this.buildContentBreadcrumbs(viewData); | |
tagSpinner.hidden = true; | |
tagContent.hidden = false; | |
}); | |
}); | |
} | |
getLocationPathArray({ pathString }) { | |
const pathArray = this.pathStringToPathArray(pathString); | |
const pathArrayWithoutRoot = this.removeRootLocation(pathArray); | |
return pathArrayWithoutRoot; | |
} | |
handleTagRemove(tag) { | |
const removedLocationId = parseInt(tag.dataset.locationId, 10); | |
this.removeLocation(removedLocationId); | |
tag.remove(); | |
if (!this.isMultipleSelect) { | |
this.toggleBtnVisibility(true); | |
} | |
} | |
removeLocation(locationId) { | |
this.selectedIds.delete(locationId); | |
this.onSelectionChanged(this.selectedIds); | |
} | |
addLocations(newlySelectedItems) { | |
const newlySelectedLocationsIds = newlySelectedItems.map((item) => item.id); | |
this.selectedIds = new Set([...this.selectedIds, ...newlySelectedLocationsIds]); | |
this.onSelectionChanged(this.selectedIds, newlySelectedItems); | |
} | |
attachTagEventHandlers(tag) { | |
const removeTagBtn = tag.querySelector('.ez-tag__remove-btn'); | |
removeTagBtn.addEventListener('click', this.handleTagRemove.bind(this, tag), false); | |
} | |
toggleBtnVisibility(isVisible) { | |
const selectLocationsBtn = this.container.querySelector(SELECTOR_LOCATION_PICKER_BUTTON); | |
selectLocationsBtn.hidden = !isVisible; | |
} | |
closeUDW() { | |
ReactDOM.unmountComponentAtNode(udwContainer); | |
} | |
handleUdwConfirm(newlySelectedItems) { | |
this.closeUDW(); | |
if (!newlySelectedItems.length) { | |
return; | |
} | |
this.addLocations(newlySelectedItems); | |
if (this.isMultipleSelect) { | |
this.addLocationsTags(newlySelectedItems); | |
} else { | |
this.toggleBtnVisibility(false); | |
this.addLocationSingleTag(newlySelectedItems[0]); | |
} | |
} | |
openUDW(event) { | |
event.preventDefault(); | |
const config = JSON.parse(event.currentTarget.dataset.udwConfig); | |
ReactDOM.render( | |
React.createElement( | |
eZ.modules.UniversalDiscovery, | |
Object.assign( | |
{ | |
startingLocationId: eZ.adminUiConfig.universalDiscoveryWidget.startingLocationId, | |
restInfo: { token, siteaccess }, | |
...this.udwConfig, | |
onConfirm: this.handleUdwConfirm, | |
onCancel: this.closeUDW, | |
multiple: this.isMultipleSelect, | |
canSelectContent: ({ item }, callback) => { | |
callback(!this.selectedIds.has(item.id)); | |
}, | |
}, | |
config | |
) | |
), | |
udwContainer | |
); | |
} | |
init() { | |
const tags = [...this.container.querySelectorAll(SELECTOR_EZ_TAG)]; | |
const selectLocationsBtn = this.container.querySelector(SELECTOR_LOCATION_PICKER_BUTTON); | |
this.selectedIds = new Set(tags.map((tag) => parseInt(tag.dataset.id, 10))); | |
selectLocationsBtn.addEventListener('click', this.openUDW, false); | |
tags.forEach(this.attachTagEventHandlers); | |
} | |
} | |
global.eZ.addConfig('core.LocationPicker', LocationPicker); | |
})(window, window.document, window.eZ, window.React, window.ReactDOM, window.Translator); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment