From 5b7e5a133e5326a98b974b7e9e390ac393d1a05e Mon Sep 17 00:00:00 2001 From: Sean Fridman Date: Mon, 13 Apr 2015 13:42:11 -0400 Subject: Client friendly error handling --- examples/index.js | 2 ++ 1 file changed, 2 insertions(+) (limited to 'examples/index.js') diff --git a/examples/index.js b/examples/index.js index 95d2bcf..3e9f509 100644 --- a/examples/index.js +++ b/examples/index.js @@ -4,6 +4,8 @@ var app = okcms.createApp({ root: 'public', + debug: false, + schemas: { page: { id: {type: 'string'}, -- cgit v1.2.3-70-g09d2 From 8898bbe48285c7f9f11760ef420cca43d683d5e0 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 28 Mar 2016 13:59:50 -0400 Subject: modify links field to specify text and uri --- app/index.js | 1 + app/node_modules/okdb/index.js | 2 +- app/node_modules/okschema/index.js | 17 +++++++- examples/db.json | 9 +++- examples/index.js | 5 ++- package.json | 2 +- themes/okadmin/public/css/main.css | 8 ++++ themes/okadmin/public/js/app.js | 34 ++++++--------- themes/okadmin/templates/partials/inputs.liquid | 56 +++++++++++++++++++------ 9 files changed, 93 insertions(+), 41 deletions(-) (limited to 'examples/index.js') diff --git a/app/index.js b/app/index.js index 6a1c74f..06b1591 100644 --- a/app/index.js +++ b/app/index.js @@ -28,6 +28,7 @@ function OKCMS(options) { var app = express(); app.enable('strict routing'); + app.disable('x-powered-by'); var root = this._root = options.root || 'public'; var adminConfig = options.admin || {}; diff --git a/app/node_modules/okdb/index.js b/app/node_modules/okdb/index.js index 4820c8c..ad8d9a7 100644 --- a/app/node_modules/okdb/index.js +++ b/app/node_modules/okdb/index.js @@ -97,7 +97,7 @@ FSDB.prototype.update = function(collection, id, data) { } var result = chain.assign(cloneDeep(data)).value(); - if (result ) { + if (result) { return resolve(cloneDeep(result)); } else { return resolve(null, new Error('Problem updating document')); diff --git a/app/node_modules/okschema/index.js b/app/node_modules/okschema/index.js index 330ad6b..82aa13f 100644 --- a/app/node_modules/okschema/index.js +++ b/app/node_modules/okschema/index.js @@ -63,8 +63,21 @@ var types = { assertValid: function(spec, value) {} }, 'tag-list': { - parent: 'string', - assertValid: function(spec, value) {} + parent: [{ + uri: { type: 'string' }, + text: { type: 'string' } + }], + assertValid: function(spec, value) { + var message; + var actual; + if (!value || !value.length) { + throw [{ + message: 'Not an array', + expected: JSON.stringify(this.parent), + actual: value + }]; + } + } }, 'date': { parent: 'string', diff --git a/examples/db.json b/examples/db.json index 20d4510..4319237 100644 --- a/examples/db.json +++ b/examples/db.json @@ -99,7 +99,14 @@ "title": "About Us", "body": "Just a small bakery", "id": "about", - "__index": 1 + "__index": "1", + "links": [ + { + "text": "asdf2", + "uri": "asdf" + } + ], + "dateCreated": "" }, { "title": "ok...", diff --git a/examples/index.js b/examples/index.js index 3e9f509..bf51dfc 100644 --- a/examples/index.js +++ b/examples/index.js @@ -10,7 +10,8 @@ var app = okcms.createApp({ page: { id: {type: 'string'}, title: {type: 'string'}, - body: {type: 'text'} + body: {type: 'text'}, + links: {type: 'link-list'}, }, bread: { type: {type: 'string', id: true}, @@ -19,7 +20,7 @@ var app = okcms.createApp({ color: {type: 'enum', options: ["red","blue","green"]}, video: {type: 'video'}, images: {type: 'captioned-image-list'} - } + }, }, resources: [ diff --git a/package.json b/package.json index 192685c..faf3cc9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "okcms", - "version": "0.1.18", + "version": "0.1.19", "description": "great", "main": "app/index.js", "scripts": { diff --git a/themes/okadmin/public/css/main.css b/themes/okadmin/public/css/main.css index a5fbdeb..9289fdf 100644 --- a/themes/okadmin/public/css/main.css +++ b/themes/okadmin/public/css/main.css @@ -305,6 +305,14 @@ button, input[type=submit] { .main.resource form .video-element input[type=text] { width: 15em; } +.main.resource form .group input[type=text].link-input, +.main.resource form .group input[type=text].link-input-new { + width: 13.05em; + padding: 0 0 0 0.5em; +} +.main.resource form .links li { + height: auto; +} .main .link-list .add-link-btn, .main .link-list .remove-link-btn { margin: 0; diff --git a/themes/okadmin/public/js/app.js b/themes/okadmin/public/js/app.js index edf9980..17b35d0 100644 --- a/themes/okadmin/public/js/app.js +++ b/themes/okadmin/public/js/app.js @@ -120,35 +120,25 @@ var OKAdmin = function(){ e.stopPropagation() var $delegate = $(e.delegateTarget) var $list = $delegate.find('.links') - var length = $list.find('input').length - var name = $delegate.parent('.property').data('name') - var $new = $delegate.find('.link-input-new') - var input = document.createElement('input') - var delBtn = document.createElement('button') - var inputName = name + '[' + length + ']' - $(input).attr({ - name: inputName, - type: 'text', - value: $new.val() - }) - $list.append(input) - $(delBtn).addClass('remove-link-btn') - $(delBtn).data('for', inputName) - delBtn.innerHTML = '-' - $list.append(delBtn) - $new.val('') + var $linkText = $delegate.find(".link-input-new.link-text") + var $linkURI = $delegate.find(".link-input-new.link-uri") + + var template = $delegate.find(".link-template").html() + var $el = $(template) + $el.find(".link-text").val( $linkText.val() ) + $el.find(".link-uri").val( $linkURI.val() ) + $list.append($el) + console.log($list, template) + $linkText.val("") + $linkURI.val("") }) // Remove a link from the list $('.link-list').on('click', '.remove-link-btn', function(e) { e.preventDefault() e.stopPropagation() - var $delegate = $(e.delegateTarget) var $target = $(e.target) - var inputName = $target.data('for') - var $input = $delegate.find('[name="' + inputName + '"]') - $input.remove() - $target.remove() + $target.closest("li").remove() }) // fix post indexing in list-driven inputs diff --git a/themes/okadmin/templates/partials/inputs.liquid b/themes/okadmin/templates/partials/inputs.liquid index c6efc68..55d5fb8 100644 --- a/themes/okadmin/templates/partials/inputs.liquid +++ b/themes/okadmin/templates/partials/inputs.liquid @@ -79,26 +79,58 @@ value="{{spec.value}}" placeholder="Enter a comma separated list of tags."> - {% elsif type == 'link-list' %} + {% elsif type == 'link-list' %} {% elsif type == 'media-list' %} -- cgit v1.2.3-70-g09d2 From d8e9b4d5334db049feec81b0083c3adcedaf7e12 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 28 Mar 2016 19:10:26 -0400 Subject: allow generic urls in media field --- examples/db.json | 15 +++++++++ examples/index.js | 6 ++++ themes/okadmin/public/js/app.js | 38 ++++++++++++++++------- themes/okadmin/public/js/parser.js | 4 +-- themes/okadmin/templates/partials/inputs.liquid | 41 ++++++++++++++++++++----- 5 files changed, 83 insertions(+), 21 deletions(-) (limited to 'examples/index.js') diff --git a/examples/db.json b/examples/db.json index 9ab7233..b9de44b 100644 --- a/examples/db.json +++ b/examples/db.json @@ -124,5 +124,20 @@ ], "dateCreated": "" } + ], + "test": [ + { + "id": "test", + "title": "tEst", + "media": [ + { + "uri": "http://asdf.us/", + "caption": "ASDF", + "type": "link" + } + ], + "__index": "0", + "dateCreated": "Mon, 28 Mar 2016 23:02:45 GMT" + } ] } \ No newline at end of file diff --git a/examples/index.js b/examples/index.js index bf51dfc..4bf385f 100644 --- a/examples/index.js +++ b/examples/index.js @@ -21,12 +21,18 @@ var app = okcms.createApp({ video: {type: 'video'}, images: {type: 'captioned-image-list'} }, + test: { + id: {type: 'string', hidden: true}, + title: {type: 'string'}, + media: {type: 'media-list'}, + } }, resources: [ { type: 'page', static: {id: 'about'}}, { type: 'page', static: {id: 'contact'}}, { type: 'bread' }, + { type: 'test' }, ], services: { diff --git a/themes/okadmin/public/js/app.js b/themes/okadmin/public/js/app.js index da398eb..61fc8c8 100644 --- a/themes/okadmin/public/js/app.js +++ b/themes/okadmin/public/js/app.js @@ -47,17 +47,33 @@ var OKAdmin = function(){ $("ol", parent).prepend($el) } uploader.addVideo = function(media){ - console.log(media) - var videoTemplate = $(".video-template", parent).html() - var $el = $(videoTemplate) - $el.addClass("loaded") - $el.find(".video-type").val( media.type ) - $el.find(".video-token").val( media.token ) - $el.find(".video-title").val( media.title ) - $el.find(".video-thumb").val( media.thumbnail ) - $el.find("img").attr("src", media.thumbnail ) - $("ol", parent).prepend($el) - } + switch (media.type) { + case 'youtube': + case 'vimeo': + case 'video': + var videoTemplate = $(".video-template", parent).html() + var $el = $(videoTemplate) + $el.addClass("loaded") + $el.find(".video-type").val( media.type ) + $el.find(".video-token").val( media.token ) + $el.find(".video-title").val( media.title ) + $el.find(".video-thumb").val( media.thumbnail ) + $el.find(".video-width").val( media.width ) + $el.find(".video-height").val( media.height ) + $el.find("img").attr("src", media.thumbnail ) + $("ol", parent).prepend($el) + break + case 'link': + var linkTemplate = $(".link-template", parent).html() + var $el = $(linkTemplate) + $el.addClass("loaded") + $el.find(".uri").val( media.url ) + $("ol", parent).prepend($el) + break + default: + alert("Unsupported link type!") + } + } }) // delete image from gallery $(document).on("mousedown", ".media-list .remove", function(){ diff --git a/themes/okadmin/public/js/parser.js b/themes/okadmin/public/js/parser.js index 411f425..95b391c 100644 --- a/themes/okadmin/public/js/parser.js +++ b/themes/okadmin/public/js/parser.js @@ -145,7 +145,6 @@ var Parser = { '&color=ff6600&auto_play=false&show_artwork=true">' } }, - /* { type: 'link', regex: /^http.+/i, @@ -163,8 +162,7 @@ var Parser = { tag: function (media) { return '' + media.url + '' } - } - */ + }, ], tumblr: function(url, cb){ diff --git a/themes/okadmin/templates/partials/inputs.liquid b/themes/okadmin/templates/partials/inputs.liquid index 4acb435..77ee7a4 100644 --- a/themes/okadmin/templates/partials/inputs.liquid +++ b/themes/okadmin/templates/partials/inputs.liquid @@ -29,6 +29,8 @@ + + @@ -143,11 +145,12 @@ - + + +
    {% for image in spec.value %} - {% if image.token %} + {% if image.type and (image.type == "vimeo" or image.type == "youtube" or image.type == "video") %}
  1. + + @@ -185,11 +201,22 @@
  2. + {% elsif image.type and image.type == "link" %} + {% else %}
  3. + - {{image.caption}} + + {{image.caption | strip_html}}
  4. {% endif %} @@ -210,7 +237,7 @@
  5. - {{image.caption}} +
  6. @@ -220,7 +247,7 @@
  7. - {{image.caption}} + {{image.caption | strip_html}}
  8. {% endfor %} @@ -238,7 +265,7 @@ + + -- cgit v1.2.3-70-g09d2 From 654053736a74aa8cd4344e9c4f5e5a7ebeefc33e Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Wed, 6 Apr 2016 19:11:22 -0400 Subject: Store booleans as type boolean --- app/index.js | 2 +- app/node_modules/okadminview/index.js | 3 ++- app/node_modules/okschema/index.js | 13 ++++++++----- examples/db.json | 3 ++- examples/index.js | 1 + 5 files changed, 14 insertions(+), 8 deletions(-) (limited to 'examples/index.js') diff --git a/app/index.js b/app/index.js index d478a03..1a8f97e 100644 --- a/app/index.js +++ b/app/index.js @@ -151,7 +151,7 @@ OKCMS.prototype._createResources = function(resourceConfig, db, schemaCache) { var schema = schemaCache[type]; if (!schema) throw new Error('Resource config references nonexistent schema ' + type); - var resource = OKResource({ + var resource = new OKResource({ type: type, db: db, schema: schema diff --git a/app/node_modules/okadminview/index.js b/app/node_modules/okadminview/index.js index ec3cd86..b94c814 100644 --- a/app/node_modules/okadminview/index.js +++ b/app/node_modules/okadminview/index.js @@ -247,6 +247,7 @@ function OKAdminView(options) { if (!resource) { error(req, res, 400)(new Error('No such resource ' + type)); } else { + var spec = resource.spec try { resource.assertValid(data); resource.update(id, data).then(function(updated) { @@ -254,7 +255,7 @@ function OKAdminView(options) { res.redirect(303, '../' + resource.getID(updated)); }).fail(error(req, res, 500)); } catch (errors) { - var templateData = transformData(meta, resource, data); + var templateData = transformData(meta, spec, resource, data); view.renderResource(req, res, assign(templateData, {errors: errors})); } } diff --git a/app/node_modules/okschema/index.js b/app/node_modules/okschema/index.js index 8162fd4..b3d4cc2 100644 --- a/app/node_modules/okschema/index.js +++ b/app/node_modules/okschema/index.js @@ -66,7 +66,7 @@ var types = { assertValid: function(spec, value) {} }, 'flag': { - parent: 'string', + parent: 'boolean', assertValid: function(spec, value) {} }, 'foreign-key': { @@ -207,14 +207,17 @@ OKSchema.prototype.assertValid = function(data) { // Run through custom validators, they'll throw if invalid Object.keys(data).forEach(function(prop) { var type = spec[prop].type; - if (types[type]) { - types[type].assertValid(spec[prop], data[prop]); - // Also check if it's a number type and try to cast it + + // Check if it's a number/boolean and try to cast it // otherwise pass and let mschema handle - } else if (type === 'number') { + if (type === 'number') { try { data[prop] = parseFloat(data[prop]); } catch (err) {} + } else if (type === 'flag') { + data[prop] = data[prop] == "true" ? true : false + } else if (types[type]) { + types[type].assertValid(spec[prop], data[prop]); } }); var result = mschema.validate(data, this.toMschema()); diff --git a/examples/db.json b/examples/db.json index da7c19a..8805342 100644 --- a/examples/db.json +++ b/examples/db.json @@ -207,7 +207,8 @@ "title": "clouds35.mp3", "thumb": "http://okfocus.s3.amazonaws.com/misc/okcms/video.png" } - ] + ], + "flagged": true } ] } \ No newline at end of file diff --git a/examples/index.js b/examples/index.js index 57bce4b..fe37954 100644 --- a/examples/index.js +++ b/examples/index.js @@ -24,6 +24,7 @@ var app = okcms.createApp({ test: { id: {type: 'string', hidden: true}, title: {type: 'string'}, + flagged: {type: 'flag'}, media: {type: 'media-list'}, } }, -- cgit v1.2.3-70-g09d2 From 180cf3eaa829fd04f759488d76641c4656caa245 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 11 Apr 2016 14:20:33 -0400 Subject: rewrite file upload code to use knox directly --- app/node_modules/okserver/index.js | 2 + app/node_modules/okservices/oks3/index.js | 136 +++++++++++++++----------- app/node_modules/okservices/oks3/package.json | 5 +- app/node_modules/okservices/oks3/upload.js | 80 +++++++++++++++ examples/index.js | 7 +- themes/okadmin/public/js/upload.js | 2 +- 6 files changed, 166 insertions(+), 66 deletions(-) create mode 100644 app/node_modules/okservices/oks3/upload.js (limited to 'examples/index.js') diff --git a/app/node_modules/okserver/index.js b/app/node_modules/okserver/index.js index 3428565..302911d 100644 --- a/app/node_modules/okserver/index.js +++ b/app/node_modules/okserver/index.js @@ -52,6 +52,8 @@ function OKServer(options) { * other middleware. */ + // Disable silly express header + app.disable('x-powered-by') // Serve user static files app.use(express.static(root)); // Serve admin interface static files diff --git a/app/node_modules/okservices/oks3/index.js b/app/node_modules/okservices/oks3/index.js index 34c5840..c636308 100644 --- a/app/node_modules/okservices/oks3/index.js +++ b/app/node_modules/okservices/oks3/index.js @@ -1,5 +1,5 @@ -var skipper = require('skipper'); -var skipperS3 = require('skipper-s3') +var upload = require("./upload") +var multer = require('multer') // Hack to prevent this god-forsaken module from crashing our shit var d = require('domain').create() @@ -20,7 +20,6 @@ function OKS3(options) { if (!options.s3.audio) options.s3.audio = {} if (!options.s3.video) options.s3.video = {} -/* // TODO: maxBytes property doesn't work - if you upload a large file, // it will just hang until you reload the browser, and then CRASH. @@ -34,85 +33,104 @@ function OKS3(options) { if (! ('maxbytes' in options.s3.audio)) options.s3.audio.maxbytes = options.s3.maxbytes } -*/ - if (options.s3.image.preserveFilename) - options.s3.image.preserveFilename = preserveFilename - if (options.s3.video.preserveFilename) - options.s3.video.preserveFilename = preserveFilename - if (options.s3.audio.preserveFilename) - options.s3.audio.preserveFilename = preserveFilename + if (typeof options.s3.image.allowed !== "boolean") + options.s3.image.allowed = true + if (typeof options.s3.video.allowed !== "boolean") + options.s3.video.allowed = false + if (typeof options.s3.audio.allowed !== "boolean") + options.s3.audio.allowed = false + + upload.init({ + key: options.s3.key, + secret: options.s3.secret, + bucket: options.s3.bucket, + }) var express = options.express; var router = express.Router(); - router.use(skipper()); + var mult = multer() - // req should have a method `file` on it which is - // provided by skipper. Use that to do AWS stuff - router.post('/image', function(req, res) { + router.post('/image', mult.single('image'), function(req, res) { d.run(function () { - var skip = req.file('image').upload({ - adapter: skipperS3, - key: options.s3.key, - secret: options.s3.secret, - bucket: options.s3.bucket, + + if (! options.s3.image.allowed) { + return res.status(500).json({ error: "Image uploading not permitted" }) + } + + upload.put({ + file: req.file, + preserveFilename: options.s3.image.preserveFilename, dirname: options.s3.dirname, - // maxBytes: options.s3.image.maxbytes, - saveAs: options.s3.image.preserveFilename, - headers: { - 'x-amz-acl': 'public-read' + types: { + 'image/gif': 'gif', + 'image/jpeg': 'jpg', + 'image/jpg': 'jpg', + 'image/png': 'png', + }, + unacceptable: function(err){ + res.json({ error: err }) + }, + success: function(url){ + res.json({ url: url }) } - }, function (err, uploadedFiles) { - if (err) return res.status(500).send(err) - res.json(uploadedFiles); - }); + }) + }); }); - router.post('/audio', function(req, res) { + router.post('/audio', mult.single('audio'), function(req, res) { d.run(function () { - if (! options.s3.allowAudioUploads) { - return res.status(500).json({ error: "audio uploading not permitted" }) + + if (! options.s3.image.allowed) { + return res.status(500).json({ error: "Audio uploading not permitted" }) } - req.file('audio').upload({ - adapter: skipperS3, - key: options.s3.key, - secret: options.s3.secret, - bucket: options.s3.bucket, + + upload.put({ + file: req.file, + preserveFilename: options.s3.audio.preserveFilename, dirname: options.s3.dirname, - // maxBytes: options.s3.audio.maxbytes, - saveAs: options.s3.audio.preserveFilename, - headers: { - 'x-amz-acl': 'public-read' + types: { + 'audio/mp3': 'mp3', + 'audio/mpeg': 'mp3', + 'audio/wav': 'wav', + 'audio/flac': 'flac', + }, + unacceptable: function(err){ + res.json({ error: err }) + }, + success: function(url){ + res.json({ url: url }) } - }, function (err, uploadedFiles) { - if (err) res.status(500).send(err) - res.json(uploadedFiles); - }); + }) + }); }); - router.post('/video', function(req, res) { + router.post('/video', mult.single('video'), function(req, res) { d.run(function () { - if (! options.s3.allowVideoUploads) { - return res.status(500).json({ error: "video uploading not permitted" }) + + if (! options.s3.image.allowed) { + return res.status(500).json({ error: "Video uploading not permitted" }) } - req.file('video').upload({ - adapter: skipperS3, - key: options.s3.key, - secret: options.s3.secret, - bucket: options.s3.bucket, + + upload.put({ + file: req.file, + preserveFilename: options.s3.video.preserveFilename, dirname: options.s3.dirname, - // maxBytes: options.s3.video.maxbytes, - saveAs: options.s3.video.preserveFilename, - headers: { - 'x-amz-acl': 'public-read' + types: { + 'video/mp4': 'mp4', + 'video/webm': 'webm', + }, + unacceptable: function(err){ + res.json({ error: err }) + }, + success: function(url){ + res.json({ url: url }) } - }, function (err, uploadedFiles) { - if (err) res.status(500).send(err) - res.json(uploadedFiles); - }); + }) + }); }); diff --git a/app/node_modules/okservices/oks3/package.json b/app/node_modules/okservices/oks3/package.json index 19a2d2a..35bb4ce 100644 --- a/app/node_modules/okservices/oks3/package.json +++ b/app/node_modules/okservices/oks3/package.json @@ -9,7 +9,8 @@ "author": "OKFocus", "license": "None", "dependencies": { - "skipper": "^0.5.9", - "skipper-s3": "^0.5.6" + "knox": "^0.9.2", + "multer": "^1.1.0", + "node-uuid": "^1.4.7", } } diff --git a/app/node_modules/okservices/oks3/upload.js b/app/node_modules/okservices/oks3/upload.js new file mode 100644 index 0000000..6b16d61 --- /dev/null +++ b/app/node_modules/okservices/oks3/upload.js @@ -0,0 +1,80 @@ + +var knox = require('knox') +var moment = require('moment') +var uuid = require('node-uuid') + +var s3 + +var acceptableuploadTypes = { + 'image/gif': 'gif', + 'image/jpeg': 'jpg', + 'image/jpg': 'jpg', + 'image/png': 'png', +} + +module.exports = {} + +module.exports.init = function (opt){ + s3 = knox.createClient({ + key: opt.key, + secret: opt.secret, + bucket: opt.bucket, + }) +} + +module.exports.put = function (opt) { + var filename + var err + var now = new Date() + + var file = opt.file + + var types = opt.types || acceptableuploadTypes + var extension = types[file.mimetype] + + if (opt.preserveFilename) { + filename = file.originalname + } + else { + filename = uuid.v1() + "." + extension; + } + + var remote_path = "/" + opt.dirname + "/" + filename + + if (! extension) { + err = "Unacceptable filetype." + } + else if (opt.maxSize && file.size > opt.maxSize) { + err = "File too large. Uploads can be a maximum of " + opt.maxSize + " bytes." + } + + if (err) { + console.error(">>>", err) + opt.unacceptable && opt.unacceptable(err) + return + } + + opt.acceptable && opt.acceptable(err) + + // console.log("upload >", remote_path) + s3.putBuffer(file.buffer, remote_path, { + 'Content-Length': file.size, + 'Content-Type': file.mimetype, + 'x-amz-acl': 'public-read' + }, function(err, s3res) { + if (err || s3res.statusCode !== 200) { + console.error(err); + if (s3res && s3res.resume) { + s3res.resume() + } + return; + } + + var file_url = s3res.url || s3res.req.url + + opt.success && opt.success(file_url) + }).on('error', function(err, s3res){ + console.error(err) + s3res && s3res.resume && s3res.resume() + }) +} diff --git a/examples/index.js b/examples/index.js index fe37954..31ae8d2 100644 --- a/examples/index.js +++ b/examples/index.js @@ -42,10 +42,9 @@ var app = okcms.createApp({ secret: process.env.S3_SECRET, bucket: process.env.S3_BUCKET, dirname: "okcms-example", - // TODO: maxbytes stuff isn't working, need to change underlying module - image: { preserveFilename: false, maxbytes: 20000 }, - video: { preserveFilename: true, maxbytes: 0 }, - audio: { preserveFilename: true, maxbytes: 150000000 }, + image: { allowed: true, preserveFilename: false, maxbytes: 2*1024*1024 }, + video: { allowed: true, preserveFilename: true, maxbytes: 200*1024*1024 }, + audio: { allowed: true, preserveFilename: true, maxbytes: 100*1024*1024 }, } }, diff --git a/themes/okadmin/public/js/upload.js b/themes/okadmin/public/js/upload.js index 44a34b5..da23b1b 100644 --- a/themes/okadmin/public/js/upload.js +++ b/themes/okadmin/public/js/upload.js @@ -167,7 +167,7 @@ OKUpload.prototype.success = function(data){ console.log(data.error) return } - var url = data[0].extra.Location.replace(/%2F/, '\/') + var url = data.url console.log(url) this.parse(url) } -- cgit v1.2.3-70-g09d2 From fa343212514f1e6f975e5cf5957e440555afb815 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Thu, 14 Apr 2016 14:14:34 -0400 Subject: example services --- examples/index.js | 9 +++++++ examples/lib/okdumpfm/index.js | 39 ++++++++++++++++++++++++++++++ examples/lib/okdumpfm/package.json | 14 +++++++++++ examples/lib/okexample/index.js | 48 +++++++++++++++++++++++++++++++++++++ examples/lib/okexample/package.json | 11 +++++++++ 5 files changed, 121 insertions(+) create mode 100644 examples/lib/okdumpfm/index.js create mode 100644 examples/lib/okdumpfm/package.json create mode 100644 examples/lib/okexample/index.js create mode 100644 examples/lib/okexample/package.json (limited to 'examples/index.js') diff --git a/examples/index.js b/examples/index.js index 31ae8d2..3bbed28 100644 --- a/examples/index.js +++ b/examples/index.js @@ -45,6 +45,15 @@ var app = okcms.createApp({ image: { allowed: true, preserveFilename: false, maxbytes: 2*1024*1024 }, video: { allowed: true, preserveFilename: true, maxbytes: 200*1024*1024 }, audio: { allowed: true, preserveFilename: true, maxbytes: 100*1024*1024 }, + }, + + example: { + lib: require("./lib/okexample"), + stuff: "things", + }, + + dumpfm: { + lib: require("./lib/okdumpfm"), } }, diff --git a/examples/lib/okdumpfm/index.js b/examples/lib/okdumpfm/index.js new file mode 100644 index 0000000..4dc5461 --- /dev/null +++ b/examples/lib/okdumpfm/index.js @@ -0,0 +1,39 @@ +var request = require('request') + +/** + * Example service which queries the Dump search. + */ +function OKDumpfm (options) { + if (!(this instanceof OKDumpfm)) return new OKDumpfm(options) + options = options || {} + if (!options.express) + throw new Error('Express not provided to OKDumpfm'); + + var express = options.express + var router = express.Router() + + router.get('*', function (req, res) { + var query = req.query.q + request('http://dump.fm/cmd/search/' + query, function (err, response, body) { + if (err || response.statusCode !== 200) { + res.status(response.statusCode) + res.send(err) + } else { + res.set('Content-Type', 'application/json; charset=utf-8') + res.send(body) + } + }) + }) + + router.post('*', function (req, res) { + throw new Error('OKDumpfm POST requests not implemented') + }) + + this._router = router +} + +OKDumpfm.prototype.middleware = function () { + return this._router +} + +module.exports = OKDumpfm diff --git a/examples/lib/okdumpfm/package.json b/examples/lib/okdumpfm/package.json new file mode 100644 index 0000000..17bcba2 --- /dev/null +++ b/examples/lib/okdumpfm/package.json @@ -0,0 +1,14 @@ +{ + "name": "okdumpfm", + "version": "1.0.0", + "description": "service to query the dump search API", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "okfocus ", + "license": "LNT", + "dependencies": { + "request": "^2.71.0" + } +} diff --git a/examples/lib/okexample/index.js b/examples/lib/okexample/index.js new file mode 100644 index 0000000..b614697 --- /dev/null +++ b/examples/lib/okexample/index.js @@ -0,0 +1,48 @@ + +/** + * Example service to show how these things should be set up. + * + * Services should be added to index.js in the proper area, + * with any configuration parameters that you want passed in: + * + * services: { + * example: { + * lib: require("./lib/okexample"), + * stuff: "things", + * } + * }, + * + * The service will be mounted on /_services/example + * + * This binds to route '*' but you can specify e.g. "/thing", + * and it will be mounted on /_services/example/thing + */ + +function OKExample (options) { + if (!(this instanceof OKExample)) return new OKExample(options) + options = options || {} + if (!options.express) + throw new Error('Express not provided to OKDumpfm'); + if (!options.config) + throw new Error('Configuration not provided to OKDumpfm'); + + var express = options.express + var router = express.Router() + var config = options.config + + router.get('*', function (req, res) { + res.send(config.stuff) + }) + + router.post('*', function (req, res) { + throw new Error('OKExample POST requests not implemented') + }) + + this._router = router +} + +OKExample.prototype.middleware = function () { + return this._router +} + +module.exports = OKExample diff --git a/examples/lib/okexample/package.json b/examples/lib/okexample/package.json new file mode 100644 index 0000000..2b2a47c --- /dev/null +++ b/examples/lib/okexample/package.json @@ -0,0 +1,11 @@ +{ + "name": "okexample", + "version": "1.0.0", + "description": "example service", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "okfocus ", + "license": "LNT" +} -- cgit v1.2.3-70-g09d2 From c98560cca095ef27b909ac47baf843362bffb28d Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Thu, 14 Apr 2016 20:32:08 -0400 Subject: OKWebhook module for receiving pushes from git --- app/index.js | 7 ++ app/node_modules/okservices/okwebhook/index.js | 83 ++++++++++++++++++++++ app/node_modules/okservices/okwebhook/package.json | 11 +++ examples/index.js | 11 ++- examples/lib/okexample/index.js | 5 +- 5 files changed, 114 insertions(+), 3 deletions(-) create mode 100644 app/node_modules/okservices/okwebhook/index.js create mode 100644 app/node_modules/okservices/okwebhook/package.json (limited to 'examples/index.js') diff --git a/app/index.js b/app/index.js index 8c3abb9..48e713a 100644 --- a/app/index.js +++ b/app/index.js @@ -15,6 +15,7 @@ var OKServer = require('okserver'); var OKSchema = require('okschema'); var OKS3Service = require('okservices/oks3'); var OKTwitterService = require('okservices/oktwitter') +var OKWebhookService = require('okservices/okwebhook') require('dotenv').load(); @@ -110,6 +111,12 @@ function OKCMS(options) { credentials: config, }); break + case 'webhook': + services.webhook = OKWebhookService({ + express: express, + config: config, + }); + break default: services[key] = config.lib({ db: resourceCache, diff --git a/app/node_modules/okservices/okwebhook/index.js b/app/node_modules/okservices/okwebhook/index.js new file mode 100644 index 0000000..d04e662 --- /dev/null +++ b/app/node_modules/okservices/okwebhook/index.js @@ -0,0 +1,83 @@ + +/** + * Service which will listen for a Github webhook, fired on push. + * This service can be used to rebuild / restart the app automatically + * when new code is pushed. + */ + +var crypto = require('crypto') +var exec = require('child_process').exec +var path = require('path') + +function OKWebhook (options) { + if (!(this instanceof OKWebhook)) return new OKWebhook(options) + options = options || {} + if (!options.express) + throw new Error('Express not provided to OKWebhook'); + if (!options.config) + throw new Error('Configuration not provided to OKWebhook'); + if (options.config.active && !options.config.secret) + throw new Error('Github secret not provided to OKWebhook'); + if (options.config.active && !options.config.command) + throw new Error('Build command not provided to OKWebhook'); + + var express = options.express + var router = express.Router() + var config = options.config + + var secret = config.secret + var command = config.command + + router.get('/', function (req, res) { + res.send('GET not supported') + }) + + router.post('/', getBody, function (req, res) { + if (!config.active) + return + console.log("OKWebhook received push") + var event = req.headers['x-github-event'] + if (event !== "push") { + return res.sendStatus(500) + } + var sig = req.headers['x-hub-signature'].split('=')[1] + var text = req.rawBody + var hash = crypto.createHmac('sha1', secret).update(text).digest('hex') + if (hash !== sig) { + return res.sendStatus(500) + } + res.sendStatus(200) + var cwd = path.dirname(command) + exec(command, { cwd: cwd }, function(err, stdout, stderr){ + // may not fire if process was restarted.. + console.log(process.env) + console.log(stdout) + }) + }) + + function getBody (req, res, next) { + req.rawBody = '' + // req.setEncoding('utf8') + + req.on('data', function(chunk) { + req.rawBody += chunk + }) + + req.on('end', function() { + try { + req.body = JSON.parse(req.rawBody) + } catch (e) { + return res.sendStatus(500) + } + next() + }) + } + + this._router = router +} + +OKWebhook.prototype.middleware = function () { + return this._router +} + +module.exports = OKWebhook diff --git a/app/node_modules/okservices/okwebhook/package.json b/app/node_modules/okservices/okwebhook/package.json new file mode 100644 index 0000000..0436f01 --- /dev/null +++ b/app/node_modules/okservices/okwebhook/package.json @@ -0,0 +1,11 @@ +{ + "name": "okwebhook", + "version": "1.0.0", + "description": "webhook to receive pushes from github", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "okfocus ", + "license": "LNT" +} diff --git a/examples/index.js b/examples/index.js index 3bbed28..efbfc38 100644 --- a/examples/index.js +++ b/examples/index.js @@ -1,10 +1,13 @@ var okcms = require('..'); +var isProduction = process.env.OK_PRODUCTION === 'true' + var app = okcms.createApp({ root: 'public', - debug: true, + debug: !isProduction, + production: isProduction, schemas: { page: { @@ -47,6 +50,12 @@ var app = okcms.createApp({ audio: { allowed: true, preserveFilename: true, maxbytes: 100*1024*1024 }, }, + webhook: { + active: false, + secret: 'test', + command: '/path/to/build.sh', + }, + example: { lib: require("./lib/okexample"), stuff: "things", diff --git a/examples/lib/okexample/index.js b/examples/lib/okexample/index.js index b614697..04c5984 100644 --- a/examples/lib/okexample/index.js +++ b/examples/lib/okexample/index.js @@ -22,13 +22,14 @@ function OKExample (options) { if (!(this instanceof OKExample)) return new OKExample(options) options = options || {} if (!options.express) - throw new Error('Express not provided to OKDumpfm'); + throw new Error('Express not provided to OKExample'); if (!options.config) - throw new Error('Configuration not provided to OKDumpfm'); + throw new Error('Configuration not provided to OKExample'); var express = options.express var router = express.Router() var config = options.config + var db = options.db router.get('*', function (req, res) { res.send(config.stuff) -- cgit v1.2.3-70-g09d2 From f76ec56f3d70da6359905e9b9666f581599edd4f Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Thu, 21 Apr 2016 18:02:31 -0400 Subject: fix issue with single input fields, store image width/height --- examples/db.json | 24 ++++++++++++++++++++++- examples/index.js | 6 ++++++ package.json | 4 ++-- themes/okadmin/public/css/main.css | 4 +++- themes/okadmin/public/js/app.js | 26 ++++++++++++++++--------- themes/okadmin/templates/partials/inputs.liquid | 18 +++++++++++++++-- 6 files changed, 67 insertions(+), 15 deletions(-) (limited to 'examples/index.js') diff --git a/examples/db.json b/examples/db.json index 8805342..401bf26 100644 --- a/examples/db.json +++ b/examples/db.json @@ -153,6 +153,13 @@ "id": "red", "title": "Red", "media": [ + { + "uri": "https://ltho.s3.amazonaws.com/okcms-example/a91c4210-080c-11e6-8a7d-f30231d4ec26.png", + "width": "800", + "height": "800", + "caption": "", + "type": "image" + }, { "uri": "http://asdf.us/", "caption": "ASDF", @@ -160,7 +167,8 @@ } ], "__index": 0, - "dateCreated": "Mon, 28 Mar 2016 23:02:45 GMT" + "dateCreated": "Mon, 28 Mar 2016 23:02:45 GMT", + "flagged": false }, { "id": "blue", @@ -210,5 +218,19 @@ ], "flagged": true } + ], + "flour": [ + { + "id": "test", + "title": "TEST", + "image": { + "uri": "https://ltho.s3.amazonaws.com/okcms-example/7be163d0-080b-11e6-8a7d-f30231d4ec26.png", + "caption": "", + "width": "800", + "height": "800" + }, + "__index": 0, + "dateCreated": "Thu, 21 Apr 2016 21:52:44 GMT" + } ] } \ No newline at end of file diff --git a/examples/index.js b/examples/index.js index efbfc38..341a50b 100644 --- a/examples/index.js +++ b/examples/index.js @@ -29,6 +29,11 @@ var app = okcms.createApp({ title: {type: 'string'}, flagged: {type: 'flag'}, media: {type: 'media-list'}, + }, + flour: { + id: {type: 'string', hidden: true}, + title: {type: 'string'}, + image: {type: 'image'}, } }, @@ -37,6 +42,7 @@ var app = okcms.createApp({ { type: 'page', static: {id: 'contact'}}, { type: 'bread' }, { type: 'test' }, + { type: 'flour' }, ], services: { diff --git a/package.json b/package.json index 619b1c8..971efed 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "okcms", - "version": "0.1.33", - "description": "great", + "version": "0.1.34", + "description": "The dopest CMS on the planet.", "main": "app/index.js", "scripts": { "postinstall": "./install.sh", diff --git a/themes/okadmin/public/css/main.css b/themes/okadmin/public/css/main.css index 15b8781..e539a71 100644 --- a/themes/okadmin/public/css/main.css +++ b/themes/okadmin/public/css/main.css @@ -291,7 +291,9 @@ button, input[type=submit] { height: 7em; } .main.resource form img { - width: 10em; + width: auto; + height: auto; + max-width: 10em; max-height: 6em; border: 0; } diff --git a/themes/okadmin/public/js/app.js b/themes/okadmin/public/js/app.js index 59fc6ae..578d99f 100644 --- a/themes/okadmin/public/js/app.js +++ b/themes/okadmin/public/js/app.js @@ -9,8 +9,10 @@ var OKAdmin = function(){ var url = media.url var imageTemplate = $(".image-template", parent).html() var $el = $(imageTemplate) - $el.find(".uri").val(url) - $el.find("img").attr("src", url) + $el.find(".uri").val(media.url) + $el.find(".image-width").val(media.width) + $el.find(".image-height").val(media.height) + $el.find("img").attr("src", media.url) $("ol", parent).prepend($el) } }) @@ -44,8 +46,10 @@ var OKAdmin = function(){ var url = media.url var imageTemplate = $(".image-template", parent).html() var $el = $(imageTemplate) - $el.find(".uri").val(url) - $el.find("img").attr("src", url) + $el.find(".uri").val(media.url) + $el.find(".image-width").val(media.width) + $el.find(".image-height").val(media.height) + $el.find("img").attr("src", media.url) $("ol", parent).prepend($el) } uploader.addMedia = function(media){ @@ -103,11 +107,13 @@ var OKAdmin = function(){ var $el = $(this) var uploader = new OKUpload () uploader.bind( this ) - uploader.add = function(url){ - console.log(url) - $el.find(".uri").val(url) + uploader.add = function(media){ + console.log(media) + $el.find(".uri").val(media.url) $el.find(".caption").val("") - $el.find("img").attr("src", url).show() + $el.find(".image-width").val(media.width) + $el.find(".image-height").val(media.height) + $el.find("img").attr("src", media.url).show() $el.addClass("loaded") } }) @@ -117,6 +123,8 @@ var OKAdmin = function(){ var $el = $(this).closest(".image") $el.removeClass('loaded') $el.find(".uri").val("") + $el.find(".image-width").val("") + $el.find(".image-height").val("") $el.find(".caption").val("") $el.find("img").attr("src", "") } @@ -141,7 +149,7 @@ var OKAdmin = function(){ $el.parent().addClass("loaded") $el.parent().find(".video-type").val( media.type ) $el.parent().find(".video-token").val( media.token ) - $el.parent().find(".video-uri").val( media.uri ) + $el.parent().find(".video-uri").val( media.url ) $el.parent().find(".video-title").val( media.title ) $el.parent().find(".video-thumb").val( media.thumbnail ) $el.parent().find(".video-width").val( media.width ) diff --git a/themes/okadmin/templates/partials/inputs.liquid b/themes/okadmin/templates/partials/inputs.liquid index 373e580..e71f4ad 100644 --- a/themes/okadmin/templates/partials/inputs.liquid +++ b/themes/okadmin/templates/partials/inputs.liquid @@ -48,6 +48,8 @@
    + + {{spec.value.caption | escape}}
    @@ -154,6 +156,8 @@ + + @@ -165,8 +169,8 @@ - - + + @@ -249,6 +253,8 @@
  9. + + {{image.caption | strip_html}} @@ -271,6 +277,8 @@