summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJules Laplace <jules@okfoc.us>2016-04-05 14:05:35 -0400
committerJules Laplace <jules@okfoc.us>2016-04-05 14:05:35 -0400
commit56580705e3a62eaf1c498c1c0456fc33fe3b2f76 (patch)
treee0e42a12aae98aacc733e3f7bb210d72d63c9d19
parentcd929e1c38c02c1d048abe702c04c7d4d6188011 (diff)
broaden media support
-rw-r--r--app/node_modules/okserver/index.js2
-rw-r--r--app/node_modules/okservices/oks3/index.js54
-rw-r--r--examples/db.json29
-rw-r--r--examples/index.js5
-rw-r--r--package.json2
-rw-r--r--themes/okadmin/public/css/main.css3
-rw-r--r--themes/okadmin/public/js/app.js18
-rw-r--r--themes/okadmin/public/js/parser.js31
-rw-r--r--themes/okadmin/public/js/upload.js61
-rw-r--r--themes/okadmin/templates/partials/inputs.liquid68
10 files changed, 226 insertions, 47 deletions
diff --git a/app/node_modules/okserver/index.js b/app/node_modules/okserver/index.js
index ee1b4fb..3428565 100644
--- a/app/node_modules/okserver/index.js
+++ b/app/node_modules/okserver/index.js
@@ -60,7 +60,7 @@ function OKServer(options) {
app.use(router);
// Add services
if (services.s3) {
- app.use('/_services/image', services.s3.middleware());
+ app.use('/_services/s3', services.s3.middleware());
}
if (services.twitter) {
app.use('/_services/twitter', services.twitter.middleware())
diff --git a/app/node_modules/okservices/oks3/index.js b/app/node_modules/okservices/oks3/index.js
index d556c20..dc0ca19 100644
--- a/app/node_modules/okservices/oks3/index.js
+++ b/app/node_modules/okservices/oks3/index.js
@@ -4,7 +4,7 @@ var skipperS3 = require('skipper-s3')
// Hack to prevent this god-forsaken module from crashing our shit
var d = require('domain').create()
d.on('error', function (err) {
- console.error('Stupid error in S3 upload. Image upload probably prematurely canceled')
+ console.error('Stupid error in S3 upload. Upload probably prematurely canceled')
})
function OKS3(options) {
@@ -20,9 +20,9 @@ function OKS3(options) {
router.use(skipper());
- router.post('/', function(req, res) {
- // req should have a method `file` on it which is
- // provided by skipper. Use that to do AWS stuff
+ // 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) {
d.run(function () {
req.file('image').upload({
adapter: skipperS3,
@@ -38,7 +38,51 @@ function OKS3(options) {
if (err) res.status(500).send(err)
res.json(uploadedFiles);
});
- })
+ });
+ });
+
+ router.post('/audio', function(req, res) {
+ d.run(function () {
+ if (! options.s3.allowAudioUploads) {
+ 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,
+ dirname: options.s3.dirname,
+ maxBytes: options.s3.maxbytesAudio,
+ headers: {
+ 'x-amz-acl': 'public-read'
+ }
+ }, function (err, uploadedFiles) {
+ if (err) res.status(500).send(err)
+ res.json(uploadedFiles);
+ });
+ });
+ });
+
+ router.post('/video', function(req, res) {
+ d.run(function () {
+ if (! options.s3.allowVideoUploads) {
+ 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,
+ dirname: options.s3.dirname,
+ maxBytes: options.s3.maxbytesVideo,
+ headers: {
+ 'x-amz-acl': 'public-read'
+ }
+ }, function (err, uploadedFiles) {
+ if (err) res.status(500).send(err)
+ res.json(uploadedFiles);
+ });
+ });
});
this._middleware = router;
diff --git a/examples/db.json b/examples/db.json
index 1d045c3..3650355 100644
--- a/examples/db.json
+++ b/examples/db.json
@@ -174,7 +174,34 @@
"title": "Green",
"__index": 1,
"dateCreated": "Tue, 05 Apr 2016 15:17:57 GMT",
- "media": []
+ "media": [
+ {
+ "type": "video",
+ "token": "https://ltho.s3.amazonaws.com/ee12b137-1c8a-400a-87e3-89cbee7b4da6.mp4",
+ "uri": "",
+ "width": "400",
+ "height": "400",
+ "title": "ee12b137-1c8a-400a-87e3-89cbee7b4da6.mp4",
+ "thumb": "http://okfocus.s3.amazonaws.com/misc/okcms/video.png"
+ },
+ {
+ "type": "youtube",
+ "token": "y_35kXCQxN4",
+ "uri": "",
+ "width": "640",
+ "height": "360",
+ "title": "dëf lëöpär¨d¨¨¨¨<>~!@~#!:I!@",
+ "thumb": "http://i.ytimg.com/vi/y_35kXCQxN4/hqdefault.jpg"
+ },
+ {
+ "type": "audio",
+ "token": "http://asdf.us/clouds35.mp3",
+ "uri": "",
+ "duration": "225.645792",
+ "title": "clouds35.mp3",
+ "thumb": "http://okfocus.s3.amazonaws.com/misc/okcms/video.png"
+ }
+ ]
}
]
} \ No newline at end of file
diff --git a/examples/index.js b/examples/index.js
index 81d9241..e9de0a3 100644
--- a/examples/index.js
+++ b/examples/index.js
@@ -40,6 +40,11 @@ var app = okcms.createApp({
key: process.env.S3_KEY,
secret: process.env.S3_SECRET,
bucket: process.env.S3_BUCKET,
+ allowVideoUploads: true,
+ allowAudioUploads: true,
+ maxsize: 200,
+ maxsizeVideo: 150000000,
+ maxsizeAudio: 150000000,
}
},
diff --git a/package.json b/package.json
index c95a2bc..c3a7280 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "okcms",
- "version": "0.1.24",
+ "version": "0.1.27",
"description": "great",
"main": "app/index.js",
"scripts": {
diff --git a/themes/okadmin/public/css/main.css b/themes/okadmin/public/css/main.css
index 2f2d376..15b8781 100644
--- a/themes/okadmin/public/css/main.css
+++ b/themes/okadmin/public/css/main.css
@@ -303,6 +303,7 @@ button, input[type=submit] {
width: 15em;
height: 6em;
}
+.main.resource form .audio-element input[type=text],
.main.resource form .video-element input[type=text] {
width: 15em;
}
@@ -353,10 +354,12 @@ button, input[type=submit] {
margin: 0; padding: 0;
cursor: pointer;
}
+.audio-element:hover .remove,
.video-element:hover .remove,
.image-element:hover .remove {
display: block;
}
+.audio-element .remove:hover,
.video-element .remove:hover,
.image-element .remove:hover {
color: red;
diff --git a/themes/okadmin/public/js/app.js b/themes/okadmin/public/js/app.js
index e79f704..a12f517 100644
--- a/themes/okadmin/public/js/app.js
+++ b/themes/okadmin/public/js/app.js
@@ -5,7 +5,8 @@ var OKAdmin = function(){
var parent = this
var uploader = new OKUpload ()
uploader.bind( this )
- uploader.add = function(url){
+ uploader.add = function(media){
+ var url = media.url
var imageTemplate = $(".image-template", parent).html()
var $el = $(imageTemplate)
$el.find(".uri").val(url)
@@ -46,7 +47,7 @@ var OKAdmin = function(){
$el.find("img").attr("src", url)
$("ol", parent).prepend($el)
}
- uploader.addVideo = function(media){
+ uploader.addMedia = function(media){
switch (media.type) {
case 'youtube':
case 'vimeo':
@@ -64,6 +65,19 @@ var OKAdmin = function(){
$el.find("img").attr("src", media.thumbnail )
$("ol", parent).prepend($el)
break
+ case 'audio':
+ var audioTemplate = $(".audio-template", parent).html()
+ var $el = $(audioTemplate)
+ $el.addClass("loaded")
+ $el.find(".audio-type").val( media.type )
+ $el.find(".audio-token").val( media.token )
+ $el.find(".audio-uri").val( media.uri )
+ $el.find(".audio-title").val( media.title )
+ $el.find(".audio-thumb").val( media.thumbnail )
+ $el.find(".audio-duration").val( media.duration )
+ $el.find("img").attr("src", media.thumbnail )
+ $("ol", parent).prepend($el)
+ break
case 'link':
var linkTemplate = $(".link-template", parent).html()
var $el = $(linkTemplate)
diff --git a/themes/okadmin/public/js/parser.js b/themes/okadmin/public/js/parser.js
index b4a087d..4ab9a6c 100644
--- a/themes/okadmin/public/js/parser.js
+++ b/themes/okadmin/public/js/parser.js
@@ -53,6 +53,31 @@ var Parser = {
return '<video src="' + media.url + '">';
}
}, {
+ type: 'audio',
+ regex: /\.(wav|mp3)(\?.*)?$/i,
+ fetch: function(url, done) {
+ var audio = document.createElement("audio")
+ var url_parts = url.replace(/\?.*$/, "").split("/")
+ var filename = url_parts[ url_parts.length-1 ]
+ audio.addEventListener("loadedmetadata", function(){
+ var duration = audio.duration
+ audio = null
+ done({
+ url: url,
+ type: "audio",
+ token: url,
+ thumbnail: "http://okfocus.s3.amazonaws.com/misc/okcms/audio.png",
+ title: filename,
+ duration: duration,
+ })
+ })
+ audio.src = url
+ audio.load()
+ },
+ tag: function (media) {
+ return '<audio src="' + media.url + '">';
+ }
+ }, {
type: 'youtube',
regex: /(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/ ]{11})/i,
fetch: function(url, done) {
@@ -116,8 +141,7 @@ var Parser = {
// return '<img class="video" type="vimeo" vid="'+media.token+'" src="'+media.thumbnail+'"><span class="playvid">&#9654;</span>';
return '<div class="video" style="width: ' + media.width + 'px; height: ' + media.height + 'px; overflow: hidden; position: relative;"><iframe frameborder="0" scrolling="no" seamless="seamless" webkitallowfullscreen="webkitAllowFullScreen" mozallowfullscreen="mozallowfullscreen" allowfullscreen="allowfullscreen" id="okplayer" src="http://player.vimeo.com/video/' + media.token + '?api=1&title=0&byline=0&portrait=0&playbar=0&player_id=okplayer&loop=0&autoplay=0" width="' + media.width + '" height="' + media.height + '" style="position: absolute; top: 0px; left: 0px; width: ' + media.width + 'px; height: ' + media.height + 'px;"></iframe></div>'
}
- },
- {
+ }, {
type: 'soundcloud',
regex: /soundcloud.com\/[-a-zA-Z0-9]+\/[-a-zA-Z0-9]+\/?$/i,
fetch: function (url, done) {
@@ -128,13 +152,14 @@ var Parser = {
+ '&client_id='
+ '0673fbe6fc794a7750f680747e863b10',
success: function(result) {
- // console.log(result)
+ console.log(result)
done({
url: url,
type: "soundcloud",
token: result.id,
thumbnail: result.artwork_url || result.user.avatar_url,
title: result.user.username + " - " + result.title,
+ duration: result.duration,
width: 166,
height: 166,
})
diff --git a/themes/okadmin/public/js/upload.js b/themes/okadmin/public/js/upload.js
index cfc1199..2ce14ad 100644
--- a/themes/okadmin/public/js/upload.js
+++ b/themes/okadmin/public/js/upload.js
@@ -1,6 +1,8 @@
var OKUpload = function(){
- this.action = "/_services/image"
+ this.action = this.imageAction = "/_services/s3/image"
+ this.videoAction = "/_services/s3/video"
+ this.audioAction = "/_services/s3/audio"
}
OKUpload.prototype.bind = function(rapper){
var uploader = this
@@ -14,18 +16,25 @@ OKUpload.prototype.bind = function(rapper){
$(".add-url", rapper).on("keydown blur", pressEnter( function(e){
var url = $(this).val()
$(this).val("")
- if (! url) return
- Parser.parse( url, function(media){
- console.log(url, media)
- if (media.type == "image") {
- uploader.add(url)
- }
- else {
- uploader.addVideo(media)
- }
- })
+ uploader.parse(url)
}))
}
+OKUpload.prototype.parse = function(url){
+ if (! url) return
+ var uploader = this
+ Parser.parse( url, function(media){
+ console.log(url, media)
+ if (! media) {
+ alert("Not a valid link")
+ }
+ else if (media.type == "image") {
+ uploader.add(media)
+ }
+ else {
+ uploader.addMedia(media)
+ }
+ })
+}
OKUpload.prototype.handleFileSelect = function(e) {
e.stopPropagation();
e.preventDefault();
@@ -33,13 +42,29 @@ OKUpload.prototype.handleFileSelect = function(e) {
var files = e.dataTransfer ? e.dataTransfer.files : e.target.files;
for (var i = 0, f; f = files[i]; i++) {
- if ( ! f.type.match('image.*')) {
+ if ( ! f.type.match('image.*') && ! f.type.match('video.*') ) {
continue;
}
this.upload(f)
}
}
OKUpload.prototype.upload = function(f){
+
+ var field, action
+
+ if ( f.type.match('video.*') ) {
+ field = 'video'
+ action = this.videoAction
+ }
+ else if ( f.type.match('audio.*') ) {
+ field = 'audio'
+ action = this.audioAction
+ }
+ else {
+ field = 'image'
+ action = this.imageAction || this.action
+ }
+
this.xhrCount += 1
this.$progress.addClass("loading")
@@ -51,10 +76,10 @@ OKUpload.prototype.upload = function(f){
this.$progress.append($loader)
var fd = new FormData()
- fd.append('image', f)
+ fd.append(field, f)
var request = new XMLHttpRequest()
- request.open("POST", this.action, true)
+ request.open("POST", action, true)
request.addEventListener("progress", updateProgress.bind(this));
request.addEventListener("load", transferComplete.bind(this));
@@ -77,6 +102,7 @@ OKUpload.prototype.upload = function(f){
this.success( responseData )
}
catch (e) {
+ console.log(request.responseText)
console.log("ERROR PARSING JSON")
}
}
@@ -121,12 +147,15 @@ OKUpload.prototype.success = function(data){
return
}
var url = data[0].extra.Location
- this.add(url)
+ this.parse(url)
}
OKUpload.prototype.add = function(media){
console.log(media)
}
-OKUpload.prototype.addVideo = function(media){
+OKUpload.prototype.addMedia = function(media){
+ console.log(media)
+}
+OKUpload.prototype.addAudio = function(media){
console.log(media)
}
OKUpload.prototype.error = function(error){
diff --git a/themes/okadmin/templates/partials/inputs.liquid b/themes/okadmin/templates/partials/inputs.liquid
index e618c61..0cd7f6b 100644
--- a/themes/okadmin/templates/partials/inputs.liquid
+++ b/themes/okadmin/templates/partials/inputs.liquid
@@ -9,14 +9,14 @@
{% if type == 'string' %}
<input
- name="{{name}}" type="text" value="{{spec.value}}">
+ name="{{name}}" type="text" value="{{spec.value | escape}}">
{% elsif type == 'text' %}
<textarea
- name="{{name}}">{{spec.value}}</textarea>
+ name="{{name}}">{{spec.value | escape}}</textarea>
{% elsif type == 'number' %}
<input
type="number"
- name="{{name}}" value="{{spec.value}}">
+ name="{{name}}" value="{{spec.value | escape}}">
{% elsif type == 'enum' or type == 'foreign-key' %}
<select
name="{{name}}">
@@ -32,9 +32,9 @@
<input name="{{name}}[width]" value="{{spec.value.width}}" type="hidden" class="video-width" hidden>
<input name="{{name}}[height]" value="{{spec.value.height}}" type="hidden" class="video-height" hidden>
<label>Title</label>
- <input name="{{name}}[title]" type="text" value="{{spec.value.title}}" class="video-title">
+ <input name="{{name}}[title]" type="text" value="{{spec.value.title | escape}}" class="video-title">
<label>Thumbnail</label>
- <input name="{{name}}[thumb]" type="text" value="{{spec.value.thumb}}" class="video-thumb">
+ <input name="{{name}}[thumb]" type="text" value="{{spec.value.thumb | escape}}" class="video-thumb">
</div>
{% elsif type == 'image' %}
<div class="image group {% if spec.value.uri %}loaded{% endif %}">
@@ -47,8 +47,8 @@
</div>
<div class="image-element">
<input class="uri" type="hidden" name="{{name}}[uri]" value="{{spec.value.uri}}">
- <textarea class="caption" name="{{name}}[caption]">{{spec.value.caption}}</textarea>
- <img src="{{spec.value.uri}}" alt="{{spec.value.caption}}">
+ <textarea class="caption" name="{{name}}[caption]">{{spec.value.caption | escape}}</textarea>
+ <img src="{{spec.value.uri}}" alt="{{spec.value.caption | escape}}">
<button class="remove">x</button>
</div>
</div>
@@ -78,7 +78,7 @@
{% elsif type == 'tag-list' %}
<div class="tag-list">
<input name="{{name}}"
- value="{{spec.value}}"
+ value="{{spec.value | escape}}"
placeholder="Enter a comma separated list of tags.">
</div>
@@ -90,13 +90,13 @@
<div class="handle"></div>
<input
name="{{name}}[{{forloop.index0}}][text]"
- value="{{link.text}}"
+ value="{{link.text | escape}}"
type="text"
placeholder="Link text"
class="link-input link-text">
<input
name="{{name}}[{{forloop.index0}}][uri]"
- value="{{link.uri}}"
+ value="{{link.uri | escape}}"
type="text"
placeholder="URL"
class="link-input link-uri">
@@ -142,8 +142,8 @@
<div class="media-list group loaded">
<div class="fields">
<div class="add-image-button">
- <input type="file" accept="image/*" multiple>
- <button>+ Add images</button>
+ <input type="file" accept="image/*,video/*,audio/*" multiple>
+ <button>+ Add media</button>
</div>
<input class="add-url" type="text" placeholder="+ Add Image/Video/Link URL">
</div>
@@ -177,6 +177,23 @@
</li>
</script>
+ <script type="text/html" class="audio-template">
+ <li class="audio-element">
+ <div style="float: left">
+ <input name="{{name}}[][type]" type="hidden" class="audio-type" hidden>
+ <input name="{{name}}[][token]" type="hidden" class="audio-token" hidden>
+ <input name="{{name}}[][uri]" type="hidden" class="audio-uri" hidden>
+ <input name="{{name}}[][duration]" value="{{image.duration}}" type="hidden" class="audio-duration" hidden>
+ <label>Caption</label>
+ <input name="{{name}}[][title]" type="text" class="audio-title">
+ <label>Thumbnail</label>
+ <input name="{{name}}[][thumb]" type="text" class="audio-thumb">
+ </div>
+ <img>
+ <button class="remove">x</button>
+ </li>
+ </script>
+
<script type="text/html" class="link-template">
<li class="link-element">
<input class="uri" type="text" name="{{name}}[][uri]" value="">
@@ -197,19 +214,34 @@
<input name="{{name}}[{{forloop.index0}}][width]" value="{{image.width}}" type="hidden" class="video-width" hidden>
<input name="{{name}}[{{forloop.index0}}][height]" value="{{image.height}}" type="hidden" class="video-height" hidden>
<label>Caption</label>
- <input name="{{name}}[{{forloop.index0}}][title]" value="{{image.title}}" type="text" class="video-title">
+ <input name="{{name}}[{{forloop.index0}}][title]" value="{{image.title | escape}}" type="text" class="video-title">
<label>Thumbnail</label>
<input name="{{name}}[{{forloop.index0}}][thumb]" value="{{image.thumb}}" type="text" class="video-thumb">
</div>
<img src="{{image.thumb}}">
<button class="remove">x</button>
</li>
+ {% elsif image.type and (image.type == "audio" or image.type == "soundcloud") %}
+ <li class="audio-element">
+ <div style="float: left">
+ <input name="{{name}}[{{forloop.index0}}][type]" value="{{image.type}}" type="hidden" class="audio-type" hidden>
+ <input name="{{name}}[{{forloop.index0}}][token]" value="{{image.token}}" type="hidden" class="audio-token" hidden>
+ <input name="{{name}}[{{forloop.index0}}][uri]" value="{{image.uri}}" type="hidden" class="audio-uri" hidden>
+ <input name="{{name}}[{{forloop.index0}}][duration]" value="{{image.duration}}" type="hidden" class="audio-duration" hidden>
+ <label>Caption</label>
+ <input name="{{name}}[{{forloop.index0}}][title]" value="{{image.title | escape}}" type="text" class="audio-title">
+ <label>Thumbnail</label>
+ <input name="{{name}}[{{forloop.index0}}][thumb]" value="{{image.thumb}}" type="text" class="audio-thumb">
+ </div>
+ <img src="{{image.thumb}}">
+ <button class="remove">x</button>
+ </li>
{% elsif image.type and image.type == "link" %}
<li class="link-element">
<label>URL</label>
<input class="uri" type="text" name="{{name}}[][uri]" value="{{image.uri}}">
<label>Caption</label>
- <textarea class="caption" name="{{name}}[][caption]" placeholder="Caption">{{image.caption}}</textarea>
+ <textarea class="caption" name="{{name}}[][caption]" placeholder="Caption">{{image.caption | escape}}</textarea>
<input type="hidden" name="{{name}}[][type]" value="link">
<button class="remove">x</button>
</li>
@@ -217,7 +249,7 @@
<li class="image-element">
<label>Caption</label>
<input type="hidden" name="{{name}}[][uri]" value="{{image.uri}}">
- <textarea class="caption" name="{{name}}[][caption]">{{image.caption}}</textarea>
+ <textarea class="caption" name="{{name}}[][caption]">{{image.caption | escape}}</textarea>
<input type="hidden" name="{{name}}[][type]" value="image">
<img src="{{image.uri}}" alt="{{image.caption | strip_html}}">
<button class="remove">x</button>
@@ -249,7 +281,7 @@
{% for image in spec.value %}
<li class="image-element">
<input type="hidden" name="{{name}}[{{forloop.index0}}][uri]" value="{{image.uri}}">
- <textarea class="caption" name="{{name}}[{{forloop.index0}}][caption]">{{image.caption}}</textarea>
+ <textarea class="caption" name="{{name}}[{{forloop.index0}}][caption]">{{image.caption | escape}}</textarea>
<img src="{{image.uri}}" alt="{{image.caption | strip_html}}">
<button class="remove">x</button>
</li>
@@ -282,8 +314,8 @@
<img src="{{image.uri}}" alt="{{image.caption | strip_html}}">
<button class="remove">x</button>
<input type="hidden" name="{{name}}[{{forloop.index0}}][uri]" value="{{image.uri}}">
- <input class="caption" name="{{name}}[{{forloop.index0}}][label]" value="{{image.label}}" placeholder="Name">
- <input class="caption" name="{{name}}[{{forloop.index0}}][caption]" value="{{image.caption}}" placeholder="Email">
+ <input class="caption" name="{{name}}[{{forloop.index0}}][label]" value="{{image.label | escape}}" placeholder="Name">
+ <input class="caption" name="{{name}}[{{forloop.index0}}][caption]" value="{{image.caption | escape}}" placeholder="Email">
</li>
{% endfor %}
</ol>