apostrophe-snippets
Advanced tools
Comparing version 0.0.6 to 0.0.7
676
index.js
@@ -145,46 +145,2 @@ var async = require('async'); | ||
self._app.post(self._action + '/insert', function(req, res) { | ||
var snippet; | ||
var title; | ||
var thumbnail; | ||
var content; | ||
var slug; | ||
var tags; | ||
title = req.body.title.trim(); | ||
// Validation is annoying, automatic cleanup is awesome | ||
if (!title.length) { | ||
title = self.getDefaultTitle(); | ||
} | ||
slug = self._apos.slugify(title); | ||
thumbnailContent = JSON.parse(req.body.thumbnail); | ||
self._apos.sanitizeItems(thumbnailContent); | ||
content = JSON.parse(req.body.content); | ||
self._apos.sanitizeItems(content); | ||
tags = req.body.tags; | ||
async.series([ prepare, insert ], send); | ||
function prepare(callback) { | ||
snippet = { title: title, type: self._instance, tags: tags, areas: { thumbnail: { items: thumbnailContent }, body: { items: content } }, slug: slug, createdAt: new Date(), publishedAt: new Date() }; | ||
snippet.sortTitle = self._apos.sortify(snippet.title); | ||
return self.beforeInsert(req, req.body, snippet, callback); | ||
} | ||
function insert(callback) { | ||
return self._apos.putPage(req, slug, snippet, callback); | ||
} | ||
function send(err) { | ||
if (err) { | ||
res.statusCode = 500; | ||
return res.send('error'); | ||
} | ||
return res.send(JSON.stringify(snippet)); | ||
} | ||
}); | ||
self.beforeInsert = function(req, data, snippet, callback) { | ||
@@ -198,201 +154,70 @@ return callback(null); | ||
self._app.post(self._action + '/update', function(req, res) { | ||
var snippet; | ||
var title; | ||
var content; | ||
var originalSlug; | ||
var slug; | ||
var tags; | ||
// Fields to be imported or read from the browser when saving a new item. | ||
// You can read properties directly or leverage this mechanism to handle the types | ||
// that it supports painlessly. It's not meant to cover everything, just tricky | ||
// field types that would otherwise be very challenging to implement, such as areas. | ||
// (In fact, right now it only covers areas!) | ||
title = self._apos.sanitizeString(req.body.title, self.getDefaultTitle()); | ||
tags = req.body.tags; | ||
originalSlug = self._apos.sanitizeString(req.body.originalSlug); | ||
slug = self._apos.slugify(req.body.slug); | ||
if (!slug.length) { | ||
slug = originalSlug; | ||
self.convertFields = [ | ||
{ | ||
// This one will always import as an empty area for now when importing CSV. | ||
// TODO: allow URLs in CSV to be imported. | ||
name: 'thumbnail', | ||
type: 'area' | ||
}, | ||
{ | ||
name: 'body', | ||
type: 'area' | ||
} | ||
]; | ||
thumbnailContent = JSON.parse(req.body.thumbnail); | ||
self._apos.sanitizeItems(thumbnailContent); | ||
content = JSON.parse(req.body.content); | ||
self._apos.sanitizeItems(content); | ||
async.series([ getSnippet, massage, update, redirect ], send); | ||
function getSnippet(callback) { | ||
self._apos.getPage(req, originalSlug, function(err, page) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
if (!page) { | ||
return callback('No such ' + self._instance); | ||
} | ||
if (page.type !== self._instance) { | ||
return callback('Not a ' + self._instance); | ||
} | ||
snippet = page; | ||
return callback(null); | ||
// Very handy for imports of all kinds: convert plaintext to an area with | ||
// one rich text item if it is not blank, otherwise an empty area. null and | ||
// undefined are tolerated and converted to empty areas. | ||
self.textToArea = function(text) { | ||
var area = { items: [] }; | ||
if ((typeof(text) === 'string') && text.length) { | ||
area.items.push({ | ||
type: 'richText', | ||
content: self._apos.escapeHtml(text) | ||
}); | ||
} | ||
return area; | ||
}; | ||
function massage(callback) { | ||
snippet.title = title; | ||
snippet.slug = slug; | ||
snippet.tags = tags; | ||
snippet.sortTitle = self._apos.sortify(title); | ||
snippet.areas = { thumbnail: { items: thumbnailContent }, body: { items: content } }; | ||
return self.beforeUpdate(req, req.body, snippet, callback); | ||
} | ||
function update(callback) { | ||
self._apos.putPage(req, originalSlug, snippet, callback); | ||
} | ||
function redirect(callback) { | ||
self._apos.updateRedirect(originalSlug, slug, callback); | ||
} | ||
function send(err) { | ||
if (err) { | ||
res.statusCode = 500; | ||
console.log(err); | ||
return res.send('error'); | ||
// Converters from various formats for various types | ||
self.converters = { | ||
csv: { | ||
area: function(data, name, snippet) { | ||
if (!snippet.areas) { | ||
snippet.areas = {}; | ||
} | ||
snippet.areas[name] = self.textToArea(data[name]); | ||
} | ||
return res.send(JSON.stringify(snippet)); | ||
} | ||
}); | ||
self._app.post(self._action + '/trash', function(req, res) { | ||
async.series([ get, permissions, beforeTrash, trashSnippet], respond); | ||
var slug; | ||
var snippet; | ||
var trash = self._apos.sanitizeBoolean(req.body.trash); | ||
function get(callback) { | ||
slug = req.body.slug; | ||
return self._apos.pages.findOne({ slug: slug }, function(err, snippetArg) { | ||
snippet = snippetArg; | ||
if(!snippet) { | ||
return callback('Not Found'); | ||
}, | ||
form: { | ||
area: function(data, name, snippet) { | ||
var content = []; | ||
try { | ||
content = JSON.parse(data[name]); | ||
} catch (e) { | ||
// Always recover graciously and import something reasonable, like an empty area | ||
} | ||
if (snippet.type !== self._instance) { | ||
return callback('Not a ' + self._instance); | ||
self._apos.sanitizeItems(content); | ||
if (!snippet.areas) { | ||
snippet.areas = {}; | ||
} | ||
return callback(err); | ||
}); | ||
} | ||
function permissions(callback) { | ||
return self._apos.permissions(req, 'edit-page', snippet, function(err) { | ||
// If there is no permissions error then we are cool | ||
// enough to trash the post | ||
return callback(err); | ||
}); | ||
} | ||
function beforeTrash(callback) { | ||
if (self.beforeTrash) { | ||
return self.beforeTrash(req, snippet, trash, callback); | ||
snippet.areas[name] = { items: content }; | ||
} | ||
return callback(null); | ||
} | ||
}; | ||
function trashSnippet(callback) { | ||
var action; | ||
if (trash) { | ||
action = { $set: { trash: true } }; | ||
} else { | ||
action = { $unset: { trash: true } }; | ||
} | ||
self._apos.pages.update({slug: snippet.slug}, action, callback); | ||
} | ||
function respond(err) { | ||
if (err) { | ||
res.statusCode = 404; | ||
return res.send(err); | ||
} | ||
res.statusCode = 200; | ||
return res.send('ok'); | ||
} | ||
}); | ||
self._app.post(self._action + '/import', function(req, res) { | ||
var file = req.files.file; | ||
var rows = 0; | ||
var headings = []; | ||
var s = csv().from.stream(fs.createReadStream(file.path)); | ||
var active = 0; | ||
var date = new Date(); | ||
req.aposImported = moment().format(); | ||
s.on('record', function(row, index) { | ||
active++; | ||
// s.pause() avoids an explosion of rows being processed simultaneously | ||
// by async mongo calls, etc. However note this does not | ||
// stop more events from coming in because the parser will | ||
// keep going with its current block of raw data. So we still | ||
// have to track the number of still-active async handleRow calls ): | ||
// Also there is no guarantee imports are in order, however that shouldn't | ||
// matter since we always rely on some index such as title or publication date | ||
s.pause(); | ||
if (!index) { | ||
handleHeadings(row, afterRow); | ||
} else { | ||
handleRow(row, function(err) { | ||
if (!err) { | ||
rows++; | ||
return afterRow(); | ||
} else { | ||
console.log(err); | ||
s.end(); | ||
active--; | ||
} | ||
}); | ||
} | ||
function afterRow() { | ||
s.resume(); | ||
active--; | ||
} | ||
}) | ||
.on('error', function(count) { | ||
respondWhenDone('error'); | ||
}) | ||
.on('end', function(count) { | ||
respondWhenDone('ok'); | ||
self.convertAllFields = function(from, data, snippet) { | ||
_.each(self.convertFields, function(field) { | ||
self.converters[from][field.type](data, field.name, snippet); | ||
}); | ||
}; | ||
function handleHeadings(row, callback) { | ||
headings = row; | ||
var i; | ||
for (i = 0; (i < headings.length); i++) { | ||
headings[i] = self._apos.camelName(headings[i]); | ||
} | ||
return callback(); | ||
} | ||
self.areas = [ 'thumbnail', 'body' ]; | ||
function handleRow(row, callback) { | ||
// Ignore blank rows without an error | ||
if (!_.some(row, function(column) { return column !== ''; })) { | ||
return callback(null); | ||
} | ||
var data = {}; | ||
var i; | ||
for (i = 0; (i < headings.length); i++) { | ||
data[headings[i]] = row[i]; | ||
} | ||
self.importCreateItem(req, data, callback); | ||
} | ||
function respondWhenDone(status) { | ||
if (active) { | ||
return setTimeout(function() { respondWhenDone(status); }, 100); | ||
} | ||
res.send({ status: status, rows: rows }); | ||
} | ||
}); | ||
self.importCreateItem = function(req, data, callback) { | ||
@@ -409,18 +234,16 @@ // "Why the try/catch?" Because the CSV reader has some sort of | ||
tags = tags.concat(categories); | ||
var published = self._apos.sanitizeBoolean(data.published, true); | ||
var snippet = { | ||
type: self._instance, | ||
areas: { | ||
body: { | ||
items: [ | ||
{ | ||
type: 'richText', | ||
content: data.richText || (data.text ? self._apos.escapeHtml(data.text) : '') | ||
} | ||
] | ||
} | ||
}, | ||
areas: {}, | ||
title: data.title || self.getDefaultTitle(), | ||
tags: tags | ||
tags: tags, | ||
published: published | ||
}; | ||
console.log('convert all'); | ||
self.convertAllFields('csv', data, snippet); | ||
console.log('after convert all'); | ||
snippet.slug = self._apos.slugify(snippet.title); | ||
@@ -447,46 +270,297 @@ snippet.sortTitle = self._apos.sortify(snippet.title); | ||
self._app.get(self._action + '/get', function(req, res) { | ||
self.get(req, req.query, function(err, snippets) { | ||
return res.send(JSON.stringify(snippets)); | ||
self.addStandardRoutes = function() { | ||
// TODO: refactor lots of duplication in /insert and /update | ||
self._app.post(self._action + '/insert', function(req, res) { | ||
var snippet; | ||
var title; | ||
var thumbnail; | ||
var content; | ||
var slug; | ||
var tags; | ||
var published = self._apos.sanitizeBoolean(req.body.published, true); | ||
title = req.body.title.trim(); | ||
// Validation is annoying, automatic cleanup is awesome | ||
if (!title.length) { | ||
title = self.getDefaultTitle(); | ||
} | ||
slug = self._apos.slugify(title); | ||
snippet = { title: title, published: published, type: self._instance, tags: tags, areas: {}, slug: slug, createdAt: new Date(), publishedAt: new Date() }; | ||
snippet.sortTitle = self._apos.sortify(snippet.title); | ||
self.convertAllFields('form', req.body, snippet); | ||
tags = req.body.tags; | ||
async.series([ prepare, insert ], send); | ||
function prepare(callback) { | ||
return self.beforeInsert(req, req.body, snippet, callback); | ||
} | ||
function insert(callback) { | ||
return self._apos.putPage(req, slug, snippet, callback); | ||
} | ||
function send(err) { | ||
if (err) { | ||
res.statusCode = 500; | ||
return res.send('error'); | ||
} | ||
return res.send(JSON.stringify(snippet)); | ||
} | ||
}); | ||
}); | ||
self._app.get(self._action + '/get-one', function(req, res) { | ||
self.get(req, req.query, function(err, snippets) { | ||
if (snippets && snippets.length) { | ||
res.send(JSON.stringify(snippets[0])); | ||
} else { | ||
res.send(JSON.stringify(null)); | ||
self._app.post(self._action + '/update', function(req, res) { | ||
var snippet; | ||
var title; | ||
var content; | ||
var originalSlug; | ||
var slug; | ||
var tags; | ||
var published = self._apos.sanitizeBoolean(req.body.published, true); | ||
title = self._apos.sanitizeString(req.body.title, self.getDefaultTitle()); | ||
tags = req.body.tags; | ||
originalSlug = self._apos.sanitizeString(req.body.originalSlug); | ||
slug = self._apos.slugify(req.body.slug); | ||
if (!slug.length) { | ||
slug = originalSlug; | ||
} | ||
async.series([ getSnippet, massage, update, redirect ], send); | ||
function getSnippet(callback) { | ||
self._apos.getPage(req, originalSlug, function(err, page) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
if (!page) { | ||
return callback('No such ' + self._instance); | ||
} | ||
if (page.type !== self._instance) { | ||
return callback('Not a ' + self._instance); | ||
} | ||
snippet = page; | ||
return callback(null); | ||
}); | ||
} | ||
function massage(callback) { | ||
snippet.areas = {}; | ||
self.convertAllFields('form', req.body, snippet); | ||
snippet.title = title; | ||
snippet.slug = slug; | ||
snippet.tags = tags; | ||
snippet.sortTitle = self._apos.sortify(title); | ||
snippet.published = published; | ||
return self.beforeUpdate(req, req.body, snippet, callback); | ||
} | ||
function update(callback) { | ||
self._apos.putPage(req, originalSlug, snippet, callback); | ||
} | ||
function redirect(callback) { | ||
self._apos.updateRedirect(originalSlug, slug, callback); | ||
} | ||
function send(err) { | ||
if (err) { | ||
res.statusCode = 500; | ||
console.log(err); | ||
return res.send('error'); | ||
} | ||
return res.send(JSON.stringify(snippet)); | ||
} | ||
}); | ||
}); | ||
self._app.get(self._action + '/autocomplete', function(req, res) { | ||
var options = { | ||
fields: { title: 1, _id: 1 }, | ||
limit: 10 | ||
}; | ||
if (req.query.term !== undefined) { | ||
options.titleSearch = req.query.term; | ||
} else if (req.query.ids !== undefined) { | ||
options._id = { $in: req.query.ids }; | ||
} else { | ||
res.statusCode = 404; | ||
return res.send('bad arguments'); | ||
} | ||
// Format it as value & id properties for compatibility with jquery UI autocomplete | ||
self.get(req, options, function(err, snippets) { | ||
return res.send( | ||
JSON.stringify(_.map(snippets, function(snippet) { | ||
return { value: snippet.title, id: snippet._id }; | ||
})) | ||
); | ||
self._app.post(self._action + '/trash', function(req, res) { | ||
async.series([ get, permissions, beforeTrash, trashSnippet], respond); | ||
var slug; | ||
var snippet; | ||
var trash = self._apos.sanitizeBoolean(req.body.trash); | ||
function get(callback) { | ||
slug = req.body.slug; | ||
return self._apos.pages.findOne({ slug: slug }, function(err, snippetArg) { | ||
snippet = snippetArg; | ||
if(!snippet) { | ||
return callback('Not Found'); | ||
} | ||
if (snippet.type !== self._instance) { | ||
return callback('Not a ' + self._instance); | ||
} | ||
return callback(err); | ||
}); | ||
} | ||
function permissions(callback) { | ||
return self._apos.permissions(req, 'edit-page', snippet, function(err) { | ||
// If there is no permissions error then we are cool | ||
// enough to trash the post | ||
return callback(err); | ||
}); | ||
} | ||
function beforeTrash(callback) { | ||
if (self.beforeTrash) { | ||
return self.beforeTrash(req, snippet, trash, callback); | ||
} | ||
return callback(null); | ||
} | ||
function trashSnippet(callback) { | ||
var action; | ||
if (trash) { | ||
action = { $set: { trash: true } }; | ||
} else { | ||
action = { $unset: { trash: true } }; | ||
} | ||
self._apos.pages.update({slug: snippet.slug}, action, callback); | ||
} | ||
function respond(err) { | ||
if (err) { | ||
res.statusCode = 404; | ||
return res.send(err); | ||
} | ||
res.statusCode = 200; | ||
return res.send('ok'); | ||
} | ||
}); | ||
}); | ||
self._app.post(self._action + '/import', function(req, res) { | ||
var file = req.files.file; | ||
var rows = 0; | ||
var headings = []; | ||
var s = csv().from.stream(fs.createReadStream(file.path)); | ||
var active = 0; | ||
var date = new Date(); | ||
req.aposImported = moment().format(); | ||
s.on('record', function(row, index) { | ||
active++; | ||
// s.pause() avoids an explosion of rows being processed simultaneously | ||
// by async mongo calls, etc. However note this does not | ||
// stop more events from coming in because the parser will | ||
// keep going with its current block of raw data. So we still | ||
// have to track the number of still-active async handleRow calls ): | ||
// Also there is no guarantee imports are in order, however that shouldn't | ||
// matter since we always rely on some index such as title or publication date | ||
s.pause(); | ||
if (!index) { | ||
handleHeadings(row, afterRow); | ||
} else { | ||
handleRow(row, function(err) { | ||
if (!err) { | ||
rows++; | ||
return afterRow(); | ||
} else { | ||
console.log(err); | ||
s.end(); | ||
active--; | ||
} | ||
}); | ||
} | ||
function afterRow() { | ||
s.resume(); | ||
active--; | ||
} | ||
}) | ||
.on('error', function(count) { | ||
respondWhenDone('error'); | ||
}) | ||
.on('end', function(count) { | ||
respondWhenDone('ok'); | ||
}); | ||
function handleHeadings(row, callback) { | ||
headings = row; | ||
var i; | ||
for (i = 0; (i < headings.length); i++) { | ||
headings[i] = self._apos.camelName(headings[i]); | ||
} | ||
return callback(); | ||
} | ||
function handleRow(row, callback) { | ||
// Ignore blank rows without an error | ||
if (!_.some(row, function(column) { return column !== ''; })) { | ||
return callback(null); | ||
} | ||
var data = {}; | ||
var i; | ||
for (i = 0; (i < headings.length); i++) { | ||
data[headings[i]] = row[i]; | ||
} | ||
self.importCreateItem(req, data, callback); | ||
} | ||
function respondWhenDone(status) { | ||
if (active) { | ||
return setTimeout(function() { respondWhenDone(status); }, 100); | ||
} | ||
res.send({ status: status, rows: rows }); | ||
} | ||
}); | ||
self._app.get(self._action + '/get', function(req, res) { | ||
self.get(req, req.query, function(err, snippets) { | ||
return res.send(JSON.stringify(snippets)); | ||
}); | ||
}); | ||
self._app.get(self._action + '/get-one', function(req, res) { | ||
self.get(req, req.query, function(err, snippets) { | ||
if (snippets && snippets.length) { | ||
res.send(JSON.stringify(snippets[0])); | ||
} else { | ||
res.send(JSON.stringify(null)); | ||
} | ||
}); | ||
}); | ||
self._app.get(self._action + '/autocomplete', function(req, res) { | ||
var options = { | ||
fields: { title: 1, _id: 1 }, | ||
limit: 10 | ||
}; | ||
if (req.query.term !== undefined) { | ||
options.titleSearch = req.query.term; | ||
} else if (req.query.ids !== undefined) { | ||
options._id = { $in: req.query.ids }; | ||
} else { | ||
res.statusCode = 404; | ||
return res.send('bad arguments'); | ||
} | ||
// Format it as value & id properties for compatibility with jquery UI autocomplete | ||
self.get(req, options, function(err, snippets) { | ||
return res.send( | ||
JSON.stringify(_.map(snippets, function(snippet) { | ||
return { value: snippet.title, id: snippet._id }; | ||
})) | ||
); | ||
}); | ||
}); | ||
}; | ||
self.addStandardRoutes(); | ||
// Extra routes added at project level or in a module that extends this module | ||
if (options.addRoutes) { | ||
options.addRoutes(); | ||
} | ||
// Serve our assets. This is the final route so it doesn't | ||
// beat out the rest. | ||
// beat out the rest. (TODO: consider moving all asset routes so that this | ||
// is not an issue anymore.) | ||
// | ||
// You don't override js and stylesheet assets, rather you serve more of them | ||
// from your own module and enhance what's already in browserland | ||
// from your own module and enhance what's already in browserland. | ||
self._app.get(self._action + '/*', self._apos.static(self._webAssetDir + '/public')); | ||
@@ -542,3 +616,3 @@ | ||
var options = {}; | ||
extend(options, optionsArg, true); | ||
extend(true, options, optionsArg); | ||
@@ -621,2 +695,5 @@ // Consume special options then remove them, turning the rest into mongo criteria | ||
q.toArray(function(err, snippetsArg) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
snippets = snippetsArg; | ||
@@ -671,3 +748,3 @@ got = snippets.length; | ||
var options = {}; | ||
extend(options, optionsArg, true); | ||
extend(true, options, optionsArg); | ||
var oldSkip = options.skip || 0; | ||
@@ -814,3 +891,3 @@ options.skip = oldSkip + limit; | ||
// to maximize performance information about the pages examined is retained in | ||
// req.bestPageCache for the lifetime of the request so that many calls for many | ||
// req.aposBestPageCache for the lifetime of the request so that many calls for many | ||
// snippets do not result in an explosion of database activity on behalf of a | ||
@@ -822,2 +899,5 @@ // single request. | ||
self.findBestPage = function(req, snippet, callback) { | ||
if (req.aposBestPageCache && req.aposBestPageCache[snippet.type]) { | ||
return go(); | ||
} | ||
var typeNames = _.map(typesByInstanceType[snippet.type] || [], function(type) { return type.name; }); | ||
@@ -830,30 +910,24 @@ var pages = self._apos.pages.find({ type: { $in: typeNames }, slug: /^\// }).toArray(function(err, pages) { | ||
} | ||
// Play nice with invocations of findBestPage for other types | ||
// as part of the same request | ||
if (!req.bestPageCache) { | ||
req.bestPageCache = {}; | ||
if (!req.aposBestPageCache) { | ||
req.aposBestPageCache = {}; | ||
} | ||
if (!req.bestPageCache[snippet.type]) { | ||
var viewable = []; | ||
async.eachSeries(pages, function(page, callback) { | ||
self._apos.permissions(req, 'view-page', page, function(err) { | ||
if (!err) { | ||
viewable.push(page); | ||
} | ||
return callback(null); | ||
}); | ||
}, function(err) { | ||
if (err) { | ||
return callback(err); | ||
var viewable = []; | ||
async.eachSeries(pages, function(page, callback) { | ||
self._apos.permissions(req, 'view-page', page, function(err) { | ||
if (!err) { | ||
viewable.push(page); | ||
} | ||
req.bestPageCache[snippet.type] = viewable; | ||
go(); | ||
return callback(null); | ||
}); | ||
} else { | ||
}, function(err) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
req.aposBestPageCache[snippet.type] = viewable; | ||
go(); | ||
} | ||
}); | ||
}); | ||
function go() { | ||
var viewable = req.bestPageCache[snippet.type]; | ||
var viewable = req.aposBestPageCache[snippet.type]; | ||
var tags = snippet.tags || []; | ||
@@ -886,2 +960,8 @@ var bestScore; | ||
// blog posts add the publication date to the URL. | ||
// | ||
// TODO: this exposes that we're not really letting people change | ||
// the root of the site from / yet. We need to make that a global | ||
// option to the pages module and not just an option to pages.serve, | ||
// or perhaps stuff it into req if we're really going to support | ||
// multiple "sites" per domain etc. | ||
@@ -904,3 +984,3 @@ self.permalink = function(snippet, page) { | ||
self._apos.addDiffListener(function(snippet, lines) { | ||
self._apos.addListener('diff', function(snippet, lines) { | ||
if (snippet.type === self._instance) { | ||
@@ -907,0 +987,0 @@ self.addDiffLines(snippet, lines); |
{ | ||
"name": "apostrophe-snippets", | ||
"version": "0.0.6", | ||
"version": "0.0.7", | ||
"description": "Reusable content snippets for the Apostrophe content management system. The blog and events modules are built on this foundation, which is also useful in and of itself.", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -66,5 +66,10 @@ // NOTES FOR REUSE: | ||
init: function(callback) { | ||
$el.find('[name=published]').val(1); | ||
// TODO: these cascades mean we should have async.series browser-side. | ||
// Also we should provide an easier way to enable areas, and a way to | ||
// limit controls in areas | ||
return self.enableArea($el, 'body', null, function() { | ||
return self.enableSingleton($el, 'thumbnail', null, 'slideshow', { limit: 1, label: 'Thumbnail' }, function() { | ||
self.afterPopulatingEditor($el, {}, callback); | ||
// Pass empty areas object to simplify logic elsewhere | ||
self.afterPopulatingEditor($el, { areas: {} }, callback); | ||
}); | ||
@@ -173,3 +178,4 @@ }); | ||
thumbnail: self.getSingletonJSON($el, 'thumbnail'), | ||
content: self.getAreaJSON($el, 'body'), | ||
body: self.getAreaJSON($el, 'body'), | ||
published: $el.find('[name=published]').val(), | ||
originalSlug: options.slug | ||
@@ -321,2 +327,13 @@ }; | ||
// TODO: this boolean field prep stuff is done often enough to belong | ||
// in editor.js | ||
var published = snippet.published; | ||
if (published === undefined) { | ||
published = 1; | ||
} else { | ||
// Simple POST friendly boolean values | ||
published = published ? '1' : '0'; | ||
} | ||
$el.find('[name=published]').val(published); | ||
// name=slug must always exist, at least as a hidden field, to support this | ||
@@ -323,0 +340,0 @@ apos.suggestSlugOnTitleEdits($el.find('[name=title]'), $el.find('[name=slug]')); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
71847
1510