2020-07-07 07:22:42 +03:00
|
|
|
import $ from 'jquery';
|
2020-06-19 19:06:49 +03:00
|
|
|
import ModalComponent from 'ghost-admin/components/modal-base';
|
2020-07-07 07:22:42 +03:00
|
|
|
import copyTextToClipboard from 'ghost-admin/utils/copy-text-to-clipboard';
|
2020-06-29 20:37:11 +03:00
|
|
|
import {alias, reads} from '@ember/object/computed';
|
2020-06-19 19:06:49 +03:00
|
|
|
import {computed} from '@ember/object';
|
2020-07-07 07:22:42 +03:00
|
|
|
import {htmlSafe} from '@ember/string';
|
|
|
|
import {run} from '@ember/runloop';
|
2020-06-19 19:06:49 +03:00
|
|
|
import {inject as service} from '@ember/service';
|
2020-07-07 07:22:42 +03:00
|
|
|
import {task, timeout} from 'ember-concurrency';
|
2020-07-21 20:12:55 +03:00
|
|
|
const ICON_EXTENSIONS = ['gif', 'jpg', 'jpeg', 'png', 'svg'];
|
|
|
|
|
|
|
|
const ICON_MAPPING = [
|
|
|
|
{
|
2020-07-24 17:59:41 +03:00
|
|
|
icon: 'portal-icon-1',
|
2020-07-21 20:12:55 +03:00
|
|
|
value: 'icon-1'
|
|
|
|
},
|
|
|
|
{
|
2020-07-24 17:59:41 +03:00
|
|
|
icon: 'portal-icon-2',
|
2020-07-21 20:12:55 +03:00
|
|
|
value: 'icon-2'
|
|
|
|
},
|
|
|
|
{
|
2020-07-24 17:59:41 +03:00
|
|
|
icon: 'portal-icon-3',
|
2020-07-21 20:12:55 +03:00
|
|
|
value: 'icon-3'
|
|
|
|
},
|
|
|
|
{
|
2020-07-24 17:59:41 +03:00
|
|
|
icon: 'portal-icon-4',
|
2020-07-21 20:12:55 +03:00
|
|
|
value: 'icon-4'
|
|
|
|
},
|
|
|
|
{
|
2020-07-24 17:59:41 +03:00
|
|
|
icon: 'portal-icon-5',
|
2020-07-21 20:12:55 +03:00
|
|
|
value: 'icon-5'
|
|
|
|
}
|
|
|
|
];
|
2020-06-19 19:06:49 +03:00
|
|
|
|
|
|
|
export default ModalComponent.extend({
|
|
|
|
settings: service(),
|
2020-06-29 20:37:11 +03:00
|
|
|
membersUtils: service(),
|
2020-06-25 23:45:47 +03:00
|
|
|
config: service(),
|
|
|
|
page: 'signup',
|
2020-07-07 07:22:42 +03:00
|
|
|
iconExtensions: null,
|
|
|
|
defaultButtonIcons: null,
|
|
|
|
isShowModalLink: true,
|
|
|
|
customIcon: null,
|
2020-07-30 16:12:44 +03:00
|
|
|
showLinksPage: false,
|
2020-07-30 13:56:07 +03:00
|
|
|
showLeaveSettingsModal: false,
|
2020-06-25 23:45:47 +03:00
|
|
|
confirm() {},
|
2020-06-29 20:37:11 +03:00
|
|
|
|
2020-07-16 08:42:00 +03:00
|
|
|
allowSelfSignup: alias('settings.membersAllowFreeSignup'),
|
2020-06-29 20:37:11 +03:00
|
|
|
|
|
|
|
isStripeConfigured: reads('membersUtils.isStripeEnabled'),
|
2020-06-19 19:06:49 +03:00
|
|
|
|
2020-07-30 13:56:07 +03:00
|
|
|
buttonIcon: computed('settings.portalButtonIcon', function () {
|
|
|
|
const defaultIconKeys = this.defaultButtonIcons.map(buttonIcon => buttonIcon.value);
|
|
|
|
return (this.settings.get('portalButtonIcon') || defaultIconKeys[0]);
|
|
|
|
}),
|
|
|
|
|
2020-07-07 07:22:42 +03:00
|
|
|
backgroundStyle: computed('settings.accentColor', function () {
|
|
|
|
let color = this.get('settings.accentColor') || '#ffffff';
|
|
|
|
return htmlSafe(`background-color: ${color}`);
|
|
|
|
}),
|
|
|
|
|
2020-08-26 19:08:03 +03:00
|
|
|
colorPickerValue: computed('settings.accentColor', function () {
|
|
|
|
return this.get('settings.accentColor') || '#ffffff';
|
|
|
|
}),
|
|
|
|
|
2020-07-07 07:22:42 +03:00
|
|
|
accentColor: computed('settings.accentColor', function () {
|
|
|
|
let color = this.get('settings.accentColor');
|
|
|
|
if (color && color[0] === '#') {
|
|
|
|
return color.slice(1);
|
|
|
|
}
|
|
|
|
return color;
|
|
|
|
}),
|
|
|
|
|
|
|
|
showModalLinkOrAttribute: computed('isShowModalLink', function () {
|
|
|
|
if (this.isShowModalLink) {
|
|
|
|
return `${this.config.get('blogUrl')}/#/portal`;
|
|
|
|
}
|
|
|
|
return `data-portal`;
|
|
|
|
}),
|
|
|
|
|
2020-07-30 13:56:07 +03:00
|
|
|
portalPreviewUrl: computed('buttonIcon', 'page', 'isFreeChecked', 'isMonthlyChecked', 'isYearlyChecked', 'settings.{portalName,portalButton,portalButtonSignupText,portalButtonStyle,accentColor}', function () {
|
2020-06-25 23:45:47 +03:00
|
|
|
const baseUrl = this.config.get('blogUrl');
|
2020-07-23 18:33:31 +03:00
|
|
|
const portalBase = '/#/portal/preview';
|
2020-06-25 23:45:47 +03:00
|
|
|
const settingsParam = new URLSearchParams();
|
|
|
|
settingsParam.append('button', this.settings.get('portalButton'));
|
|
|
|
settingsParam.append('name', this.settings.get('portalName'));
|
|
|
|
settingsParam.append('isFree', this.isFreeChecked);
|
|
|
|
settingsParam.append('isMonthly', this.isMonthlyChecked);
|
|
|
|
settingsParam.append('isYearly', this.isYearlyChecked);
|
|
|
|
settingsParam.append('page', this.page);
|
2020-07-08 18:23:29 +03:00
|
|
|
if (this.buttonIcon) {
|
|
|
|
settingsParam.append('buttonIcon', encodeURIComponent(this.buttonIcon));
|
|
|
|
}
|
2020-07-30 13:56:07 +03:00
|
|
|
settingsParam.append('signupButtonText', encodeURIComponent(this.settings.get('portalButtonSignupText')));
|
2020-07-07 07:22:42 +03:00
|
|
|
if (this.settings.get('accentColor')) {
|
|
|
|
settingsParam.append('accentColor', encodeURIComponent(`${this.settings.get('accentColor')}`));
|
|
|
|
}
|
2020-07-30 13:56:07 +03:00
|
|
|
if (this.settings.get('portalButtonStyle')) {
|
|
|
|
settingsParam.append('buttonStyle', encodeURIComponent(this.settings.get('portalButtonStyle')));
|
2020-07-07 07:22:42 +03:00
|
|
|
}
|
2020-06-25 23:45:47 +03:00
|
|
|
return `${baseUrl}${portalBase}?${settingsParam.toString()}`;
|
|
|
|
}),
|
|
|
|
|
2020-07-07 07:22:42 +03:00
|
|
|
showIconSetting: computed('selectedButtonStyle', function () {
|
|
|
|
const selectedButtonStyle = this.get('selectedButtonStyle.name') || '';
|
|
|
|
return selectedButtonStyle.includes('icon');
|
|
|
|
}),
|
|
|
|
|
2020-07-16 16:21:14 +03:00
|
|
|
showButtonTextSetting: computed('selectedButtonStyle', function () {
|
|
|
|
const selectedButtonStyle = this.get('selectedButtonStyle.name') || '';
|
|
|
|
return selectedButtonStyle.includes('text');
|
|
|
|
}),
|
|
|
|
|
2020-06-29 20:37:11 +03:00
|
|
|
isFreeChecked: computed('settings.portalPlans.[]', 'allowSelfSignup', function () {
|
2020-06-19 19:06:49 +03:00
|
|
|
const allowedPlans = this.settings.get('portalPlans') || [];
|
2020-06-29 20:37:11 +03:00
|
|
|
return (this.allowSelfSignup && allowedPlans.includes('free'));
|
2020-06-19 19:06:49 +03:00
|
|
|
}),
|
|
|
|
|
|
|
|
isMonthlyChecked: computed('settings.portalPlans.[]', 'isStripeConfigured', function () {
|
|
|
|
const allowedPlans = this.settings.get('portalPlans') || [];
|
|
|
|
return (this.isStripeConfigured && allowedPlans.includes('monthly'));
|
|
|
|
}),
|
|
|
|
|
|
|
|
isYearlyChecked: computed('settings.portalPlans.[]', 'isStripeConfigured', function () {
|
|
|
|
const allowedPlans = this.settings.get('portalPlans') || [];
|
|
|
|
return (this.isStripeConfigured && allowedPlans.includes('yearly'));
|
|
|
|
}),
|
|
|
|
|
2020-07-07 07:22:42 +03:00
|
|
|
selectedButtonStyle: computed('settings.portalButtonStyle', function () {
|
|
|
|
return this.buttonStyleOptions.find((buttonStyle) => {
|
|
|
|
return (buttonStyle.name === this.settings.get('portalButtonStyle'));
|
|
|
|
});
|
|
|
|
}),
|
|
|
|
|
2020-06-19 19:06:49 +03:00
|
|
|
init() {
|
|
|
|
this._super(...arguments);
|
2020-08-11 09:34:42 +03:00
|
|
|
this.set('hidePreviewFrame', true);
|
2020-07-07 07:22:42 +03:00
|
|
|
this.buttonStyleOptions = [
|
|
|
|
{name: 'icon-and-text', label: 'Icon and text'},
|
|
|
|
{name: 'icon-only', label: 'Icon only'},
|
|
|
|
{name: 'text-only', label: 'Text only'}
|
|
|
|
];
|
2020-07-21 20:12:55 +03:00
|
|
|
this.defaultButtonIcons = ICON_MAPPING;
|
2020-07-07 07:22:42 +03:00
|
|
|
this.iconExtensions = ICON_EXTENSIONS;
|
2020-07-08 18:23:29 +03:00
|
|
|
const portalButtonIcon = this.settings.get('portalButtonIcon') || '';
|
2020-07-21 20:12:55 +03:00
|
|
|
const defaultIconKeys = this.defaultButtonIcons.map(buttonIcon => buttonIcon.value);
|
|
|
|
if (portalButtonIcon && !defaultIconKeys.includes(portalButtonIcon)) {
|
|
|
|
this.set('customIcon', this.settings.get('portalButtonIcon'));
|
2020-07-07 07:22:42 +03:00
|
|
|
}
|
2020-06-19 19:06:49 +03:00
|
|
|
},
|
|
|
|
|
2020-08-11 09:34:42 +03:00
|
|
|
didInsertElement() {
|
|
|
|
this._super(...arguments);
|
|
|
|
run.later(this, function () {
|
|
|
|
this.set('hidePreviewFrame', false);
|
|
|
|
}, 1200);
|
|
|
|
},
|
|
|
|
|
2020-06-19 19:06:49 +03:00
|
|
|
actions: {
|
|
|
|
toggleFreePlan(isChecked) {
|
|
|
|
this.updateAllowedPlan('free', isChecked);
|
|
|
|
},
|
|
|
|
toggleMonthlyPlan(isChecked) {
|
|
|
|
this.updateAllowedPlan('monthly', isChecked);
|
|
|
|
},
|
|
|
|
toggleYearlyPlan(isChecked) {
|
|
|
|
this.updateAllowedPlan('yearly', isChecked);
|
|
|
|
},
|
2020-07-07 07:22:42 +03:00
|
|
|
togglePortalButton(showButton) {
|
|
|
|
this.settings.set('portalButton', showButton);
|
2020-06-19 19:06:49 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
togglePortalName(showSignupName) {
|
|
|
|
this.settings.set('portalName', showSignupName);
|
|
|
|
},
|
|
|
|
|
|
|
|
confirm() {
|
|
|
|
return this.saveTask.perform();
|
|
|
|
},
|
|
|
|
|
|
|
|
isPlanSelected(plan) {
|
|
|
|
const allowedPlans = this.settings.get('portalPlans');
|
|
|
|
return allowedPlans.includes(plan);
|
2020-06-25 23:45:47 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
switchPreviewPage(page) {
|
2020-07-30 16:12:44 +03:00
|
|
|
if (page === 'links') {
|
|
|
|
this.set('showLinksPage', true);
|
|
|
|
this.set('page', '');
|
|
|
|
} else {
|
|
|
|
this.set('showLinksPage', false);
|
|
|
|
this.set('page', page);
|
|
|
|
}
|
2020-07-07 07:22:42 +03:00
|
|
|
},
|
|
|
|
|
2020-08-26 19:08:03 +03:00
|
|
|
updateAccentColor(color) {
|
|
|
|
this._validateAccentColor(color);
|
|
|
|
},
|
2020-07-07 07:22:42 +03:00
|
|
|
|
2020-08-26 19:08:03 +03:00
|
|
|
validateAccentColor() {
|
|
|
|
this._validateAccentColor(this.get('accentColor'));
|
2020-07-07 07:22:42 +03:00
|
|
|
},
|
|
|
|
setButtonStyle(buttonStyle) {
|
2020-07-30 13:56:07 +03:00
|
|
|
this.settings.set('portalButtonStyle', buttonStyle.name);
|
2020-07-07 07:22:42 +03:00
|
|
|
},
|
|
|
|
setSignupButtonText(event) {
|
2020-07-30 13:56:07 +03:00
|
|
|
this.settings.set('portalButtonSignupText', event.target.value);
|
2020-07-07 07:22:42 +03:00
|
|
|
},
|
|
|
|
/**
|
|
|
|
* Fired after an image upload completes
|
|
|
|
* @param {string} property - Property name to be set on `this.settings`
|
|
|
|
* @param {UploadResult[]} results - Array of UploadResult objects
|
|
|
|
* @return {string} The URL that was set on `this.settings.property`
|
|
|
|
*/
|
|
|
|
imageUploaded(property, results) {
|
|
|
|
if (results[0]) {
|
|
|
|
this.set('customIcon', results[0].url);
|
2020-07-30 13:56:07 +03:00
|
|
|
this.settings.set('portalButtonIcon', results[0].url);
|
2020-07-07 07:22:42 +03:00
|
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* Opens a file selection dialog - Triggered by "Upload Image" buttons,
|
|
|
|
* searches for the hidden file input within the .gh-setting element
|
|
|
|
* containing the clicked button then simulates a click
|
|
|
|
* @param {MouseEvent} event - MouseEvent fired by the button click
|
|
|
|
*/
|
|
|
|
triggerFileDialog(event) {
|
|
|
|
// simulate click to open file dialog
|
|
|
|
// using jQuery because IE11 doesn't support MouseEvent
|
|
|
|
$(event.target)
|
|
|
|
.closest('.gh-setting-action')
|
|
|
|
.find('input[type="file"]')
|
|
|
|
.click();
|
|
|
|
},
|
|
|
|
|
2020-08-19 18:00:06 +03:00
|
|
|
deleteCustomIcon() {
|
|
|
|
this.set('customIcon', null);
|
|
|
|
const defaultIconKeys = ICON_MAPPING.map(buttonIcon => buttonIcon.value);
|
|
|
|
this.settings.set('portalButtonIcon', defaultIconKeys[0]);
|
|
|
|
},
|
|
|
|
|
2020-07-07 07:22:42 +03:00
|
|
|
selectDefaultIcon(icon) {
|
2020-07-30 13:56:07 +03:00
|
|
|
this.settings.set('portalButtonIcon', icon);
|
|
|
|
},
|
|
|
|
|
|
|
|
closeLeaveSettingsModal() {
|
|
|
|
this.set('showLeaveSettingsModal', false);
|
|
|
|
},
|
|
|
|
|
|
|
|
leaveSettings() {
|
|
|
|
this.closeModal();
|
2020-06-19 19:06:49 +03:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
updateAllowedPlan(plan, isChecked) {
|
|
|
|
const allowedPlans = this.settings.get('portalPlans') || [];
|
|
|
|
|
|
|
|
if (!isChecked) {
|
|
|
|
this.settings.set('portalPlans', allowedPlans.filter(p => p !== plan));
|
|
|
|
} else {
|
|
|
|
allowedPlans.push(plan);
|
|
|
|
this.settings.set('portalPlans', [...allowedPlans]);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2020-08-26 19:08:03 +03:00
|
|
|
_validateAccentColor(color) {
|
|
|
|
let newColor = color;
|
|
|
|
let oldColor = this.get('settings.accentColor');
|
|
|
|
let errMessage = '';
|
|
|
|
|
|
|
|
// reset errors and validation
|
|
|
|
this.get('settings.errors').remove('accentColor');
|
|
|
|
this.get('settings.hasValidated').removeObject('accentColor');
|
|
|
|
|
|
|
|
if (newColor === '') {
|
|
|
|
// Clear out the accent color
|
|
|
|
this.set('settings.accentColor', '');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// accentColor will be null unless the user has input something
|
|
|
|
if (!newColor) {
|
|
|
|
newColor = oldColor;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (newColor[0] !== '#') {
|
|
|
|
newColor = `#${newColor}`;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (newColor.match(/#[0-9A-Fa-f]{6}$/)) {
|
|
|
|
this.set('settings.accentColor', '');
|
|
|
|
run.schedule('afterRender', this, function () {
|
|
|
|
this.set('settings.accentColor', newColor);
|
|
|
|
this.set('accentColor', newColor.slice(1));
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
errMessage = 'The color should be in valid hex format';
|
|
|
|
this.get('settings.errors').add('accentColor', errMessage);
|
|
|
|
this.get('settings.hasValidated').pushObject('accentColor');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2020-07-07 07:22:42 +03:00
|
|
|
copyLinkOrAttribute: task(function* () {
|
|
|
|
copyTextToClipboard(this.showModalLinkOrAttribute);
|
|
|
|
yield timeout(this.isTesting ? 50 : 3000);
|
|
|
|
}),
|
|
|
|
|
2020-06-19 19:06:49 +03:00
|
|
|
saveTask: task(function* () {
|
|
|
|
yield this.settings.save();
|
|
|
|
this.closeModal();
|
|
|
|
}).drop()
|
|
|
|
});
|