mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-11-01 11:35:55 +01:00
fixed topic thumbs
This commit is contained in:
@@ -80,6 +80,13 @@
|
||||
"composer.submit": "Submit",
|
||||
"composer.replying_to": "Replying to",
|
||||
"composer.new_topic": "New Topic",
|
||||
|
||||
"composer.uploading": "uploading...",
|
||||
"composer.thumb_url_label": "Paste a topic thumbnail URL",
|
||||
"composer.thumb_title": "Add a thumbnail to this topic",
|
||||
"composer.thumb_url_placeholder": "http://example.com/thumb.png",
|
||||
"composer.thumb_file_label": "Or upload a file",
|
||||
"composer.thumb_remove": "Clear fields",
|
||||
"composer.drag_and_drop_images": "Drag and Drop Images Here",
|
||||
"composer.content_is_parsed_with": "Content is parsed with",
|
||||
"composer.upload_instructions": "Upload images by dragging & dropping them."
|
||||
|
||||
@@ -4,6 +4,11 @@ define(['taskbar'], function(taskbar) {
|
||||
posts: {}
|
||||
};
|
||||
|
||||
function resetInputFile($el) {
|
||||
$el.wrap('<form />').closest('form').get(0).reset();
|
||||
$el.unwrap();
|
||||
}
|
||||
|
||||
function allowed() {
|
||||
if(!(parseInt(app.uid, 10) > 0 || config.allowGuestPosting)) {
|
||||
app.alert({
|
||||
@@ -21,16 +26,265 @@ define(['taskbar'], function(taskbar) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function push(post) {
|
||||
var uuid = utils.generateUUID();
|
||||
|
||||
translator.translate('[[topic:composer.new_topic]]', function(newTopicStr) {
|
||||
taskbar.push('composer', uuid, {
|
||||
title: post.title ? post.title : newTopicStr,
|
||||
icon: post.picture
|
||||
});
|
||||
});
|
||||
|
||||
composer.posts[uuid] = post;
|
||||
composer.posts[uuid].uploadsInProgress = [];
|
||||
|
||||
composer.load(uuid);
|
||||
}
|
||||
|
||||
//http://stackoverflow.com/questions/14441456/how-to-detect-which-device-view-youre-on-using-twitter-bootstrap-api
|
||||
function findBootstrapEnvironment() {
|
||||
var envs = ['xs', 'sm', 'md', 'lg'];
|
||||
|
||||
$el = $('<div>');
|
||||
$el.appendTo($('body'));
|
||||
|
||||
for (var i = envs.length - 1; i >= 0; i--) {
|
||||
var env = envs[i];
|
||||
|
||||
$el.addClass('hidden-'+env);
|
||||
if ($el.is(':hidden')) {
|
||||
$el.remove();
|
||||
return env;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function composerAlert(title, message) {
|
||||
$('.action-bar button').removeAttr('disabled');
|
||||
app.alert({
|
||||
type: 'danger',
|
||||
timeout: 2000,
|
||||
title: title,
|
||||
message: message,
|
||||
alert_id: 'post_error'
|
||||
});
|
||||
}
|
||||
|
||||
function initializeDragAndDrop(post_uuid) {
|
||||
|
||||
if(jQuery.event.props.indexOf('dataTransfer') === -1) {
|
||||
jQuery.event.props.push('dataTransfer');
|
||||
}
|
||||
|
||||
var draggingDocument = false;
|
||||
|
||||
var postContainer = $('#cmp-uuid-' + post_uuid),
|
||||
fileForm = postContainer.find('#fileForm'),
|
||||
drop = postContainer.find('.imagedrop'),
|
||||
tabContent = postContainer.find('.tab-content'),
|
||||
textarea = postContainer.find('textarea');
|
||||
|
||||
$(document).off('dragstart').on('dragstart', function(e) {
|
||||
draggingDocument = true;
|
||||
}).off('dragend').on('dragend', function(e) {
|
||||
draggingDocument = false;
|
||||
});
|
||||
|
||||
textarea.on('dragenter', function(e) {
|
||||
if(draggingDocument) {
|
||||
return;
|
||||
}
|
||||
drop.css('top', tabContent.position().top + 'px');
|
||||
drop.css('height', textarea.height());
|
||||
drop.css('line-height', textarea.height() + 'px');
|
||||
drop.show();
|
||||
|
||||
drop.on('dragleave', function(ev) {
|
||||
drop.hide();
|
||||
drop.off('dragleave');
|
||||
});
|
||||
});
|
||||
|
||||
function cancel(e) {
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
|
||||
drop.on('dragover', cancel);
|
||||
drop.on('dragenter', cancel);
|
||||
|
||||
drop.on('drop', function(e) {
|
||||
e.preventDefault();
|
||||
var dt = e.dataTransfer,
|
||||
files = dt.files;
|
||||
|
||||
if(files.length) {
|
||||
var fd = new FormData();
|
||||
for (var i = 0, file; file = dt.files[i]; i++) {
|
||||
fd.append('files[]', file, file.name);
|
||||
}
|
||||
|
||||
fileForm[0].reset();
|
||||
uploadContentFiles({files: files, post_uuid: post_uuid, route: '/api/post/upload', formData: fd});
|
||||
}
|
||||
|
||||
drop.hide();
|
||||
return false;
|
||||
});
|
||||
|
||||
$(window).off('paste').on('paste', function(event) {
|
||||
|
||||
var items = (event.clipboardData || event.originalEvent.clipboardData).items;
|
||||
|
||||
if(items && items.length) {
|
||||
|
||||
var blob = items[0].getAsFile();
|
||||
if(blob) {
|
||||
blob.name = 'upload-'+ utils.generateUUID();
|
||||
|
||||
var fd = new FormData();
|
||||
fd.append('files[]', blob, blob.name);
|
||||
|
||||
fileForm[0].reset();
|
||||
uploadContentFiles({files: [blob], post_uuid: post_uuid, route: '/api/post/upload', formData: fd});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function uploadContentFiles(params) {
|
||||
var files = params.files,
|
||||
post_uuid = params.post_uuid,
|
||||
route = params.route,
|
||||
formData = params.formData,
|
||||
callback = params.callback,
|
||||
postContainer = $('#cmp-uuid-' + post_uuid),
|
||||
textarea = postContainer.find('textarea'),
|
||||
text = textarea.val(),
|
||||
uploadForm = postContainer.find('#fileForm');
|
||||
|
||||
uploadForm.attr('action', route);
|
||||
|
||||
for(var i = 0; i < files.length; ++i) {
|
||||
var isImage = files[i].type.match('image.*');
|
||||
text += (isImage ? '!' : '') + '[' + files[i].name + '](uploading...) ';
|
||||
|
||||
if(files[i].size > parseInt(config.maximumFileSize, 10) * 1024) {
|
||||
uploadForm[0].reset();
|
||||
return composerAlert('File too big', 'Maximum allowed file size is ' + config.maximumFileSize + 'kbs');
|
||||
}
|
||||
}
|
||||
|
||||
textarea.val(text);
|
||||
|
||||
uploadForm.off('submit').submit(function() {
|
||||
|
||||
$(this).find('#postUploadCsrf').val($('#csrf_token').val());
|
||||
if(formData) {
|
||||
formData.append('_csrf', $('#csrf_token').val());
|
||||
}
|
||||
|
||||
composer.posts[post_uuid].uploadsInProgress.push(1);
|
||||
|
||||
$(this).ajaxSubmit({
|
||||
resetForm: true,
|
||||
clearForm: true,
|
||||
formData: formData,
|
||||
error: function(xhr) {
|
||||
app.alertError('Error uploading file!\nStatus : ' + xhr.status + '\nMessage : ' + xhr.responseText);
|
||||
if (typeof callback == 'function')
|
||||
callback(xhr);
|
||||
},
|
||||
uploadProgress: function(event, position, total, percent) {
|
||||
var current = textarea.val();
|
||||
for(var i=0; i<files.length; ++i) {
|
||||
var re = new RegExp(files[i].name + "]\\([^)]+\\)", 'g');
|
||||
textarea.val(current.replace(re, files[i].name+'](uploading ' + percent + '%)'));
|
||||
}
|
||||
},
|
||||
success: function(uploads) {
|
||||
|
||||
if(uploads && uploads.length) {
|
||||
for(var i=0; i<uploads.length; ++i) {
|
||||
var current = textarea.val();
|
||||
var re = new RegExp(uploads[i].name + "]\\([^)]+\\)", 'g');
|
||||
textarea.val(current.replace(re, uploads[i].name + '](' + uploads[i].url + ')'));
|
||||
}
|
||||
}
|
||||
|
||||
textarea.focus();
|
||||
if (typeof callback == 'function')
|
||||
callback(null, uploads);
|
||||
},
|
||||
|
||||
complete: function(xhr, status) {
|
||||
uploadForm[0].reset();
|
||||
composer.posts[post_uuid].uploadsInProgress.pop();
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
uploadForm.submit();
|
||||
}
|
||||
|
||||
function uploadTopicThumb(params) {
|
||||
var post_uuid = params.post_uuid,
|
||||
route = params.route,
|
||||
formData = params.formData,
|
||||
callback = params.callback,
|
||||
postContainer = $('#cmp-uuid-' + post_uuid),
|
||||
spinner = postContainer.find('.topic-thumb-spinner'),
|
||||
thumbForm = postContainer.find('#thumbForm');
|
||||
|
||||
thumbForm.attr('action', route);
|
||||
|
||||
thumbForm.off('submit').submit(function() {
|
||||
var csrf = $('#csrf_token').val();
|
||||
$(this).find('#thumbUploadCsrf').val(csrf);
|
||||
|
||||
if(formData) {
|
||||
formData.append('_csrf', csrf);
|
||||
}
|
||||
|
||||
spinner.removeClass('hide');
|
||||
composer.posts[post_uuid].uploadsInProgress.push(1);
|
||||
|
||||
$(this).ajaxSubmit({
|
||||
formData: formData,
|
||||
error: function(xhr) {
|
||||
app.alertError('Error uploading file!\nStatus : ' + xhr.status + '\nMessage : ' + xhr.responseText);
|
||||
if (typeof callback == 'function')
|
||||
callback(xhr);
|
||||
},
|
||||
success: function(uploads) {
|
||||
postContainer.find('#topic-thumb-url').val((uploads[0] || {}).url || '').trigger('change');
|
||||
if (typeof callback == 'function')
|
||||
callback(null, uploads);
|
||||
},
|
||||
complete: function() {
|
||||
composer.posts[post_uuid].uploadsInProgress.pop();
|
||||
spinner.addClass('hide');
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
thumbForm.submit();
|
||||
}
|
||||
|
||||
composer.newTopic = function(cid) {
|
||||
if(allowed()) {
|
||||
push({
|
||||
cid: cid,
|
||||
title: '',
|
||||
body: '',
|
||||
modified: false
|
||||
modified: false,
|
||||
isMain: true
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
composer.addQuote = function(tid, pid, title, username, text){
|
||||
if (allowed()) {
|
||||
@@ -58,10 +312,11 @@ define(['taskbar'], function(taskbar) {
|
||||
tid: tid,
|
||||
title: title,
|
||||
body: text,
|
||||
modified: false
|
||||
modified: false,
|
||||
isMain: false
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
composer.editPost = function(pid) {
|
||||
if(allowed()) {
|
||||
@@ -73,27 +328,13 @@ define(['taskbar'], function(taskbar) {
|
||||
pid: pid,
|
||||
title: threadData.title,
|
||||
body: threadData.body,
|
||||
modified: false
|
||||
modified: false,
|
||||
isMain: !threadData.index,
|
||||
topic_thumb: threadData.topic_thumb
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function push(post) {
|
||||
var uuid = utils.generateUUID();
|
||||
|
||||
translator.translate('[[topic:composer.new_topic]]', function(newTopicStr) {
|
||||
taskbar.push('composer', uuid, {
|
||||
title: post.title ? post.title : newTopicStr,
|
||||
icon: post.picture
|
||||
});
|
||||
});
|
||||
|
||||
composer.posts[uuid] = post;
|
||||
composer.posts[uuid].uploadsInProgress = [];
|
||||
|
||||
composer.load(uuid);
|
||||
}
|
||||
};
|
||||
|
||||
composer.load = function(post_uuid) {
|
||||
if($('#cmp-uuid-' + post_uuid).length) {
|
||||
@@ -101,12 +342,15 @@ define(['taskbar'], function(taskbar) {
|
||||
} else {
|
||||
composer.createNewComposer(post_uuid);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
composer.createNewComposer = function(post_uuid) {
|
||||
|
||||
templates.preload_template('composer', function() {
|
||||
var composerTemplate = templates['composer'].parse({});
|
||||
var composerTemplate = templates['composer'].parse({
|
||||
allowTopicsThumbnail: config.allowTopicsThumbnail && composer.posts[post_uuid].isMain && config.hasImageUploadPlugin
|
||||
});
|
||||
|
||||
translator.translate(composerTemplate, function(composerTemplate) {
|
||||
composerTemplate = $(composerTemplate);
|
||||
|
||||
@@ -124,7 +368,19 @@ define(['taskbar'], function(taskbar) {
|
||||
|
||||
var postData = composer.posts[post_uuid],
|
||||
titleEl = postContainer.find('.title'),
|
||||
bodyEl = postContainer.find('textarea');
|
||||
bodyEl = postContainer.find('textarea'),
|
||||
thumbToggleBtnEl = postContainer.find('.topic-thumb-toggle-btn'),
|
||||
|
||||
toggleThumbEls = function(){
|
||||
if (config.allowTopicsThumbnail && composer.posts[post_uuid].isMain) {
|
||||
var url = composer.posts[post_uuid].topic_thumb || '';
|
||||
postContainer.find('input#topic-thumb-url').val(url);
|
||||
postContainer.find('img.topic-thumb-preview').attr('src', url);
|
||||
if (url)
|
||||
postContainer.find('.topic-thumb-clear-btn').removeClass('hide');
|
||||
thumbToggleBtnEl.removeClass('hide');
|
||||
}
|
||||
};
|
||||
|
||||
if (parseInt(postData.tid) > 0) {
|
||||
translator.translate('[[topic:composer.replying_to]]: ' + postData.title, function(newTitle) {
|
||||
@@ -139,13 +395,44 @@ define(['taskbar'], function(taskbar) {
|
||||
titleEl.prop('disabled', false);
|
||||
}
|
||||
});
|
||||
toggleThumbEls();
|
||||
} else {
|
||||
titleEl.val(postData.title);
|
||||
titleEl.prop('disabled', false);
|
||||
toggleThumbEls();
|
||||
}
|
||||
|
||||
bodyEl.val(postData.body);
|
||||
|
||||
thumbToggleBtnEl.on('click', function() {
|
||||
var container = postContainer.find('.topic-thumb-container');
|
||||
if (container.hasClass('hide')) {
|
||||
container.removeClass('hide');
|
||||
} else {
|
||||
container.addClass('hide');
|
||||
}
|
||||
});
|
||||
|
||||
postContainer.on('click', '.topic-thumb-clear-btn', function(e) {
|
||||
postContainer.find('input#topic-thumb-url').val('').trigger('change');
|
||||
resetInputFile(postContainer.find('input#topic-thumb-file'));
|
||||
$(this).addClass('hide');
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
postContainer.on('paste change keypress', 'input#topic-thumb-url', function(e) {
|
||||
var urlEl = $(this);
|
||||
setTimeout(function(){
|
||||
var url = urlEl.val();
|
||||
if (url) {
|
||||
postContainer.find('.topic-thumb-clear-btn').removeClass('hide');
|
||||
} else {
|
||||
resetInputFile(postContainer.find('input#topic-thumb-file'));
|
||||
postContainer.find('.topic-thumb-clear-btn').addClass('hide');
|
||||
}
|
||||
postContainer.find('img.topic-thumb-preview').attr('src', url);
|
||||
}, 100);
|
||||
});
|
||||
|
||||
postContainer.on('change', 'input, textarea', function() {
|
||||
composer.posts[post_uuid].modified = true;
|
||||
@@ -192,7 +479,12 @@ define(['taskbar'], function(taskbar) {
|
||||
case 'fa fa-bold':
|
||||
if (selectionStart === selectionEnd) {
|
||||
// Nothing selected
|
||||
var cursorPos = postContentEl[0].selectionStart;
|
||||
insertIntoInput(postContentEl, "**bolded text**");
|
||||
|
||||
// Highlight "link url"
|
||||
postContentEl[0].selectionStart = cursorPos + 12;
|
||||
postContentEl[0].selectionEnd = cursorPos + 20;
|
||||
} else {
|
||||
// Text selected
|
||||
postContentEl.val(postContentEl.val().slice(0, selectionStart) + '**' + postContentEl.val().slice(selectionStart, selectionEnd) + '**' + postContentEl.val().slice(selectionEnd));
|
||||
@@ -241,7 +533,18 @@ define(['taskbar'], function(taskbar) {
|
||||
$('#files').on('change', function(e) {
|
||||
var files = e.target.files;
|
||||
if(files) {
|
||||
uploadSubmit(files, post_uuid, '/api/post/upload');
|
||||
uploadContentFiles({files: files, post_uuid: post_uuid, route: '/api/post/upload'});
|
||||
}
|
||||
});
|
||||
|
||||
postContainer.find('#topic-thumb-file').on('change', function(e) {
|
||||
var files = e.target.files;
|
||||
if(files) {
|
||||
var fd = new FormData();
|
||||
for (var i = 0, file; file = files[i]; i++) {
|
||||
fd.append('files[]', file, file.name);
|
||||
}
|
||||
uploadTopicThumb({files: files, post_uuid: post_uuid, route: '/api/topic/thumb/upload', formData: fd});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -342,24 +645,6 @@ define(['taskbar'], function(taskbar) {
|
||||
});
|
||||
}
|
||||
|
||||
//http://stackoverflow.com/questions/14441456/how-to-detect-which-device-view-youre-on-using-twitter-bootstrap-api
|
||||
function findBootstrapEnvironment() {
|
||||
var envs = ['xs', 'sm', 'md', 'lg'];
|
||||
|
||||
$el = $('<div>');
|
||||
$el.appendTo($('body'));
|
||||
|
||||
for (var i = envs.length - 1; i >= 0; i--) {
|
||||
var env = envs[i];
|
||||
|
||||
$el.addClass('hidden-'+env);
|
||||
if ($el.is(':hidden')) {
|
||||
$el.remove();
|
||||
return env;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
composer.activateReposition = function(post_uuid) {
|
||||
|
||||
if(composer.active && composer.active !== post_uuid) {
|
||||
@@ -400,7 +685,7 @@ define(['taskbar'], function(taskbar) {
|
||||
$('body').css({'margin-bottom': postContainer.css('height')});
|
||||
|
||||
composer.focusElements(post_uuid);
|
||||
}
|
||||
};
|
||||
|
||||
composer.focusElements = function(post_uuid) {
|
||||
var postContainer = $('#cmp-uuid-' + post_uuid),
|
||||
@@ -415,15 +700,18 @@ define(['taskbar'], function(taskbar) {
|
||||
} else if (parseInt(postData.cid) > 0) {
|
||||
titleEl.focus();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
composer.post = function(post_uuid) {
|
||||
var postData = composer.posts[post_uuid],
|
||||
postContainer = $('#cmp-uuid-' + post_uuid),
|
||||
titleEl = postContainer.find('.title'),
|
||||
bodyEl = postContainer.find('textarea');
|
||||
bodyEl = postContainer.find('textarea'),
|
||||
thumbEl = postContainer.find('input#topic-thumb-url');
|
||||
|
||||
titleEl.val(titleEl.val().trim());
|
||||
bodyEl.val(bodyEl.val().trim());
|
||||
thumbEl.val(thumbEl.val().trim());
|
||||
|
||||
var checkTitle = parseInt(postData.cid, 10) || parseInt(postData.pid, 10);
|
||||
|
||||
@@ -439,20 +727,22 @@ define(['taskbar'], function(taskbar) {
|
||||
|
||||
if (parseInt(postData.cid, 10) > 0) {
|
||||
socket.emit('topics.post', {
|
||||
'title' : titleEl.val(),
|
||||
'content' : bodyEl.val(),
|
||||
'category_id' : postData.cid
|
||||
title: titleEl.val(),
|
||||
content: bodyEl.val(),
|
||||
topic_thumb: thumbEl.val(),
|
||||
category_id: postData.cid
|
||||
}, done);
|
||||
} else if (parseInt(postData.tid, 10) > 0) {
|
||||
socket.emit('posts.reply', {
|
||||
'topic_id' : postData.tid,
|
||||
'content' : bodyEl.val()
|
||||
topic_id: postData.tid,
|
||||
content: bodyEl.val()
|
||||
}, done);
|
||||
} else if (parseInt(postData.pid, 10) > 0) {
|
||||
socket.emit('posts.edit', {
|
||||
pid: postData.pid,
|
||||
content: bodyEl.val(),
|
||||
title: titleEl.val()
|
||||
title: titleEl.val(),
|
||||
topic_thumb: thumbEl.val()
|
||||
}, done);
|
||||
}
|
||||
|
||||
@@ -462,18 +752,7 @@ define(['taskbar'], function(taskbar) {
|
||||
composer.discard(post_uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function composerAlert(title, message) {
|
||||
$('.action-bar button').removeAttr('disabled');
|
||||
app.alert({
|
||||
type: 'danger',
|
||||
timeout: 2000,
|
||||
title: title,
|
||||
message: message,
|
||||
alert_id: 'post_error'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
composer.discard = function(post_uuid) {
|
||||
if (composer.posts[post_uuid]) {
|
||||
@@ -484,14 +763,14 @@ define(['taskbar'], function(taskbar) {
|
||||
$('body').css({'margin-bottom': 0});
|
||||
$('.action-bar button').removeAttr('disabled');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
composer.minimize = function(post_uuid) {
|
||||
var postContainer = $('#cmp-uuid-' + post_uuid);
|
||||
postContainer.css('visibility', 'hidden');
|
||||
composer.active = undefined;
|
||||
taskbar.minimize('composer', post_uuid);
|
||||
}
|
||||
};
|
||||
|
||||
function initializeDragAndDrop(post_uuid) {
|
||||
|
||||
@@ -642,7 +921,6 @@ define(['taskbar'], function(taskbar) {
|
||||
uploadForm.submit();
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
newTopic: composer.newTopic,
|
||||
newReply: composer.newReply,
|
||||
|
||||
@@ -35,6 +35,11 @@
|
||||
<input type="checkbox" data-field="allowGuestSearching"> <strong>Allow guests to search without logging in</strong>
|
||||
</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" data-field="allowTopicsThumbnail"> <strong>Allow users to upload topic thumbnails</strong>
|
||||
</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" data-field="useOutgoingLinksPage"> <strong>Use Outgoing Links Warning Page</strong>
|
||||
|
||||
@@ -36,8 +36,14 @@
|
||||
<li class="category-item {topics.deleted-class} {topics.unread-class}" itemprop="itemListElement">
|
||||
|
||||
<div class="col-md-12 col-xs-12 panel panel-default topic-row">
|
||||
|
||||
<!--
|
||||
todo: tidy this up, not sure what to do with the topic thumbs
|
||||
todo: fix this nesting if issue#1065 is a win
|
||||
todo: add a check for config.allowTopicsThumbnail if issue#1066 is a win
|
||||
-->
|
||||
<a href="../../user/{topics.userslug}" class="pull-left">
|
||||
<img class="img-rounded user-img" src="{topics.picture}" title="{topics.username}" />
|
||||
<img src="<!-- IF topics.thumb -->{topics.thumb}<!-- ELSE -->{topics.picture}<!-- ENDIF topics.thumb -->" class="img-rounded user-img" title="{topics.username}"/>
|
||||
</a>
|
||||
|
||||
<h3>
|
||||
|
||||
@@ -1,6 +1,40 @@
|
||||
<div class="composer">
|
||||
|
||||
<style>
|
||||
/* todo: move this to base theme */
|
||||
.topic-thumb-container { width: 95%; margin-top: 5px; background: rgb(255, 255, 255); background: rgba(255, 255, 255, 0.6); padding: 10px; }
|
||||
.topic-thumb-btn { cursor: hand; cursor: pointer; }
|
||||
.topic-thumb-toggle-btn { margin: -25px 3% 0 0; }
|
||||
.topic-thumb-preview { width: auto; height: auto; max-width: 100px; max-height: 100px }
|
||||
.topic-thumb-ctrl.form-group { display: inline-block; vertical-align: -50% !important; }
|
||||
</style>
|
||||
|
||||
<div class="composer-container">
|
||||
<input class="title form-control" type="text" tabIndex="1" placeholder="[[topic:composer.title_placeholder]]" />
|
||||
|
||||
<!-- IF allowTopicsThumbnail -->
|
||||
<i class="fa fa-picture-o pull-right topic-thumb-btn topic-thumb-toggle-btn hide" title="[[topic:composer.thumb_title]]"></i>
|
||||
<div class="topic-thumb-container center-block hide">
|
||||
<form id="thumbForm" method="post" class="topic-thumb-form form-inline" enctype="multipart/form-data">
|
||||
<img class="topic-thumb-preview"></img>
|
||||
<div class="form-group">
|
||||
<label for="topic-thumb-url">[[topic:composer.thumb_url_label]]</label>
|
||||
<input type="text" id="topic-thumb-url" class="form-control" placeholder="[[topic:composer.thumb_url_placeholder]]" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<!-- todo: drag and drop? -->
|
||||
<label for="topic-thumb-file">[[topic:composer.thumb_file_label]]</label>
|
||||
<input type="file" id="topic-thumb-file" class="form-control" />
|
||||
</div>
|
||||
<div class="form-group topic-thumb-ctrl">
|
||||
<i class="fa fa-spinner fa-spin hide topic-thumb-spinner" title="[[topic:composer.uploading]]"></i>
|
||||
<i class="fa fa-times topic-thumb-btn hide topic-thumb-clear-btn" title="[[topic:composer.thumb_remove]]"></i>
|
||||
<input id="thumbUploadCsrf" type="hidden" name="_csrf">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<!-- ENDIF allowTopicsThumbnail -->
|
||||
|
||||
<div class="btn-toolbar formatting-bar">
|
||||
<div class="btn-group">
|
||||
<span class="btn btn-link" tabindex="-1"><i class="fa fa-bold"></i></span>
|
||||
|
||||
@@ -217,6 +217,9 @@ var async = require('async'),
|
||||
}, {
|
||||
field: 'allowGuestSearching',
|
||||
value: 0
|
||||
}, {
|
||||
field: 'allowTopicsThumbnail',
|
||||
value: 0
|
||||
}, {
|
||||
field: 'allowRegistration',
|
||||
value: 1
|
||||
|
||||
@@ -4,6 +4,7 @@ var fs = require('fs'),
|
||||
winston = require('winston'),
|
||||
nconf = require('nconf'),
|
||||
|
||||
translator = require('../public/src/translator'),
|
||||
utils = require('./../public/src/utils'),
|
||||
db = require('./database'),
|
||||
plugins = require('./plugins'),
|
||||
|
||||
@@ -64,7 +64,9 @@ var winston = require('winston'),
|
||||
}
|
||||
|
||||
|
||||
PostTools.edit = function(uid, pid, title, content) {
|
||||
PostTools.edit = function(uid, pid, title, content, options) {
|
||||
options || (options = {});
|
||||
|
||||
var websockets = require('./socket.io'),
|
||||
success = function() {
|
||||
posts.setPostFields(pid, {
|
||||
@@ -85,6 +87,12 @@ var winston = require('winston'),
|
||||
|
||||
topics.setTopicField(tid, 'title', title);
|
||||
topics.setTopicField(tid, 'slug', slug);
|
||||
|
||||
topics.setTopicField(tid, 'thumb', options.topic_thumb);
|
||||
|
||||
db.searchRemove('topic', tid, function() {
|
||||
db.searchIndex('topic', title, tid);
|
||||
});
|
||||
}
|
||||
|
||||
posts.getPostData(pid, function(err, postData) {
|
||||
|
||||
@@ -2,9 +2,7 @@ var db = require('./database'),
|
||||
utils = require('./../public/src/utils'),
|
||||
user = require('./user'),
|
||||
topics = require('./topics'),
|
||||
categories = require('./categories'),
|
||||
favourites = require('./favourites'),
|
||||
threadTools = require('./threadTools'),
|
||||
postTools = require('./postTools'),
|
||||
categories = require('./categories'),
|
||||
plugins = require('./plugins'),
|
||||
|
||||
@@ -11,7 +11,7 @@ var path = require('path'),
|
||||
ThreadTools = require('../threadTools'),
|
||||
posts = require('../posts'),
|
||||
categories = require('../categories'),
|
||||
categoryTools = require('../categoryTools')
|
||||
categoryTools = require('../categoryTools'),
|
||||
meta = require('../meta'),
|
||||
Plugins = require('../plugins'),
|
||||
utils = require('../../public/src/utils'),
|
||||
@@ -57,6 +57,7 @@ var path = require('path'),
|
||||
config.useOutgoingLinksPage = parseInt(meta.config.useOutgoingLinksPage, 10) === 1;
|
||||
config.allowGuestPosting = parseInt(meta.config.allowGuestPosting, 10) === 1;
|
||||
config.allowFileUploads = parseInt(meta.config.allowFileUploads, 10) === 1;
|
||||
config.allowTopicsThumbnail = parseInt(meta.config.allowTopicsThumbnail, 10) === 1;
|
||||
config.usePagination = parseInt(meta.config.usePagination, 10) === 1;
|
||||
config.topicsPerPage = meta.config.topicsPerPage || 20;
|
||||
config.postsPerPage = meta.config.postsPerPage || 20;
|
||||
@@ -424,7 +425,7 @@ var path = require('path'),
|
||||
}
|
||||
});
|
||||
|
||||
app.post('/post/upload', function(req, res, next) {
|
||||
function upload(req, res, filesIterator, next) {
|
||||
if(!req.user) {
|
||||
return res.json(403, {message:'not allowed'});
|
||||
}
|
||||
@@ -445,21 +446,33 @@ var path = require('path'),
|
||||
}
|
||||
}
|
||||
|
||||
async.map(files, function(file, next) {
|
||||
async.map(files, filesIterator, function(err, images) {
|
||||
deleteTempFiles();
|
||||
if(err) {
|
||||
return res.json(500, err.message);
|
||||
}
|
||||
res.json(200, images);
|
||||
});
|
||||
}
|
||||
|
||||
app.post('/post/upload', function(req, res, next) {
|
||||
upload(req, res, function(file, next) {
|
||||
if(file.type.match('image.*')) {
|
||||
posts.uploadPostImage(file, next);
|
||||
} else {
|
||||
posts.uploadPostFile(file, next);
|
||||
}
|
||||
}, function(err, images) {
|
||||
deleteTempFiles();
|
||||
|
||||
if(err) {
|
||||
return res.json(500, err.message);
|
||||
}
|
||||
|
||||
res.json(200, images);
|
||||
}, next)
|
||||
});
|
||||
|
||||
app.post('/topic/thumb/upload', function(req, res, next) {
|
||||
upload(req, res, function(file, next) {
|
||||
if(file.type.match('image.*')) {
|
||||
topics.uploadTopicThumb(file, next);
|
||||
} else {
|
||||
res.json(500, {message: 'Invalid File'});
|
||||
}
|
||||
}, next);
|
||||
});
|
||||
|
||||
app.get('/reset', function (req, res) {
|
||||
|
||||
@@ -29,19 +29,21 @@ SocketModules.composer.push = function(socket, pid, callback) {
|
||||
posts.getPostFields(pid, ['content'], next);
|
||||
},
|
||||
function(next) {
|
||||
topics.getTitleByPid(pid, function(title) {
|
||||
next(null, title);
|
||||
});
|
||||
topics.getTopicDataByPid(pid, next);
|
||||
},
|
||||
function(next) {
|
||||
posts.getPidIndex(pid, next);
|
||||
}
|
||||
], function(err, results) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
callback(null, {
|
||||
title: results[1],
|
||||
pid: pid,
|
||||
body: results[0].content
|
||||
body: results[0].content,
|
||||
title: results[1].title,
|
||||
topic_thumb: results[1].thumb,
|
||||
index: results[2]
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -148,7 +148,7 @@ SocketPosts.edit = function(socket, data, callback) {
|
||||
return callback(new Error('content-too-short'));
|
||||
}
|
||||
|
||||
postTools.edit(socket.uid, data.pid, data.title, data.content);
|
||||
postTools.edit(socket.uid, data.pid, data.title, data.content, {topic_thumb: data.topic_thumb});
|
||||
callback();
|
||||
};
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ SocketTopics.post = function(socket, data, callback) {
|
||||
return callback(new Error('not-logged-in'));
|
||||
}
|
||||
|
||||
topics.post(socket.uid, data.title, data.content, data.category_id, function(err, result) {
|
||||
topics.post({uid: socket.uid, title: data.title, content: data.content, cid: data.category_id, thumb: data.topic_thumb}, function(err, result) {
|
||||
if(err) {
|
||||
if (err.message === 'title-too-short') {
|
||||
module.parent.exports.emitAlert(socket, 'Title too short', 'Please enter a longer title. At least ' + meta.config.minimumTitleLength + ' characters.');
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
var async = require('async'),
|
||||
gravatar = require('gravatar'),
|
||||
path = require('path'),
|
||||
nconf = require('nconf'),
|
||||
validator = require('validator'),
|
||||
S = require('string'),
|
||||
@@ -8,6 +9,7 @@ var async = require('async'),
|
||||
db = require('./database'),
|
||||
posts = require('./posts'),
|
||||
utils = require('./../public/src/utils'),
|
||||
plugins = require('./plugins'),
|
||||
user = require('./user'),
|
||||
categories = require('./categories'),
|
||||
categoryTools = require('./categoryTools'),
|
||||
@@ -21,7 +23,12 @@ var async = require('async'),
|
||||
|
||||
(function(Topics) {
|
||||
|
||||
Topics.create = function(uid, title, cid, callback) {
|
||||
Topics.create = function(data, callback) {
|
||||
var uid = data.uid,
|
||||
title = data.title,
|
||||
cid = data.cid,
|
||||
thumb = data.thumb;
|
||||
|
||||
db.incrObjectField('global', 'nextTid', function(err, tid) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
@@ -42,7 +49,8 @@ var async = require('async'),
|
||||
'viewcount': 0,
|
||||
'locked': 0,
|
||||
'deleted': 0,
|
||||
'pinned': 0
|
||||
'pinned': 0,
|
||||
'thumb': thumb || ''
|
||||
}, function(err) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
@@ -62,7 +70,13 @@ var async = require('async'),
|
||||
});
|
||||
};
|
||||
|
||||
Topics.post = function(uid, title, content, cid, callback) {
|
||||
Topics.post = function(data, callback) {
|
||||
var uid = data.uid,
|
||||
title = data.title,
|
||||
content = data.content,
|
||||
cid = data.cid,
|
||||
thumb = data.thumb;
|
||||
|
||||
if (title) {
|
||||
title = title.trim();
|
||||
}
|
||||
@@ -99,7 +113,7 @@ var async = require('async'),
|
||||
user.isReadyToPost(uid, next);
|
||||
},
|
||||
function(next) {
|
||||
Topics.create(uid, title, cid, next);
|
||||
Topics.create({uid: uid, title: title, cid: cid, thumb: thumb}, next);
|
||||
},
|
||||
function(tid, next) {
|
||||
Topics.reply(tid, uid, content, next);
|
||||
@@ -211,7 +225,7 @@ var async = require('async'),
|
||||
posts.getCidByPid(mainPid, callback);
|
||||
}
|
||||
}, function(err, results) {
|
||||
Topics.create(results.postData.uid, title, results.cid, function(err, tid) {
|
||||
Topics.create({uid: results.postData.uid, title: title, cid: results.cid}, function(err, tid) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
@@ -807,6 +821,7 @@ var async = require('async'),
|
||||
'pinned': topicData.pinned,
|
||||
'timestamp': topicData.timestamp,
|
||||
'slug': topicData.slug,
|
||||
'thumb': topicData.thumb,
|
||||
'postcount': topicData.postcount,
|
||||
'viewcount': topicData.viewcount,
|
||||
'pageCount': pageCount,
|
||||
@@ -895,11 +910,41 @@ var async = require('async'),
|
||||
};
|
||||
|
||||
Topics.getTitleByPid = function(pid, callback) {
|
||||
Topics.getTopicFieldByPid('title', pid, callback);
|
||||
};
|
||||
|
||||
Topics.getTopicFieldByPid = function(field, pid, callback) {
|
||||
posts.getPostField(pid, 'tid', function(err, tid) {
|
||||
Topics.getTopicField(tid, 'title', function(err, title) {
|
||||
callback(title);
|
||||
Topics.getTopicField(tid, field, callback);
|
||||
});
|
||||
};
|
||||
|
||||
Topics.getTopicDataByPid = function(pid, callback) {
|
||||
posts.getPostField(pid, 'tid', function(err, tid) {
|
||||
Topics.getTopicData(tid, callback);
|
||||
});
|
||||
};
|
||||
|
||||
Topics.uploadTopicThumb = function(image, callback) {
|
||||
|
||||
if(plugins.hasListeners('filter:uploadImage')) {
|
||||
plugins.fireHook('filter:uploadImage', image, callback);
|
||||
} else {
|
||||
if (meta.config.allowTopicsThumbnail) {
|
||||
var filename = 'upload-' + utils.generateUUID() + path.extname(image.name);
|
||||
require('./file').saveFileToLocal(filename, image.path, function(err, upload) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
callback(null, {
|
||||
url: upload.url,
|
||||
name: image.name
|
||||
});
|
||||
});
|
||||
} else {
|
||||
callback(new Error('Topic Thumbnails are disabled!'));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Topics.markAsUnreadForAll = function(tid, callback) {
|
||||
|
||||
@@ -677,7 +677,7 @@ module.exports.server = server;
|
||||
posts: topicData
|
||||
});
|
||||
});
|
||||
},
|
||||
}
|
||||
], function (err, data) {
|
||||
if (err) {
|
||||
if (err.message === 'not-enough-privileges') {
|
||||
@@ -927,7 +927,7 @@ module.exports.server = server;
|
||||
return custom_routes.templates.map(function(tpl) {
|
||||
return tpl.template.split('.tpl')[0];
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
plugins.ready(function() {
|
||||
plugins.fireHook('filter:server.create_routes', custom_routes, function(err, custom_routes) {
|
||||
|
||||
@@ -25,7 +25,7 @@ describe('Topic\'s', function() {
|
||||
describe('.post', function() {
|
||||
|
||||
it('should create a new topic with proper parameters', function(done) {
|
||||
Topics.post(topic.userId, topic.title, topic.content, topic.categoryId, function(err, result) {
|
||||
Topics.post({uid: topic.userId, title: topic.title, content: topic.content, cid: topic.categoryId}, function(err, result) {
|
||||
assert.equal(err, null, 'was created with error');
|
||||
assert.ok(result);
|
||||
|
||||
@@ -36,7 +36,7 @@ describe('Topic\'s', function() {
|
||||
it('should fail to create new topic with wrong parameters', function(done) {
|
||||
topic.userId = null;
|
||||
|
||||
Topics.post(topic.userId, topic.title, topic.content, topic.categoryId, function(err, result) {
|
||||
Topics.post({uid: topic.userId, title: topic.title, content: topic.content, cid: topic.categoryId}, function(err, result) {
|
||||
assert.equal(err.message, 'invalid-user');
|
||||
done();
|
||||
});
|
||||
@@ -48,7 +48,7 @@ describe('Topic\'s', function() {
|
||||
var newPost;
|
||||
|
||||
beforeEach(function(done){
|
||||
Topics.post(topic.userId, topic.title, topic.content, topic.categoryId, function(err, result) {
|
||||
Topics.post({uid: topic.userId, title: topic.title, content: topic.content, cid: topic.categoryId}, function(err, result) {
|
||||
newTopic = result.topicData;
|
||||
newPost = result.postData;
|
||||
done();
|
||||
|
||||
Reference in New Issue
Block a user