Updated specific tier handling for default post access setting (#2246)

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

Default content visibility for specific tiers is now stored across 2 settings - `tiers` on `default_content_visibility` and list of tier ids on `default_content_visibility_tiers` setting, which is consistent with pattern of storing visibility on posts. This change -

- updates visibility filter UI for default content visibility segment select
- cleans up common visibility segment select component to handle ids directly instead of nql segments
- updates setting model
This commit is contained in:
Rishabh Garg 2022-02-04 21:00:59 +05:30 committed by GitHub
parent bc1cede1f4
commit e493afdb16
5 changed files with 33 additions and 30 deletions

View File

@ -83,7 +83,7 @@
{{#if (eq this.post.visibility "tiers")}}
<GhFormGroup @errors={{this.post.errors}} @hasValidated={{this.post.hasValidated}} @property="tiers" @class="nt3">
<GhPostSettingsMenu::VisibilitySegmentSelect
@segment={{this.post.visibilitySegment}}
@tiers={{this.post.tiers}}
@onChange={{action "setVisibility"}}
@renderInPlace={{true}}
@hideOptionsWhenAllSelected={{true}}

View File

@ -21,13 +21,6 @@ export default class VisibilitySegmentSelect extends Component {
}
get options() {
if (this.args.hideOptionsWhenAllSelected) {
const selectedSegments = this.selectedOptions.mapBy('segment');
if (selectedSegments.includes('status:free') && selectedSegments.includes('status:-free')) {
return this._options.filter(option => !option.groupName);
}
}
return this._options;
}
@ -48,17 +41,20 @@ export default class VisibilitySegmentSelect extends Component {
}
get selectedOptions() {
const segments = (this.args.segment || '').split(',');
return this.flatOptions.filter(option => segments.includes(option.segment));
const tierList = this.args.tiers.map((product) => {
return this.products.find((p) => {
return p.id === product.id;
});
}).filter(d => !!d);
const tierIdList = tierList.map(d => d.id);
return this.flatOptions.filter(option => tierIdList.includes(option.id));
}
@action
setSegment(options) {
const segment = options.mapBy('segment').join(',') || null;
let ids = segment?.split(',').map((d) => {
let slug = d.replace('product:', '');
let ids = options.mapBy('id').map((id) => {
let product = this.products.find((p) => {
return p.slug === slug;
return p.id === id;
});
return {
id: product.id,
@ -88,15 +84,15 @@ export default class VisibilitySegmentSelect extends Component {
products.forEach((product) => {
productsGroup.options.push({
name: product.name,
segment: `product:${product.slug}`,
id: product.id,
count: product.count?.members,
class: 'segment-product'
});
});
options.push(productsGroup);
if (this.args.selectDefaultProduct && !this.args.segment) {
this.args.onChange?.(productsGroup.options[0].segment);
if (this.args.selectDefaultProduct && !this.args.tiers) {
this.setSegment([productsGroup.options[0]]);
}
}
}

View File

@ -25,13 +25,11 @@
</PowerSelect>
{{#if this.hasVisibilityFilter}}
<div class="mt2">
<GhMembersSegmentSelect
@hideLabels={{true}}
<GhPostSettingsMenu::VisibilitySegmentSelect
@selectDefaultProduct={{true}}
@segment={{this.settings.defaultContentVisibility}}
@tiers={{this.visibilityTiers}}
@onChange={{action "setVisibility"}}
@renderInPlace={{true}}
@hideDefaultSegments={{true}}
@hideOptionsWhenAllSelected={{true}}
/>
{{#if this.showSegmentError}}

View File

@ -32,7 +32,7 @@ export default class SettingsMembersDefaultPostAccess extends Component {
defaultOptions.push({
name: 'Specific tier(s)',
description: 'Members with any of the selected tiers',
value: 'filter',
value: 'tiers',
icon: 'members-segment',
icon_color: 'yellow'
});
@ -44,20 +44,29 @@ export default class SettingsMembersDefaultPostAccess extends Component {
return this.feature.get('multipleProducts') && !['public', 'members', 'paid'].includes(this.settings.get('defaultContentVisibility'));
}
get visibilityTiers() {
const visibilityTiersData = this.settings.get('defaultContentVisibilityTiers');
return visibilityTiersData.map((id) => {
return {id};
});
}
get selectedOption() {
if (this.settings.get('membersSignupAccess') === 'none') {
return this.options.find(o => o.value === 'public');
}
if (!['public', 'members', 'paid'].includes(this.settings.get('defaultContentVisibility'))) {
return this.options.find(o => o.value === 'filter');
}
return this.options.find(o => o.value === this.settings.get('defaultContentVisibility'));
}
@action
setVisibility(segment) {
if (segment) {
this.settings.set('defaultContentVisibility', segment);
const productIds = segment?.map((product) => {
return product.id;
});
this.settings.set('defaultContentVisibility', 'tiers');
this.settings.set('defaultContentVisibilityTiers', productIds);
this.showSegmentError = false;
} else {
this.settings.set('defaultContentVisibility', '');
@ -68,10 +77,9 @@ export default class SettingsMembersDefaultPostAccess extends Component {
@action
setDefaultContentVisibility(option) {
if (this.settings.get('membersSignupAccess') !== 'none') {
if (option.value === 'filter') {
this.settings.set('defaultContentVisibility', '');
} else {
this.settings.set('defaultContentVisibility', option.value);
if (option.value === 'tiers') {
this.settings.set('defaultContentVisibilityTiers', []);
}
}
}

View File

@ -55,6 +55,7 @@ export default Model.extend(ValidationEngine, {
*/
membersSignupAccess: attr('string'),
defaultContentVisibility: attr('string'),
defaultContentVisibilityTiers: attr('json-string'),
membersFromAddress: attr('string'),
membersSupportAddress: attr('string'),
membersReplyAddress: attr('string'),