Ghost/ghost/admin/app/templates/settings/general.hbs
Kevin Ansfield 32e6567e5b Added global meta data and Twitter/Facebook card settings (#1287)
closes https://github.com/TryGhost/Ghost/issues/10921

- added new fields to settings model
- added "Site meta settings" section to general settings
2019-08-21 16:16:59 +01:00

493 lines
30 KiB
Handlebars
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<section class="gh-canvas">
<div>
<GhCanvasHeader class="gh-canvas-header">
<h2 class="gh-canvas-title" data-test-screen-title>
General settings
</h2>
<section class="view-actions">
{{gh-task-button "Save settings" task=save class="gh-btn gh-btn-blue gh-btn-icon" data-test-save-button=true}}
</section>
</GhCanvasHeader>
{{#if showLeaveSettingsModal}}
{{gh-fullscreen-modal "leave-settings"
confirm=(action "leaveSettings")
close=(action "toggleLeaveSettingsModal")
modifier="action wide"}}
{{/if}}
<section class="view-container">
<div class="gh-setting-header gh-first-header">Publication info</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">Title &amp; description</div>
<div class="gh-setting-desc">The details used to identify your publication around the web</div>
{{#liquid-if pubInfoOpen}}
<div class="gh-setting-content-extended">
{{#gh-form-group errors=settings.errors hasValidated=settings.hasValidated property="title"}}
{{gh-text-input
value=(readonly settings.title)
input=(action (mut settings.title) value="target.value")
focus-out=(action "validate" "title" target=settings)
data-test-title-input=true
}}
{{gh-error-message errors=settings.errors property="title"}}
<p>The name of your site</p>
{{/gh-form-group}}
{{#gh-form-group errors=settings.errors hasValidated=settings.hasValidated property="description" class="description-container"}}
{{gh-text-input
value=(readonly settings.description)
input=(action (mut settings.description) value="target.value")
focus-out=(action "validate" "description" target=settings)
data-test-description-input=true
}}
{{gh-error-message errors=settings.errors property="description"}}
<p>Used in your theme, meta data and search results</p>
{{/gh-form-group}}
</div>
{{/liquid-if}}
</div>
<div class="gh-setting-action">
<button type="button" class="gh-btn" {{action (toggle "pubInfoOpen" this)}} data-test-toggle-pub-info><span>{{if pubInfoOpen "Close" "Expand"}}</span></button>
</div>
</div>
<div class="gh-setting">
<div class="gh-setting-content">
<div class="gh-setting-title">Site timezone</div>
<div class="gh-setting-desc">Set the time and date of your publication, used for all published posts</div>
{{#liquid-if timezoneOpen}}
<div class="gh-setting-content-extended">
{{gh-timezone-select
activeTimezone=settings.activeTimezone
availableTimezones=availableTimezones
update=(action "setTimezone")}}
</div>
{{/liquid-if}}
</div>
<div class="gh-setting-action">
<button type="button" class="gh-btn" {{action (toggle "timezoneOpen" this)}} data-test-toggle-timezone><span>{{if timezoneOpen "Close" "Expand"}}</span></button>
</div>
</div>
<div class="gh-setting-last">
<div class="gh-setting-content">
<div class="gh-setting-title">Publication Language</div>
<div class="gh-setting-desc">Set the language/locale which is used on your site</div>
{{#liquid-if defaultLocaleOpen}}
<div class="gh-setting-content-extended">
{{#gh-form-group errors=settings.errors hasValidated=settings.hasValidated property="defaultLocale"}}
{{gh-text-input
value=(readonly settings.defaultLocale)
input=(action (mut settings.defaultLocale) value="target.value")
focus-out=(action "validate" "defaultLocale" target=settings)
data-test-default-locale-input=true
}}
{{gh-error-message errors=settings.errors property="defaultLocale"}}
<p>Default: English (<strong>en</strong>); you can add translation files to your theme for <a href="https://ghost.org/docs/api/handlebars-themes/helpers/translate/" target="_blank" rel="noopener">any language</a></p>
{{/gh-form-group}}
</div>
{{/liquid-if}}
</div>
<div class="gh-setting-action">
<button type="button" class="gh-btn" {{action (toggle "defaultLocaleOpen" this)}} data-test-toggle-default-locale><span>{{if defaultLocaleOpen "Close" "Expand"}}</span></button>
</div>
</div>
</div>
<div class="gh-setting-header">Publication identity</div>
<div class="flex flex-column br3 shadow-1 bg-grouped-table pa5">
<div class="gh-setting-first" data-test-setting="icon">
{{#gh-uploader
extensions=iconExtensions
paramsHash=(hash purpose="icon")
onComplete=(action "imageUploaded" "icon")
as |uploader|
}}
<div class="gh-setting-content">
<div class="gh-setting-title">Publication icon</div>
<div class="gh-setting-desc">A square, social icon used in the UI of your publication, at least 60x60px</div>
{{#each uploader.errors as |error|}}
<div class="gh-setting-error" data-test-error="icon">{{or error.context error.message}}</div>
{{/each}}
</div>
<div class="gh-setting-action gh-setting-action-smallimg">
{{#if uploader.isUploading}}
{{uploader.progressBar}}
{{else if settings.icon}}
<img class="blog-icon" src="{{settings.icon}}" onclick={{action "triggerFileDialog"}} alt="icon" data-test-icon-img>
<button type="button" class="gh-setting-action-smallimg-delete" {{action "removeImage" "icon"}} data-test-delete-image="icon">
<span>delete</span>
</button>
{{else}}
<button type="button" class="gh-btn" onclick={{action "triggerFileDialog"}} data-test-image-upload-btn="icon">
<span>Upload Image</span>
</button>
{{/if}}
<div style="display:none">
{{gh-file-input multiple=false action=uploader.setFiles accept=iconMimeTypes data-test-file-input="icon"}}
</div>
</div>
{{/gh-uploader}}
</div>
<div class="gh-setting" data-test-setting="logo">
{{#gh-uploader
extensions=imageExtensions
onComplete=(action "imageUploaded" "logo")
as |uploader|
}}
<div class="gh-setting-content">
<div class="gh-setting-title">Publication logo</div>
<div class="gh-setting-desc">The primary logo for your brand displayed across your theme, should be transparent and at least 600px x 72px</div>
{{#each uploader.errors as |error|}}
<div class="gh-setting-error" data-test-error="logo">{{or error.context error.message}}</div>
{{/each}}
</div>
<div class="gh-setting-action gh-setting-action-smallimg">
{{#if uploader.isUploading}}
{{uploader.progressBar}}
{{else if settings.logo}}
<img class="blog-logo" src="{{settings.logo}}" onclick={{action "triggerFileDialog"}} alt="logo" data-test-logo-img>
<button type="button" class="gh-setting-action-smallimg-delete" {{action "removeImage" "logo"}} data-test-delete-image="logo">
<span>delete</span>
</button>
{{else}}
<button type="button" class="gh-btn" onclick={{action "triggerFileDialog"}} data-test-image-upload-btn="logo">
<span>Upload Image</span>
</button>
{{/if}}
<div style="display:none">
{{gh-file-input multiple=false action=uploader.setFiles accept=imageMimeTypes data-test-file-input="logo"}}
</div>
</div>
{{/gh-uploader}}
</div>
<div class="gh-setting-last" data-test-setting="coverImage">
{{#gh-uploader
extensions=imageExtensions
onComplete=(action "imageUploaded" "coverImage")
as |uploader|
}}
<div class="gh-setting-content">
<div class="gh-setting-title">Publication cover</div>
<div class="gh-setting-desc">An optional large background image for your site</div>
{{#each uploader.errors as |error|}}
<div class="gh-setting-error" data-test-error="coverImage">{{or error.context error.message}}</div>
{{/each}}
</div>
<div class="gh-setting-action gh-setting-action-largeimg">
{{#if uploader.isUploading}}
{{uploader.progressBar}}
{{else if settings.coverImage}}
<img class="blog-cover" src="{{settings.coverImage}}" onclick={{action "triggerFileDialog"}} alt="cover photo" data-test-cover-img>
<button type="button" class="gh-setting-action-largeimg-delete" {{action "removeImage" "coverImage"}} data-test-delete-image="coverImage">
<span>delete</span>
</button>
{{else}}
<button type="button" class="gh-btn" onclick={{action "triggerFileDialog"}} data-test-image-upload-btn="coverImage">
<span>Upload Image</span>
</button>
{{/if}}
<div style="display:none">
{{gh-file-input multiple=false action=uploader.setFiles accept=imageMimeTypes data-test-file-input="coverImage"}}
</div>
</div>
{{/gh-uploader}}
</div>
</div>
<div class="gh-setting-header">Site meta settings</div>
<div class="flex flex-column br3 shadow-1 bg-grouped-table pa5">
<div class="gh-setting-first flex-column">
<div class="flex flex-row justify-between w-100">
<div class="gh-setting-content">
<div class="gh-setting-title">Meta data</div>
<div class="gh-setting-desc">Extra content for search engines</div>
</div>
<div class="gh-setting-action">
<button type="button" class="gh-btn" {{action (toggle "metaDataOpen" this)}} data-test-toggle-meta><span>{{if metaDataOpen "Close" "Expand"}}</span></button>
</div>
</div>
{{#liquid-if metaDataOpen}}
<div class="gh-setting-content-extended">
<div class="flex flex-column flex-row-ns">
<div class="flex-basis-1-2-m flex-basis-2-3-l mr5">
{{#gh-form-group errors=this.settings.errors hasValidated=this.settings.hasValidated property="metaTitle"}}
<label for="metaTitle">Meta title</label>
{{gh-text-input
id="metaTitle"
type="text"
placeholder=(truncate this.settings.title 70)
value=(readonly this.settings.metaTitle)
input=(action (mut this.settings.metaTitle) value="target.value")
data-test-input="metaTitle"
}}
{{gh-error-message errors=this.settings.errors property="metaTitle" data-test-error="metaTitle"}}
<p>Recommended: <b>70</b> characters. Youve used <b>{{gh-count-down-characters this.settings.metaTitle 70}}</b></p>
{{/gh-form-group}}
{{#gh-form-group errors=this.settings.errors hasValidated=this.settings.hasValidated property="metaDescription"}}
<label for="metaDescription">Meta description</label>
{{gh-textarea
id="metaDescription"
type="text"
placeholder=(truncate this.settings.description 300)
value=(readonly this.settings.metaDescription)
input=(action (mut this.settings.metaDescription) value="target.value")
data-test-input="metaDescription"
}}
{{gh-error-message errors=this.settings.errors property="metaDescription" data-test-error="metaDescription"}}
<p>Recommended: <b>156</b> characters. Youve used <b>{{gh-count-down-characters this.settings.metaDescription 156}}</b></p>
{{/gh-form-group}}
</div>
<div class="flex-basis-1-2-m flex-basis-1-3-l">
<label>Search engine result preview</label>
<div class="seo-preview">
<div class="seo-preview-title">{{truncate (or this.settings.metaTitle this.settings.title) 70}}</div>
<div class="seo-preview-link">{{truncate this.config.blogUrl 70}}</div>
<div class="seo-preview-description">{{truncate (or this.settings.metaDescription this.settings.description) 300}}</div>
</div>
</div>
</div>
</div>
{{/liquid-if}}
</div>
<div class="gh-setting flex-column">
<div class="flex flex-row justify-between w-100">
<div class="gh-setting-content">
<div class="gh-setting-title">Twitter card</div>
<div class="gh-setting-desc">Customise structured data of your site for Twitter</div>
</div>
<div class="gh-setting-action">
<button type="button" class="gh-btn" {{action (toggle "twitterCardOpen" this)}} data-test-toggle-twitter><span>{{if twitterCardOpen "Close" "Expand"}}</span></button>
</div>
</div>
{{#liquid-if twitterCardOpen}}
<div class="gh-setting-content-extended">
<div class="flex flex-column flex-row-ns">
<div class="flex-basis-1-2-m flex-basis-2-3-l mr5 nudge-top--7">
{{#gh-form-group}}
{{gh-image-uploader-with-preview
image=this.settings.twitterImage
text="Add Twitter image"
allowUnsplash=true
update=(action (mut this.settings.twitterImage))
remove=(action (mut this.settings.twitterImage ""))
}}
{{/gh-form-group}}
{{#gh-form-group errors=this.settings.errors hasValidated=this.settings.hasValidated property="twitterTitle"}}
<label for="twitterTitle">Twitter title</label>
{{gh-text-input
id="twitterTitle"
type="text"
placeholder=(truncate this.settings.title 70)
value=(readonly this.settings.twitterTitle)
input=(action (mut this.settings.twitterTitle) value="target.value")
data-test-input="twitterTitle"
}}
{{gh-error-message errors=this.settings.errors property="twitterTitle" data-test-error="twitterTitle"}}
{{/gh-form-group}}
{{#gh-form-group errors=this.settings.errors hasValidated=this.settings.hasValidated property="twitterDescription"}}
<label for="twitterDescription">Twitter description</label>
{{gh-textarea
id="twitterDescription"
placeholder=(truncate this.settings.description 300)
value=(readonly this.settings.twitterDescription)
input=(action (mut this.settings.twitterDescription) value="target.value")
data-test-input="twitterDescription"
}}
{{gh-error-message errors=this.settings.errors property="twitterDescription" data-test-error="twitterDescription"}}
{{/gh-form-group}}
</div>
<div class="flex-basis-1-2-m flex-basis-1-3-l nt4-ns">
<label>Preview</label>
<div class="gh-twitter-preview">
{{#if this.settings.twitterImage}}
<div class="gh-twitter-preview-image" style={{background-image-style this.settings.twitterImage}}></div>
{{/if}}
<div class="gh-twitter-preview-content">
<div class="gh-twitter-preview-title">{{or this.settings.twitterTitle this.settings.title}}</div>
<div class="gh-twitter-preview-description">{{truncate (or this.settings.twitterDescription this.settings.description) 155}}</div>
<div class="gh-twitter-preview-footer">
<div class="gh-twitter-preview-footer-left">
{{this.config.blogDomain}}
</div>
<div class="gh-twitter-preview-footer-right">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{{/liquid-if}}
</div>
<div class="gh-setting-last flex-column">
<div class="flex flex-row justify-between w-100">
<div class="gh-setting-content">
<div class="gh-setting-title">Facebook card</div>
<div class="gh-setting-desc">Customise structured data of your site</div>
</div>
<div class="gh-setting-action">
<button type="button" class="gh-btn" {{action (toggle "facebookCardOpen" this)}} data-test-toggle-facebook><span>{{if facebookCardOpen "Close" "Expand"}}</span></button>
</div>
</div>
{{#liquid-if facebookCardOpen}}
<div class="gh-setting-content-extended">
<div class="flex flex-column flex-row-ns">
<div class="flex-basis-1-2-m flex-basis-2-3-l mr5 nudge-top--7">
{{#gh-form-group}}
{{gh-image-uploader-with-preview
image=this.settings.ogImage
text="Add Facebook image"
allowUnsplash=true
update=(action (mut this.settings.ogImage))
remove=(action (mut this.settings.ogImage ""))
}}
{{/gh-form-group}}
{{#gh-form-group errors=this.settings.errors hasValidated=this.settings.hasValidated property="ogTitle"}}
<label for="ogTitle">Facebook title</label>
{{gh-text-input
id="ogTitle"
type="text"
placeholder=(truncate this.settings.title 70)
value=(readonly this.settings.ogTitle)
input=(action (mut this.settings.ogTitle) value="target.value")
data-test-input="ogTitle"
}}
{{gh-error-message errors=this.settings.errors property="ogTitle" data-test-error="ogTitle"}}
{{/gh-form-group}}
{{#gh-form-group errors=this.settings.errors hasValidated=this.settings.hasValidated property="ogDescription"}}
<label for="ogDescription">Facebook description</label>
{{gh-textarea
id="ogDescription"
placeholder=(truncate this.settings.description 300)
value=(readonly this.settings.ogDescription)
input=(action (mut this.settings.ogDescription) value="target.value")
data-test-input="ogDescription"
}}
{{gh-error-message errors=this.settings.errors property="ogDescription" data-test-error="ogDescription"}}
{{/gh-form-group}}
</div>
<div class="flex-basis-1-2-m flex-basis-1-3-l nt4-ns">
<label>Preview</label>
<div class="gh-og-preview">
{{#if this.settings.ogImage}}
<div class="gh-og-preview-image" style={{background-image-style this.settings.ogImage}}></div>
{{/if}}
<div class="gh-og-preview-content">
<div class="gh-og-preview-title">{{truncate (or this.settings.ogTitle this.settings.title) 88}}</div>
<div class="gh-og-preview-description">{{truncate (or this.settings.ogDescription this.settings.description) 300}}</div>
<div class="gh-og-preview-footer">
<div class="gh-og-preview-footer-left">
{{this.config.blogDomain}}
</div>
<div class="gh-og-preview-footer-right"></div>
</div>
</div>
</div>
</div>
</div>
</div>
{{/liquid-if}}
</div>
</div>
<div class="gh-setting-header">Social accounts</div>
<div class="flex flex-column br3 shadow-1 bg-grouped-table pa5">
<div class="gh-setting-first gh-setting-last">
<div class="gh-setting-content">
<div class="gh-setting-title">Social accounts</div>
<div class="gh-setting-desc">Link your social accounts for full structured data and rich card support</div>
{{#liquid-if socialOpen}}
<div class="gh-setting-content-extended">
{{#gh-form-group errors=settings.errors hasValidated=settings.hasValidated property="facebook"}}
{{gh-text-input
type="url"
placeholder="https://www.facebook.com/ghost"
autocorrect="off"
value=(readonly settings.facebook)
input=(action (mut _scratchFacebook) value="target.value")
focus-out=(action "validateFacebookUrl")
data-test-facebook-input=true
}}
{{gh-error-message errors=settings.errors property="facebook" data-test-facebook-error=true}}
<p>URL of your publication's Facebook Page</p>
{{/gh-form-group}}
{{#gh-form-group errors=settings.errors hasValidated=settings.hasValidated property="twitter"}}
{{gh-text-input
type="url"
placeholder="https://twitter.com/ghost"
autocorrect="off"
value=(readonly settings.twitter)
input=(action (mut _scratchTwitter) value="target.value")
focus-out=(action "validateTwitterUrl")
data-test-twitter-input=true
}}
{{gh-error-message errors=settings.errors property="twitter" data-test-twitter-error=true}}
<p>URL of your publication's Twitter profile</p>
{{/gh-form-group}}
</div>
{{/liquid-if}}
</div>
<div class="gh-setting-action">
<button type="button" class="gh-btn" {{action (toggle "socialOpen" this)}} data-test-toggle-social><span>{{if socialOpen "Close" "Expand"}}</span></button>
</div>
</div>
</div>
<div class="gh-setting-header">Advanced settings</div>
<div class="flex flex-column br3 shadow-1 bg-grouped-table pa5">
<div class="gh-setting-first gh-setting-last">
<div class="gh-setting-content">
<div class="gh-setting-title">Make this site private</div>
<div class="gh-setting-desc">
Enable protection with simple shared password. All search engine optimization and social features will be disabled.
{{#if settings.isPrivate}}
<span class="avoid-break-out">
<br><br>
A private RSS feed is available at
<a href="{{privateRSSUrl}}" target="_blank" rel="noopener">{{privateRSSUrl}}</a>
</span>
{{/if}}
</div>
{{#if settings.isPrivate}}
<div class="gh-setting-content-extended">
{{#gh-form-group errors=settings.errors hasValidated=settings.hasValidated property="password"}}
{{gh-text-input
value=(readonly settings.password)
name="general[password]"
focus-out=(action "validate" "password" target=settings)
input=(action (mut settings.password) value="target.value")
data-test-password-input=true
}}
{{gh-error-message errors=settings.errors property="password" data-test-password-error=true}}
<p>Set the password for this site</p>
{{/gh-form-group}}
</div>
{{/if}}
</div>
<div class="gh-setting-action">
<div class="for-switch">
<label class="switch" for="settings-private">
<input
type="checkbox"
checked={{settings.isPrivate}}
id="settings-private"
onclick={{action "toggleIsPrivate" value="target.checked"}}
data-test-private-checkbox
>
<span class="input-toggle-component"></span>
</label>
</div>
</div>
</div>
</div>
</section>
</div>
</section>
{{outlet}}