Added portal preview to offer screen

refs https://github.com/TryGhost/Team/issues/1137

- adds new portal preview using portal offer url on offer screen
- adds new utility to calculate portal offer preview url from data
- fixed tiny bug with discount type currency not shown correctly
This commit is contained in:
Rishabh 2021-10-18 14:31:29 +05:30
parent 9120f0d820
commit bb575dbb87
3 changed files with 109 additions and 8 deletions

View File

@ -16,10 +16,12 @@ export default class OffersController extends Controller {
@service settings;
@service store;
@service modals;
@service membersUtils;
@service notifications;
@tracked cadences = [];
@tracked products = [];
@tracked portalPreviewUrl = '';
@tracked showUnsavedChangesModal = false;
@tracked durations = [
@ -51,6 +53,7 @@ export default class OffersController extends Controller {
@tracked defaultProps = null;
leaveScreenTransition = null;
portalPreviewGuid = Date.now().valueOf();
constructor() {
super(...arguments);
@ -114,9 +117,24 @@ export default class OffersController extends Controller {
});
});
this.cadences = cadences;
const defaultCadence = this.cadences[0]?.name;
if (this.offer && !this.offer.tier) {
this.defaultProps = {};
this.updateCadence(this.cadences[0]?.name, this.defaultProps);
this.updatePortalPreview({forceRefresh: false});
} else if (defaultCadence) {
const [,, currency] = (defaultCadence || '').split('-');
this.offertypes = [
{
label: '%',
offertype: 'percent'
},
{
label: currency.toUpperCase(),
offertype: 'fixed'
}
];
this.updatePortalPreview({forceRefresh: false});
}
}
@ -164,6 +182,37 @@ export default class OffersController extends Controller {
this.isLoading = false;
}
@action
portalPreviewInserted() {}
@action
portalPreviewDestroyed() {}
@action
updatePortalPreview({forceRefresh} = {forceRefresh: false}) {
const newUrl = new URL(this.membersUtils.getOfferPortalPreviewUrl({
name: this.offer.name || 'No Name',
code: this.offer.code || 'no-code',
displayTitle: this.offer.displayTitle,
displayDescription: this.offer.displayDescription,
type: this.offer.type,
cadence: this.offer.cadence || this.defaultProps?.cadence,
amount: this.offer.amount,
duration: this.offer.duration,
durationInMonths: '',
currency: this.offer.currency || this.defaultProps?.currency,
status: this.offer.currency,
tierId: this.offer?.tier?.id || this.defaultProps?.tier?.id
}));
if (forceRefresh) {
this.portalPreviewGuid = Date.now().valueOf();
}
newUrl.searchParams.set('v', `${this.portalPreviewGuid}`);
this.portalPreviewUrl = newUrl;
}
@action
save() {
return this.saveTask.perform();
@ -203,7 +252,6 @@ export default class OffersController extends Controller {
@action
setup() {
this.fetchProducts.perform();
// this.fetchOfferTask.perform();
}
@action
@ -215,11 +263,12 @@ export default class OffersController extends Controller {
setDiscountType(discountType) {
if (!this.isDiscountSectionDisabled) {
this._saveOfferProperty('type', discountType);
}
if (this.offer.type === 'fixed' && this.offer.amount !== '') {
this.offer.amount = this.offer.amount * 100;
} else if (this.offer.amount !== '') {
this.offer.amount = this.offer.amount / 100;
if (this.offer.type === 'fixed' && this.offer.amount !== '') {
this.offer.amount = this.offer.amount * 100;
} else if (this.offer.amount !== '') {
this.offer.amount = this.offer.amount / 100;
}
this.updatePortalPreview({forceRefresh: false});
}
}
@ -322,6 +371,7 @@ export default class OffersController extends Controller {
offertype: 'fixed'
}
];
this.updatePortalPreview({forceRefresh: false});
}
}
@ -341,5 +391,6 @@ export default class OffersController extends Controller {
}
this.offer[propKey] = newValue;
this.updatePortalPreview({forceRefresh: false});
}
}

View File

@ -141,4 +141,45 @@ export default class MembersUtilsService extends Service {
return `${baseUrl}${portalBase}?${settingsParam.toString()}`;
}
getOfferPortalPreviewUrl(overrides) {
const {
disableBackground = false,
name,
code,
displayTitle = 'Offer Name',
displayDescription = 'Offer description',
type,
cadence,
amount = 0,
duration,
durationInMonths,
currency = 'usd',
status,
tierId
} = overrides;
const baseUrl = this.config.get('blogUrl');
const portalBase = '/#/portal/preview/offer';
const settingsParam = new URLSearchParams();
settingsParam.append('name', encodeURIComponent(name));
settingsParam.append('code', encodeURIComponent(code));
settingsParam.append('display_title', encodeURIComponent(displayTitle));
settingsParam.append('display_description', encodeURIComponent(displayDescription));
settingsParam.append('type', encodeURIComponent(type));
settingsParam.append('cadence', encodeURIComponent(cadence));
settingsParam.append('amount', encodeURIComponent(amount));
settingsParam.append('duration', encodeURIComponent(duration));
settingsParam.append('duration_in_months', encodeURIComponent(durationInMonths));
settingsParam.append('currency', encodeURIComponent(currency));
settingsParam.append('status', encodeURIComponent(status));
settingsParam.append('tier_id', encodeURIComponent(tierId));
if (disableBackground) {
settingsParam.append('disableBackground', 'true');
}
return `${baseUrl}${portalBase}?${settingsParam.toString()}`;
}
}

View File

@ -6,7 +6,7 @@
{{#if this.offer.isNew}}
New Offer
{{else}}
{{this.offer.name}}
{{this.offer.name}}
{{#if (eq this.offer.status "archived")}}
<span class="gh-badge gh-badge-title">Archived</span>
{{/if}}
@ -201,7 +201,16 @@
<div class="gh-offer-portal-preview">
<div>
<h4 class="gh-main-section-header small bn">Preview</h4>
<div class="gh-offer-portal-preview-mock">Portal preview</div>
<div class="gh-setting-members-portalpreview">
<div class="gh-setting-members-portal-mock">
<GhSiteIframe
scrolling="no"
@src={{this.portalPreviewUrl}}
@invisibleUntilLoaded="portal-ready"
@onInserted={{this.portalPreviewInserted}}
@onDestroyed={{this.portalPreviewDestroyed}} />
</div>
</div>
</div>
</div>
</div>