mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-10 23:36:14 -05:00
Merge pull request #722 from ericterpstra/370-post-settings-permalink
Added post-settings menu with edit permalink field
This commit is contained in:
commit
486b2406b1
11 changed files with 235 additions and 58 deletions
|
@ -521,7 +521,15 @@ body.zen {
|
|||
|
||||
}
|
||||
|
||||
#entry-settings {
|
||||
#entry-controls {
|
||||
@include box-sizing(border-box);
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
padding: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.entry-settings {
|
||||
@include icon($i-settings, 1.1em){vertical-align: 0;};
|
||||
@include box-sizing(border-box);
|
||||
display: inline-block;
|
||||
|
@ -535,9 +543,9 @@ body.zen {
|
|||
}
|
||||
}
|
||||
|
||||
#entry-settings-menu {
|
||||
.entry-settings-menu {
|
||||
position: absolute;
|
||||
bottom: 50px;
|
||||
bottom: 40px;
|
||||
right: -5px;
|
||||
}
|
||||
|
||||
|
|
|
@ -232,7 +232,7 @@
|
|||
ul {
|
||||
position: absolute;
|
||||
top:15px;
|
||||
right:-15px;
|
||||
right:-10px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -241,11 +241,6 @@
|
|||
margin-right:7px;
|
||||
padding: 5px;
|
||||
}
|
||||
.post-settings {
|
||||
@include icon($i-settings, 14px);
|
||||
padding: 5px;
|
||||
margin-right: -5px;
|
||||
}
|
||||
|
||||
img {
|
||||
width:100%;
|
||||
|
|
|
@ -831,6 +831,59 @@ nav {
|
|||
@extend %menu-right;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Post Settings
|
||||
========================================================================== */
|
||||
|
||||
.post-setting {
|
||||
min-width: 260px;
|
||||
border-bottom: 1px solid #35393b;
|
||||
|
||||
&:first-child {
|
||||
margin-top: -6px;
|
||||
}
|
||||
|
||||
input {
|
||||
width: 100%;
|
||||
background: none;
|
||||
border: none;
|
||||
color: #e2edf2;
|
||||
line-height: 1.68em;
|
||||
}
|
||||
}
|
||||
|
||||
.post-setting-label {
|
||||
float: left;
|
||||
width: 26%;
|
||||
text-align: right;
|
||||
padding: 10px 2%;
|
||||
border-right: 1px solid #35393b;
|
||||
}
|
||||
|
||||
.post-setting-field {
|
||||
float: left;
|
||||
width: 64%;
|
||||
padding: 8px 2%;
|
||||
|
||||
input:focus {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
.post-settings {
|
||||
@include icon($i-settings, 14px);
|
||||
padding: 5px;
|
||||
/* margin-right: -5px;*/
|
||||
}
|
||||
|
||||
.post-setting-calendar {
|
||||
@include icon-after($i-calendar, 18px);
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
position: absolute;
|
||||
margin-top: -25px; /* This doesn't work in FF */
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Notifications
|
||||
|
|
|
@ -10,6 +10,22 @@
|
|||
<a class="post-edit" href="#"><span class="hidden">Edit Post</span></a>
|
||||
<a class="post-settings" href="#" data-toggle=".menu-drop-right"><span class="hidden">Post Settings</span></a>
|
||||
<ul class="menu-drop-right overlay">
|
||||
<li class="post-setting">
|
||||
<div class="post-setting-label">
|
||||
<label for="url">URL</label>
|
||||
</div>
|
||||
<div class="post-setting-field">
|
||||
<input class="post-setting-slug" type="text" value="{{{slug}}}">
|
||||
</div>
|
||||
</li>
|
||||
<!--<li class="post-setting">
|
||||
<div class="post-setting-label">
|
||||
<label for="url">Pub Date</label>
|
||||
</div>
|
||||
<div class="post-setting-field">
|
||||
<input class="post-setting-date" type="text" value=""><span class="post-setting-calendar"></span>
|
||||
</div>
|
||||
</li>-->
|
||||
<li><a href="#" class="delete">Delete</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
|
|
@ -114,7 +114,6 @@
|
|||
activeId: null,
|
||||
|
||||
events: {
|
||||
'click .post-controls .delete' : 'deletePost',
|
||||
'click .post-controls .post-edit' : 'editPost'
|
||||
},
|
||||
|
||||
|
@ -129,53 +128,6 @@
|
|||
}
|
||||
},
|
||||
|
||||
deletePost: function (e) {
|
||||
e.preventDefault();
|
||||
var self = this;
|
||||
this.addSubview(new Ghost.Views.Modal({
|
||||
model: {
|
||||
options: {
|
||||
close: false,
|
||||
confirm: {
|
||||
accept: {
|
||||
func: function () {
|
||||
self.model.destroy({
|
||||
wait: true
|
||||
}).then(function () {
|
||||
Ghost.notifications.addItem({
|
||||
type: 'success',
|
||||
message: 'Your post has been deleted.',
|
||||
status: 'passive'
|
||||
});
|
||||
}, function () {
|
||||
Ghost.notifications.addItem({
|
||||
type: 'error',
|
||||
message: 'Your post could not be deleted. Please try again.',
|
||||
status: 'passive'
|
||||
});
|
||||
});
|
||||
},
|
||||
text: "Yes"
|
||||
},
|
||||
reject: {
|
||||
func: function () {
|
||||
return true;
|
||||
},
|
||||
text: "No"
|
||||
}
|
||||
},
|
||||
type: "action",
|
||||
style: ["wide", "centered"],
|
||||
animation: 'fade'
|
||||
},
|
||||
content: {
|
||||
template: 'blank',
|
||||
title: 'Are you sure you want to delete this post?'
|
||||
}
|
||||
}
|
||||
}));
|
||||
},
|
||||
|
||||
editPost: function (e) {
|
||||
e.preventDefault();
|
||||
// for now this will disable "open in new tab", but when we have a Router implemented
|
||||
|
@ -194,6 +146,11 @@
|
|||
this.$('.wrapper').on('click', 'a', function (e) {
|
||||
$(e.currentTarget).attr('target', '_blank');
|
||||
});
|
||||
|
||||
if (this.model !== 'undefined') {
|
||||
this.addSubview(new Ghost.View.PostSettings({el: $('.post-controls'), model: this.model})).render();
|
||||
}
|
||||
|
||||
Ghost.temporary.initToggles(this.$el);
|
||||
return this;
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
initialize: function () {
|
||||
this.addSubview(new Ghost.View.EditorTagWidget({el: this.$('#entry-tags'), model: this.model})).render();
|
||||
this.addSubview(new ActionsWidget({el: this.$('#entry-actions'), model: this.model})).render();
|
||||
this.addSubview(new Ghost.View.PostSettings({el: $('#entry-controls'), model: this.model})).render();
|
||||
},
|
||||
|
||||
render: function () { return this; }
|
||||
|
|
113
core/client/views/post-settings.js
Normal file
113
core/client/views/post-settings.js
Normal file
|
@ -0,0 +1,113 @@
|
|||
// The Post Settings Menu available in the content preview screen, as well as the post editor.
|
||||
|
||||
/*global window, document, $, _, Backbone, Ghost */
|
||||
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
Ghost.View.PostSettings = Ghost.View.extend({
|
||||
|
||||
events: {
|
||||
'blur .post-setting-slug' : 'editSlug',
|
||||
'click .post-setting-slug' : 'selectSlug',
|
||||
'click .delete' : 'deletePost'
|
||||
},
|
||||
|
||||
render: function () {
|
||||
var slug = this.model ? this.model.get('slug') : '';
|
||||
//var pubDate = this.model.get('published_at');
|
||||
|
||||
//pubDate = moment(pubDate).format('DD MMM YY');
|
||||
|
||||
$('.post-setting-slug').val(slug);
|
||||
//$('.post-setting-date').val(pubDate);
|
||||
},
|
||||
|
||||
selectSlug: function (e) {
|
||||
e.currentTarget.select();
|
||||
},
|
||||
|
||||
editSlug: function (e) {
|
||||
e.preventDefault();
|
||||
var self = this,
|
||||
slug = self.model.get('slug'),
|
||||
slugEl = e.currentTarget,
|
||||
newSlug = slugEl.value;
|
||||
|
||||
// Ignore empty or unchanged slugs
|
||||
if (newSlug.length === 0 || slug === newSlug) {
|
||||
slugEl.value = slug === undefined ? '' : slug;
|
||||
return;
|
||||
}
|
||||
|
||||
this.model.save({
|
||||
slug: newSlug
|
||||
}, {
|
||||
success : function (model, response, options) {
|
||||
// Repopulate slug in case it changed on the server (e.g. 'new-slug-2')
|
||||
slugEl.value = model.get('slug');
|
||||
},
|
||||
error : function (model, xhr) {
|
||||
Ghost.notifications.addItem({
|
||||
type: 'error',
|
||||
message: Ghost.Views.Utils.getRequestErrorMessage(xhr),
|
||||
status: 'passive'
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
deletePost: function (e) {
|
||||
e.preventDefault();
|
||||
var self = this;
|
||||
this.addSubview(new Ghost.Views.Modal({
|
||||
model: {
|
||||
options: {
|
||||
close: false,
|
||||
confirm: {
|
||||
accept: {
|
||||
func: function () {
|
||||
self.model.destroy({
|
||||
wait: true
|
||||
}).then(function () {
|
||||
// Redirect to content screen if deleting post from editor.
|
||||
if (window.location.pathname.indexOf('editor') > -1) {
|
||||
window.location = '/ghost/content/';
|
||||
}
|
||||
Ghost.notifications.addItem({
|
||||
type: 'success',
|
||||
message: 'Your post has been deleted.',
|
||||
status: 'passive'
|
||||
});
|
||||
}, function () {
|
||||
Ghost.notifications.addItem({
|
||||
type: 'error',
|
||||
message: 'Your post could not be deleted. Please try again.',
|
||||
status: 'passive'
|
||||
});
|
||||
});
|
||||
},
|
||||
text: "Yes"
|
||||
},
|
||||
reject: {
|
||||
func: function () {
|
||||
return true;
|
||||
},
|
||||
text: "No"
|
||||
}
|
||||
},
|
||||
type: "action",
|
||||
style: ["wide", "centered"],
|
||||
animation: 'fade'
|
||||
},
|
||||
content: {
|
||||
template: 'blank',
|
||||
title: 'Are you sure you want to delete this post?'
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}());
|
|
@ -47,6 +47,7 @@ Post = GhostBookshelf.Model.extend({
|
|||
|
||||
saving: function () {
|
||||
// Deal with the related data here
|
||||
var self = this;
|
||||
|
||||
// Remove any properties which don't belong on the post model
|
||||
this.attributes = this.pick(this.permittedAttributes);
|
||||
|
@ -55,6 +56,14 @@ Post = GhostBookshelf.Model.extend({
|
|||
|
||||
this.set('title', this.get('title').trim());
|
||||
|
||||
if (this.hasChanged('slug')) {
|
||||
// Pass the new slug through the generator to strip illegal characters, detect duplicates
|
||||
return this.generateSlug(this.get('slug'))
|
||||
.then(function (slug) {
|
||||
self.set({slug: slug});
|
||||
});
|
||||
}
|
||||
|
||||
if (this.hasChanged('status') && this.get('status') === 'published') {
|
||||
this.set('published_at', new Date());
|
||||
// This will need to go elsewhere in the API layer.
|
||||
|
|
|
@ -84,6 +84,7 @@
|
|||
<!-- // require '/public/views/*' -->
|
||||
<script src="/public/views/base.js"></script>
|
||||
<script src="/public/models/uploadModal.js"></script>
|
||||
<script src="/public/views/post-settings.js"></script>
|
||||
<script src="/public/views/blog.js"></script>
|
||||
<script src="/public/views/editor.js"></script>
|
||||
<script src="/public/views/editor-tag-widget.js"></script>
|
||||
|
|
|
@ -40,6 +40,30 @@
|
|||
<ul class="suggestions overlay"></ul>
|
||||
</section>
|
||||
<div class="right">
|
||||
|
||||
<section id="entry-controls">
|
||||
<a class="entry-settings" href="#" data-toggle=".menu-right"><span class="hidden">Post Settings</span></a>
|
||||
<ul class="entry-settings-menu menu-right overlay">
|
||||
<li class="post-setting">
|
||||
<div class="post-setting-label">
|
||||
<label for="url">URL</label>
|
||||
</div>
|
||||
<div class="post-setting-field">
|
||||
<input class="post-setting-slug" type="text" value="" />
|
||||
</div>
|
||||
</li>
|
||||
<!--<li class="post-setting">
|
||||
<div class="post-setting-label">
|
||||
<label for="url">Pub Date</label>
|
||||
</div>
|
||||
<div class="post-setting-field">
|
||||
<input class="post-setting-date" type="text" value=""><span class="post-setting-calendar"></span>
|
||||
</div>
|
||||
</li>-->
|
||||
<li><a href="#" class="delete">Delete</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section id="entry-actions" class="splitbutton-save">
|
||||
<button type="button" class="button-save js-post-button"></button>
|
||||
<a class="options up" data-toggle="ul" href="#"><span class="hidden">Options</span></a>
|
||||
|
|
|
@ -100,7 +100,7 @@ describe('Admin Controller', function() {
|
|||
});
|
||||
|
||||
it('should send correct path to image when today is in Jan 2014', function(done) {
|
||||
clock = sinon.useFakeTimers(1388534400000); // Wed Jan 01 2014 00:00:00 GMT+0000 (GMT)
|
||||
clock = sinon.useFakeTimers(1388707200000); // Wed Jan 03 2014 00:00:00 GMT+0000 (GMT)
|
||||
sinon.stub(res, 'send', function(data) {
|
||||
data.should.equal('/content/images/2014/Jan/IMAGE.jpg');
|
||||
return done();
|
||||
|
|
Loading…
Add table
Reference in a new issue