mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-29 13:52:10 +03:00
09435ecf76
no issue Keeps component JS backing files and template files in the same directory which avoids hunting across directories when working with components. Also lets you see all components when looking at one directory, whereas previously template-only or js-only components may not have been obvious without looking at both directories. - ran [codemod](https://github.com/ember-codemods/ember-component-template-colocation-migrator/) for app-level components - manually moved in-repo-addon component templates in `lib/koenig-editor` - removed all explicit `layout` imports as JS/template associations are now made at build-time removing the need for them - updated `.embercli` to default to new flat component structure
454 lines
28 KiB
Handlebars
454 lines
28 KiB
Handlebars
<div class="settings-menu-container">
|
||
<div id="entry-controls">
|
||
<div class="{{if this.isViewingSubview 'settings-menu-pane-out-left' 'settings-menu-pane-in'}} settings-menu settings-menu-pane">
|
||
<div class="settings-menu-header">
|
||
<h4>{{capitalize this.post.displayName}} settings</h4>
|
||
<button class="close settings-menu-header-action" {{action "closeMenus" target=this.ui}} data-test-close-settings-menu>
|
||
{{svg-jar "close"}}<span class="hidden">Close</span>
|
||
</button>
|
||
</div>
|
||
<div class="settings-menu-content">
|
||
<GhImageUploaderWithPreview
|
||
@image={{this.post.featureImage}}
|
||
@text={{concat "Upload " this.post.displayName " image"}}
|
||
@allowUnsplash={{true}}
|
||
@update={{action "setCoverImage"}}
|
||
@remove={{action "clearCoverImage"}}
|
||
/>
|
||
<form>
|
||
<div class="form-group">
|
||
<label for="url">{{capitalize this.post.displayName}} URL</label>
|
||
{{!-- new posts don't have a preview link --}}
|
||
{{#unless this.post.isNew}}
|
||
{{#if this.post.isPublished}}
|
||
<a class="post-view-link" target="_blank" href="{{this.post.url}}">
|
||
View {{this.post.displayName}} {{svg-jar "external"}}
|
||
</a>
|
||
{{else}}
|
||
<a class="post-view-link" target="_blank" href="{{this.post.previewUrl}}">
|
||
Preview {{svg-jar "external"}}
|
||
</a>
|
||
{{/if}}
|
||
{{/unless}}
|
||
|
||
<div class="gh-input-icon gh-icon-link">
|
||
{{svg-jar "link"}}
|
||
<GhTextInput
|
||
@class="post-setting-slug"
|
||
@id="url"
|
||
@name="post-setting-slug"
|
||
@value={{readonly this.slugValue}}
|
||
@input={{action (mut this.slugValue) value="target.value"}}
|
||
@focus-out={{action "updateSlug" this.slugValue}}
|
||
@stopEnterKeyDownPropagation={{true}} />
|
||
</div>
|
||
<GhUrlPreview @slug={{this.slugValue}} @tagName="p" @classNames="description" />
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
{{#if (or this.post.isDraft this.post.isPublished this.post.pastScheduledTime)}}
|
||
<label>Publish date</label>
|
||
{{else}}
|
||
<label>Scheduled date</label>
|
||
{{/if}}
|
||
<GhDateTimePicker
|
||
@date={{this.post.publishedAtBlogDate}}
|
||
@time={{this.post.publishedAtBlogTime}}
|
||
@setDate={{action "setPublishedAtBlogDate"}}
|
||
@setTime={{action "setPublishedAtBlogTime"}}
|
||
@errors={{this.post.errors}}
|
||
@dateErrorProperty="publishedAtBlogDate"
|
||
@timeErrorProperty="publishedAtBlogTime"
|
||
@maxDate="now"
|
||
@disabled={{this.post.isScheduled}}
|
||
@isActive={{and this.showSettingsMenu (not this.isViewingSubview)}}
|
||
/>
|
||
{{#unless (or this.post.isDraft this.post.isPublished this.post.pastScheduledTime)}}
|
||
<p>Use the publish menu to re-schedule</p>
|
||
{{/unless}}
|
||
</div>
|
||
|
||
{{#unless this.session.user.isContributor}}
|
||
<div class="form-group">
|
||
<label for="tag-input">Tags</label>
|
||
<GhPsmTagsInput @post={{this.post}} @triggerId="tag-input" />
|
||
</div>
|
||
{{/unless}}
|
||
|
||
|
||
{{#if this.feature.members}}
|
||
{{#if this.showVisibilityInput}}
|
||
<div class="form-group">
|
||
<label for="visibility-input">Post access</label>
|
||
<GhPsmVisibilityInput @post={{this.post}} @triggerId="visibility-input" />
|
||
</div>
|
||
{{/if}}
|
||
{{/if}}
|
||
|
||
|
||
<GhFormGroup @errors={{this.post.errors}} @hasValidated={{this.post.hasValidated}} @property="customExcerpt">
|
||
<label for="custom-excerpt">Excerpt</label>
|
||
<GhTextarea
|
||
@class="post-setting-custom-excerpt"
|
||
@id="custom-excerpt"
|
||
@name="post-setting-custom-excerpt"
|
||
@value={{readonly this.customExcerptScratch}}
|
||
@input={{action (mut this.customExcerptScratch) value="target.value"}}
|
||
@focus-out={{action "setCustomExcerpt" this.customExcerptScratch}}
|
||
@stopEnterKeyDownPropagation="true"
|
||
data-test-field="custom-excerpt"
|
||
/>
|
||
<GhErrorMessage @errors={{this.post.errors}} @property="customExcerpt" data-test-error="custom-excerpt" />
|
||
</GhFormGroup>
|
||
|
||
{{#unless this.session.user.isAuthorOrContributor}}
|
||
<GhFormGroup @class="for-select" @errors={{this.post.errors}} @hasValidated={{this.post.hasValidated}} @property="authors" data-test-input="authors">
|
||
<label for="author-list">Authors</label>
|
||
<GhPsmAuthorsInput @selectedAuthors={{this.post.authors}} @updateAuthors={{action "changeAuthors"}} @triggerId="author-list" />
|
||
<GhErrorMessage @errors={{this.post.errors}} @property="authors" data-test-error="authors" />
|
||
</GhFormGroup>
|
||
{{/unless}}
|
||
|
||
<ul class="nav-list nav-list-block">
|
||
<li class="nav-list-item" {{action "showSubview" "meta-data"}} data-test-button="meta-data">
|
||
<button type="button">
|
||
<b>Meta data</b>
|
||
<span>Extra content for search engines</span>
|
||
</button>
|
||
{{svg-jar "arrow-right"}}
|
||
</li>
|
||
<li class="nav-list-item" {{action "showSubview" "twitter-data"}} data-test-button="twitter-data">
|
||
<button type="button">
|
||
<b>Twitter card</b>
|
||
<span>Customise structured data for Twitter</span>
|
||
</button>
|
||
{{svg-jar "arrow-right"}}
|
||
</li>
|
||
<li class="nav-list-item" {{action "showSubview" "facebook-data"}} data-test-button="facebook-data">
|
||
<button type="button">
|
||
<b>Facebook card</b>
|
||
<span>Customise Open Graph data</span>
|
||
</button>
|
||
{{svg-jar "arrow-right"}}
|
||
</li>
|
||
{{#if (and this.feature.members (eq this.post.displayName "post") this.session.user.isOwnerOrAdmin)}}
|
||
<li class="nav-list-item" {{action "showSubview" "email-settings"}} data-test-button="email-settings">
|
||
<button type="button">
|
||
<b>Email newsletter</b>
|
||
<span>Customise email settings</span>
|
||
</button>
|
||
{{svg-jar "arrow-right"}}
|
||
</li>
|
||
{{/if}}
|
||
<li class="nav-list-item" {{action "showSubview" "codeinjection"}} data-test-button="codeinjection">
|
||
<button type="button">
|
||
<b>Code injection</b>
|
||
<span>Add styles/scripts to the header & footer</span>
|
||
</button>
|
||
{{svg-jar "arrow-right"}}
|
||
</li>
|
||
</ul>
|
||
|
||
{{#unless this.session.user.isAuthorOrContributor}}
|
||
<div class="form-group for-checkbox">
|
||
<label class="checkbox" for="featured" {{action "toggleFeatured" bubbles="false"}}>
|
||
<input
|
||
type="checkbox"
|
||
checked={{this.post.featured}}
|
||
class="gh-input post-settings-featured"
|
||
onclick={{action (mut this.post.featured) value="target.checked"}}
|
||
data-test-checkbox="featured"
|
||
>
|
||
<span class="input-toggle-component"></span>
|
||
<p>Feature this {{this.post.displayName}}</p>
|
||
</label>
|
||
</div>
|
||
{{/unless}}
|
||
|
||
<GhPsmTemplateSelect
|
||
@post={{this.post}}
|
||
@onTemplateSelect={{action (mut this.post.customTemplate)}} />
|
||
|
||
{{#unless this.post.isNew}}
|
||
<button type="button" class="gh-btn gh-btn-hover-red gh-btn-icon settings-menu-delete-button" {{action "deletePost"}}><span>{{svg-jar "trash"}} Delete {{this.post.displayName}}</span></button>
|
||
{{/unless}}
|
||
|
||
</form>
|
||
</div>{{! .settings-menu-content }}
|
||
</div>{{! .post-settings-menu }}
|
||
|
||
<div class="{{if this.isViewingSubview 'settings-menu-pane-in' 'settings-menu-pane-out-right'}} settings-menu settings-menu-pane">
|
||
<div class="active">
|
||
{{#if this.isViewingSubview}}
|
||
{{#if (eq this.subview "meta-data")}}
|
||
<div class="settings-menu-header subview">
|
||
<button {{action "closeSubview"}} class="back settings-menu-header-action" data-test-button="close-psm-subview">{{svg-jar "arrow-left"}}<span class="hidden">Back</span></button>
|
||
<h4>Meta data</h4>
|
||
<div style="width:23px;"></div>
|
||
</div>
|
||
|
||
<div class="settings-menu-content">
|
||
<form {{action "discardEnter" on="submit"}}>
|
||
<GhFormGroup @errors={{this.post.errors}} @hasValidated={{this.post.hasValidated}} @property="metaTitle">
|
||
<label for="meta-title">Meta title</label>
|
||
<GhTextInput
|
||
@class="post-setting-meta-title"
|
||
@id="meta-title"
|
||
@name="post-setting-meta-title"
|
||
@value={{readonly this.metaTitleScratch}}
|
||
@input={{action (mut this.metaTitleScratch) value="target.value"}}
|
||
@focus-out={{action "setMetaTitle" this.metaTitleScratch}}
|
||
@stopEnterKeyDownPropagation={{true}}
|
||
data-test-field="meta-title" />
|
||
<p>Recommended: <b>70</b> characters. You’ve used {{gh-count-down-characters this.metaTitleScratch 70}}</p>
|
||
<GhErrorMessage @errors={{this.post.errors}} @property="meta-title" />
|
||
</GhFormGroup>
|
||
|
||
<GhFormGroup @errors={{this.post.errors}} @hasValidated={{this.post.hasValidated}} @property="metaDescription">
|
||
<label for="meta-description">Meta description</label>
|
||
<GhTextarea
|
||
@class="post-setting-meta-description"
|
||
@id="meta-description"
|
||
@name="post-setting-meta-description"
|
||
@value={{readonly this.metaDescriptionScratch}}
|
||
@input={{action (mut this.metaDescriptionScratch) value="target.value"}}
|
||
@focus-out={{action "setMetaDescription" this.metaDescriptionScratch}}
|
||
@stopEnterKeyDownPropagation="true"
|
||
data-test-field="meta-description" />
|
||
<p>Recommended: <b>156</b> characters. You’ve used {{gh-count-down-characters this.metaDescriptionScratch 156}}</p>
|
||
<GhErrorMessage @errors={{this.post.errors}} @property="meta-description" />
|
||
</GhFormGroup>
|
||
|
||
<GhFormGroup @errors={{this.post.errors}} @hasValidated={{this.post.hasValidated}} @property="canonicalUrl">
|
||
<label for="canonicalUrl">Canonical URL</label>
|
||
<GhTextInput
|
||
@class="post-setting-canonicalUrl"
|
||
@name="post-setting-canonicalUrl"
|
||
@value={{readonly this.canonicalUrlScratch}}
|
||
@input={{action (mut this.canonicalUrlScratch) value="target.value"}}
|
||
@focus-out={{action "setCanonicalUrl" this.canonicalUrlScratch}}
|
||
@stopEnterKeyDownPropagation="true"
|
||
data-test-field="canonicalUrl" />
|
||
<GhErrorMessage @errors={{this.post.errors}} @property="canonicalUrl" />
|
||
</GhFormGroup>
|
||
|
||
<div class="form-group">
|
||
<label>Search Engine Result Preview</label>
|
||
<div class="seo-preview">
|
||
<div class="seo-preview-title">{{truncate this.seoTitle 70}}</div>
|
||
<div class="seo-preview-link">{{truncate this.seoURL 70}}</div>
|
||
<div class="seo-preview-description">{{truncate this.seoDescription 300}}</div>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
{{/if}}
|
||
|
||
{{#if (eq this.subview "twitter-data")}}
|
||
<div class="settings-menu-header subview">
|
||
<button {{action "closeSubview"}} class="back settings-menu-header-action" data-test-button="close-psm-subview">{{svg-jar "arrow-left"}}<span class="hidden">Back</span></button>
|
||
<h4>Twitter card</h4>
|
||
<div style="width:23px;"></div>
|
||
</div>
|
||
|
||
<div class="settings-menu-content">
|
||
|
||
<form {{action "discardEnter" on="submit"}}>
|
||
<GhImageUploaderWithPreview
|
||
@image={{this.post.twitterImage}}
|
||
@text="Add Twitter image"
|
||
@allowUnsplash={{true}}
|
||
@update={{action "setTwitterImage"}}
|
||
@remove={{action "clearTwitterImage"}}
|
||
/>
|
||
<GhFormGroup @errors={{this.post.errors}} @hasValidated={{this.post.hasValidated}} @property="twitterTitle">
|
||
<label for="twitter-title">Twitter title</label>
|
||
<GhTextInput
|
||
@class="post-setting-twitter-title"
|
||
@id="twitter-title"
|
||
@name="post-setting-twitter-title"
|
||
@placeholder={{truncate this.twitterTitle 40}}
|
||
@value={{readonly this.twitterTitleScratch}}
|
||
@input={{action (mut this.twitterTitleScratch) value="target.value"}}
|
||
@focus-out={{action "setTwitterTitle" this.twitterTitleScratch}}
|
||
@stopEnterKeyDownPropagation={{true}}
|
||
data-test-field="twitter-title" />
|
||
<GhErrorMessage @errors={{this.post.errors}} @property="twitterTitle" data-test-error="twitter-title" />
|
||
</GhFormGroup>
|
||
|
||
<GhFormGroup @errors={{this.post.errors}} @hasValidated={{this.post.hasValidated}} @property="twitterDescription">
|
||
<label for="twitter-description">Twitter description</label>
|
||
<GhTextarea
|
||
@class="post-setting-twitter-description"
|
||
@id="twitter-description"
|
||
@name="post-setting-twitter-description"
|
||
@placeholder={{truncate this.twitterDescription 155}}
|
||
@stopEnterKeyDownPropagation="true"
|
||
@value={{readonly this.twitterDescriptionScratch}}
|
||
@input={{action (mut this.twitterDescriptionScratch) value="target.value"}}
|
||
@focus-out={{action "setTwitterDescription" this.twitterDescriptionScratch}}
|
||
data-test-field="twitter-description" />
|
||
<GhErrorMessage @errors={{this.post.errors}} @property="twitterDescription" data-test-error="twitter-description" />
|
||
</GhFormGroup>
|
||
|
||
<div class="form-group">
|
||
<label>Preview</label>
|
||
<div class="gh-twitter-preview">
|
||
{{#if this.twitterImage}}
|
||
<div class="gh-twitter-preview-image" style={{background-image-style this.twitterImage}}></div>
|
||
{{/if}}
|
||
<div class="gh-twitter-preview-content">
|
||
<div class="gh-twitter-preview-title">{{this.twitterTitle}}</div>
|
||
<div class="gh-twitter-preview-description">{{truncate this.twitterDescription 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>
|
||
|
||
</form>
|
||
</div>
|
||
{{/if}}
|
||
|
||
{{#if (eq this.subview "email-settings")}}
|
||
<GhPostSettingsMenu::Email
|
||
@post={{this.post}}
|
||
@savePostTask={{this.savePost}}
|
||
@toggleEmailPreviewModal={{this.toggleEmailPreviewModal}}
|
||
@close={{action "closeSubview"}}
|
||
/>
|
||
{{/if}}
|
||
|
||
{{#if (eq this.subview "facebook-data")}}
|
||
<div class="settings-menu-header subview">
|
||
<button {{action "closeSubview"}} class="back settings-menu-header-action" data-test-button="close-psm-subview">{{svg-jar "arrow-left"}}<span class="hidden">Back</span></button>
|
||
<h4>Facebook card</h4>
|
||
<div style="width:23px;"></div>
|
||
</div>
|
||
|
||
<div class="settings-menu-content">
|
||
<form {{action "discardEnter" on="submit"}}>
|
||
<GhImageUploaderWithPreview
|
||
@image={{this.post.ogImage}}
|
||
@text="Add Facebook image"
|
||
@allowUnsplash={{true}}
|
||
@update={{action "setOgImage"}}
|
||
@remove={{action "clearOgImage"}}
|
||
/>
|
||
<GhFormGroup @errors={{this.post.errors}} @hasValidated={{this.post.hasValidated}} @property="ogTitle">
|
||
<label for="og-title">Facebook title</label>
|
||
<GhTextInput
|
||
@class="post-setting-og-title"
|
||
@id="og-title"
|
||
@name="post-setting-og-title"
|
||
@placeholder={{truncate this.facebookTitle 40}}
|
||
@value={{readonly this.ogTitleScratch}}
|
||
@input={{action (mut this.ogTitleScratch) value="target.value"}}
|
||
@focus-out={{action "setOgTitle" this.ogTitleScratch}}
|
||
@stopEnterKeyDownPropagation={{true}}
|
||
data-test-field="og-title" />
|
||
<GhErrorMessage @errors={{this.post.errors}} @property="ogTitle" data-test-error="og-title" />
|
||
</GhFormGroup>
|
||
|
||
<GhFormGroup @errors={{this.post.errors}} @hasValidated={{this.post.hasValidated}} @property="ogDescription">
|
||
<label for="og-description">Facebook description</label>
|
||
<GhTextarea
|
||
@class="post-setting-og-description"
|
||
@id="og-description" @name="post-setting-og-description"
|
||
@placeholder={{truncate this.facebookDescription 160}}
|
||
@value={{readonly this.ogDescriptionScratch}}
|
||
@input={{action (mut this.ogDescriptionScratch) value="target.value"}}
|
||
@focus-out={{action "setOgDescription" this.ogDescriptionScratch}}
|
||
@stopEnterKeyDownPropagation="true"
|
||
data-test-field="og-description" />
|
||
<GhErrorMessage @errors={{this.post.errors}} @property="ogDescription" data-test-error="og-description" />
|
||
</GhFormGroup>
|
||
|
||
<div class="form-group">
|
||
<label>Preview</label>
|
||
<div class="gh-og-preview">
|
||
{{#if this.facebookImage}}
|
||
<div class="gh-og-preview-image" style={{background-image-style this.facebookImage}}></div>
|
||
{{/if}}
|
||
<div class="gh-og-preview-content">
|
||
<div class="gh-og-preview-title">{{truncate this.facebookTitle 88}}</div>
|
||
<div class="gh-og-preview-description">{{truncate this.facebookDescription 300}}</div>
|
||
<div class="gh-og-preview-footer">
|
||
<div class="gh-og-preview-footer-left">
|
||
{{this.config.blogDomain}} <span class="gh-og-preview-footer-left-divider">|</span> by <span class="gh-og-preview-footer-author">{{author-names this.post.authors}}</span>
|
||
</div>
|
||
<div class="gh-og-preview-footer-right">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</form>
|
||
</div>
|
||
{{/if}}
|
||
|
||
{{#if (eq this.subview "codeinjection")}}
|
||
<div class="settings-menu-header subview">
|
||
<button {{action "closeSubview"}} class="back settings-menu-header-action" data-test-button="close-psm-subview">{{svg-jar "arrow-left"}}<span class="hidden">Back</span></button>
|
||
<h4>Code injection</h4>
|
||
<div style="width:23px;"></div>
|
||
</div>
|
||
|
||
<div class="settings-menu-content settings-menu-content-codeinjection">
|
||
<form {{action "discardEnter" on="submit"}}>
|
||
<GhFormGroup @errors={{this.post.errors}} @hasValidated={{this.post.hasValidated}} @property="codeinjectionHead">
|
||
<label for="codeinjection-head">{{capitalize this.post.displayName}} header <code>\{{ghost_head}}</code></label>
|
||
<GhCmEditor @value={{this.codeinjectionHeadScratch}}
|
||
@id="post-setting-codeinjection-head"
|
||
@class="post-setting-codeinjection"
|
||
@name="post-setting-codeinjection-head"
|
||
@focusOut={{action "setHeaderInjection" this.codeinjectionHeadScratch}}
|
||
@stopEnterKeyDownPropagation="true"
|
||
@update={{action (mut this.codeinjectionHeadScratch)}}
|
||
data-test-field="codeinjection-head" />
|
||
<GhErrorMessage @errors={{this.post.errors}} @property="codeinjectionHead" data-test-error="codeinjection-head" />
|
||
</GhFormGroup>
|
||
|
||
<GhFormGroup @errors={{this.post.errors}} @hasValidated={{this.post.hasValidated}} @property="codeinjectionFoot">
|
||
<label for="codeinjection-foot">{{capitalize this.post.displayName}} footer <code>\{{ghost_foot}}</code></label>
|
||
<GhCmEditor @value={{this.codeinjectionFootScratch}}
|
||
@id="post-setting-codeinjection-foot"
|
||
@class="post-setting-codeinjection"
|
||
@name="post-setting-codeinjection-foot"
|
||
@focusOut={{action "setFooterInjection" this.codeinjectionFootScratch}}
|
||
@stopEnterKeyDownPropagation="true"
|
||
@update={{action (mut this.codeinjectionFootScratch)}}
|
||
data-test-field="codeinjection-foot" />
|
||
<GhErrorMessage @errors={{this.post.errors}} @property="codeinjectionFoot" data-test-error="codeinjection-foot" />
|
||
</GhFormGroup>
|
||
</form>
|
||
</div>
|
||
{{/if}}
|
||
{{/if}}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{{!--
|
||
_showThrobbers is on a timer so that throbbers don't get positioned until
|
||
the slide-in animation has finished and it gets toggled when the meta
|
||
pane is shown
|
||
--}}
|
||
{{#if this._showThrobbers}}
|
||
{{#unless this.session.user.isAuthorOrContributor}}
|
||
<GhTourItem @throbberId="featured-post"
|
||
@target="label[for='featured'] p"
|
||
@throbberAttachment="middle middle"
|
||
@throbberOffset="0px -20px"
|
||
@popoverTriangleClass="bottom-right"
|
||
/>
|
||
{{/unless}}
|
||
{{/if}}
|