mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-28 22:43:30 +03:00
Added preview to tier edit modal
This commit is contained in:
parent
922c304e3b
commit
a1cd55b848
@ -5,7 +5,8 @@
|
||||
</span>
|
||||
{{/unless}}
|
||||
|
||||
<div class="gh-blognav-line">
|
||||
<div class="gh-blognav-line {{unless this.name "placeholder"}}">
|
||||
{{svg-jar "check-2"}}
|
||||
<GhValidationStatusContainer
|
||||
@tagName="span"
|
||||
@class="gh-blognav-label"
|
||||
|
@ -1,132 +1,184 @@
|
||||
<header class="modal-header" data-test-modal="webhook-form">
|
||||
<h1 data-test-text="title">{{this.title}}</h1>
|
||||
</header>
|
||||
<button class="close" href title="Close" {{action "closeModal"}} {{action (optional this.noop) on="mouseDown"}}>
|
||||
{{svg-jar "close"}}
|
||||
</button>
|
||||
|
||||
<form>
|
||||
<div class="modal-body gh-form-edit-product">
|
||||
<div class="gh-main-section columns-3">
|
||||
<div class="gh-main-section-block span-2">
|
||||
<h4 class="gh-main-section-header small bn">Basic</h4>
|
||||
<div class="gh-main-section-content grey gh-product-priceform-block">
|
||||
<GhFormGroup @errors={{this.errors}} @property="name">
|
||||
<label for="name" class="fw6">Name</label>
|
||||
<GhTextInput
|
||||
@value={{readonly this.product.name}}
|
||||
@input={{action (mut this.product.name) value="target.value"}}
|
||||
@name="name"
|
||||
@placeholder="Bronze"
|
||||
@id="name"
|
||||
@class="gh-input" />
|
||||
<GhErrorMessage @errors={{this.errors}} @property="name" />
|
||||
</GhFormGroup>
|
||||
<GhFormGroup @errors={{this.errors}} @property="description">
|
||||
<label for="description" class="fw6">Description</label>
|
||||
<GhTextInput
|
||||
@value={{readonly this.product.description}}
|
||||
@input={{action (mut this.product.description) value="target.value"}}
|
||||
@name="description"
|
||||
@placeholder="Full access to premium content"
|
||||
@id="description"
|
||||
@class="gh-input" />
|
||||
<GhErrorMessage @errors={{this.errors}} @property="description" />
|
||||
</GhFormGroup>
|
||||
<GhFormGroup @errors={{this.settings.errors}} @hasValidated={{this.settings.hasValidated}} @property="prices">
|
||||
<div class="gh-settings-members-pricelabelcont">
|
||||
<label for="monthlyPrice">Prices</label>
|
||||
<span>–</span>
|
||||
<div>
|
||||
<span class="gh-setting-members-currency gh-select">
|
||||
<div class="gh-setting-members-currencylabel">
|
||||
<span>{{this.currency}}</span>
|
||||
{{svg-jar "arrow-down-small"}}
|
||||
</div>
|
||||
<OneWaySelect
|
||||
@value={{this.selectedCurrency}}
|
||||
id="currency"
|
||||
name="currency"
|
||||
@options={{readonly this.allCurrencies}}
|
||||
@optionValuePath="value"
|
||||
@optionLabelPath="label"
|
||||
@update={{action "setCurrency"}}
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gh-setting-members-prices">
|
||||
<div class="gh-product-modal-content">
|
||||
<header class="modal-header" data-test-modal="webhook-form">
|
||||
<h1 data-test-text="title">{{this.title}}</h1>
|
||||
</header>
|
||||
|
||||
<div class="gh-input-group">
|
||||
<GhTextInput
|
||||
@id="monthlyPrice"
|
||||
@value={{readonly this.stripeMonthlyAmount}}
|
||||
@type="number"
|
||||
@input={{action (mut this.stripeMonthlyAmount) value="target.value"}}
|
||||
@focus-out={{action "validateStripePlans"}}
|
||||
/>
|
||||
<span class="gh-input-append"><span class="ttu">{{this.currency}}</span>/month</span>
|
||||
<form>
|
||||
<div class="modal-body gh-form-edit-product">
|
||||
<div class="gh-main-section columns-3">
|
||||
<div class="gh-main-section-block span-2">
|
||||
<h4 class="gh-main-section-header small bn">Basic</h4>
|
||||
<div class="gh-main-section-content grey gh-product-priceform-block">
|
||||
<GhFormGroup @errors={{this.errors}} @property="name">
|
||||
<label for="name" class="fw6">Name</label>
|
||||
<GhTextInput
|
||||
@value={{readonly this.product.name}}
|
||||
@input={{action (mut this.product.name) value="target.value"}}
|
||||
@name="name"
|
||||
@placeholder="Bronze"
|
||||
@id="name"
|
||||
@class="gh-input" />
|
||||
<GhErrorMessage @errors={{this.errors}} @property="name" />
|
||||
</GhFormGroup>
|
||||
<GhFormGroup @errors={{this.errors}} @property="description">
|
||||
<label for="description" class="fw6">Description</label>
|
||||
<GhTextInput
|
||||
@value={{readonly this.product.description}}
|
||||
@input={{action (mut this.product.description) value="target.value"}}
|
||||
@name="description"
|
||||
@placeholder="Full access to premium content"
|
||||
@id="description"
|
||||
@class="gh-input" />
|
||||
<GhErrorMessage @errors={{this.errors}} @property="description" />
|
||||
</GhFormGroup>
|
||||
<GhFormGroup @errors={{this.settings.errors}} @hasValidated={{this.settings.hasValidated}} @property="prices">
|
||||
<div class="gh-settings-members-pricelabelcont">
|
||||
<label for="monthlyPrice">Prices</label>
|
||||
<span>–</span>
|
||||
<div>
|
||||
<span class="gh-setting-members-currency gh-select">
|
||||
<div class="gh-setting-members-currencylabel">
|
||||
<span>{{this.currency}}</span>
|
||||
{{svg-jar "arrow-down-small"}}
|
||||
</div>
|
||||
<OneWaySelect
|
||||
@value={{this.selectedCurrency}}
|
||||
id="currency"
|
||||
name="currency"
|
||||
@options={{readonly this.allCurrencies}}
|
||||
@optionValuePath="value"
|
||||
@optionLabelPath="label"
|
||||
@update={{action "setCurrency"}}
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gh-input-group">
|
||||
<GhTextInput
|
||||
@id="yearlyPrice"
|
||||
@value={{readonly this.stripeYearlyAmount}}
|
||||
@type="number"
|
||||
@input={{action (mut this.stripeYearlyAmount) value="target.value"}}
|
||||
@focus-out={{this.validateStripePlans}}
|
||||
@placeholder=''
|
||||
data-test-title-input={{true}}
|
||||
/>
|
||||
<span class="gh-input-append"><span class="ttu">{{this.currency}}</span>/year</span>
|
||||
<div class="gh-setting-members-prices">
|
||||
|
||||
<div class="gh-input-group">
|
||||
<GhTextInput
|
||||
@id="monthlyPrice"
|
||||
@value={{readonly this.stripeMonthlyAmount}}
|
||||
@type="number"
|
||||
@input={{action (mut this.stripeMonthlyAmount) value="target.value"}}
|
||||
@focus-out={{action "validateStripePlans"}}
|
||||
/>
|
||||
<span class="gh-input-append"><span class="ttu">{{this.currency}}</span>/month</span>
|
||||
</div>
|
||||
<div class="gh-input-group">
|
||||
<GhTextInput
|
||||
@id="yearlyPrice"
|
||||
@value={{readonly this.stripeYearlyAmount}}
|
||||
@type="number"
|
||||
@input={{action (mut this.stripeYearlyAmount) value="target.value"}}
|
||||
@focus-out={{this.validateStripePlans}}
|
||||
@placeholder=''
|
||||
data-test-title-input={{true}}
|
||||
/>
|
||||
<span class="gh-input-append"><span class="ttu">{{this.currency}}</span>/year</span>
|
||||
</div>
|
||||
</div>
|
||||
{{#if this.stripePlanError}}
|
||||
<p class="response w-100"><span class="red">{{this.stripePlanError}}</span></p>
|
||||
{{/if}}
|
||||
</GhFormGroup>
|
||||
</div>
|
||||
|
||||
<h4 class="gh-main-section-header small bn">Benefits</h4>
|
||||
<div class="gh-main-section-content grey gh-product-form-benefits">
|
||||
<div class="gh-product-benefits">
|
||||
<form id="product-benefits" class="gh-blognav" novalidate="novalidate">
|
||||
<SortableObjects
|
||||
@sortableObjectList={{this.benefits}}
|
||||
@useSwap={{false}}
|
||||
@sortEndAction={{action "reorderItems"}}
|
||||
>
|
||||
{{#each this.benefits as |benefitItem index|}}
|
||||
<DraggableObject @content={{benefitItem}} @dragHandle=".gh-blognav-grab" @isSortable={{true}}>
|
||||
<GhBenefitItem
|
||||
@benefitItem={{benefitItem}}
|
||||
@id={{index}}
|
||||
@addItem={{action "addBenefit"}}
|
||||
@focusItem={{action "focusItem"}}
|
||||
@deleteItem={{action "deleteBenefit"}}
|
||||
@updateLabel={{action "updateLabel"}}
|
||||
data-test-navitem={{index}} />
|
||||
</DraggableObject>
|
||||
{{/each}}
|
||||
</SortableObjects>
|
||||
<GhBenefitItem
|
||||
@benefitItem={{this.newBenefit}}
|
||||
@addItem={{action "addBenefit"}}
|
||||
@deleteItem={{action "deleteBenefit"}}
|
||||
@updateLabel={{action "updateLabel"}}
|
||||
data-test-navitem="new" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gh-main-section-block gh-product-form-tierpreview">
|
||||
<div class="gh-product-form-tierpreview-content">
|
||||
<h4 class="gh-main-section-header small bn">Tier Preview</h4>
|
||||
<div class="gh-main-section-content" style="border-color: {{this.settings.accentColor}}">
|
||||
<span class="checkmark" style="background-color: {{this.settings.accentColor}}"></span>
|
||||
|
||||
{{#if this.product.name}}
|
||||
<h4>{{this.product.name}}</h4>
|
||||
{{else}}
|
||||
<h4 class="placeholder">Bronze</h4>
|
||||
{{/if}}
|
||||
|
||||
{{#if this.product.description}}
|
||||
<p>{{this.product.description}}</p>
|
||||
{{else}}
|
||||
<p class="placeholder">Full access to premium content</p>
|
||||
{{/if}}
|
||||
|
||||
{{#if this.benefits}}
|
||||
<ul>
|
||||
{{#each this.benefits as |benefitItem index|}}
|
||||
<li>{{svg-jar "check-2"}} <span>{{benefitItem.name}}</span></li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
{{else}}
|
||||
<ul class="placeholder">
|
||||
<li>{{svg-jar "check-2"}} <span>Expert analysis</span></li>
|
||||
</ul>
|
||||
{{/if}}
|
||||
|
||||
<div class="price">
|
||||
|
||||
{{#if this.stripeMonthlyAmount}}
|
||||
<span class="monthly-price">
|
||||
{{this.stripeMonthlyAmount}}
|
||||
<span class="period"><span class="currency">{{this.currency}}</span>/month</span>
|
||||
</span>
|
||||
{{else}}
|
||||
<span class="monthly-price placeholder">
|
||||
0
|
||||
<span class="period"><span class="currency">{{this.currency}}</span>/month</span>
|
||||
</span>
|
||||
{{/if}}
|
||||
|
||||
{{#if this.stripeYearlyAmount}}
|
||||
<span class="yearly-price">{{this.stripeYearlyAmount}}<span class="currency">{{this.currency}}</span>/year</span>
|
||||
{{else}}
|
||||
<span class="yearly-price placeholder">0<span class="currency">{{this.currency}}</span>/year</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
{{#if this.stripePlanError}}
|
||||
<p class="response w-100"><span class="red">{{this.stripePlanError}}</span></p>
|
||||
{{/if}}
|
||||
</GhFormGroup>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gh-main-section-block">
|
||||
<h4 class="gh-main-section-header small bn">Benefits</h4>
|
||||
<div class="gh-main-section-content grey gh-product-form-benefits">
|
||||
<div class="gh-product-benefits">
|
||||
<form id="product-benefits" class="gh-blognav" novalidate="novalidate">
|
||||
<SortableObjects
|
||||
@sortableObjectList={{this.benefits}}
|
||||
@useSwap={{false}}
|
||||
@sortEndAction={{action "reorderItems"}}
|
||||
>
|
||||
{{#each this.benefits as |benefitItem index|}}
|
||||
<DraggableObject @content={{benefitItem}} @dragHandle=".gh-blognav-grab" @isSortable={{true}}>
|
||||
<GhBenefitItem
|
||||
@benefitItem={{benefitItem}}
|
||||
@id={{index}}
|
||||
@addItem={{action "addBenefit"}}
|
||||
@focusItem={{action "focusItem"}}
|
||||
@deleteItem={{action "deleteBenefit"}}
|
||||
@updateLabel={{action "updateLabel"}}
|
||||
data-test-navitem={{index}} />
|
||||
</DraggableObject>
|
||||
{{/each}}
|
||||
</SortableObjects>
|
||||
<GhBenefitItem
|
||||
@benefitItem={{this.newBenefit}}
|
||||
@addItem={{action "addBenefit"}}
|
||||
@deleteItem={{action "deleteBenefit"}}
|
||||
@updateLabel={{action "updateLabel"}}
|
||||
data-test-navitem="new" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="modal-footer modal-footer-spread items-center">
|
||||
<div class="modal-footer-hint">
|
||||
Completely lost? <a href="https://ghost.org/help/topic/members/" target="_blank" rel="noopener noreferrer">Check the documentation</a>
|
||||
</div>
|
||||
<div class="modal-footer top-shadow items-center">
|
||||
<div>
|
||||
<button
|
||||
class="gh-btn"
|
||||
|
@ -94,6 +94,11 @@
|
||||
padding: 0 32px;
|
||||
}
|
||||
|
||||
.modal-footer.top-shadow {
|
||||
margin-bottom: -4px;
|
||||
padding-top: 4px;
|
||||
}
|
||||
|
||||
.fullscreen-modal-body-scrolling .modal-footer:before,
|
||||
.modal-footer.top-shadow:before {
|
||||
position: absolute;
|
||||
@ -103,7 +108,7 @@
|
||||
right: -32px;
|
||||
height: 6px;
|
||||
background: hsla(0,0%,100%,0);
|
||||
box-shadow: 0 -0.3px 1px rgb(0 0 0 / 3%), 0 -4px 7px rgb(0 0 0 / 6%);
|
||||
box-shadow: 0 -0.3px 1px rgb(0 0 0 / 3%), 0 -4px 4px rgb(0 0 0 / 4%);
|
||||
}
|
||||
|
||||
.modal-footer.top-shadow:before {
|
||||
|
@ -370,6 +370,13 @@
|
||||
max-width: 900px;
|
||||
}
|
||||
|
||||
.gh-product-modal-content {
|
||||
margin: -32px -32px 0;
|
||||
padding: 32px 32px 0;
|
||||
max-height: calc(100vh - 16vw);
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
.gh-form-edit-product .gh-main-section {
|
||||
margin-bottom: 32px;
|
||||
grid-template-columns: 1fr 0.9fr 1.1fr;
|
||||
@ -401,22 +408,37 @@
|
||||
}
|
||||
|
||||
.gh-form-edit-product .gh-main-section-content.gh-product-form-benefits {
|
||||
max-height: 275px;
|
||||
overflow: scroll;
|
||||
flex-grow: 1;
|
||||
padding: 12px 16px 0 0;
|
||||
padding-left: 8px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.gh-product-benefits .gh-input {
|
||||
font-size: 1.3rem;
|
||||
height: 32px;
|
||||
padding: 6px 28px 6px 8px;
|
||||
padding: 6px 28px 6px 30px;
|
||||
}
|
||||
|
||||
.gh-product-benefits .gh-blognav-line {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.gh-product-benefits .gh-blognav-line svg {
|
||||
position: absolute;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
top: 13px;
|
||||
left: 11px;
|
||||
}
|
||||
|
||||
.gh-product-benefits .gh-blognav-line.placeholder {
|
||||
color: var(--midlightgrey);
|
||||
}
|
||||
|
||||
.gh-product-benefits .gh-blognav-line svg path {
|
||||
stroke-width: 3px;
|
||||
}
|
||||
|
||||
.gh-product-benefits .gh-blognav-item {
|
||||
position: relative;
|
||||
align-items: flex-start;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.gh-product-benefits .gh-blognav-label {
|
||||
@ -431,13 +453,13 @@
|
||||
|
||||
.gh-product-benefits .gh-blognav-delete {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
top: 4px;
|
||||
right: 8px;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.gh-product-benefits .gh-blognav-add {
|
||||
margin-top: 8px;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.gh-product-benefits .gh-blognav-grab {
|
||||
@ -450,7 +472,7 @@
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.gh-product-benefits .gh-blognav-item:not(.gh-blognav-item--sortable) {
|
||||
.gh-product-benefits .gh-blognav-item:not(.gh-blognav-item--sortable):not(:last-of-type) {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
@ -460,4 +482,140 @@
|
||||
font-weight: 400;
|
||||
padding: 0 16px;
|
||||
margin-top: -12px;
|
||||
}
|
||||
|
||||
.gh-product-form-tierpreview-content {
|
||||
position: sticky;
|
||||
top: 45px;
|
||||
height: max-content;
|
||||
}
|
||||
|
||||
.gh-product-form-tierpreview .gh-main-section-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
background: #fff;
|
||||
border: 2px solid var(--blackgrey);
|
||||
border-radius: 4px;
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.gh-product-form-tierpreview .gh-main-section-content .checkmark {
|
||||
position: relative;
|
||||
background-color: var(--blackgrey);
|
||||
border-radius: 999px;
|
||||
height: 18px;
|
||||
width: 18px;
|
||||
}
|
||||
|
||||
.gh-product-form-tierpreview .gh-main-section-content .checkmark::after {
|
||||
display: block;
|
||||
position: absolute;
|
||||
content: "";
|
||||
left: 6.5px;
|
||||
top: 2.5px;
|
||||
width: 5px;
|
||||
height: 11px;
|
||||
border: solid #fff;
|
||||
border-width: 0 2px 2px 0;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.gh-product-form-tierpreview .gh-main-section-content h4 {
|
||||
font-size: 1.3rem;
|
||||
font-weight: 500;
|
||||
line-height: 1.45em;
|
||||
letter-spacing: 0.5px;
|
||||
text-transform: uppercase;
|
||||
margin-top: 7px;
|
||||
text-align: center;
|
||||
min-height: 24px;
|
||||
word-break: break-word;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.gh-product-form-tierpreview .gh-main-section-content p {
|
||||
font-size: 1.35rem;
|
||||
font-weight: 500;
|
||||
line-height: 1.45em;
|
||||
text-align: center;
|
||||
color: #474747;
|
||||
padding: 16px 0;
|
||||
margin: 8px 0 20px;
|
||||
width: 100%;
|
||||
border-top: 1px solid #eaeaea;
|
||||
border-bottom: 1px solid #eaeaea;
|
||||
}
|
||||
|
||||
.gh-product-form-tierpreview .price {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.gh-product-form-tierpreview .monthly-price {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
font-size: 3.3rem;
|
||||
font-weight: 500;
|
||||
line-height: 1em;
|
||||
color: #3d3d3d;
|
||||
}
|
||||
|
||||
.gh-product-form-tierpreview .monthly-price .period {
|
||||
font-size: 1.3rem;
|
||||
line-height: 1.6em;
|
||||
color: #515151;
|
||||
letter-spacing: 0.3px;
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
.gh-product-form-tierpreview .yearly-price {
|
||||
font-size: 1.2rem;
|
||||
line-height: 1.6em;
|
||||
color: #aeaeae;
|
||||
text-align: center;
|
||||
margin-top: 4px;
|
||||
letter-spacing: 0.3px;
|
||||
height: 18px;
|
||||
margin-top: -1px;
|
||||
}
|
||||
|
||||
.gh-product-form-tierpreview .currency {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.gh-product-form-tierpreview ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
min-height: 100px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.gh-product-form-tierpreview li {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
font-size: 1.3rem;
|
||||
line-height: 1.45em;
|
||||
color: #686868;
|
||||
margin: 0 0 12px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.gh-product-form-tierpreview li svg {
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
min-width: 12px;
|
||||
margin: 3px 6px 0 0;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.gh-product-form-tierpreview li svg path {
|
||||
stroke-width: 3px;
|
||||
}
|
||||
|
||||
.gh-product-form-tierpreview .placeholder {
|
||||
opacity: 0.35;
|
||||
}
|
1
ghost/admin/public/assets/icons/check-2.svg
Normal file
1
ghost/admin/public/assets/icons/check-2.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><defs><style>.a{fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5px;}</style></defs><g id="Artboard" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round"><polyline id="Path" class="a" points="1.6 14.5120847 8.66491448 21.5769992 22.3412274 2.5769992"></polyline></g></svg>
|
After Width: | Height: | Size: 429 B |
Loading…
Reference in New Issue
Block a user