apostrophe-snippets
Advanced tools
Comparing version 0.0.2 to 0.0.3
88
index.js
@@ -145,2 +145,3 @@ var async = require('async'); | ||
var title; | ||
var thumbnail; | ||
var content; | ||
@@ -157,2 +158,5 @@ var slug; | ||
thumbnailContent = JSON.parse(req.body.thumbnail); | ||
self._apos.sanitizeItems(thumbnailContent); | ||
content = JSON.parse(req.body.content); | ||
@@ -174,3 +178,3 @@ self._apos.sanitizeItems(content); | ||
function prepare(callback) { | ||
snippet = { title: title, type: self._instance, tags: tags, areas: { body: { items: content } }, slug: slug, createdAt: new Date(), publishedAt: new Date() }; | ||
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); | ||
@@ -209,11 +213,7 @@ return self.beforeInsert(req, req.body, snippet, callback); | ||
title = req.body.title.trim(); | ||
// Validation is annoying, automatic cleanup is awesome | ||
if (!title.length) { | ||
title = self.getDefaultTitle(); | ||
} | ||
title = self._apos.sanitizeString(req.body.title, self.getDefaultTitle()); | ||
tags = req.body.tags; | ||
originalSlug = req.body.originalSlug; | ||
originalSlug = self._apos.sanitizeString(req.body.originalSlug); | ||
slug = self._apos.slugify(req.body.slug); | ||
@@ -224,2 +224,5 @@ if (!slug.length) { | ||
thumbnailContent = JSON.parse(req.body.thumbnail); | ||
self._apos.sanitizeItems(thumbnailContent); | ||
content = JSON.parse(req.body.content); | ||
@@ -259,3 +262,3 @@ self._apos.sanitizeItems(content); | ||
snippet.sortTitle = self._apos.sortify(title); | ||
snippet.areas = { body: { items: content } }; | ||
snippet.areas = { thumbnail: { items: thumbnailContent }, body: { items: content } }; | ||
return self.beforeUpdate(req, req.body, snippet, callback); | ||
@@ -402,28 +405,30 @@ } | ||
self.importCreateItem = function(req, data, callback) { | ||
var tags = []; | ||
if (Array.isArray(data.tags)) { | ||
tags.concat(data.tags); | ||
} | ||
if (Array.isArray(data.categories)) { | ||
tags.concat(data.categories); | ||
} | ||
var snippet = { | ||
type: self._instance, | ||
areas: { | ||
body: { | ||
items: [ | ||
{ | ||
type: 'richText', | ||
content: data.richText || (data.text ? self._apos.escapeHtml(data.text) : '') | ||
} | ||
] | ||
} | ||
}, | ||
title: data.title || self.getDefaultTitle(), | ||
tags: self._apos.tagsToArray(tags) | ||
}; | ||
snippet.slug = self._apos.slugify(snippet.title); | ||
snippet.sortTitle = self._apos.sortify(snippet.title); | ||
// Something is eating error messages here if I don't log them myself | ||
// "Why the try/catch?" Because the CSV reader has some sort of | ||
// try/catch of its own that is making it impossible to log any | ||
// errors if we don't catch them. TODO: go looking for that and fix it. | ||
try { | ||
var tags = ''; | ||
tags = self._apos.sanitizeString(data.tags); | ||
tags = self._apos.tagsToArray(tags); | ||
var categories = self._apos.sanitizeString(data.categories); | ||
categories = self._apos.tagsToArray(categories); | ||
tags = tags.concat(categories); | ||
var snippet = { | ||
type: self._instance, | ||
areas: { | ||
body: { | ||
items: [ | ||
{ | ||
type: 'richText', | ||
content: data.richText || (data.text ? self._apos.escapeHtml(data.text) : '') | ||
} | ||
] | ||
} | ||
}, | ||
title: data.title || self.getDefaultTitle(), | ||
tags: tags | ||
}; | ||
snippet.slug = self._apos.slugify(snippet.title); | ||
snippet.sortTitle = self._apos.sortify(snippet.title); | ||
self.beforeInsert(req, data, snippet, function(err) { | ||
@@ -841,3 +846,2 @@ if (err) { | ||
// Register the snippet-reuse widget unless we've been told not to | ||
@@ -848,6 +852,22 @@ _.defaults(options, { widget: true }); | ||
} | ||
var browserOptions = options.browser || {}; | ||
// The option can't be .constructor because that has a special meaning | ||
// in a javascript object (not the one you'd expect, either) http://stackoverflow.com/questions/4012998/what-it-the-significance-of-the-javascript-constructor-property | ||
var browser = { | ||
pages: browserOptions.pages || 'aposPages', | ||
construct: browserOptions.construct || getManagerName(self._instance) | ||
}; | ||
self._apos.pushGlobalCall('@.replaceType(?, new @())', browser.pages, self.name, browser.construct); | ||
if (options.widget) { | ||
widget({ apos: self._apos, app: self._app, snippets: self, name: self.name, label: self.label }); | ||
self._apos.pushGlobalCall('@.addWidgetType()', browser.construct); | ||
} | ||
function getManagerName() { | ||
return 'Apos' + self._instance.charAt(0).toUpperCase() + self._instance.substr(1) + 's'; | ||
} | ||
if (callback) { | ||
@@ -854,0 +874,0 @@ // Invoke callback on next tick so that the constructor's return |
{ | ||
"name": "apostrophe-snippets", | ||
"version": "0.0.2", | ||
"version": "0.0.3", | ||
"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", |
@@ -37,3 +37,2 @@ // NOTES FOR REUSE: | ||
self._css = apos.cssName(self._instance); | ||
apos.log("Setting up for " + self._instance); | ||
self._action = '/apos-' + self._css; | ||
@@ -44,3 +43,2 @@ self._pages = options.pages; | ||
serialize: function($el, $details) { | ||
apos.log('serialize called'); | ||
var data = { tags: apos.tagsToArray($details.find('[name="typeSettings[tags]"]').val()) }; | ||
@@ -50,3 +48,2 @@ return data; | ||
unserialize: function(data, $el, $details) { | ||
apos.log('unserialize called'); | ||
$details.find('[name="typeSettings[tags]"]').val(apos.tagsToString(data.tags)); | ||
@@ -57,5 +54,3 @@ } | ||
// Make a new snippet | ||
apos.log('self._css is ' + self._css); | ||
$('body').on('click', '[data-new-' + self._css + ']', function() { | ||
apos.log('we got inside click'); | ||
var $el = apos.modalFromTemplate('.apos-new-' + self._css, { | ||
@@ -66,4 +61,6 @@ save: function(callback) { | ||
init: function(callback) { | ||
return self.enableArea($el, [], function() { | ||
self.afterPopulatingEditor($el, {}, callback); | ||
return self.enableArea($el, 'body', null, function() { | ||
return self.enableSingleton($el, 'thumbnail', null, 'slideshow', { limit: 1, label: 'Thumbnail' }, function() { | ||
self.afterPopulatingEditor($el, {}, callback); | ||
}); | ||
}); | ||
@@ -94,11 +91,70 @@ } | ||
self.enableArea = function($el, content, callback) { | ||
$.post('/apos/edit-virtual-area', { content: JSON.stringify(content) }, function(data) { | ||
var editView = $el.find('[data-body-edit-view]'); | ||
editView.append(data); | ||
return callback(null); | ||
} | ||
); | ||
self.enableSingleton = function($el, name, area, type, optionsArg, callback) { | ||
if (typeof(optionsArg) === 'function') { | ||
callback = optionsArg; | ||
optionsArg = {}; | ||
} | ||
var items = []; | ||
if (area && area.items) { | ||
items = area.items; | ||
} | ||
var options = {}; | ||
$.extend(options, optionsArg); | ||
$.extend(options, { | ||
type: type | ||
}); | ||
refreshSingleton(items, callback); | ||
function refreshSingleton(items, callback) { | ||
options.content = JSON.stringify(items); | ||
$.post('/apos/edit-virtual-singleton', options, function(data) { | ||
var $editView = $el.find('[data-' + name + '-edit-view]'); | ||
$editView.html(''); | ||
$editView.append(data); | ||
// getSingletonJSON will pick it up from here | ||
$editView.data('items', items); | ||
// If an edit takes place, refresh so we can see the new preview here | ||
// in the form. This isn't an issue with areas since they are always | ||
// in the edit state in a form. TODO: consider whether it would be | ||
// better to create a container that allows widgets to be rendered | ||
// inline, without a nested dialog box | ||
var $singleton = $editView.find('.apos-singleton:first'); | ||
$singleton.bind('apos-edited', function(e, data) { | ||
refreshSingleton([data]); | ||
}); | ||
if (callback) { | ||
return callback(null); | ||
} | ||
}); | ||
} | ||
}; | ||
self.enableArea = function($el, name, area, callback) { | ||
var items = []; | ||
if (area && area.items) { | ||
items = area.items; | ||
} | ||
$.post('/apos/edit-virtual-area', { content: JSON.stringify(items) }, function(data) { | ||
var $editView = $el.find('[data-' + name + '-edit-view]'); | ||
$editView.append(data); | ||
return callback(null); | ||
}); | ||
}; | ||
self.getSingletonJSON = function($el, name) { | ||
var items = $el.find('[data-' + name + '-edit-view]').data('items'); | ||
items = items || []; | ||
return JSON.stringify(items); | ||
}; | ||
self.getAreaJSON = function($el, name) { | ||
return apos.stringifyArea($el.find('[data-' + name + '-edit-view] [data-editable]')); | ||
}; | ||
self.insertOrUpdate = function($el, action, options, callback) { | ||
@@ -110,3 +166,4 @@ var data = { | ||
type: $el.find('[name="type"]').val(), | ||
content: apos.stringifyArea($el.find('[data-editable]')), | ||
thumbnail: self.getSingletonJSON($el, 'thumbnail'), | ||
content: self.getAreaJSON($el, 'body'), | ||
originalSlug: options.slug | ||
@@ -145,3 +202,2 @@ }; | ||
var snippets; | ||
apos.log('manage clicked for ' + self._css); | ||
$el = apos.modalFromTemplate('.apos-manage-' + self._css, { | ||
@@ -174,8 +230,3 @@ init: function(callback) { | ||
if (callback) { | ||
apos.log('calling back after populating manager'); | ||
apos.log('$snippets.length is ' + $snippets.length); | ||
apos.log('Inserted snippets: ' + $el.find('[data-item]:not(.apos-template)').length); | ||
return callback(null); | ||
} else { | ||
apos.log('enh no callback'); | ||
} | ||
@@ -201,3 +252,2 @@ }); | ||
snippet = data.pop(); | ||
apos.log(snippet); | ||
@@ -208,4 +258,2 @@ $el.find('[name=title]').val(snippet.title); | ||
apos.log('BEFORE suggest slug'); | ||
apos.log($el[0]); | ||
// name=slug must always exist, at least as a hidden field, to support this | ||
@@ -226,4 +274,8 @@ apos.suggestSlugOnTitleEdits($el.find('[name=title]'), $el.find('[name=slug]')); | ||
self.enableArea($el, snippet.areas.body ? snippet.areas.body.items : [], function() { | ||
self.afterPopulatingEditor($el, snippet, callback); | ||
// TODO: looks like it's probably worth having the async module client side | ||
self.enableArea($el, 'body', snippet.areas.body, function() { | ||
self.enableSingleton($el, 'thumbnail', snippet.areas.thumbnail, 'slideshow', { | ||
limit: 1, label: 'Thumbnail' }, function() { | ||
self.afterPopulatingEditor($el, snippet, callback); | ||
}); | ||
}); | ||
@@ -242,3 +294,2 @@ }); | ||
$('body').on('click', '[data-import-' + self._css + ']', function() { | ||
apos.log('import clicked for ' + self._css); | ||
var valid = false; | ||
@@ -262,3 +313,2 @@ $el = apos.modalFromTemplate('.apos-import-' + self._css, { | ||
var data = data.result; | ||
apos.log(data); | ||
if (data.status === 'ok') { | ||
@@ -265,0 +315,0 @@ alert('Successful import. Imported ' + data.rows + ' items.'); |
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
Sorry, the diff of this file is not supported yet
60972
1251