0
Fork 0
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:
Rishabh 2022-10-19 18:54:54 +05:30 committed by Rishabh Garg
parent b310b3a97a
commit 3db8fb5a1c
4 changed files with 97 additions and 42 deletions

View file

@ -12,7 +12,7 @@
<div class="gh-links-list-title">
Link
</div>
{{/if}}
{{/if}}
<div class="gh-links-list-title">
No. of Members
</div>
@ -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">&nbsp;&ndash; 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}}

View file

@ -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);
this.editingLink = null;
// const title = event.target.value;
// this.args.post.title = title.trim();
// this.args.post.save();
// this.editingLink = false;
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;
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() {

View file

@ -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}}

View file

@ -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() {