2017-02-17 08:50:07 +03:00
<section class="gh-canvas">
<header class="gh-canvas-header">
2017-05-30 16:23:38 +03:00
<h2 class="gh-canvas-title" data-test-screen-title>Labs</h2>
2015-06-13 17:34:09 +03:00
</header>
2014-12-14 20:56:04 +03:00
2017-02-17 08:50:07 +03:00
<section class="view-container settings-debug">
2018-03-19 12:57:31 +03:00
<p class="gh-box gh-box-info"> {{ svg-jar "idea" }} This is a testing ground for experimental features which aren't quite ready for primetime. They may change, break or inexplicably disappear at any time.</p>
2017-02-17 17:10:02 +03:00
<div class="gh-setting-header">Migration options</div>
<div class="gh-setting">
<div class="gh-setting-content">
<div class="gh-setting-title">Import content</div>
<div class="gh-setting-desc">Import posts from another Ghost installation</div>
</div>
<div class="gh-setting-action">
<form id="settings-import" enctype="multipart/form-data">
2017-09-22 22:59:05 +03:00
{{ gh-file-upload
id="importfile"
classNames="flex"
uploadButtonText=uploadButtonText
onUpload=(action "onUpload")
acceptEncoding=importMimeType
data-test-file-input="import"}}
2017-02-17 17:10:02 +03:00
</form>
</div>
</div>
2017-05-24 16:36:59 +03:00
{{ # if importErrors }}
2017-09-22 22:59:05 +03:00
<div class="gh-import-errors {{ if importSuccessful "gh-import-errors-warning" }} " data-test-import-errors>
2017-05-24 16:36:59 +03:00
<div class="gh-import-errors-title">
{{ # if importSuccessful }}
Import successful with warnings
{{ else }}
Import failed
{{ / if }}
</div>
{{ # each importErrors as | error | }}
2017-09-22 22:59:05 +03:00
<div class="gh-import-error" data-test-import-error>
<p class="gh-import-error-message" data-test-import-error-message>
2017-05-24 16:36:59 +03:00
{{ # if error .help }} {{ error .help }} : {{ / if }} {{ error .message }}
</p>
{{ # if error .context }}
2017-09-22 22:59:05 +03:00
<div class="gh-import-error-entry" data-test-import-error-context>
2017-05-24 16:36:59 +03:00
<pre> {{ error .context }} </pre>
</div>
{{ / if }}
</div>
{{ / each }}
</div>
{{ / if }}
2017-02-17 17:10:02 +03:00
<div class="gh-setting">
<div class="gh-setting-content">
<div class="gh-setting-title">Export your content</div>
<div class="gh-setting-desc">Download all of your posts and settings in a single, glorious JSON file</div>
</div>
<div class="gh-setting-action">
2017-09-21 18:01:40 +03:00
<button type="button" class="gh-btn gh-btn-hover-blue" {{ action "downloadFile" "db" }} ><span>Export</span></button>
2017-02-17 17:10:02 +03:00
</div>
</div>
<div class="gh-setting">
<div class="gh-setting-content">
<div class="gh-setting-title">Delete all content</div>
<div class="gh-setting-desc">Permanently delete all posts and tags from the database, a hard reset</div>
</div>
<div class="gh-setting-action">
<button type="button" class="gh-btn gh-btn-hover-red js-delete" {{ action "toggleDeleteAllModal" }} ><span>Delete</span></button>
</div>
</div>
<div class="gh-setting-header">Testing tools</div>
<div class="gh-setting">
<div class="gh-setting-content">
<div class="gh-setting-title">Test email configuration</div>
<div class="gh-setting-desc">Send yourself a test email to make sure everything is working</div>
</div>
<div class="gh-setting-action">
2017-04-07 18:23:45 +03:00
{{ gh-task-button "Send" successText = "Sent" task = sendTestEmail class = "gh-btn gh-btn-hover-blue gh-btn-icon" }}
2017-02-17 17:10:02 +03:00
</div>
</div>
<div class="gh-setting-header">Beta features</div>
2019-01-15 13:23:49 +03:00
{{ # if ( not-eq feature .labs .publicAPI undefined ) }}
<div class="gh-setting">
<div class="gh-setting-content">
<div class="gh-setting-title">Public API (deprecated)</div>
<div class="gh-setting-desc">⚠️ Please use the Content API instead, more info in <a href="https://docs.ghost.org/api/content/">the docs</a></div>
</div>
<div class="gh-setting-action">
<div class="for-checkbox"> {{ gh-feature-flag "publicAPI" }} </div>
</div>
2017-02-17 17:10:02 +03:00
</div>
2019-01-15 13:23:49 +03:00
{{ / if }}
2017-02-17 18:58:08 +03:00
<div class="gh-setting">
<div class="gh-setting-content">
<div class="gh-setting-title">Night shift</div>
<div class="gh-setting-desc">Swap Ghost admin's colours to a dark background which is easy on the eyes</div>
</div>
<div class="gh-setting-action">
2017-02-17 21:03:07 +03:00
<div class="for-checkbox"> {{ gh-feature-flag "nightShift" }} </div>
2017-02-17 18:58:08 +03:00
</div>
</div>
2019-02-26 06:29:57 +03:00
<div class="gh-setting {{ if feature .members "gh-labs-disabled" }} ">
2017-02-17 17:10:02 +03:00
<div class="gh-setting-content">
<div class="gh-setting-title">Subscribers</div>
2019-02-26 06:29:57 +03:00
<div class="gh-setting-desc">Collect email addresses from your readers, more info in <a
href="https://docs.ghost.org/faq/enable-subscribers-feature/">the docs</a></div>
2017-02-17 17:10:02 +03:00
</div>
<div class="gh-setting-action">
2019-02-26 06:29:57 +03:00
{{ # if feature .members }}
<div class="for-checkbox"> {{ gh-feature-flag "subscribers" "disabled" }} </div>
{{ else }}
<div class="for-checkbox"> {{ gh-feature-flag "subscribers" }} </div>
{{ / if }}
2017-02-17 17:10:02 +03:00
</div>
</div>
2019-02-26 06:29:57 +03:00
{{ # if config .enableDeveloperExperiments }}
<div class="gh-setting">
<div class="gh-setting-content">
<div class="gh-setting-title">Members</div>
<div class="gh-setting-desc">Enable free or paid member registration. Restrict content by using <span class="dib blue ba br2 b--blue pa1 pt0 pb0 tag-token--internal">#members</span> hashtag on posts</div>
{{ # liquid-if feature .labs .members class = "nr20" }}
<button type="button" class="gh-btn gh-btn-labs-toggle" {{ action "toggleMemberConfig" "" }} >
{{ # if showMemberConfig }}
{{ svg-jar "arrow-down-small" }}
{{ else }}
{{ svg-jar "arrow-right-small" }}
{{ / if }}
Configure
</button>
{{ # liquid-if showMemberConfig }}
<div class="flex nl2 nr2 mt5">
<div class="gh-publishmenu-radio {{ if ( eq subscriptionSettings .isPaid false ) "active" }} flex-auto w-50 ba br4 b--whitegrey pa5 gh-labs-members-radio"
{{ action "setSubscriptionSettings" "isPaid" false on = "click" }} >
<div class="gh-publishmenu-radio-button"></div>
<div class="gh-publishmenu-radio-content">
<div class="gh-publishmenu-radio-label f3"><span class="fw6 f7 darkgrey">Free</span></div>
<div class="gh-publishmenu-radio-desc">Access to members-only posts require free user registration</div>
</div>
</div>
<div class="gh-publishmenu-radio {{ if ( eq subscriptionSettings .isPaid true ) "active" }} flex-auto w-50 ba br4 b--whitegrey pa5 ml2 gh-labs-members-radio">
<div class="gh-publishmenu-radio-button" {{ action "setSubscriptionSettings" "isPaid" true on = "click" }} ></div>
<div class="gh-publishmenu-radio-content">
<div {{ action "setSubscriptionSettings" "isPaid" true on = "click" }} >
<div class="gh-publishmenu-radio-label"><span class="fw6 f7 darkgrey">Paid</span></div>
<div class="gh-publishmenu-radio-desc">Set up paid subscriptions using Stripe</div>
</div>
</div>
</div>
</div>
{{ # liquid-if ( eq subscriptionSettings .isPaid true ) }}
2019-04-15 15:21:54 +03:00
<div class="ba br4 b--whitegrey pa5 mt5">
2019-02-26 06:29:57 +03:00
<div class="flex flex-column">
<div class="flex">
<div class="w-50 mr2">
<label class="fw6">Stripe publishable API key</label>
{{ gh-text-input
value=(readonly subscriptionSettings.stripeConfig.public_token)
input=(action "setSubscriptionSettings" "public_token")
class="mt1"
placeholder="pk_..."
}}
</div>
<div class="w-50 ml2">
<label class="fw6">Stripe secret API key</label>
{{ gh-text-input
value=(readonly subscriptionSettings.stripeConfig.secret_token)
input=(action "setSubscriptionSettings" "secret_token")
class="mt1"
placeholder="sk_..."
}}
</div>
</div>
<a href="https://stripe.com/docs/keys" target="_blank" class="mt1 self-end fw3">How to find Stripe API keys</a>
</div>
<div class="mt4 flex nb5">
<div class="w-50 mr2">
{{ # gh-form-group }}
<label class="fw6">Monthly price</label>
<div class="mt1 relative gh-labs-price-label gh-labs-monthly-price">
{{ gh-text-input
value=(readonly subscriptionSettings.stripeConfig.plans.monthly.dollarAmount)
type="number"
input=(action "setSubscriptionSettings" "month")
}}
</div>
{{ / gh-form-group }}
</div>
<div class="w-50 ml2">
{{ # gh-form-group class = "description-container" }}
<label class="fw6">Yearly price</label>
<div class="mt1 relative gh-labs-price-label gh-labs-yearly-price">
{{ gh-text-input
value=(readonly subscriptionSettings.stripeConfig.plans.yearly.dollarAmount)
type="number"
input=(action "setSubscriptionSettings" "year")
}}
</div>
{{ / gh-form-group }}
</div>
</div>
</div>
{{ / liquid-if }}
<div class="mb5 mt5">
{{ gh-task-button "Save"
task=saveSettings
successText="Saved"
runningText="Saving"
class="gh-btn gh-btn-blue gh-btn-icon"
}}
</div>
{{ / liquid-if }}
{{ / liquid-if }}
</div>
<div class="gh-setting-action">
<div class="for-checkbox"> {{ gh-feature-flag "members" }} </div>
</div>
</div>
{{ / if }}
2017-09-21 18:01:40 +03:00
<div class="gh-setting">
{{ # gh-uploader
extensions=jsonExtension
uploadUrl="/redirects/json/"
paramName="redirects"
onUploadSuccess=(perform redirectUploadResult true)
onUploadFailure=(perform redirectUploadResult false)
as |uploader|
}}
<div class="gh-setting-content">
<div class="gh-setting-title">Redirects</div>
2019-01-16 19:03:33 +03:00
<div class="gh-setting-desc">Configure redirects for old or moved content, more info in <a href="https://docs.ghost.org/tutorials/implementing-redirects/">the docs</a></div>
2017-09-21 18:01:40 +03:00
{{ # each uploader .errors as | error | }}
2019-03-07 16:40:21 +03:00
<div class="gh-setting-error" data-test-error="redirects"> {{ or error .context error .message }} </div>
2017-09-21 18:01:40 +03:00
{{ / each }}
</div>
<div class="gh-setting-action" style="display: flex; flex-direction: column">
{{ # if uploader .isUploading }}
{{ uploader .progressBar }}
{{ else }}
<button
type="button"
class="gh-btn gh-btn-icon {{ if redirectSuccess "gh-btn-green" }} {{ if redirectFailure "gh-btn-red" }} "
onclick= {{ action "triggerFileDialog" }}
data-test-button="upload-redirects"
>
<span>
{{ # if redirectSuccess }}
2018-03-19 12:57:31 +03:00
{{ svg-jar "check-circle" }} Uploaded
2017-09-21 18:01:40 +03:00
{{ else if redirectFailure }}
2018-03-19 12:57:31 +03:00
{{ svg-jar "retry" }} Upload Failed
2017-09-21 18:01:40 +03:00
{{ else }}
Upload redirects JSON
{{ / if }}
</span>
</button>
<span><a href="#" {{ action "downloadFile" "redirects/json" }} data-test-link="download-redirects">Download current redirects</a></span>
{{ / if }}
<div style="display:none">
2017-11-22 20:04:48 +03:00
{{ gh-file-input multiple = false action = uploader .setFiles accept = jsonMimeType data-test-file-input = "redirects" }}
2017-09-21 18:01:40 +03:00
</div>
</div>
{{ / gh-uploader }}
</div>
2018-07-24 14:20:53 +03:00
<div class="gh-setting">
{{ # gh-uploader
extensions=yamlExtension
uploadUrl="/settings/routes/yaml/"
paramName="routes"
onUploadSuccess=(perform routesUploadResult true)
onUploadFailure=(perform routesUploadResult false)
as |uploader|
}}
<div class="gh-setting-content">
<div class="gh-setting-title">Routes</div>
<div class="gh-setting-desc">Configure dynamic routing by modifying the routes.yaml file</div>
{{ # each uploader .errors as | error | }}
2019-03-07 16:40:21 +03:00
<div class="gh-setting-error" data-test-error="routes"> {{ or error .context error .message }} </div>
2018-07-24 14:20:53 +03:00
{{ / each }}
</div>
<div class="gh-setting-action" style="display: flex; flex-direction: column">
{{ # if uploader .isUploading }}
{{ uploader .progressBar }}
{{ else }}
<button
type="button"
class="gh-btn gh-btn-icon {{ if routesSuccess "gh-btn-green" }} {{ if routesFailure "gh-btn-red" }} "
onclick= {{ action "triggerFileDialog" }}
data-test-button="upload-routes"
>
<span>
{{ # if routesSuccess }}
{{ svg-jar "check-circle" }} Uploaded
{{ else if routesFailure }}
{{ svg-jar "retry" }} Upload Failed
{{ else }}
Upload routes YAML
{{ / if }}
</span>
</button>
2019-04-03 21:54:05 +03:00
<span><a href="#" {{ action "downloadFile" "settings/routes/yaml" }} data-test-link="download-routes">Download current routes.yaml</a></span>
2018-07-24 14:20:53 +03:00
{{ / if }}
2017-02-17 17:10:02 +03:00
2018-07-24 14:20:53 +03:00
<div style="display:none">
{{ gh-file-input multiple = false action = uploader .setFiles accept = yamlMimeType data-test-file-input = "routes" }}
</div>
</div>
{{ / gh-uploader }}
</div>
2015-06-13 17:34:09 +03:00
</section>
2014-12-01 14:39:11 +03:00
</section>
2015-11-18 13:50:48 +03:00
{{ # if showDeleteAllModal }}
{{ gh-fullscreen-modal "delete-all"
close=(action "toggleDeleteAllModal")
modifier="action wide"}}
2017-03-02 11:49:10 +03:00
{{ / if }}