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

Adds modal Image uploader on settings page

issue #432

adds a modal template for image uploads
adds buttons to settings page to upload images for blog logo and icon
once image is uploaded displays an 'X' to reset back to dropzone
saves image and renders settings page.

ToDo

add url field when clicking on url icon

fix position of 'X' for both settings and editor
This commit is contained in:
cobbspur 2013-09-04 18:42:01 +01:00
parent 362cd425cc
commit e61f3684d5
6 changed files with 110 additions and 73 deletions

View file

@ -7,10 +7,7 @@
UploadUi = function ($dropzone, settings) { UploadUi = function ($dropzone, settings) {
var source, var source,
$link = $('<a class="js-edit-image image-edit" href="#" >' + $cancel = '<a class="image-cancel js-cancel"><span class="hidden">Delete</span></a>',
'<img src="/public/assets/img/add-image.png" width="16" height="16" alt="add, edit"></a>'),
$back = $('<a class="js-return-image image-edit" href="#" >' +
'<img src="/public/assets/img/return-image.png" width="16" height="16" alt="add, edit"></a>'),
$progress = $('<div />', { $progress = $('<div />', {
"class" : "js-upload-progress progress progress-success active", "class" : "js-upload-progress progress progress-success active",
"role": "progressbar", "role": "progressbar",
@ -30,7 +27,6 @@
add: function (e, data) { add: function (e, data) {
$progress.find('.js-upload-progress-bar').removeClass('fail'); $progress.find('.js-upload-progress-bar').removeClass('fail');
$dropzone.trigger('uploadstart'); $dropzone.trigger('uploadstart');
$dropzone.find('a.js-return-image').remove();
$dropzone.find('span.media, div.description, a.image-url, a.image-webcam') $dropzone.find('span.media, div.description, a.image-url, a.image-webcam')
.animate({opacity: 0}, 250, function () { .animate({opacity: 0}, 250, function () {
$dropzone.find('div.description').hide().css({"opacity": 100}); $dropzone.find('div.description').hide().css({"opacity": 100});
@ -55,10 +51,6 @@
$dropzone.find('div.js-fail, button.js-fail').fadeIn(1500); $dropzone.find('div.js-fail, button.js-fail').fadeIn(1500);
$dropzone.find('button.js-fail').on('click', function () { $dropzone.find('button.js-fail').on('click', function () {
$dropzone.css({minHeight: 0}); $dropzone.css({minHeight: 0});
if (source !== undefined && !$dropzone.find('a.js-return-image')[0]) {
$back.css({"opacity": 100});
$dropzone.find('.js-upload-target').after($back);
}
$dropzone.find('div.description').show(); $dropzone.find('div.description').show();
self.removeExtras(); self.removeExtras();
self.init(); self.init();
@ -69,10 +61,6 @@
$dropzone.find('img.js-upload-target').attr({"width": width, "height": height}).css({"display": "block"}); $dropzone.find('img.js-upload-target').attr({"width": width, "height": height}).css({"display": "block"});
$dropzone.find('.fileupload-loading').removeClass('fileupload-loading'); $dropzone.find('.fileupload-loading').removeClass('fileupload-loading');
$dropzone.css({"height": "auto"}); $dropzone.css({"height": "auto"});
if (!$dropzone.find('a.js-edit-image')[0]) {
$link.css({"opacity": 100});
$dropzone.find('.js-upload-target').after($link);
}
$dropzone.delay(250).animate({opacity: 100}, 1000, function () { $dropzone.delay(250).animate({opacity: 100}, 1000, function () {
self.init(); self.init();
}); });
@ -128,7 +116,7 @@
}, },
removeExtras: function () { removeExtras: function () {
$dropzone.find('span.media, div.js-upload-progress, a.image-url, a.image-webcam, div.js-fail, button.js-fail').remove(); $dropzone.find('span.media, div.js-upload-progress, a.image-url, a.image-webcam, div.js-fail, button.js-fail, a.js-cancel').remove();
}, },
initWithDropzone: function () { initWithDropzone: function () {
@ -136,18 +124,8 @@
//This is the start point if no image exists //This is the start point if no image exists
$dropzone.find('img.js-upload-target').css({"display": "none"}); $dropzone.find('img.js-upload-target').css({"display": "none"});
$dropzone.removeClass('pre-image-uploader').addClass('image-uploader'); $dropzone.removeClass('pre-image-uploader').addClass('image-uploader');
this.removeExtras();
this.buildExtras(); this.buildExtras();
$dropzone.find('a.js-edit-image').remove();
$back.on('click', function () {
$dropzone.find('a.js-return-image').remove();
$dropzone.find('img.js-upload-target').attr({"src": source}).css({"display": "block"});
self.removeExtras();
$dropzone.removeClass('image-uploader').addClass('pre-image-uploader');
self.init();
});
this.bindFileUpload(); this.bindFileUpload();
}, },
@ -157,19 +135,11 @@
source = $dropzone.find('img.js-upload-target').attr('src'); source = $dropzone.find('img.js-upload-target').attr('src');
$dropzone.removeClass('image-uploader').addClass('pre-image-uploader'); $dropzone.removeClass('image-uploader').addClass('pre-image-uploader');
$dropzone.find('div.description').hide(); $dropzone.find('div.description').hide();
$dropzone.append($cancel);
if (!$dropzone.find('a.js-edit-image')[0]) { $dropzone.find('.js-cancel').on('click', function () {
$link.css({"opacity": 100}); $dropzone.find('img.js-upload-target').attr({'src': ''});
$dropzone.find('.js-upload-target').after($link);
}
$link.on('click', function () {
$dropzone.find('a.js-edit-image').remove();
$dropzone.find('img.js-upload-target').attr({"src": ""}).css({"display": "none"});
$back.css({"cursor": "pointer", "z-index": 9999, "opacity": 100});
$dropzone.find('.js-upload-target').after($back);
$dropzone.find('div.description').show(); $dropzone.find('div.description').show();
self.init(); self.initWithDropzone();
}); });
}, },

View file

@ -172,6 +172,10 @@
margin-left: 15px; margin-left: 15px;
} }
img {
max-width: 100%;
}
display: none; display: none;
&.active {display:block;} &.active {display:block;}

View file

@ -1015,13 +1015,12 @@ body.blur > *:not(#modal-container) {
} }
.modal-content { .modal-content {
padding: 20px; padding: 0 20px;
} }
.modal-footer { .modal-footer {
padding: 20px; padding: 20px;
padding-top: 0; padding-top: 0;
text-align: center;
} }
.modal-style-wide { .modal-style-wide {
@ -1176,17 +1175,6 @@ main {
padding-left:5px; padding-left:5px;
} }
.image-edit {
line-height: 12px;
padding: 10px;
display: block;
position: absolute;
top: 0;
left: 0;
opacity: 0;
text-decoration: none;
}
.image-webcam { .image-webcam {
@include icon($i-camera, 12px); @include icon($i-camera, 12px);
line-height: 12px; line-height: 12px;
@ -1251,7 +1239,7 @@ main {
@include box-sizing(border-box); @include box-sizing(border-box);
@include baseline; @include baseline;
position: relative; position: relative;
overflow:hidden; overflow: hidden;
height: auto; height: auto;
color: $brown; color: $brown;
@ -1260,16 +1248,31 @@ main {
left: 9999px; left: 9999px;
opacity: 0; opacity: 0;
} }
.image-edit { a {
z-index: 10000;
line-height: 12px; color: $brown;
padding: 10px;
display: block;
position: absolute;
top: 0;
left: 0;
opacity: 0;
text-decoration: none; text-decoration: none;
&:hover {
color: $darkgrey;
}
}
img {
max-width: 100%;
}
.image-cancel {
@include icon($i-x, 16px);
position: absolute;
color: white;
text-shadow: rgba(0,0,0,0.5) 0 0 1px;
top: 10px;
right: 10px;
text-decoration: none;
&:hover {
cursor: pointer;
color: white;
}
} }
} }

View file

@ -0,0 +1,4 @@
<section class="js-drop-zone">
<img id="{{options.val}}" class="js-upload-target" src="{{options.src}}"{{#unless options.src}} style="display: none"{{/unless}} alt="logo">
<input data-url="upload" class="js-fileupload" type="file" name="uploadimage">
</section>

View file

@ -15,19 +15,22 @@
<div class="form-group"> <div class="form-group">
<label><strong>Blog Logo</strong></label> <label><strong>Blog Logo</strong></label>
<section class="js-drop-zone"> {{#if logo}}
<img id="logo" class="js-upload-target" src="{{logo}}"{{#unless logo}} style="display: none"{{/unless}} alt="logo"> <a class="js-modal-logo"><img src="{{logo}}" alt="logo"></a>
<input data-url="upload" class="js-fileupload" type="file" name="uploadimage"> {{else}}
</section> <a class="button-add js-modal-logo" href="#">Upload Image</a>
{{/if}}
<p>Display a logo on your site in place of blog title</p> <p>Display a logo on your site in place of blog title</p>
</div> </div>
<div class="form-group"> <div class="form-group">
<label><strong>Blog Icon</strong></label> <label><strong>Blog Icon</strong></label>
<section class="js-drop-zone"> {{#if icon}}
<img id="icon" class="js-upload-target" src="{{icon}}"{{#unless icon}} style="display: none"{{/unless}} style="display: none" alt="icon"> <a class="js-modal-icon"><img src="{{icon}}" alt="icon"></a>
<input data-url="upload" class="js-fileupload" type="file" name="uploadimage"> {{else}}
</section> <a class="button-add js-modal-icon" href="#">Upload Image</a>
{{/if}}
<p>The icon for your blog, used in your browser tab and elsewhere</p> <p>The icon for your blog, used in your browser tab and elsewhere</p>
</div> </div>

View file

@ -151,7 +151,9 @@
id: "general", id: "general",
events: { events: {
'click .button-save': 'saveSettings' 'click .button-save': 'saveSettings',
'click .js-modal-logo': 'showLogo',
'click .js-modal-icon': 'showIcon'
}, },
saveSettings: function () { saveSettings: function () {
@ -169,7 +171,58 @@
}); });
this.model.set({availableThemes: themes}); this.model.set({availableThemes: themes});
}, },
showLogo: function () {
var settings = this.model.toJSON();
this.showUpload('#logo', 'logo', settings.logo);
},
showIcon: function () {
var settings = this.model.toJSON();
this.showUpload('#icon', 'icon', settings.icon);
},
showUpload: function (id, key, src) {
var self = this;
this.addSubview(new Ghost.Views.Modal({
model: {
options: {
close: false,
type: "action",
style: "wide",
animation: 'fadeIn',
afterRender: function () {
this.$('.js-drop-zone').upload();
},
confirm: {
accept: {
func: function () { // The function called on acceptance
var data = {};
data[key] = this.$('.js-upload-target').attr('src');
self.model.save(data, {
success: self.saveSuccess,
error: self.saveError
});
self.render();
return true;
},
buttonClass: "button-save right",
text: "Save" // The accept button text
},
reject: {
func: function () { // The function called on rejection
return true;
},
buttonClass: true,
text: "Cancel" // The reject button text
}
},
id: id,
src: src
},
content: {
template: 'uploadImage'
}
}
}));
},
templateName: 'settings/general', templateName: 'settings/general',
beforeRender: function () { beforeRender: function () {