Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EZP-31772: implement custom tag link #157

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export default class EzBtnCustomTagUpdate extends EzWidgetButton {

this.state = {
values: props.values,
linkDetails: {},
};
}

Expand Down Expand Up @@ -136,8 +137,209 @@ export default class EzBtnCustomTagUpdate extends EzWidgetButton {
* @return {Object} The rendered link.
*/
renderLink(config, attrName) {
// @todo provide dedicated support for link attribute type
return this.renderString(config, attrName);
const selectContentLabel = Translator.trans(
/*@Desc("Select content")*/ 'custom_tag.link.select_content_btn.label',
{},
'alloy_editor'
);
if (this.state.values[attrName].value) {
this.loadLinkContentInfo(attrName);
}
const linkDetails = this.state.linkDetails[attrName];

return (
<div className="attribute__wrapper">
<label className="attribute__label form-control-label">{config.label}</label>
<input
type="text"
defaultValue={config.defaultValue}
required={config.required}
className="attribute__input form-control"
value={this.state.values[attrName].value}
onChange={this.updateLinkValues.bind(this)}
data-attr-name={attrName}
/>
<div className="ez-custom-tag__link-controls">
{linkDetails
? <a href={linkDetails.href} target="_blank" className="ez-custom-tag--link"
title={linkDetails.title}>{linkDetails.title}</a>
: ''
}
<button
className="ez-btn-ae btn btn-secondary"
onClick={this.selectContent.bind(this, attrName)}
>
{selectContentLabel}
</button>
</div>
</div>
);
}

updateLinkValues(event) {
this.updateValues(event);
this.loadLinkContentInfo(event.target.dataset.attrName);
}

loadLinkContentInfo(attrName) {
const inputValue = this.state.values[attrName].value;
const linkDetails = this.state.linkDetails[attrName] || {};

let filter;
if (inputValue.startsWith('ezlocation://') && inputValue.length > 13) {
const locationId = parseInt(inputValue.substring(13));
if (!locationId) {
this.clearLinkDetails(attrName);
return;
}
if (linkDetails.locationId === locationId) {
return;
}
linkDetails.locationId = locationId;
filter = { LocationIdCriterion: locationId };
} else if (inputValue.startsWith('ezcontent://') && inputValue.length > 14) {
const contentId = parseInt(inputValue.substring(14));
if (!contentId) {
this.clearLinkDetails(attrName);
return;
}
if (linkDetails.contentId === contentId) {
return;
}
linkDetails.contentId = contentId;
filter = { ContentIdCriterion: contentId };
} else {
this.clearLinkDetails(attrName);
return;
}

const token = document.querySelector('meta[name="CSRF-Token"]').content;
const siteaccess = document.querySelector('meta[name="SiteAccess"]').content;

const body = JSON.stringify({
ViewInput: {
identifier: `custom-tag-link-info-by-id-${linkDetails.contentId || ''}-${linkDetails.locationId || ''}`,
public: false,
LocationQuery: {
Criteria: {},
FacetBuilders: {},
SortClauses: { LocationDepth: 'ascending' },
Filter: filter,
limit: 1,
offset: 0,
},
},
});
const request = new Request('/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',
'X-Siteaccess': siteaccess,
'X-CSRF-Token': token,
},
body,
mode: 'same-origin',
credentials: 'same-origin',
});

fetch(request)
.then(window.eZ.helpers.request.getJsonFromResponse)
.then((viewData) => {
const resHits = viewData.View.Result.searchHits.searchHit;
if (!resHits.length || !resHits[0].value) {
this.clearLinkDetails(attrName)
return;
}

this.setLinkDetails(attrName, resHits[0].value.Location);
});
}

setLinkDetails(attrName, location) {
const content = location.ContentInfo.Content;
const linkDetails = Object.assign({}, this.state.linkDetails);
linkDetails[attrName] = {
title: content.TranslatedName || content.Name || '',
href: Routing.generate('_ez_content_view', {
contentId: content._id,
locationId: location.id,
}),
contentId: content._id,
locationId: location.id,
};
this.setState({ linkDetails });
}

clearLinkDetails(attrName) {
if (this.state.linkDetails[attrName]) {
const linkDetails = Object.assign({}, this.state.linkDetails);
delete linkDetails[attrName];
this.setState({ linkDetails });
}
}

