Skip to content

Instantly share code, notes, and snippets.

@tischsoic
Created April 15, 2019 14:11
Show Gist options
  • Save tischsoic/55ce295d492300e1fbd15a626289ae5f to your computer and use it in GitHub Desktop.
Save tischsoic/55ce295d492300e1fbd15a626289ae5f to your computer and use it in GitHub Desktop.
eZ - LP
(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