0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-02-03 23:00:14 -05:00

Content management & editor refactor

This commit is contained in:
John O'Nolan 2015-06-03 15:44:12 +01:00 committed by Hannah Wolfe
parent c8a49033a5
commit 5b25dd2929
14 changed files with 157 additions and 430 deletions

View file

@ -60,9 +60,6 @@ export default Ember.Mixin.create({
*/
willPublish: boundOneWay('model.isPublished'),
// Make sure editor starts with markdown shown
isPreview: false,
// set by the editor route and `isDirty`. useful when checking
// whether the number of tags has changed for `isDirty`.
previousTagNames: null,
@ -361,10 +358,6 @@ export default Ember.Mixin.create({
}
},
togglePreview: function (preview) {
this.set('isPreview', preview);
},
autoSaveNew: function () {
if (this.get('model.isNew')) {
this.send('save', {silent: true, backgroundSave: true});

View file

@ -45,7 +45,7 @@
.dropdown-menu > li > a,
.dropdown-menu > li > button {
display: block;
display: flex;
clear: both;
padding: 3px 20px;
width: 100%;

View file

@ -142,12 +142,14 @@
}
.modal-footer {
display: flex;
justify-content: flex-end;
margin-top: 20px;
text-align: right;
}
.modal-footer button {
margin-left: 8px;
text-align: center;
}

View file

@ -1,6 +1,12 @@
/* Content /ghost/
/* ---------------------------------------------------------- */
.content-view-container {
position: relative;
flex-grow: 1;
display: flex;
flex-direction: column;
}
/* Show/Hide on Mobile // TODO: What the fuck does that mean?
/* ---------------------------------------------------------- */
@ -167,6 +173,12 @@
/* Preview (Right pane)
/* ---------------------------------------------------------- */
.content-preview-content .content-preview-title a {
position: relative;
color: var(--darkgrey);
text-decoration: none;
}
.content-preview {
position: absolute;
top: 0;
@ -187,31 +199,6 @@
}
}
.content-preview .unfeatured {
margin: 0 7px 0 -5px;
padding: 3px;
vertical-align: -6%;
}
.content-preview .featured {
margin: 0 7px 0 -5px;
padding: 3px;
vertical-align: -6%;
}
.content-preview .post-published-by .status a {
color: inherit;
}
.content-preview .post-published-by .status a:hover {
text-decoration: underline;
}
.content-preview .normal {
margin: 0 3px;
text-transform: none;
}
.content-preview .content-preview-content {
padding: 5%;
word-break: break-word;
@ -236,15 +223,15 @@
}
.content-preview .post-controls {
position: relative;
top: 3px;
float: right;
position: absolute;
top: 25px;
right: 25px;
}
.content-preview .post-settings-menu {
position: absolute;
top: 35px;
right: -3px;
.content-preview .post-controls .btn {
padding-right: 0;
border: none;
font-size: 18px;
}
.content-preview img {
@ -252,10 +239,6 @@
height: auto;
}
.post-preview-header {
display: block;
justify-content: space-between;
}
/* Empty State
/* ---------------------------------------------------------- */

View file

@ -5,27 +5,23 @@
/* Title
/* ---------------------------------------------------------- */
.editor .entry-title {
position: relative;
padding: 0;
height: 60px;
.gh-editor-title {
flex-grow: 1;
}
.editor .entry-title input {
.gh-editor-title input {
margin: 0;
padding: 0;
width: 100%;
height: 60px;
border: 0;
background: transparent;
color: var(--darkgrey);
text-indent: 20px;
letter-spacing: -1px;
font-size: 3.2rem;
font-size: 2.6rem;
font-weight: bold;
}
.editor .entry-title input:focus {
.gh-editor-title input:focus {
outline: 0;
}
@ -33,127 +29,54 @@
/* Container & Headers
/* ---------------------------------------------------------- */
@media (min-width: 401px) {
.editor .notifications.bottom {
bottom: 40px;
}
}
.editor .entry-markdown {
left: 0;
.view-editor {
display: flex;
}
.editor .entry-preview {
right: 0;
border-left: #e1e1e1 1px solid;
}
.editor .entry-markdown,
.editor .entry-preview {
position: absolute;
top: 60px;
bottom: 40px;
padding: 15px;
position: relative; /*TODO: Remove*/
display: flex;
flex-direction: column;
width: 50%;
}
/* Content areas at the top, and fill available space */
.editor .entry-markdown-content,
.editor .entry-preview-content {
order: 1;
flex-grow: 1;
}
/* Headers at the bottom, and fixed height */
.editor .floatingheader {
order: 2;
flex-shrink: 0;
display: flex;
justify-content: space-between;
align-items: center;
padding: 5px 15px;
height: 40px;
border-top: #e1e1e1 1px solid;
background: #fff;
/* Hide markdown icon + wordcount when we hit mobile */
/* Give the tab with the .active class the highest z-index */
/* Restore the normal height of the .active tab (inactive tab stays small, hidden behind) */
/* Restore the white bg of the currently .active tab, remove hand cursor from currently active tab */
}
@media (max-width: 400px) {
.editor .entry-markdown .markdown-help,
.editor .entry-markdown .entry-word-count,
.editor .entry-preview .markdown-help,
.editor .entry-preview .entry-word-count {
display: none;
}
color: var(--midgrey);
font-size: 1.2rem;
line-height: 1em;
}
.editor .floatingheader a {
color: var(--midgrey);
}
/* Switch to 1 col editor on small screens */
@media (max-width: 1000px) {
.editor .entry-markdown,
.editor .entry-preview {
/* Convert all content areas to small boxes */
top: 100px;
right: 0;
left: 0;
z-index: 100;
.editor .entry-markdown {
width: 100%;
border: none;
/* Correctly colour the markdown icon when inactive and hovered */
}
.editor .entry-markdown .markdown,
.editor .entry-markdown .entry-preview-content,
.editor .entry-preview .markdown,
.editor .entry-preview .entry-preview-content {
overflow: hidden;
height: 50px;
}
.editor .entry-markdown:not(.active) .markdown-help:hover:before,
.editor .entry-preview:not(.active) .markdown-help:hover:before {
color: #fff;
}
}
.editor .entry-markdown .floatingheader a,
.editor .entry-preview .floatingheader a {
color: var(--brown);
}
@media (max-width: 1000px) {
.editor .entry-markdown .floatingheader,
.editor .entry-preview .floatingheader {
position: absolute;
top: -40px;
left: 0;
width: 50%;
background: var(--brown);
box-shadow: rgba(0, 0, 0, 0.1) 0 -2px 3px inset;
color: #fff;
font-weight: normal;
cursor: pointer;
}
.editor .entry-markdown .floatingheader a,
.editor .entry-preview .floatingheader a {
color: #fff;
}
}
.editor .entry-markdown .floatingheader .entry-word-count,
.editor .entry-preview .floatingheader .entry-word-count {
position: relative;
top: 2px;
float: right;
}
.editor .entry-markdown.active,
.editor .entry-preview.active {
z-index: 200;
}
.editor .entry-markdown.active .markdown,
.editor .entry-markdown.active .entry-preview-content,
.editor .entry-preview.active .markdown,
.editor .entry-preview.active .entry-preview-content {
overflow: auto;
-webkit-overflow-scrolling: touch;
height: auto;
}
@media (max-width: 1000px) {
.editor .entry-markdown.active header,
.editor .entry-preview.active header {
border-top: #e1e1e1 1px solid;
background: #fff;
box-shadow: none;
color: var(--brown);
cursor: auto;
}
.editor .entry-markdown.active header a,
.editor .entry-preview.active header a {
color: var(--brown);
.editor .entry-preview {
display: none;
}
}
@ -162,14 +85,12 @@
/* ---------------------------------------------------------- */
.editor .entry-markdown-content {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
position: relative;
flex-grow: 1;
}
.editor .markdown-editor {
/* Legacy absolute positioning */
position: absolute;
top: 0;
right: 0;
@ -177,6 +98,7 @@
left: 0;
overflow: auto;
-webkit-overflow-scrolling: touch;
padding: 21px 20px 36px 20px;
max-width: 100%;
height: 100%;
border: 0;
@ -197,68 +119,6 @@
}
}
@media (min-width: 451px) and (max-width: 1000px) {
.editor .markdown-editor {
padding: 20px;
}
}
@media (min-width: 1001px) {
.editor .markdown-editor {
padding: 42px 20px 36px 20px;
}
}
@media (max-width: 1000px) {
.editor .entry-preview .floatingheader {
/* Align the tab of entry-preview on the right */
right: 0;
left: auto;
border-right: none;
}
}
.editor .entry-preview-content {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
overflow: auto;
-webkit-overflow-scrolling: touch;
padding: 40px 20px 37px 20px;
word-break: break-word;
hyphens: auto;
cursor: default;
}
@media (max-width: 400px) {
.editor .entry-preview-content {
padding: 15px;
}
}
@media (max-width: 1000px) {
.editor .scrolling .floatingheader {
box-shadow: none;
}
.editor .scrolling .floatingheader:before,
.editor .scrolling .floatingheader:after {
display: none;
}
}
@media (max-width: 1000px) and (max-width: 1000px) {
.editor .entry-preview-content {
box-shadow: 0 5px 5px rgba(0, 0, 0, 0.05) inset;
}
}
.markdown-help {
float: right;
padding: 5px;
}
/* FFF: Fucking Firefox Fixes
/* ---------------------------------------------------------- */
@ -276,6 +136,16 @@
/* Preview (Right pane)
/* ---------------------------------------------------------- */
.editor .entry-preview-content {
flex-grow: 1;
overflow: auto;
-webkit-overflow-scrolling: touch;
padding: 19px 20px 37px 20px;
word-break: break-word;
hyphens: auto;
cursor: default;
}
/* The styles for the actual content inside the preview */
.entry-preview-content,
.content-preview-content {
@ -350,72 +220,9 @@
}
/* Zen Mode
/* ---------------------------------------------------------- */
body.zen {
background: color(#e1e1e1 lightness(+3%));
}
body.zen .usermenu {
display: none;
}
body.zen .global-nav,
body.zen .page-header,
body.zen #publish-bar {
overflow: hidden;
height: 0;
opacity: 0;
transition: all 0.5s ease-out;
}
body.zen .page-content {
top: 0;
transition: all 0.5s ease-out;
}
body.zen .entry-markdown,
body.zen .entry-preview {
bottom: 0;
transition: all 0.5s ease-out;
}
/* Publish Bar
/* ---------------------------------------------------------- */
#publish-bar {
position: absolute;
right: 0;
bottom: 0;
left: 0;
z-index: 900;
padding: 0;
height: 40px;
border-top: #e1e1e1 1px solid;
background: #fff;
color: var(--midgrey);
transform: translateZ(0);
}
@media (max-width: 1000px) {
#publish-bar {
font-weight: normal;
}
}
#publish-bar .post-settings:hover,
#publish-bar .post-settings.active {
color: var(--darkgrey);
}
#publish-bar .post-settings-menu {
position: absolute;
right: -3px;
bottom: 41px;
}
.extended-tags {
/* When the tag bar is expanded */
position: static;
@ -502,23 +309,21 @@ body.zen .entry-preview {
#entry-actions {
position: relative;
flex-shrink: 0;
display: flex;
justify-content: flex-end;
align-items: center;
align-content: center;
margin-right: 6px;
}
#entry-actions .dropdown {
position: absolute;
top: 35px;
right: 0;
bottom: 49px;
}
#entry-actions .dropdown .dropdown-menu {
top: auto;
right: 100%;
bottom: 100%;
left: auto;
}
@ -617,7 +422,7 @@ body.zen .entry-preview {
.post-settings {
position: relative;
display: inline-block;
padding: 8px 10px;
padding: 5px 10px;
color: var(--midgrey);
transition: all 0.15s ease-out 0s;
}
@ -627,6 +432,13 @@ body.zen .entry-preview {
color: var(--darkgrey);
}
.post-settings i {
width: 16px;
height: 16px;
font-size: 16px;
line-height: 16px;
}
.post-settings-menu .dropdown-menu {
top: auto;
right: 100%;
@ -680,9 +492,17 @@ body.zen .entry-preview {
}
/* Markdown Help Modal
/* Markdown Help Icon + Modal
/* ---------------------------------------------------------- */
.markdown-help {
font-size: 16px;
}
.markdown-help:hover {
cursor: help;
}
.modal-markdown-help-table {
margin: 0 0 20px;
width: 100%;

View file

@ -190,7 +190,8 @@
padding: 12px;
color: var(--midgrey);
text-align: center;
font-size: 1.3rem;
text-transform: uppercase;
font-size: 1rem;
line-height: 1;
font-weight: 200;
}
@ -356,8 +357,18 @@
font-size: 1.4rem;
}
.view-actions {
flex-shrink: 0;
display: flex;
}
.view-actions .btn {
margin-left: 8px;
}
.view-container,
.view-content {
position: relative;
flex-grow: 1;
overflow-x: hidden;
overflow-y: auto;

View file

@ -5,86 +5,3 @@
/* Animations
/* ---------------------------------------------------------- */
/* Semi-opaque fixed-position headers - used on content/editor */
.floatingheader {
position: absolute;
top: 0;
right: 0;
left: 0;
z-index: 400;
padding: 10px 20px;
height: 40px;
background: linear-gradient(to bottom, white 0%, white 25%, rgba(255, 255, 255, 0.9) 100%);
color: var(--brown);
text-transform: uppercase;
font-size: 1.3rem;
/*Transparent gradient to make bg fade out as it goes out the top */
}
.floatingheader .button {
display: inline-block;
padding: 3px 4px;
min-height: 20px;
height: 20px;
vertical-align: top;
font-size: 10px;
}
.floatingheader .button.button-back {
position: relative;
top: -2px;
left: 3px;
display: none;
padding: 0 6px 0 3px;
}
.floatingheader .button.button-back:active {
box-shadow: none;
}
.floatingheader .button.button-back:before {
left: -8px;
border-width: 10px 8px 10px 0;
}
@media (max-width: 900px) {
.floatingheader .button.button-back {
display: inline-block;
}
}
.floatingheader small {
font-size: 0.85em;
}
.floatingheader a,
.floatingheader button {
color: var(--brown);
}
.floatingheader a:hover,
.floatingheader button:hover {
color: var(--darkgrey);
}
/* Scroll shadows
/* ---------------------------------------------------------- */
.scrolling .floatingheader {
box-shadow: rgba(0, 0, 0, 0.03) 0 1px 3px;
}
.scrolling .floatingheader:before {
content: "";
position: absolute;
bottom: -5px;
left: 50%;
z-index: -1;
margin-left: -40%;
width: 80%;
height: 5px;
background-image: radial-gradient(ellipse at center, rgba(0, 0, 0, 0.05) 0%, transparent 75%, transparent 100%);
background-position: 0 -5px;
background-size: 100% 200%;
}

View file

@ -3,7 +3,9 @@
/* Base button style */
.btn {
display: inline-block;
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 0;
padding: 9px 15px;
border: #e1e1e1 1px solid;

View file

@ -264,6 +264,10 @@ button {
box-shadow: none;
}
i {
display: block;
}
img {
max-width: 100%;
}

View file

@ -40,7 +40,7 @@
</section>
<footer class="gh-nav-footer">
{{gh-autonav-toggle onClick="toggleMaximise"}}
<a class="gh-nav-footer-sitelink" href="{{config.blogUrl}}/" target="_blank">View blog <i class="icon-external"></i></a>
<a class="gh-nav-footer-sitelink" href="{{config.blogUrl}}/" target="_blank">View blog</a>
<div class="gh-help-menu">
{{#gh-dropdown-button dropdownName="help-menu" tagName="div"}}
<div class="gh-help-button">

View file

@ -1,14 +1,19 @@
<div class="page-content">
<header>
<section class="box entry-title">
{{gh-trim-focus-input type="text" id="entry-title" class="gh-input" placeholder="Your Post Title" value=model.titleScratch
tabindex="1" focus=shouldFocusTitle}}
</section>
</header>
<header class="view-header">
<h2 class="view-title gh-editor-title">{{gh-trim-focus-input type="text" id="entry-title" class="gh-input" placeholder="Your Post Title" value=model.titleScratch
tabindex="1" focus=shouldFocusTitle}}</h2>
<section class="view-actions">
<button type="button" class="post-settings" {{action "toggleSettingsMenu"}}>
<i class="icon-settings"></i>
</button>
{{view "editor-save-button" id="entry-actions" classNameBindings="model.isNew:unsaved"}}
</section>
</header>
<section class="entry-markdown js-entry-markdown {{unless isPreview 'active'}}">
<section class="view-container view-editor">
<section class="entry-markdown js-entry-markdown">
<header {{action "togglePreview" false}} class="floatingheader">
<small>Markdown</small>
<span>Markdown</span>
<a class="markdown-help" href="" {{action "openModal" "markdown"}}><i class="icon-markdown"></i></a>
</header>
<section id="entry-markdown-content" class="entry-markdown-content">
@ -17,9 +22,10 @@
</section>
</section>
<section class="entry-preview js-entry-preview {{if isPreview 'active'}}">
<section class="entry-preview js-entry-preview">
<header {{action "togglePreview" true}} class="floatingheader">
<small>Preview <span class="entry-word-count js-entry-word-count">{{gh-count-words model.scratch}}</span></small>
<span>Preview</span>
<span class="entry-word-count js-entry-word-count">{{gh-count-words model.scratch}}</span>
</header>
<section class="entry-preview-content js-entry-preview-content">
{{gh-ed-preview classNames="rendered-markdown js-rendered-markdown"
@ -28,6 +34,4 @@
</section>
</section>
{{partial "publish-bar"}}
</div>
</section>

View file

@ -4,70 +4,70 @@
<table class="modal-markdown-help-table">
<thead>
<tr>
<th>Result</th>
<th>Markdown</th>
<th>Result</th>
<th>Shortcut</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Bold</strong></td>
<td>**text**</td>
<td><strong>Bold</strong></td>
<td>Ctrl/⌘ + B </td>
</tr>
<tr>
<td><em>Emphasize</em></td>
<td>*text*</td>
<td><em>Emphasize</em></td>
<td>Ctrl/⌘ + I</td>
</tr>
<tr>
<td><del>Strike-through</del></td>
<td>~~text~~</td>
<td><del>Strike-through</del></td>
<td>Ctrl + Alt + U</td>
</tr>
<tr>
<td><a href="#">Link</a></td>
<td>[title](http://)</td>
<td><a href="#">Link</a></td>
<td>Ctrl/⌘ + K</td>
</tr>
<tr>
<td><code>Inline Code</code></td>
<td>`code`</td>
<td><code>Inline Code</code></td>
<td>Ctrl/⌘ + Shift + K</td>
</tr>
<tr>
<td>Image</td>
<td>![alt](http://)</td>
<td>Image</td>
<td>Ctrl/⌘ + Shift + I</td>
</tr>
<tr>
<td>List</td>
<td>* item</td>
<td>List</td>
<td>Ctrl + L</td>
</tr>
<tr>
<td>Blockquote</td>
<td>> quote</td>
<td>Blockquote</td>
<td>Ctrl + Q</td>
</tr>
<tr>
<td><mark>Highlight</mark></td>
<td>==Highlight==</td>
<td><mark>Highlight</mark></td>
<td></td>
</tr>
<tr>
<td>H1</td>
<td># Heading</td>
<td>H1</td>
<td></td>
</tr>
<tr>
<td>H2</td>
<td>## Heading</td>
<td>H2</td>
<td>Ctrl/⌘ + H</td>
</tr>
<tr>
<td>H3</td>
<td>### Heading</td>
<td>H3</td>
<td>Ctrl/⌘ + H (x2)</td>
</tr>
</tbody>

View file

@ -1,4 +1,11 @@
<div class="page-content">
<header class="view-header">
<h2 class="view-title">Content</h2>
<section class="view-actions">
{{#link-to "editor.new" class="btn btn-green" title="New Post"}}New Post{{/link-to}}
</section>
</header>
<div class="view-container">
<section class="content-list js-content-list {{if postListFocused 'keyboard-focused'}}">
{{#view "paginated-scroll-box" tagName="section" classNames="content-list-content js-content-scrollbox"}}
<ol class="posts-list">

View file

@ -1,26 +1,10 @@
<header class="post-preview-header clearfix">
<button type="button" class="{{if model.featured 'featured icon-star' 'unfeatured icon-star'}}" title="Feature this post" {{action "toggleFeatured"}}>
<span class="sr-only">Star</span>
</button>
<small class="post-published-by">
<span class="status">
{{#if isPublished}}
<a title="{{model.title}}" href="{{model.absoluteUrl}}">Published</a>
{{else}}
Written
{{/if}}
</span>
<span class="normal">by</span>
<span class="author">{{#if model.author.name}}{{model.author.name}}{{else}}{{model.author.email}}{{/if}}</span>
</small>
<section class="post-controls">
{{#link-to "editor.edit" model class="btn btn-default post-edit"}}<i class="icon-edit"></i> Edit{{/link-to}}
</section>
</header>
<section class="post-controls">
{{#link-to "editor.edit" model class="btn btn-minor post-edit"}}<i class="icon-edit"></i>{{/link-to}}
</section>
{{#view "content-preview-content-view" tagName="section"}}
<div class="wrapper">
<h1>{{model.title}}</h1>
<h1 class="content-preview-title">{{#link-to "editor.edit" model}}{{model.title}}{{/link-to}}</h1>
{{gh-format-html model.html}}
</div>
{{/view}}