/**
* Runs the Universal Discovery Widget so that the user can pick a Content.
*
* @method selectContent
* @protected
*/
selectContent(attrName) {
const openUDW = () => {
const config = JSON.parse(document.querySelector(`[data-udw-config-name="richtext_embed"]`).dataset.udwConfig);
const title = Translator.trans(/*@Desc("Select content")*/ 'custom_tag.link.udw.title', {}, 'alloy_editor');
const selectContent = eZ.richText.alloyEditor.callbacks.selectContent;
const mergedConfig = Object.assign(
{
onConfirm: this.udwOnConfirm.bind(this, attrName),
onCancel: this.udwOnCancel.bind(this),
title,
multiple: false,
},
config
);

if (typeof selectContent === 'function') {
selectContent(mergedConfig);
}
};
openUDW();

this.disableUDWPropagation();
}

udwOnConfirm(attrName, items) {
this.state.values[attrName].value = 'ezlocation://' + items[0].id;
this.setLinkDetails(attrName, items[0]);

this.enableUDWPropagation();
}

udwOnCancel() {
ReactDOM.unmountComponentAtNode(document.querySelector('#react-udw'));
this.enableUDWPropagation();
}

/**
* Disable propagation to make sure attributes toolbar
* not closed by alloyeditor outside click
*/
disableUDWPropagation() {
const container = document.querySelector('body');
container.addEventListener('mousedown', this.doNotPropagate);
container.addEventListener('keydown', this.doNotPropagate);
}

enableUDWPropagation() {
const container = document.querySelector('body');
container.removeEventListener('mousedown', this.doNotPropagate);
container.removeEventListener('keydown', this.doNotPropagate);
}

doNotPropagate(event) {
event.stopPropagation();
}

/**
Expand Down
26 changes: 26 additions & 0 deletions src/bundle/Resources/public/scss/_custom-tag.scss
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,32 @@
align-items: center;
}

&__link-controls {
.btn.btn-secondary {
width: 100%;
margin: calculateRem(5px) calculateRem(5px) calculateRem(5px) 0;
color: $ez-white;
}
.ez-custom-tag--link {
display: block;
width: 100%;
padding: calculateRem(10px) calculateRem(5px) calculateRem(5px) calculateRem(5px);
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
color: $ez-color-hyperlink;
text-decoration: none;
cursor: pointer;
transition: color 0.3s $ez-admin-transition;

&:hover,
&:focus {
color: $ez-color-hyperlink-hover;
text-decoration: underline;
}
}
}

& > [data-ezelement='ezattributes'],
& > [data-ezelement='ezcontent'] {
display: none;
Expand Down
5 changes: 5 additions & 0 deletions src/bundle/Resources/public/scss/variables/colors.scss
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ $ez-ground-base: #f3f3f3;
$ez-ground-base-pale: #fafafa;
$ez-ground-base-dark: #e5e3e3;
$ez-secondary-ground: #2b84b1;
$ez-color-hyperlink: #0645ad;
$ez-color-hyperlink-hover: darken($ez-color-hyperlink, 15%);

// eZ transition function
$ez-admin-transition: cubic-bezier(0.25, 0.8, 0.25, 1);

// AlloyEditor
$ez-ae-color-primary: $ez-white !default;
Expand Down
10 changes: 10 additions & 0 deletions src/bundle/Resources/translations/alloy_editor.en.xliff
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,16 @@
<target>Save</target>
<note>key: custom_tag_update_btn.save_btn.label</note>
</trans-unit>
<trans-unit id="1cfc2dd28fe6cbd725b0ccf91be60138750af4b3" resname="custom_tag.link.select_content_btn.label">
<source>Select content</source>
<target>Select content</target>
<note>key: custom_tag.link.select_content_btn.label</note>
</trans-unit>
<trans-unit id="e1c16d681181ae931a8d56529dc9397f809b1e4a" resname="custom_tag.link.udw.title">
<source>Select content</source>
<target>Select content</target>
<note>key: custom_tag.link.udw.title</note>
</trans-unit>
<trans-unit id="5a25d3a19c8addc868947381a4eb1a699d01cf22" resname="embed.ezlocation.error">
<source>This embedded item relies on 'ezlocation' imported from Legacy. It isn't supported by Online Editor yet.</source>
<target state="new">This embedded item relies on 'ezlocation' imported from Legacy. It isn't supported by Online Editor yet.</target>
Expand Down