Skip to content
This repository has been archived by the owner on Nov 28, 2022. It is now read-only.

Commit

Permalink
Improved UI for custom redirect settings (#1775)
Browse files Browse the repository at this point in the history
refs TryGhost/Ghost#12366

* Displays URL as absolute, but still stores the path relative to the site 
* Allows pasting absolute URL's or relative
* Does not support external URL's
* Removed redundant "Links" section in Portal settings sidebar

Co-authored-by: Peter Zimon <zimo@ghost.org>
  • Loading branch information
allouis and peterzimon committed Nov 20, 2020
1 parent e2dc14b commit 42b845d
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 46 deletions.
6 changes: 6 additions & 0 deletions app/components/gh-url-input.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<GhTextInput
@value={{this.value}}
@type="text"
@input={{setValue}}
/>

35 changes: 35 additions & 0 deletions app/components/gh-url-input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import Component from '@glimmer/component';
import {action} from '@ember/object';

function ensureEndsWith(string, endsWith) {
return string.endsWith(endsWith) ? string : string + endsWith;
}

function removeLeadingSlash(string) {
return string.replace(/^\//, '');
}

export default class GhUrlInput extends Component {
constructor(owner, args) {
super(owner, args);
this.baseUrl = ensureEndsWith(args.baseUrl, '/');
this.value = args.value && args.value !== '/' ? (new URL(removeLeadingSlash(args.value), this.baseUrl)).href : '';
this.setResult = args.setResult;
}

@action
setValue(event) {
this.value = event.target.value;
if (this.result !== null) {
this.setResult(this.result);
}
}

get result() {
try {
return new URL(removeLeadingSlash(this.value), this.baseUrl);
} catch (err) {
return null;
}
}
}
72 changes: 30 additions & 42 deletions app/components/modal-portal-settings.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -251,60 +251,48 @@
{{/if}}
{{/if}}
</div>
<div class="gh-portal-setting-section divider-top">
<h4 class="gh-portal-setting-sectionheading">Links</h4>
<GhFormGroup>
<div class="flex w-100 justify-between items-center">
<h4 class="gh-portal-setting-title">Show Portal</h4>
<div {{action (toggle "isShowModalLink" this)}} class="blue pointer f8"> {{if this.isShowModalLink "Data Attribute" "Link"}} </div>
</div>
<div class="flex items-center justify-center mt1 gh-show-modal-link-form relative">
<div class="gh-portal-page-url-container">
<div class="page-url-label">
{{#if this.isShowModalLink}}
<span class="page-url-disabled">{{this.siteUrl}}/</span><span>{{this.showModalLinkOrAttribute}}</span>
{{else}}
{{this.showModalLinkOrAttribute}}
{{/if}}
</div>
<button type="button" {{action (perform this.copyLinkOrAttribute)}} class="gh-portal-setting-copy">
{{#if this.copyLinkOrAttribute.isRunning}}
{{svg-jar "check-circle" class="w4 v-mid mr1 stroke-darkgrey"}} Copied
{{else}}
<span data-tooltip="Copy">{{svg-jar "copy" class="w4 v-mid fill-darkgrey"}}</span>
{{/if}}
</button>
</div>
</div>
<div>
<span onclick={{action "switchPreviewPage" "links"}} class="blue pointer f7">Show more</span>
</div>
</GhFormGroup>
</div>
<div class="gh-portal-setting-section redirects divider-top">
<h4 class="gh-portal-setting-sectionheading">Redirects</h4>
<GhFormGroup @classNames="mt5">
<h4 class="gh-portal-setting-title">After free signup</h4>
<h4 class="gh-portal-setting-sectionheading">Welcome page</h4>
<GhFormGroup
@errors={{settings.errors}}
@hasValidated={{settings.hasValidated}}
@property="membersFreeSignupRedirect"
@classNames="mt5"
>
<h4 class="gh-portal-setting-title">For free signups</h4>
<div class="flex items-center mt2">
<GhTextInput
<GhUrlInput
@value={{readonly this.settings.membersFreeSignupRedirect}}
@type="text"
@input={{action "setFreeSignupRedirect"}}
@baseUrl={{readonly this.siteUrl}}
@setResult={{action "setFreeSignupRedirect"}}
/>
</div>
<GhErrorMessage
@errors={{settings.errors}}
@property="membersFreeSignupRedirect"
/>
</GhFormGroup>
{{#if (and this.isStripeConfigured (or this.isMonthlyChecked this.isYearlyChecked))}}
<GhFormGroup @classNames="space-l pb5">
<h4 class="gh-portal-setting-title">After paid signup</h4>
<GhFormGroup
@errors={{settings.errors}}
@hasValidated={{settings.hasValidated}}
@property="membersPaidSignupRedirect"
@classNames="space-l pb5"
>
<h4 class="gh-portal-setting-title">For paid signups</h4>

<div class="flex items-center mt2">
<GhTextInput
<GhUrlInput
@value={{readonly this.settings.membersPaidSignupRedirect}}
@type="text"
@input={{action "setPaidSignupRedirect"}}
@baseUrl={{readonly this.siteUrl}}
@setResult={{action "setPaidSignupRedirect"}}
/>
</div>
<p>URLs to redirect members after signing up. Leave them empty to redirect to homepage.</p>
<GhErrorMessage
@errors={{settings.errors}}
@property="membersPaidSignupRedirect"
/>
<p>Members will be sent to these URLs after successful signup. If empty, the homepage will be used.</p>
</GhFormGroup>
{{/if}}
</div>
Expand Down
23 changes: 19 additions & 4 deletions app/components/modal-portal-settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -176,12 +176,12 @@ export default ModalComponent.extend({
this.settings.set('portalName', showSignupName);
},

setPaidSignupRedirect(event) {
this.settings.set('membersPaidSignupRedirect', event.target.value);
setPaidSignupRedirect(url) {
this._validateSignupRedirect(url, 'membersPaidSignupRedirect');
},

setFreeSignupRedirect(event) {
this.settings.set('membersFreeSignupRedirect', event.target.value);
setFreeSignupRedirect(url) {
this._validateSignupRedirect(url, 'membersFreeSignupRedirect');
},

confirm() {
Expand Down Expand Up @@ -285,6 +285,21 @@ export default ModalComponent.extend({
}
},

_validateSignupRedirect(url, type) {
let errMessage = `Only URLs under your Ghost domain are allowed`;
this.get('settings.errors').remove(type);
this.get('settings.hasValidated').removeObject(type);

if (url.href.startsWith(this.siteUrl)) {
const path = url.href.replace(this.siteUrl, '');
this.settings.set(type, path);
return;
}

this.get('settings.errors').add(type, errMessage);
this.get('settings.hasValidated').pushObject(type);
},

_validateAccentColor(color) {
let newColor = color;
let oldColor = this.get('settings.accentColor');
Expand Down

0 comments on commit 42b845d

Please sign in to comment.