Added static components for custom products

- added link to Products in Settings main screen
- added product list page with static content
- added product detail page with static content
This commit is contained in:
Peter Zimon 2021-04-08 14:38:42 +02:00
parent d350a58769
commit 6ee31e206b
12 changed files with 345 additions and 1 deletions

View File

@ -0,0 +1,37 @@
import Controller from '@ember/controller';
import {action} from '@ember/object';
import {inject as service} from '@ember/service';
import {task} from 'ember-concurrency-decorators';
import {tracked} from '@glimmer/tracking';
export default class ProductController extends Controller {
@service settings;
@tracked showLeaveSettingsModal = false;
leaveRoute(transition) {
if (this.settings.get('hasDirtyAttributes')) {
transition.abort();
this.leaveSettingsTransition = transition;
this.showLeaveSettingsModal = true;
}
}
@action
async confirmLeave() {
this.settings.rollbackAttributes();
this.showLeaveSettingsModal = false;
this.leaveSettingsTransition.retry();
}
@action
cancelLeave() {
this.showLeaveSettingsModal = false;
this.leaveSettingsTransition = null;
}
@task({drop: true})
*saveTask() {
return yield this.settings.save();
}
}

View File

@ -0,0 +1,3 @@
import Controller from '@ember/controller';
export default class ProductsController extends Controller {}

View File

