From eda480b81ae7f16973c50904b8c6a6a6d35ea6f1 Mon Sep 17 00:00:00 2001 From: bill bittner Date: Thu, 6 Jul 2017 13:37:03 -0700 Subject: [PATCH] moved request logs to middleware and reorganized front end js --- controllers/serveController.js | 3 + controllers/showController.js | 7 -- public/assets/css/allStyle.css | 4 +- public/assets/css/componentStyle.css | 12 ++- public/assets/js/claimPublish.js | 75 ------------------- public/assets/js/generalFunctions.js | 39 ++++++++++ public/assets/js/memePublish.js | 91 ----------------------- public/assets/js/publishFunctions.js | 107 +++++++++++++++++++++++++++ routes/api-routes.js | 8 -- routes/home-routes.js | 5 +- routes/serve-routes.js | 27 ++----- routes/show-routes.js | 43 +++++++++-- server.js | 4 + views/index.handlebars | 1 + views/layouts/main.handlebars | 2 +- views/partials/asset.handlebars | 30 +------- views/show.handlebars | 36 ++++++++- views/showLite.handlebars | 34 +++++++++ 18 files changed, 283 insertions(+), 245 deletions(-) delete mode 100644 controllers/showController.js create mode 100644 public/assets/js/publishFunctions.js create mode 100644 views/showLite.handlebars diff --git a/controllers/serveController.js b/controllers/serveController.js index a836c67b..b3dfb700 100644 --- a/controllers/serveController.js +++ b/controllers/serveController.js @@ -195,4 +195,7 @@ module.exports = { }); return deferred; }, + getAllClaims (claimName) { + return getAllFreePublicClaims(claimName); + }, }; diff --git a/controllers/showController.js b/controllers/showController.js deleted file mode 100644 index c5fa80a8..00000000 --- a/controllers/showController.js +++ /dev/null @@ -1,7 +0,0 @@ -const getAllFreePublicClaims = require('../helpers/functions/getAllFreePublicClaims.js'); - -module.exports = { - getAllClaims (claimName) { - return getAllFreePublicClaims(claimName); - }, -}; diff --git a/public/assets/css/allStyle.css b/public/assets/css/allStyle.css index 7360bb7c..6047bde3 100644 --- a/public/assets/css/allStyle.css +++ b/public/assets/css/allStyle.css @@ -18,15 +18,15 @@ margin-right: 1%; padding-right: 1%; border-right: 1px lightgrey solid; - margin-bottom: 5px; } .sidebar { - float: left; + float: right; width: 32%; } footer { + display: inline-block; width: 100%; margin-bottom: 2px; padding-bottom: 2px; diff --git a/public/assets/css/componentStyle.css b/public/assets/css/componentStyle.css index 06864bcb..f7592d75 100644 --- a/public/assets/css/componentStyle.css +++ b/public/assets/css/componentStyle.css @@ -14,8 +14,14 @@ /* show routes */ -.show-image, .show-video { +.show-asset { width: 100%; + margin-bottom: 1em; + margin-top: 1em; +} + +.show-asset-lite { + margin: 0px; } .table-metadata { @@ -133,6 +139,10 @@ canvas { font-size: small; } + .show-asset-lite { + width: 100%; + } + } @media (max-width: 475px) { diff --git a/public/assets/js/claimPublish.js b/public/assets/js/claimPublish.js index c2a5c5c5..3773c69b 100644 --- a/public/assets/js/claimPublish.js +++ b/public/assets/js/claimPublish.js @@ -3,81 +3,6 @@ var socket = io(); var uploader = new SocketIOFileUpload(socket); var stagedFiles = null; -/* helper functions */ -// create a progress animation -function createProgressBar(element, size){ - var x = 1; - var adder = 1; - function addOne(){ - var bars = '

|'; - for (var i = 0; i < x; i++){ bars += ' | '; } - bars += '

'; - element.innerHTML = bars; - if (x === size){ - adder = -1; - } else if ( x === 0){ - adder = 1; - } - x += adder; - }; - setInterval(addOne, 300); -} -// preview file and stage the image for upload -function previewAndStageFile(selectedFile){ - var preview = document.getElementById('image-preview'); - var dropzone = document.getElementById('drop-zone'); - var previewReader = new FileReader(); - var nameInput = document.getElementById('publish-name'); - - preview.style.display = 'block'; - dropzone.style.display = 'none'; - - previewReader.onloadend = function () { - preview.src = previewReader.result; - }; - - if (selectedFile) { - previewReader.readAsDataURL(selectedFile); // reads the data and sets the img src - if (nameInput.value === "") { - nameInput.value = selectedFile.name.substring(0, selectedFile.name.indexOf('.')); - } - stagedFiles = [selectedFile]; // stores the selected file for upload - } else { - preview.src = ''; - } -} -// update the publish status -function updatePublishStatus(msg){ - document.getElementById('publish-status').innerHTML = msg; -} -// process the drop-zone drop -function drop_handler(ev) { - ev.preventDefault(); - // if dropped items aren't files, reject them - var dt = ev.dataTransfer; - if (dt.items) { - if (dt.items[0].kind == 'file') { - var droppedFile = dt.items[0].getAsFile(); - previewAndStageFile(droppedFile); - } - } -} -// prevent the browser's default drag behavior -function dragover_handler(ev) { - ev.preventDefault(); -} -// remove all of the drag data -function dragend_handler(ev) { - var dt = ev.dataTransfer; - if (dt.items) { - for (var i = 0; i < dt.items.length; i++) { - dt.items.remove(i); - } - } else { - ev.dataTransfer.clearData(); - } -} - /* configure the submit button */ document.getElementById('publish-submit').addEventListener('click', function(event){ event.preventDefault(); diff --git a/public/assets/js/generalFunctions.js b/public/assets/js/generalFunctions.js index 2151357b..521e26fc 100644 --- a/public/assets/js/generalFunctions.js +++ b/public/assets/js/generalFunctions.js @@ -15,4 +15,43 @@ function toggleSection(event){ masterElement.innerText = "[open]"; masterElement.dataset.open = "false"; } +} + +// create a progress animation +function createProgressBar(element, size){ + var x = 1; + var adder = 1; + function addOne(){ + var bars = '

|'; + for (var i = 0; i < x; i++){ bars += ' | '; } + bars += '

'; + element.innerHTML = bars; + if (x === size){ + adder = -1; + } else if ( x === 0){ + adder = 1; + } + x += adder; + }; + setInterval(addOne, 300); +} + +function dataURItoBlob(dataURI) { + // convert base64/URLEncoded data component to raw binary data held in a string + var byteString; + if (dataURI.split(',')[0].indexOf('base64') >= 0) + byteString = atob(dataURI.split(',')[1]); + else + byteString = unescape(dataURI.split(',')[1]); + + // separate out the mime component + var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]; + + // write the bytes of the string to a typed array + var ia = new Uint8Array(byteString.length); + for (var i = 0; i < byteString.length; i++) { + ia[i] = byteString.charCodeAt(i); + } + + return new Blob([ia], {type:mimeString}); } \ No newline at end of file diff --git a/public/assets/js/memePublish.js b/public/assets/js/memePublish.js index aeb249d9..67c13597 100644 --- a/public/assets/js/memePublish.js +++ b/public/assets/js/memePublish.js @@ -7,97 +7,6 @@ var license = 'Creative Commons'; var nsfw = false; var nameInput = document.getElementById("publish-name"); -function dataURItoBlob(dataURI) { - // convert base64/URLEncoded data component to raw binary data held in a string - var byteString; - if (dataURI.split(',')[0].indexOf('base64') >= 0) - byteString = atob(dataURI.split(',')[1]); - else - byteString = unescape(dataURI.split(',')[1]); - - // separate out the mime component - var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]; - - // write the bytes of the string to a typed array - var ia = new Uint8Array(byteString.length); - for (var i = 0; i < byteString.length; i++) { - ia[i] = byteString.charCodeAt(i); - } - - return new Blob([ia], {type:mimeString}); -} - -function startPublish() { - //download the image - var dataUrl = canvas.toDataURL('image/jpeg'); // canvas defined in memeDraw.js - var blob = dataURItoBlob(dataUrl) - var fileName = nameInput.value + ".jpg"; //note: need to dynamically grab type - var file = new File([blob], fileName, {type: 'image/jpeg', lastModified: Date.now()}); - stageAndPublish(file); -}; - -/* helper functions */ -// create a progress animation -function createProgressBar(element, size){ - var x = 1; - var adder = 1; - function addOne(){ - var bars = '

|'; - for (var i = 0; i < x; i++){ bars += ' | '; } - bars += '

'; - element.innerHTML = bars; - if (x === size){ - adder = -1; - } else if ( x === 0){ - adder = 1; - } - x += adder; - }; - setInterval(addOne, 300); -} - -function stageAndPublish(file) { - var name = nameInput.value; - var invalidCharacters = /[^A-Za-z0-9,-]/.exec(name); - // validate 'name' - if (invalidCharacters) { - alert(invalidCharacters + ' is not allowed. A-Z, a-z, 0-9, "_" and "-" only.'); - return; - } else if (name.length < 1) { - alert("You must enter a name for your claim"); - return; - } - // stage files - stagedFiles = [file]; // stores the selected file for - // make sure a file was selected - if (stagedFiles) { - // make sure only 1 file was selected - if (stagedFiles.length < 1) { - alert("A file is needed"); - return; - } - // make sure the content type is acceptable - switch (stagedFiles[0].type) { - case "image/png": - case "image/jpeg": - case "image/gif": - case "video/mp4": - uploader.submitFiles(stagedFiles); - break; - default: - alert("Only .png, .jpeg, .gif, and .mp4 files are currently supported"); - break; - } - } else { - alert("Please select a file"); - } -} - -// update the publish status -function updatePublishStatus(msg){ - document.getElementById('publish-status').innerHTML = msg; -} - /* socketio-file-upload listeners */ uploader.addEventListener('start', function(event){ event.file.meta.name = nameInput.value; diff --git a/public/assets/js/publishFunctions.js b/public/assets/js/publishFunctions.js new file mode 100644 index 00000000..1c02be73 --- /dev/null +++ b/public/assets/js/publishFunctions.js @@ -0,0 +1,107 @@ +// update the publish status +function updatePublishStatus(msg){ + document.getElementById('publish-status').innerHTML = msg; +} + +/* regular publish helper functions */ + +function previewAndStageFile(selectedFile){ + var preview = document.getElementById('image-preview'); + var dropzone = document.getElementById('drop-zone'); + var previewReader = new FileReader(); + var nameInput = document.getElementById('publish-name'); + + preview.style.display = 'block'; + dropzone.style.display = 'none'; + + previewReader.onloadend = function () { + preview.src = previewReader.result; + }; + + if (selectedFile) { + previewReader.readAsDataURL(selectedFile); // reads the data and sets the img src + if (nameInput.value === "") { + nameInput.value = selectedFile.name.substring(0, selectedFile.name.indexOf('.')); + } + stagedFiles = [selectedFile]; // stores the selected file for upload + } else { + preview.src = ''; + } +} + +/* drop zone function s*/ + +function drop_handler(ev) { + ev.preventDefault(); + // if dropped items aren't files, reject them + var dt = ev.dataTransfer; + if (dt.items) { + if (dt.items[0].kind == 'file') { + var droppedFile = dt.items[0].getAsFile(); + previewAndStageFile(droppedFile); + } + } +} + +function dragover_handler(ev) { + ev.preventDefault(); +} + +function dragend_handler(ev) { + var dt = ev.dataTransfer; + if (dt.items) { + for (var i = 0; i < dt.items.length; i++) { + dt.items.remove(i); + } + } else { + ev.dataTransfer.clearData(); + } +} + +/* meme publish functions */ + +function startPublish() { + //download the image + var dataUrl = canvas.toDataURL('image/jpeg'); // canvas defined in memeDraw.js + var blob = dataURItoBlob(dataUrl) + var fileName = nameInput.value + ".jpg"; //note: need to dynamically grab type + var file = new File([blob], fileName, {type: 'image/jpeg', lastModified: Date.now()}); + stageAndPublish(file); +}; + +function stageAndPublish(file) { + var name = nameInput.value; + var invalidCharacters = /[^A-Za-z0-9,-]/.exec(name); + // validate 'name' + if (invalidCharacters) { + alert(invalidCharacters + ' is not allowed. A-Z, a-z, 0-9, "_" and "-" only.'); + return; + } else if (name.length < 1) { + alert("You must enter a name for your claim"); + return; + } + // stage files + stagedFiles = [file]; // stores the selected file for + // make sure a file was selected + if (stagedFiles) { + // make sure only 1 file was selected + if (stagedFiles.length < 1) { + alert("A file is needed"); + return; + } + // make sure the content type is acceptable + switch (stagedFiles[0].type) { + case "image/png": + case "image/jpeg": + case "image/gif": + case "video/mp4": + uploader.submitFiles(stagedFiles); + break; + default: + alert("Only .png, .jpeg, .gif, and .mp4 files are currently supported"); + break; + } + } else { + alert("Please select a file"); + } +} \ No newline at end of file diff --git a/routes/api-routes.js b/routes/api-routes.js index 77980203..a0065a58 100644 --- a/routes/api-routes.js +++ b/routes/api-routes.js @@ -12,8 +12,6 @@ module.exports = app => { app.get('/api/claim_list/:name', ({ headers, ip, originalUrl, params }, res) => { // google analytics sendGoogleAnalytics('serve', headers, ip, originalUrl); - // log - logger.verbose(`GET request on ${originalUrl} from ${ip}`); // serve the content lbryApi .getClaimsList(params.name) @@ -27,8 +25,6 @@ module.exports = app => { }); // route to check whether spee.ch has published to a claim app.get('/api/isClaimAvailable/:name', ({ ip, originalUrl, params }, res) => { - // log - logger.verbose(`GET request on ${originalUrl} from ${ip}`); // send response publishController .checkNameAvailability(params.name) @@ -48,8 +44,6 @@ module.exports = app => { app.get('/api/resolve/:uri', ({ headers, ip, originalUrl, params }, res) => { // google analytics sendGoogleAnalytics('serve', headers, ip, originalUrl); - // log - logger.verbose(`GET request on ${originalUrl} from ${ip}`); // serve content lbryApi .resolveUri(params.uri) @@ -65,8 +59,6 @@ module.exports = app => { app.post('/api/publish', multipartMiddleware, ({ body, files, headers, ip, originalUrl }, res) => { // google analytics sendGoogleAnalytics('publish', headers, ip, originalUrl); - // log - logger.verbose(`POST request on ${originalUrl} from ${ip}`); // validate that a file was provided const file = files.speech || files.null; logger.debug(file); diff --git a/routes/home-routes.js b/routes/home-routes.js index c1ace31b..81fd3219 100644 --- a/routes/home-routes.js +++ b/routes/home-routes.js @@ -4,15 +4,12 @@ const { postToStats } = require('../controllers/statsController.js'); module.exports = app => { // route for the home page app.get('/', ({ headers, ip, originalUrl }, res) => { - // logging - logger.verbose(`GET request on ${originalUrl} from ${ip}`); // send response res.status(200).render('index'); }); // a catch-all route if someone visits a page that does not exist app.use('*', ({ originalUrl, ip }, res) => { - // logging - logger.error(`Get request on ${originalUrl} from ${ip} which was a 404`); + logger.error(`404 on ${originalUrl}`); // post to stats postToStats('show', originalUrl, ip, 'Error: 404'); // send response diff --git a/routes/serve-routes.js b/routes/serve-routes.js index 558f3d5e..c53a2627 100644 --- a/routes/serve-routes.js +++ b/routes/serve-routes.js @@ -1,7 +1,7 @@ -const errorHandlers = require('../helpers/libraries/errorHandlers.js'); -const serveController = require('../controllers/serveController.js'); const logger = require('winston'); +const { getClaimByClaimId, getClaimByName } = require('../controllers/serveController.js'); const { postToStats, sendGoogleAnalytics } = require('../controllers/statsController.js'); +const errorHandlers = require('../helpers/libraries/errorHandlers.js'); function serveFile ({ fileName, fileType, filePath }, res) { logger.info(`serving file ${fileName}`); @@ -31,26 +31,17 @@ function serveFile ({ fileName, fileType, filePath }, res) { res.status(200).sendFile(filePath, options); } -function servePage (fileInfo, res) { - logger.debug(`serving show page for ${fileInfo.fileName}`); - // set default options - res.status(200).render('show', { fileInfo }); -} - function sendAnalyticsAndLog (headers, ip, originalUrl) { // google analytics sendGoogleAnalytics('serve', headers, ip, originalUrl); - // logging - logger.verbose(`GET request on ${originalUrl} from ${ip}`); } module.exports = (app) => { - // route to fetch one free public claim + // route to serve a specific asset app.get('/:name/:claim_id', ({ headers, ip, originalUrl, params }, res) => { sendAnalyticsAndLog(headers, ip, originalUrl); // begin image-serve processes - serveController - .getClaimByClaimId(params.name, params.claim_id) + getClaimByClaimId(params.name, params.claim_id) .then(fileInfo => { // check to make sure a file was found if (!fileInfo) { @@ -61,8 +52,7 @@ module.exports = (app) => { const mimetypes = headers['accept'].split(','); if (mimetypes.includes('text/html')) { postToStats('show', originalUrl, ip, 'success'); - logger.debug('fileInfo', fileInfo); - servePage(fileInfo, res); + res.status(200).render('showLite', { fileInfo }); } else { postToStats('serve', originalUrl, ip, 'success'); serveFile(fileInfo, res); @@ -72,12 +62,11 @@ module.exports = (app) => { errorHandlers.handleRequestError('serve', originalUrl, ip, error, res); }); }); - // route to fetch one free public claim + // route to serve the winning claim app.get('/:name', ({ headers, ip, originalUrl, params }, res) => { sendAnalyticsAndLog(headers, ip, originalUrl); // begin image-serve processes - serveController - .getClaimByName(params.name) + getClaimByName(params.name) .then(fileInfo => { // check to make sure a file was found if (!fileInfo) { @@ -88,7 +77,7 @@ module.exports = (app) => { const mimetypes = headers['accept'].split(','); if (mimetypes.includes('text/html')) { postToStats('show', originalUrl, ip, 'success'); - servePage(fileInfo, res); + res.status(200).render('showLite', { fileInfo }); } else { postToStats('serve', originalUrl, ip, 'success'); serveFile(fileInfo, res); diff --git a/routes/show-routes.js b/routes/show-routes.js index 6a791d43..e7b179f3 100644 --- a/routes/show-routes.js +++ b/routes/show-routes.js @@ -1,18 +1,15 @@ -const logger = require('winston'); const errorHandlers = require('../helpers/libraries/errorHandlers.js'); -const { getAllClaims } = require('../controllers/showController.js'); +const { getClaimByClaimId, getClaimByName, getAllClaims } = require('../controllers/serveController.js'); const { getStatsSummary, postToStats } = require('../controllers/statsController.js'); module.exports = (app) => { // route to show 'about' page for spee.ch app.get('/about', ({ ip, originalUrl }, res) => { - logger.verbose(`POST request on ${originalUrl} from ${ip}`); // get and render the content res.status(200).render('about'); }); // route to show the meme-fodder meme maker app.get('/meme-fodder/play', ({ ip, originalUrl }, res) => { - logger.verbose(`POST request on ${originalUrl} from ${ip}`); // get and render the content getAllClaims('meme-fodder') .then(orderedFreePublicClaims => { @@ -25,7 +22,6 @@ module.exports = (app) => { }); // route to show statistics for spee.ch app.get('/stats', ({ ip, originalUrl }, res) => { - logger.verbose(`POST request on ${originalUrl} from ${ip}`); // get and render the content getStatsSummary() .then(result => { @@ -38,7 +34,6 @@ module.exports = (app) => { }); // route to display all free public claims at a given name app.get('/:name/all', ({ ip, originalUrl, params }, res) => { - logger.verbose(`POST request on ${originalUrl} from ${ip}`); // get and render the content getAllClaims(params.name) .then(orderedFreePublicClaims => { @@ -53,4 +48,40 @@ module.exports = (app) => { errorHandlers.handleRequestError('show', originalUrl, ip, error, res); }); }); + // route to show a specific asset + app.get('/s/:name/:claim_id', ({ ip, originalUrl, params }, res) => { + // begin image-serve processes + getClaimByClaimId(params.name, params.claim_id) + .then(fileInfo => { + // check to make sure a file was found + if (!fileInfo) { + res.status(307).render('noClaims'); + return; + } + // serve the file or the show route + postToStats('show', originalUrl, ip, 'success'); + res.status(200).render('show', { fileInfo }); + }) + .catch(error => { + errorHandlers.handleRequestError('serve', originalUrl, ip, error, res); + }); + }); + // route to show the winning free, public claim + app.get('/s/:name', ({ ip, originalUrl, params }, res) => { + // get and render the content + getClaimByName(params.name) + .then(fileInfo => { + // check to make sure a file was found + if (!fileInfo) { + res.status(307).render('noClaims'); + return; + } + // serve the show route + postToStats('show', originalUrl, ip, 'success'); + res.status(200).render('show', { fileInfo }); + }) + .catch(error => { + errorHandlers.handleRequestError('serve', originalUrl, ip, error, res); + }); + }); }; diff --git a/server.js b/server.js index e8274d5c..d81e1e14 100644 --- a/server.js +++ b/server.js @@ -29,6 +29,10 @@ app.enable('trust proxy'); // trust the proxy to get ip address for us app.use(bodyParser.json()); // for parsing application/json app.use(bodyParser.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded app.use(siofu.router); +app.use((req, res, next) => { // logging middleware + winston.verbose(`Request on ${req.originalUrl} from ${req.ip}`); + next(); +}); // configure handlebars & register it with Express app const hbs = expressHandlebars.create({ diff --git a/views/index.handlebars b/views/index.handlebars index cde6ed02..0e1302f9 100644 --- a/views/index.handlebars +++ b/views/index.handlebars @@ -9,4 +9,5 @@ + diff --git a/views/layouts/main.handlebars b/views/layouts/main.handlebars index 8e239631..ee2311da 100644 --- a/views/layouts/main.handlebars +++ b/views/layouts/main.handlebars @@ -9,8 +9,8 @@ - {{{ body }}} + {{{ body }}} {{ googleAnalytics }} diff --git a/views/partials/asset.handlebars b/views/partials/asset.handlebars index 4a475f8d..0711e8e5 100644 --- a/views/partials/asset.handlebars +++ b/views/partials/asset.handlebars @@ -1,33 +1,5 @@
-

{{fileInfo.name}}

loading...

-
- - - \ No newline at end of file + \ No newline at end of file diff --git a/views/show.handlebars b/views/show.handlebars index dbcd3a32..03ee170a 100644 --- a/views/show.handlebars +++ b/views/show.handlebars @@ -1,11 +1,43 @@
{{> topBar}} -
+
{{> asset}}
{{> footer}} -
\ No newline at end of file +
+ + + \ No newline at end of file diff --git a/views/showLite.handlebars b/views/showLite.handlebars new file mode 100644 index 00000000..e0ccfb74 --- /dev/null +++ b/views/showLite.handlebars @@ -0,0 +1,34 @@ +
+

loading...

+
+ + + \ No newline at end of file