mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-03 23:00:14 -05:00
Wired newsletter link success/error states
refs https://github.com/TryGhost/Team/issues/2116 - wires handling of success and error messages on editing a newsletter link - has the update api commented out temporarily to mock the changes
This commit is contained in:
parent
b310b3a97a
commit
3db8fb5a1c
4 changed files with 97 additions and 42 deletions
|
@ -21,8 +21,8 @@
|
|||
<div class="gh-links-list-item">
|
||||
{{#if (feature "fixNewsletterLinks")}}
|
||||
<div class="gh-links-list-url">
|
||||
{{#if link.isEditing}}
|
||||
<div class="gh-links-list-input-container">
|
||||
{{#if (eq this.editingLink link.link.link_id)}}
|
||||
<div class="gh-links-list-input-container {{if (eq this.showError link.link.link_id) "error"}}">
|
||||
<input
|
||||
aria-label="Link"
|
||||
type="text"
|
||||
|
@ -48,7 +48,7 @@
|
|||
{{link.link.title}}
|
||||
</a>
|
||||
<span class="gh-links-list-item-edited"> – edited</span>
|
||||
<span class="gh-links-list-item-success">{{svg-jar "check-circle"}}</span>
|
||||
<span class="gh-links-list-item-success {{if (eq @showSuccess link.link.link_id) "gh-links-list-item-success-show"}}">{{svg-jar "check-circle"}}</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{else}}
|
||||
|
|
|
@ -7,7 +7,8 @@ const PAGE_SIZE = 5;
|
|||
export default class LinksTable extends Component {
|
||||
@tracked page = 1;
|
||||
|
||||
@tracked editingLink = false;
|
||||
@tracked editingLink = null;
|
||||
@tracked showError = null;
|
||||
|
||||
@action
|
||||
blurElement(event) {
|
||||
|
@ -26,19 +27,26 @@ export default class LinksTable extends Component {
|
|||
cancelEdit(event) {
|
||||
event.preventDefault();
|
||||
this.editingLink = null;
|
||||
// event.target.value = this.args.post[property];
|
||||
// event.target.blur();
|
||||
this.showError = null;
|
||||
}
|
||||
|
||||
@action
|
||||
setLink(event) {
|
||||
event.preventDefault();
|
||||
this.args.updateLink(this.editingLink, event.target.value);
|
||||
try {
|
||||
const newUrl = new URL(event.target.value);
|
||||
const linkObj = this.links.find((_link) => {
|
||||
return _link.link.link_id === this.editingLink;
|
||||
});
|
||||
// Only call update if the new link is different from current link
|
||||
if (linkObj.link.to !== newUrl.href) {
|
||||
this.args.updateLink(this.editingLink, newUrl.href);
|
||||
}
|
||||
this.editingLink = null;
|
||||
// const title = event.target.value;
|
||||
// this.args.post.title = title.trim();
|
||||
// this.args.post.save();
|
||||
// this.editingLink = false;
|
||||
this.showError = null;
|
||||
} catch (e) {
|
||||
this.showError = this.editingLink;
|
||||
}
|
||||
}
|
||||
|
||||
get links() {
|
||||
|
@ -46,12 +54,7 @@ export default class LinksTable extends Component {
|
|||
}
|
||||
|
||||
get visibleLinks() {
|
||||
return this.links.slice(this.startOffset - 1, this.endOffset).map((link) => {
|
||||
return {
|
||||
...link,
|
||||
isEditing: this.editingLink === link.link.link_id
|
||||
};
|
||||
});
|
||||
return this.links.slice(this.startOffset - 1, this.endOffset);
|
||||
}
|
||||
|
||||
get startOffset() {
|
||||
|
|
|
@ -97,7 +97,10 @@
|
|||
{{#if (is-empty this.links) }}
|
||||
{{!-- Empty state --}}
|
||||
{{else}}
|
||||
<Posts::LinksTable @links={{this.links}} @updateLink={{this.updateLink}} />
|
||||
<Posts::LinksTable
|
||||
@links={{this.links}} @updateLink={{this.updateLink}}
|
||||
@showSuccess={{this.showSuccess}}
|
||||
/>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
|
|
|
@ -27,6 +27,8 @@ export default class Analytics extends Component {
|
|||
@tracked sources = null;
|
||||
@tracked links = null;
|
||||
@tracked sortColumn = 'signups';
|
||||
@tracked showSuccess;
|
||||
@tracked updateLinkId;
|
||||
displayOptions = DISPLAY_OPTIONS;
|
||||
|
||||
get post() {
|
||||
|
@ -96,8 +98,11 @@ export default class Analytics extends Component {
|
|||
|
||||
@action
|
||||
updateLink(linkId, linkTo) {
|
||||
this.updateLinkId = linkId;
|
||||
let currentLink;
|
||||
this.links = this.links?.map((link) => {
|
||||
if (link.link.link_id === linkId) {
|
||||
currentLink = new URL(link.link.originalTo);
|
||||
return {
|
||||
...link,
|
||||
link: {
|
||||
|
@ -109,6 +114,21 @@ export default class Analytics extends Component {
|
|||
}
|
||||
return link;
|
||||
});
|
||||
this.saveLink(currentLink.href, new URL(linkTo).href);
|
||||
}
|
||||
|
||||
@action
|
||||
saveLink() {
|
||||
this.showSuccess = this.updateLinkId;
|
||||
setTimeout(() => {
|
||||
this.showSuccess = null;
|
||||
}, 2000);
|
||||
|
||||
// Temp comment till API changes are merged
|
||||
// if (this._updateLinks.isRunning) {
|
||||
// return this._updateLinks.last;
|
||||
// }
|
||||
// return this._updateLinks.perform(currentLink, newLink);
|
||||
}
|
||||
|
||||
@action
|
||||
|
@ -126,6 +146,32 @@ export default class Analytics extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
updateLinkData(linksData) {
|
||||
const links = linksData.map((link) => {
|
||||
return {
|
||||
...link,
|
||||
link: {
|
||||
...link.link,
|
||||
originalTo: link.link.to,
|
||||
to: this.utils.cleanTrackedUrl(link.link.to, false),
|
||||
title: this.utils.cleanTrackedUrl(link.link.to, true)
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
// Remove duplicates by title ad merge
|
||||
const linksByTitle = links.reduce((acc, link) => {
|
||||
if (!acc[link.link.title]) {
|
||||
acc[link.link.title] = link;
|
||||
} else {
|
||||
acc[link.link.title].clicks += link.clicks;
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
this.links = Object.values(linksByTitle);
|
||||
}
|
||||
|
||||
async fetchReferrersStats() {
|
||||
if (this._fetchReferrersStats.isRunning) {
|
||||
return this._fetchReferrersStats.last;
|
||||
|
@ -140,6 +186,30 @@ export default class Analytics extends Component {
|
|||
return this._fetchLinks.perform();
|
||||
}
|
||||
|
||||
@task
|
||||
*_updateLinks(currentLink, newLink) {
|
||||
const filter = `post_id:${this.post.id}+to:'${currentLink}'`;
|
||||
let bulkUpdateUrl = this.ghostPaths.url.api(`links/bulk`) + `?filter=${encodeURIComponent(filter)}`;
|
||||
yield this.ajax.put(bulkUpdateUrl, {
|
||||
data: {
|
||||
bulk: {
|
||||
action: 'updateLink',
|
||||
meta: {link: {to: newLink}}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Refresh links data
|
||||
const linksFilter = `post_id:${this.post.id}`;
|
||||
let statsUrl = this.ghostPaths.url.api(`links/`) + `?filter=${encodeURIComponent(linksFilter)}`;
|
||||
let result = yield this.ajax.request(statsUrl);
|
||||
this.updateLinkData(result.links);
|
||||
this.showSuccess = this.updateLinkId;
|
||||
setTimeout(() => {
|
||||
this.showSuccess = null;
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
@task
|
||||
*_fetchReferrersStats() {
|
||||
let statsUrl = this.ghostPaths.url.api(`stats/referrers/posts/${this.post.id}`);
|
||||
|
@ -158,28 +228,7 @@ export default class Analytics extends Component {
|
|||
const filter = `post_id:${this.post.id}`;
|
||||
let statsUrl = this.ghostPaths.url.api(`links/`) + `?filter=${encodeURIComponent(filter)}`;
|
||||
let result = yield this.ajax.request(statsUrl);
|
||||
const links = result.links.map((link) => {
|
||||
return {
|
||||
...link,
|
||||
link: {
|
||||
...link.link,
|
||||
to: this.utils.cleanTrackedUrl(link.link.to, false),
|
||||
title: this.utils.cleanTrackedUrl(link.link.to, true)
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
// Remove duplicates by title ad merge
|
||||
const linksByTitle = links.reduce((acc, link) => {
|
||||
if (!acc[link.link.title]) {
|
||||
acc[link.link.title] = link;
|
||||
} else {
|
||||
acc[link.link.title].clicks += link.clicks;
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
this.links = Object.values(linksByTitle);
|
||||
this.updateLinkData(result.links);
|
||||
}
|
||||
|
||||
get showLinks() {
|
||||
|
|
Loading…
Add table
Reference in a new issue