@ -52,6 +52,11 @@ Router.map(function () {
this.route('settings.members-email', {path: '/settings/members-email'});
this.route('settings.members-payments', {path: '/settings/members-payments'});
this.route('settings.code-injection', {path: '/settings/code-injection'});
this.route('settings.products', {path: '/settings/products'});
this.route('settings.product', {path: '/settings/product'});
this.route('settings.price', {path: '/settings/price'});
this.route('settings.theme', {path: '/settings/theme'}, function () {
this.route('uploadtheme');
this.route('install');

View File

@ -0,0 +1,22 @@
import AuthenticatedRoute from 'ghost-admin/routes/authenticated';
import {inject as service} from '@ember/service';
export default class ProductRoute extends AuthenticatedRoute {
@service settings;
model() {
this.settings.reload();
}
actions = {
willTransition(transition) {
return this.controller.leaveRoute(transition);
}
}
buildRouteInfoMetadata() {
return {
titleToken: 'Settings - Products'
};
}
}

View File

@ -0,0 +1,9 @@
import AuthenticatedRoute from 'ghost-admin/routes/authenticated';
export default class ProductsRoute extends AuthenticatedRoute {
buildRouteInfoMetadata() {
return {
titleToken: 'Settings - Products'
};
}
}

View File

@ -66,6 +66,7 @@
@import "layouts/fullscreen-wizard.css";
@import "layouts/post-preview.css";
@import "layouts/dashboard.css";
@import "layouts/products.css";
:root {

View File

@ -66,6 +66,7 @@
@import "layouts/fullscreen-wizard.css";
@import "layouts/post-preview.css";
@import "layouts/dashboard.css";
@import "layouts/products.css";
/* ---------------------------✈️----------------------------- */

View File

@ -1108,6 +1108,10 @@
padding: 0;
}
.gh-main-section-block.span-2 {
grid-column: span 2;
}
.gh-main-section-block.with-margin,
.gh-main-section-block:not(:last-of-type) {
margin-bottom: 32px;
@ -1135,6 +1139,12 @@
border-radius: 3px;
}
.gh-main-section-content.bordered {
padding: 24px;
border: 1px solid var(--whitegrey);
border-radius: 3px;
}
.gh-main-section-content.columns-2 {
grid-template-columns: 1fr 1fr;
grid-column-gap: 40px;
@ -1145,6 +1155,7 @@
grid-column-gap: 24px;
}
.gh-main-section-content.grey {
background: var(--main-color-content-greybg);
}

View File

@ -0,0 +1,83 @@
/* Product list */
.gh-product-list-chevron {
padding-right: 0;
}
.gh-product-chevron {
display: flex;
align-items: center;
justify-content: flex-end;
color: var(--midgrey);
}
.gh-product-chevron span {
line-height: 0;
}
/* Product details */
.gh-product-details {
display: grid;
grid-template-columns: 2fr 1fr;
grid-gap: 32px;
margin-bottom: 3vw;
}
.gh-product-details-form {
display: flex;
flex-grow: 1;
align-items: flex-start;
padding-top: 20px !important;
}
.gh-product-icon-container {
width: unset;
padding-bottom: 0;
margin-bottom: 0;
}
.gh-product-icon {
display: flex;
align-items: center;
justify-content: center;
background: var(--white);
width: 124px;
height: 124px;
margin-right: 24px;
border: 1px solid var(--whitegrey);
border-radius: 3px;
}
.gh-product-details-fields {
width: 100%;
}
.gh-product-description-container {
padding-bottom: 0;
margin-bottom: 0;
}
.gh-product-details section {
display: flex;
flex-direction: column;
justify-content: stretch;
}
.gh-product-stat-container {
display: flex;
flex-direction: column;
flex-grow: 1;
border: 1px solid var(--whitegrey);
padding: 24px;
border-radius: 3px;
}
.gh-product-chart {
color: var(--whitegrey);
border: 1px solid var(--whitegrey);
border-top-color: transparent;
height: 90px;
display: flex;
align-items: center;
justify-content: center;
margin: 12px 0;
}

View File

@ -48,9 +48,16 @@
<p>Configure members usage and default access levels</p>
</div>
</LinkTo>
<LinkTo class="gh-setting-group" @route="settings.products" data-test-nav="members-access">
<span class="color-4">{{svg-jar "module"}}</span>
<div>
<h4>Products</h4>
<p>Set up subscription products and prices</p>
</div>
</LinkTo>
{{/if}}
<button type="button" class="gh-setting-group portal" {{action (toggle "showPortalSettings" this)}} data-test-toggle-membersFrom>
<span class="color-3">{{svg-jar "portal-logo-stroke"}}</span>
<span class="color-2">{{svg-jar "portal-logo-stroke"}}</span>
<div>
<h4>Portal</h4>
<p>Customize members modal signup flow</p>

View File

@ -0,0 +1,125 @@
<section class="gh-canvas">
<GhCanvasHeader class="gh-canvas-header">
<h2 class="gh-canvas-title" data-test-screen-title>
<LinkTo @route="settings">Settings</LinkTo>
<span>{{svg-jar "arrow-right"}}</span>
<LinkTo @route="settings.products">Products</LinkTo>
<span>{{svg-jar "arrow-right"}}</span>
Product name
</h2>
<section class="view-actions">
<GhTaskButton @buttonText="Save product"
@task={{this.saveTask}}
@successText="Saved"
@runningText="Saving"
@class="gh-btn gh-btn-primary gh-btn-icon"
data-test-button="save-settings"
/>
</section>
</GhCanvasHeader>
<form>
<div class="gh-product-details">
<section class="gh-product-config">
<div class="gh-main-section-content grey gh-product-details-form">
<GhFormGroup @property="name" @class="gh-product-icon-container">
<label for="member-name">Icon</label>
<div class="gh-product-icon whitegrey">Icon</div>
</GhFormGroup>
<div class="gh-product-details-fields">
<GhFormGroup @property="name" @classNames="max-width">
<label for="member-name">Product name</label>
<GhTextInput data-test-input="member-name" />
<GhErrorMessage @property="name" />
</GhFormGroup>
<GhFormGroup @property="name" @classNames="max-width gh-product-description-container">
<label for="member-name">Description</label>
<GhTextInput data-test-input="member-name" />
<GhErrorMessage @property="name" />
</GhFormGroup>
</div>
</div>
</section>
<section class="gh-product-stats">
<div class="gh-product-stat-container">
<h4 class="gh-dashboard-header">Members</h4>
<div class="gh-product-chart">CHART</div>
<div class="gh-product-stat-details">
<span class="data">330</span>
<span class="info">members have access to this product</span>
</div>
<LinkTo @route="members">See members &rarr;</LinkTo>
</div>
</section>
</div>
</form>
<div class="gh-main-section">
<div class="gh-main-section-block p0">
<ol class="gh-price-list gh-list">
<li class="gh-list-row header">
<div class="gh-list-header gh-list-cellwidth-70">Prices</div>
<div class="gh-list-header gh-list-cellwidth-10"></div>
</li>
<li class="gh-list-row">
<LinkTo @route="settings.product" class="gh-list-data gh-list-cellwidth-70 gh-price-list-title">
<h3 class="gh-price-list-name">
Monthly
</h3>
<p class="ma0 pa0 f8 midgrey gh-price-list-description">
$5 USD / month &bull; Full access
</p>
</LinkTo>
<LinkTo @route="settings.product" class="gh-list-data gh-list-cellwidth-30">
<div class="gh-price-list-actions">
</div>
</LinkTo>
</li>
<li class="gh-list-row">
<LinkTo @route="settings.product" class="gh-list-data gh-list-cellwidth-70 gh-price-list-title">
<h3 class="gh-price-list-name">
Yearly
</h3>
<p class="ma0 pa0 f8 midgrey gh-price-list-description">
$50 USD / month &bull; 37% discount
</p>
</LinkTo>
<LinkTo @route="settings.product" class="gh-list-data gh-list-cellwidth-30">
<div class="gh-price-list-actions">
</div>
</LinkTo>
</li>
<li class="gh-list-row">
<LinkTo @route="settings.product" class="gh-list-data gh-list-cellwidth-70 gh-price-list-title">
<h3 class="gh-price-list-name">
Complimentary
</h3>
<p class="ma0 pa0 f8 midgrey gh-price-list-description">
$0 USD / year &bull; Free of charge subscription
</p>
</LinkTo>
<LinkTo @route="settings.product" class="gh-list-data gh-list-cellwidth-30">
<div class="gh-price-list-actions">
</div>
</LinkTo>
</li>
</ol>
</div>
</div>
{{#if this.showLeaveSettingsModal}}
<GhFullscreenModal
@modal="leave-settings"
@confirm={{this.confirmLeave}}
@close={{this.cancelLeave}}
@modifier="action wide"
/>
{{/if}}
</section>

View File

@ -0,0 +1,40 @@
<section class="gh-canvas">
<GhCanvasHeader class="gh-canvas-header">
<h2 class="gh-canvas-title" data-test-screen-title>
<LinkTo @route="settings">Settings</LinkTo>
<span>{{svg-jar "arrow-right"}}</span>
Products
</h2>
<section class="view-actions">
<LinkTo @route="settings.products" class="gh-btn gh-btn-primary" data-test-new-member-button="true"><span>New product</span></LinkTo>
</section>
</GhCanvasHeader>
<section class="view-container">
<section class="content-list">
<ol class="gh-product-list gh-list">
<li class="gh-list-row header">
<div class="gh-list-header gh-list-cellwidth-70"></div>
<div class="gh-list-header gh-list-cellwidth-30"></div>
</li>
<li class="gh-list-row">
<LinkTo @route="settings.product" class="gh-list-data gh-list-cellwidth-70 gh-product-list-title">
<h3 class="gh-product-list-name">
Product name
</h3>
<p class="ma0 pa0 f8 midgrey gh-product-list-description">
Product description
</p>
</LinkTo>
<LinkTo @route="settings.product" class="gh-list-data gh-list-cellwidth-30 gh-product-list-chevron">
<div class="gh-product-chevron">
<span>330 members</span>
<span>{{svg-jar "arrow-right" class="w6 h6 fill-midgrey pa1"}}</span>
</div>
</LinkTo>
</li>
</ol>
</section>
</section>
</section>