mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-01 22:02:11 +03:00
a29e687da6
no issue
325 lines
18 KiB
Handlebars
325 lines
18 KiB
Handlebars
<section class="gh-canvas">
|
|
<GhCanvasHeader class="gh-canvas-header">
|
|
<h2 class="gh-canvas-title" data-test-screen-title>
|
|
Labs
|
|
</h2>
|
|
</GhCanvasHeader>
|
|
|
|
<section class="view-container settings-debug">
|
|
<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>
|
|
|
|
<div class="gh-setting-header">Migration options</div>
|
|
<div class="flex flex-column br3 shadow-1 bg-grouped-table pa5 mt2">
|
|
<div class="gh-setting-first">
|
|
<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">
|
|
{{gh-file-upload
|
|
id="importfile"
|
|
classNames="flex"
|
|
uploadButtonText=uploadButtonText
|
|
onUpload=(action "onUpload")
|
|
acceptEncoding=importMimeType
|
|
data-test-file-input="import"}}
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
{{#if importErrors}}
|
|
<div class="gh-import-errors {{if importSuccessful "gh-import-errors-warning"}}" data-test-import-errors>
|
|
<div class="gh-import-errors-title">
|
|
{{#if importSuccessful}}
|
|
Import successful with warnings
|
|
{{else}}
|
|
Import failed
|
|
{{/if}}
|
|
</div>
|
|
|
|
{{#each importErrors as |error|}}
|
|
<div class="gh-import-error" data-test-import-error>
|
|
<p class="gh-import-error-message" data-test-import-error-message>
|
|
{{#if error.help}}{{error.help}}: {{/if}}{{error.message}}
|
|
</p>
|
|
|
|
{{#if error.context}}
|
|
<div class="gh-import-error-entry" data-test-import-error-context>
|
|
<pre>{{error.context}}</pre>
|
|
</div>
|
|
{{/if}}
|
|
</div>
|
|
{{/each}}
|
|
</div>
|
|
{{/if}}
|
|
|
|
<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">
|
|
<button type="button" class="gh-btn gh-btn-hover-blue" {{action "downloadFile" "db"}}><span>Export</span></button>
|
|
</div>
|
|
</div>
|
|
<div class="gh-setting-last">
|
|
<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>
|
|
|
|
<div class="gh-setting-header">Testing tools</div>
|
|
<div class="flex flex-column br3 shadow-1 bg-grouped-table pa5 mt2">
|
|
<div class="gh-setting-first gh-setting-last">
|
|
<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">
|
|
{{gh-task-button "Send" successText="Sent" task=sendTestEmail class="gh-btn gh-btn-hover-blue gh-btn-icon"}}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="gh-setting-header">Beta features</div>
|
|
<div class="flex flex-column br3 shadow-1 bg-grouped-table pa5 mt2">
|
|
<div class="gh-setting-first">
|
|
<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">
|
|
<div class="for-switch">{{gh-feature-flag "nightShift"}}</div>
|
|
</div>
|
|
</div>
|
|
{{#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://ghost.org/docs/api/content/">the docs</a></div>
|
|
</div>
|
|
<div class="gh-setting-action">
|
|
<div class="for-switch">{{gh-feature-flag "publicAPI"}}</div>
|
|
</div>
|
|
</div>
|
|
{{/if}}
|
|
<div class="gh-setting {{if feature.members "gh-labs-disabled"}}" data-tooltip="{{if feature.members "Disabled when members is turned on"}}">
|
|
<div class="gh-setting-content">
|
|
<div class="gh-setting-title">Subscribers</div>
|
|
<div class="gh-setting-desc">Collect email addresses from your readers, more info in <a
|
|
href="https://ghost.org/faq/enable-subscribers-feature/">the docs</a></div>
|
|
</div>
|
|
<div class="gh-setting-action">
|
|
{{#if feature.members}}
|
|
<div class="for-switch">{{gh-feature-flag "subscribers" "disabled"}}</div>
|
|
{{else}}
|
|
<div class="for-switch">{{gh-feature-flag "subscribers" }}</div>
|
|
{{/if}}
|
|
</div>
|
|
</div>
|
|
{{#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.</div>
|
|
|
|
{{#liquid-if feature.labs.members class="nr25"}}
|
|
|
|
<div class="flex ba br4 b--whitegrey pa5 pt4 mt5">
|
|
<section class="gh-visibility-menu-content w-50">
|
|
<label class="dib f8 fw6 mb4">Default post access</label>
|
|
|
|
<div class="gh-radio {{if (eq settings.defaultContentVisibility "public") "active"}}"
|
|
{{action "setDefaultContentVisibility" "public" on="click"}}>
|
|
<div class="gh-radio-button" data-test-publishmenu-unpublished-option></div>
|
|
<div class="gh-radio-content">
|
|
<div class="gh-radio-label">Public</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="gh-radio {{if (eq settings.defaultContentVisibility "members") "active"}}"
|
|
{{action "setDefaultContentVisibility" "members" on="click"}}>
|
|
<div class="gh-radio-button" data-test-publishmenu-published-option></div>
|
|
<div class="gh-radio-content">
|
|
<div class="gh-radio-label">Free and paying members</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="gh-radio {{if (eq settings.defaultContentVisibility "paid") "active"}}"
|
|
{{action "setDefaultContentVisibility" "paid" on="click"}}>
|
|
<div class="gh-radio-button" data-test-publishmenu-published-option></div>
|
|
<div class="gh-radio-content">
|
|
<div class="gh-radio-label">Only paying members</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="flex flex-column ml5">
|
|
<label class="fw6 f8">Stripe publishable API key</label>
|
|
{{gh-text-input
|
|
value=(readonly subscriptionSettings.stripeConfig.public_token)
|
|
input=(action "setSubscriptionSettings" "public_token")
|
|
class="mt1"
|
|
}}
|
|
|
|
<label class="fw6 f8 mt4">Stripe secret API key</label>
|
|
{{gh-text-input
|
|
value=(readonly subscriptionSettings.stripeConfig.secret_token)
|
|
input=(action "setSubscriptionSettings" "secret_token")
|
|
class="mt1"
|
|
}}
|
|
<a href="https://dashboard.stripe.com/account/apikeys" target="_blank" class="mt1 fw4 f8">Where to find Stripe
|
|
API keys</a>
|
|
|
|
<div class="mt5 flex nb5">
|
|
<div class="w-50 mr3">
|
|
{{#gh-form-group}}
|
|
<label class="fw6 f8">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 f8">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>
|
|
|
|
</section>
|
|
</div>
|
|
|
|
<div class="mb5 mt5">
|
|
{{gh-task-button "Save members settings"
|
|
task=saveSettings
|
|
successText="Saved"
|
|
runningText="Saving"
|
|
class="gh-btn gh-btn-blue gh-btn-icon"
|
|
}}
|
|
</div>
|
|
|
|
{{/liquid-if}}
|
|
</div>
|
|
<div class="gh-setting-action">
|
|
<div class="for-switch">{{gh-feature-flag "members"}}</div>
|
|
</div>
|
|
</div>
|
|
{{/if}}
|
|
<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>
|
|
<div class="gh-setting-desc">Configure redirects for old or moved content, more info in <a href="https://ghost.org/tutorials/implementing-redirects/">the docs</a></div>
|
|
{{#each uploader.errors as |error|}}
|
|
<div class="gh-setting-error" data-test-error="redirects">{{or error.context error.message}}</div>
|
|
{{/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}}
|
|
{{svg-jar "check-circle"}} Uploaded
|
|
{{else if redirectFailure}}
|
|
{{svg-jar "retry"}} Upload Failed
|
|
{{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">
|
|
{{gh-file-input multiple=false action=uploader.setFiles accept=jsonMimeType data-test-file-input="redirects"}}
|
|
</div>
|
|
</div>
|
|
{{/gh-uploader}}
|
|
</div>
|
|
<div class="gh-setting-last">
|
|
{{#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|}}
|
|
<div class="gh-setting-error" data-test-error="routes">{{or error.context error.message}}</div>
|
|
{{/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>
|
|
<span><a href="#" {{action "downloadFile" "settings/routes/yaml"}} data-test-link="download-routes">Download current routes.yaml</a></span>
|
|
{{/if}}
|
|
|
|
<div style="display:none">
|
|
{{gh-file-input multiple=false action=uploader.setFiles accept=yamlMimeType data-test-file-input="routes"}}
|
|
</div>
|
|
</div>
|
|
{{/gh-uploader}}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</section>
|
|
|
|
{{#if showDeleteAllModal}}
|
|
{{gh-fullscreen-modal "delete-all"
|
|
close=(action "toggleDeleteAllModal")
|
|
modifier="action wide"}}
|
|
{{/if}}
|