diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..3599a0a --- /dev/null +++ b/.eslintrc @@ -0,0 +1,69 @@ +{ + "parserOptions": { + "ecmaVersion": 7, + "sourceType": "module", + "ecmaFeatures": {} + }, + "rules": { + "constructor-super": 2, + "for-direction": 2, + "getter-return": 2, + "no-case-declarations": 2, + "no-class-assign": 2, + "no-compare-neg-zero": 2, + "no-cond-assign": 2, + "no-console": 2, + "no-const-assign": 2, + "no-constant-condition": 2, + "no-control-regex": 1, + "no-debugger": 2, + "no-delete-var": 2, + "no-dupe-args": 2, + "no-dupe-class-members": 2, + "no-dupe-keys": 2, + "no-duplicate-case": 2, + "no-empty": 2, + "no-empty-character-class": 2, + "no-empty-pattern": 2, + "no-ex-assign": 2, + "no-extra-boolean-cast": 2, + "no-extra-semi": 2, + "no-fallthrough": 2, + "no-func-assign": 2, + "no-global-assign": 2, + "no-inner-declarations": 2, + "no-invalid-regexp": 2, + "no-irregular-whitespace": 2, + "no-mixed-spaces-and-tabs": 2, + "no-new-symbol": 2, + "no-obj-calls": 2, + "no-octal": 2, + "no-redeclare": 2, + "no-regex-spaces": 2, + "no-self-assign": 2, + "no-sparse-arrays": 2, + "no-this-before-super": 2, + "no-undef": 2, + "no-unexpected-multiline": 2, + "no-unreachable": 2, + "no-unsafe-finally": 2, + "no-unsafe-negation": 2, + "no-unused-labels": 2, + "no-unused-vars": 2, + "no-useless-escape": 1, + "require-yield": 2, + "use-isnan": 2, + "valid-typeof": 2, + "no-duplicate-imports": 2 + }, + "env": { + "node": true, + "browser": true, + "es6": true + }, + "globals": { + "_": false, + "hljs": false, + "Sortable": false + } +} \ No newline at end of file diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..6b13dc8 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,5 @@ +.babelrc +README.md +*.pug +*.styl + diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..8b8bad9 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,17 @@ +{ + "arrowParens": "avoid", + "bracketSpacing": true, + "htmlWhitespaceSensitivity": "css", + "insertPragma": false, + "jsxBracketSameLine": false, + "jsxSingleQuote": true, + "parser": "babel", + "proseWrap": "preserve", + "requirePragma": false, + "semi": true, + "singleQuote": true, + "trailingComma": "none", + "useTabs": true, + "tabWidth": 4, + "printWidth": 100 +} \ No newline at end of file diff --git a/brain/api/content/posts.js b/brain/api/content/posts.js index 98de1f1..1d026bd 100644 --- a/brain/api/content/posts.js +++ b/brain/api/content/posts.js @@ -2,20 +2,11 @@ import DateUtils from '../../tools/utilities/DateUtils'; import StringUtils from '../../tools/utilities/StringUtils'; import * as DataEvent from '../../tools/events/DataEvent'; import sanitize from 'sanitize-html'; -import RightsManager, -{ - TASK_CREATE, - TASK_UPDATE, - TASK_READ, - TASK_DELETE, - OBJECT_CLIENT_ADMIN, - OBJECT_CLIENT_USER, - OBJECT_PROJECT_CLIENT, - OBJECT_PROJECT_FOLIO, - OBJECT_BOOKMARK, - OBJECT_POST -} -from '../../tools/utilities/RightsManager'; +import RightsManager, { + TASK_CREATE, + TASK_UPDATE, + OBJECT_POST +} from '../../tools/utilities/RightsManager'; const express = require('express'); const router = express.Router(); const multer = require('multer'); @@ -24,227 +15,182 @@ const fs = require('fs-extra'); const Models = require('../../models'); const dateUtils = new DateUtils(); const rightsManager = new RightsManager(); -const uploadPath = "./content/blog-images/" + dateUtils.getDate('year', new Date()) + "/" + dateUtils.getDate('month', new Date()); +const uploadPath = + './content/blog-images/' + + dateUtils.getDate('year', new Date()) + + '/' + + dateUtils.getDate('month', new Date()); const Sequelize = require('sequelize'); const Op = Sequelize.Op; const _ = require('lodash'); -fs.ensureDir(uploadPath, function(err) -{ - //console.log(err) // => null - // dir has now been created, including the directory it is to be placed in -}) -var storage = multer.diskStorage( -{ - destination: function(req, file, cb) - { - cb(null, uploadPath) - }, - filename: function(req, file, cb) - { - var splice = file.originalname.split(':'); - cb(null, splice[0]); - } +fs.ensureDir(uploadPath, () => { + //console.log(err) // => null + // dir has now been created, including the directory it is to be placed in }); -var feature_upload = multer( -{ - storage: storage +var storage = multer.diskStorage({ + destination: function(req, file, cb) { + cb(null, uploadPath); + }, + filename: function(req, file, cb) { + var splice = file.originalname.split(':'); + cb(null, splice[0]); + } +}); +var feature_upload = multer({ + storage: storage }).array('feature_image'); -var post_upload = multer( -{ - storage: storage +var post_upload = multer({ + storage: storage }).array('post_image'); //** SYNC POSTS */ -router.post("/sync", (req, res, next) => -{ - let payload = req.body; - Models.User.findById(req.session.user.id).then((user) => - { - if (rightsManager.check(user.role, OBJECT_POST, TASK_UPDATE)) - { - for (let index = 0; index < payload.length; index++) - { - const item = payload[index]; - Models.FreshPost.findOne( - { - where: - { - "post": - { - [Op.contains]: - { - uuid: item.post.uuid - } - } - } - }).then(found => - { - let buffed = sanitize(item.post.plaintext, - { - allowedTags: ['del', 'a', 'iframe', 'img', ], - allowedAttributes: - { - a: ['href', 'name', 'target'], - img: ['src'], - iframe: ['height', 'width', 'src', 'frameborder', 'allow', 'allowfullscreen'] - } - }) - buffed = new StringUtils().decodeHTML(buffed); - item.post.plaintext = buffed; - item.post.html = md.render(buffed, - { - html: true, - xhtmlOut: true, - }); - if (!_.isEqual(item.post, found.post)) - { - found.update(item).then(updated => - { - console.log("UPDATED", updated); - }).catch(err => - { - //console.log("***ERROR***", err); - }) - } - else - { - //chilld - } - }).catch(err => - { - //console.log("***ERRRORZ****", err); - Models.FreshPost.create(item).then(fresh => - { - //console.log(fresh) - }) - }) - } - res.json( - { - message: "postsSynced" - }); - } - else - { - res.json( - { - message: "Nah. You can't do that. Talk to the admin, sport." - }); - } - }); -}) -router.get('/json', function(req, res, next) -{ - Models.FreshPost.findAll( - { - order: [ - ['id', 'DESC'] - ] - }).then(function(posts) - { - let newlist = []; - for (let index = 0; index < posts.length; index++) - { - let item = posts[index].post; - if (typeof item.deleted == 'undefined' || item.deleted == false) - { - newlist.push(posts[index]) - } - else - { - continue - } - } - res.json(newlist) - }).catch(function(err) - { - //next(err); - }) -}) +router.post('/sync', (req, res) => { + let payload = req.body; + Models.User.findById(req.session.user.id).then(user => { + if (rightsManager.check(user.role, OBJECT_POST, TASK_UPDATE)) { + for (let index = 0; index < payload.length; index++) { + const item = payload[index]; + Models.FreshPost.findOne({ + where: { + post: { + [Op.contains]: { + uuid: item.post.uuid + } + } + } + }) + .then(found => { + let buffed = sanitize(item.post.plaintext, { + allowedTags: ['del', 'a', 'iframe', 'img'], + allowedAttributes: { + a: ['href', 'name', 'target'], + img: ['src'], + iframe: [ + 'height', + 'width', + 'src', + 'frameborder', + 'allow', + 'allowfullscreen' + ] + } + }); + buffed = new StringUtils().decodeHTML(buffed); + item.post.plaintext = buffed; + item.post.html = md.render(buffed, { + html: true, + xhtmlOut: true + }); + if (!_.isEqual(item.post, found.post)) { + found + .update(item) + .then(() => { + //console.log('UPDATED', updated); + }) + .catch(() => { + //console.log("***ERROR***", err); + }); + } else { + //chilld + } + }) + .catch(() => { + //console.log("***ERRRORZ****", err); + Models.FreshPost.create(item).then(() => { + //console.log(fresh) + }); + }); + } + res.json({ + message: 'postsSynced' + }); + } else { + res.json({ + message: "Nah. You can't do that. Talk to the admin, sport." + }); + } + }); +}); +router.get('/json', function(req, res) { + Models.FreshPost.findAll({ + order: [['id', 'DESC']] + }) + .then(function(posts) { + let newlist = []; + for (let index = 0; index < posts.length; index++) { + let item = posts[index].post; + if (typeof item.deleted == 'undefined' || item.deleted == false) { + newlist.push(posts[index]); + } else { + continue; + } + } + res.json(newlist); + }) + .catch(() => { + //next(err); + }); +}); /*** POST IMAGE */ -router.post('/add-post-image', function(req, res, next) -{ - //console.log(req.body); - if (!req.session.user) return res.json( - { - message: "You need to be logged in, champ." - }); - Models.User.findById(req.session.user.id).then((user) => - { - if (rightsManager.check(user.role, OBJECT_POST, TASK_CREATE)) - { - post_upload(req, res, function(err) - { - if (err) - { - //console.log('Error in Saving Entry: ' + err); - res.json( - { - message: err - }); - throw err; - } - else - { - var postImage = req.files[0].path; - return res.json( - { - message: DataEvent.POST_IMAGE_ADDED, - url: postImage.substr(7, postImage.length) - }); - } - }); - } - else - { - res.json( - { - message: "Nah. You can't do that. Talk to the admin, sport." - }); - } - }); +router.post('/add-post-image', function(req, res) { + //console.log(req.body); + if (!req.session.user) + return res.json({ + message: 'You need to be logged in, champ.' + }); + Models.User.findById(req.session.user.id).then(user => { + if (rightsManager.check(user.role, OBJECT_POST, TASK_CREATE)) { + post_upload(req, res, function(err) { + if (err) { + //console.log('Error in Saving Entry: ' + err); + res.json({ + message: err + }); + throw err; + } else { + var postImage = req.files[0].path; + return res.json({ + message: DataEvent.POST_IMAGE_ADDED, + url: postImage.substr(7, postImage.length) + }); + } + }); + } else { + res.json({ + message: "Nah. You can't do that. Talk to the admin, sport." + }); + } + }); }); -router.post('/add-feature-image', function(req, res, next) -{ - //console.log(req.body); - if (!req.session.user) return res.json( - { - message: "You need to be logged in, champ." - }); - Models.User.findById(req.session.user.id).then((user) => - { - if (rightsManager.check(user.role, OBJECT_POST, TASK_CREATE)) - { - feature_upload(req, res, function(err) - { - if (err) - { - //console.log('Error in Saving Entry: ' + err); - res.json( - { - message: err - }); - throw err; - } - else - { - var postImage = req.files[0].path; - return res.json( - { - message: DataEvent.FEATURE_IMAGE_ADDED, - url: postImage.substr(7, postImage.length) - }); - } - }); - } - else - { - res.json( - { - message: "Nah. You can't do that. Talk to the admin, sport." - }); - } - }); +router.post('/add-feature-image', function(req, res) { + //console.log(req.body); + if (!req.session.user) + return res.json({ + message: 'You need to be logged in, champ.' + }); + Models.User.findById(req.session.user.id).then(user => { + if (rightsManager.check(user.role, OBJECT_POST, TASK_CREATE)) { + feature_upload(req, res, function(err) { + if (err) { + //console.log('Error in Saving Entry: ' + err); + res.json({ + message: err + }); + throw err; + } else { + var postImage = req.files[0].path; + return res.json({ + message: DataEvent.FEATURE_IMAGE_ADDED, + url: postImage.substr(7, postImage.length) + }); + } + }); + } else { + res.json({ + message: "Nah. You can't do that. Talk to the admin, sport." + }); + } + }); }); -module.exports = router; \ No newline at end of file +module.exports = router; diff --git a/brain/api/content/settings.js b/brain/api/content/settings.js index 767e290..5357429 100644 --- a/brain/api/content/settings.js +++ b/brain/api/content/settings.js @@ -1,21 +1,11 @@ import DateUtils from '../../tools/utilities/DateUtils'; -import StringUtils from '../../tools/utilities/StringUtils'; import * as DataEvent from '../../tools/events/DataEvent'; -import RightsManager, -{ - TASK_CREATE, - TASK_UPDATE, - TASK_READ, - TASK_DELETE, - OBJECT_CLIENT_ADMIN, - OBJECT_CLIENT_USER, - OBJECT_PROJECT_CLIENT, - OBJECT_PROJECT_FOLIO, - OBJECT_BOOKMARK, - OBJECT_POST, - OBJECT_SETTINGS -} -from '../../tools/utilities/RightsManager'; +import RightsManager, { + TASK_CREATE, + TASK_UPDATE, + OBJECT_POST, + OBJECT_SETTINGS +} from '../../tools/utilities/RightsManager'; const express = require('express'); const router = express.Router(); const multer = require('multer'); @@ -23,252 +13,200 @@ const fs = require('fs-extra'); const Models = require('../../models'); const dateUtils = new DateUtils(); const rightsManager = new RightsManager(); -const uploadPath = "./content/user-images/" + dateUtils.getDate('year', new Date()) + "/" + dateUtils.getDate('month', new Date()); -const Sequelize = require('sequelize'); -const Op = Sequelize.Op; -const _ = require('lodash'); -fs.ensureDir(uploadPath, function(err) -{ - //console.log(err) // => null - // dir has now been created, including the directory it is to be placed in -}) -var storage = multer.diskStorage( -{ - destination: function(req, file, cb) - { - cb(null, uploadPath) - }, - filename: function(req, file, cb) - { - var splice = file.originalname.split(':'); - cb(null, splice[0]); - } +const uploadPath = + './content/user-images/' + + dateUtils.getDate('year', new Date()) + + '/' + + dateUtils.getDate('month', new Date()); +fs.ensureDir(uploadPath, () => { + //console.log(err) // => null + // dir has now been created, including the directory it is to be placed in }); -var avatar_upload = multer( -{ - storage: storage +var storage = multer.diskStorage({ + destination: function(req, file, cb) { + cb(null, uploadPath); + }, + filename: function(req, file, cb) { + var splice = file.originalname.split(':'); + cb(null, splice[0]); + } +}); +var avatar_upload = multer({ + storage: storage }).array('avatar_upload'); -var background_upload = multer( -{ - storage: storage +var background_upload = multer({ + storage: storage }).array('background_upload'); //** SYNC POSTS */ -router.post("/sync", (req, res, next) => -{ - let payload = req.body; - Models.User.findById(req.session.user.id).then((user) => - { - if (rightsManager.check(user.role, OBJECT_SETTINGS, TASK_UPDATE)) - { - fs.readJson('config/site-settings.json').then(obj => - { - if (user.hande != payload.handle || user.email != payload.email) - { - user.update( - { - handle: payload.handle, - email: payload.email - }).then(updated => - { - console.log("UPDATED") - }).catch(err => - { - console.log("ERR", err); - }) - } - else - { - console.log("USER NOT UPDATED") - } - obj.url = payload.url; - obj.title = payload.title; - obj.description = payload.descriptions; - obj.private = payload.private; - obj.theme = payload.theme; - obj.background = payload.background; //TODO: make this url relative - //mail stuff - obj.email.active = payload.mailSettings.activeProtocol; - obj.email.smtp.domain = payload.mailSettings.smtp.domain; - obj.email.smtp.email = payload.mailSettings.smtp.email; - obj.email.smtp.password = payload.mailSettings.smtp.password; - obj.email.mailgun.domain = payload.mailSettings.mailgun.domain; - obj.email.mailgun['api-key'] = payload.mailSettings.mailgun.key; - fs.writeJson('config/site-settings.json', obj).then(() => - { - res.json( - { - message: DataEvent.SETTINGS_UPDATED - }); - }).catch(err => - { - console.error(err) - }) - }).catch(err => - { - console.error(err) - }) - } - else - { - res.json( - { - message: "Nah. You can't do that. Talk to the admin, sport." - }); - } - }); -}) - -router.get('/nav', function(req, res, next) -{ - fs.readJson('config/site-settings.json').then(obj => - { - fs.writeJson('config/site-settings.json', obj).then(() => - { - res.json(obj.menu); - }).catch(err => - { - console.error(err) - }) - }).catch(err => - { - console.error(err) - }) -}) +router.post('/sync', (req, res) => { + let payload = req.body; + Models.User.findById(req.session.user.id).then(user => { + if (rightsManager.check(user.role, OBJECT_SETTINGS, TASK_UPDATE)) { + fs.readJson('config/site-settings.json') + .then(obj => { + if (user.hande != payload.handle || user.email != payload.email) { + user.update({ + handle: payload.handle, + email: payload.email + }) + .then(() => { + //console.log('UPDATED'); + }) + .catch(() => { + //console.log('ERR', err); + }); + } else { + //console.log('USER NOT UPDATED'); + } + obj.url = payload.url; + obj.title = payload.title; + obj.description = payload.descriptions; + obj.private = payload.private; + obj.theme = payload.theme; + obj.background = payload.background; //TODO: make this url relative + //mail stuff + obj.email.active = payload.mailSettings.activeProtocol; + obj.email.smtp.domain = payload.mailSettings.smtp.domain; + obj.email.smtp.email = payload.mailSettings.smtp.email; + obj.email.smtp.password = payload.mailSettings.smtp.password; + obj.email.mailgun.domain = payload.mailSettings.mailgun.domain; + obj.email.mailgun['api-key'] = payload.mailSettings.mailgun.key; + fs.writeJson('config/site-settings.json', obj) + .then(() => { + res.json({ + message: DataEvent.SETTINGS_UPDATED + }); + }) + .catch(() => { + //console.error(err); + }); + }) + .catch(() => { + //console.error(err); + }); + } else { + res.json({ + message: "Nah. You can't do that. Talk to the admin, sport." + }); + } + }); +}); -router.post("/nav-sync", (req, res, next) => -{ - let payload = req.body; - Models.User.findById(req.session.user.id).then((user) => - { - if (rightsManager.check(user.role, OBJECT_SETTINGS, TASK_UPDATE)) - { - fs.readJson('config/site-settings.json').then(obj => - { - - obj.menu = payload; - fs.writeJson('config/site-settings.json', obj).then(() => - { - res.json( - { - message: DataEvent.SETTINGS_UPDATED - }); - }).catch(err => - { - console.error(err) - }) - }).catch(err => - { - console.error(err) - }) - } - else - { - res.json( - { - message: "Nah. You can't do that. Talk to the admin, sport." - }); - } - }); -}) +router.get('/nav', function(req, res) { + fs.readJson('config/site-settings.json') + .then(obj => { + fs.writeJson('config/site-settings.json', obj) + .then(() => { + res.json(obj.menu); + }) + .catch(() => { + //console.error(err); + }); + }) + .catch(() => { + //console.error(err); + }); +}); +router.post('/nav-sync', (req, res) => { + let payload = req.body; + Models.User.findById(req.session.user.id).then(user => { + if (rightsManager.check(user.role, OBJECT_SETTINGS, TASK_UPDATE)) { + fs.readJson('config/site-settings.json') + .then(obj => { + obj.menu = payload; + fs.writeJson('config/site-settings.json', obj) + .then(() => { + res.json({ + message: DataEvent.SETTINGS_UPDATED + }); + }) + .catch(() => { + //console.error(err); + }); + }) + .catch(() => { + //console.error(err); + }); + } else { + res.json({ + message: "Nah. You can't do that. Talk to the admin, sport." + }); + } + }); +}); /*** UPLOAD AVATAR */ -router.post('/add-avatar', function(req, res, next) -{ - //console.log(req.body); - if (!req.session.user) return res.json( - { - message: "You need to be logged in, champ." - }); - Models.User.findById(req.session.user.id).then((user) => - { - if (rightsManager.check(user.role, OBJECT_POST, TASK_CREATE)) - { - avatar_upload(req, res, function(err) - { - if (err) - { - res.json( - { - message: err - }); - throw err; - } - else - { - var avatar = req.files[0].path; - user.update( - { - avatar: avatar.substr(7, avatar.length) - }).then(updated => - { - - req.session.user = updated; - }).catch(err => - { - console.log("ERR", err); - }) - return res.json( - { - message: DataEvent.AVATAR_UPLOADED, - url: avatar.substr(7, avatar.length) - }); - } - }); - } - else - { - res.json( - { - message: "Nah. You can't do that. Talk to the admin, sport." - }); - } - }); +router.post('/add-avatar', function(req, res) { + //console.log(req.body); + if (!req.session.user) + return res.json({ + message: 'You need to be logged in, champ.' + }); + Models.User.findById(req.session.user.id).then(user => { + if (rightsManager.check(user.role, OBJECT_POST, TASK_CREATE)) { + avatar_upload(req, res, function(err) { + if (err) { + res.json({ + message: err + }); + throw err; + } else { + var avatar = req.files[0].path; + user.update({ + avatar: avatar.substr(7, avatar.length) + }) + .then(updated => { + req.session.user = updated; + }) + .catch(() => { + //console.log('ERR', err); + }); + return res.json({ + message: DataEvent.AVATAR_UPLOADED, + url: avatar.substr(7, avatar.length) + }); + } + }); + } else { + res.json({ + message: "Nah. You can't do that. Talk to the admin, sport." + }); + } + }); }); /*** UPLOAD FEATURE BACKGROUND */ -router.post('/add-feature-background', function(req, res, next) -{ - //console.log(req.body); - if (!req.session.user) return res.json( - { - message: "You need to be logged in, champ." - }); - Models.User.findById(req.session.user.id).then((user) => - { - if (rightsManager.check(user.role, OBJECT_POST, TASK_CREATE)) - { - background_upload(req, res, function(err) - { - if (err) - { - res.json( - { - message: err - }); - throw err; - } - else - { - var bgImage = req.files[0].path; - return res.json( - { - message: DataEvent.SITE_BACKGROUND_UPLOADED, - url: bgImage.substr(7, bgImage.length) - }); - } - }); - } - else - { - res.json( - { - message: "Nah. You can't do that. Talk to the admin, sport." - }); - } - }); +router.post('/add-feature-background', function(req, res) { + //console.log(req.body); + if (!req.session.user) + return res.json({ + message: 'You need to be logged in, champ.' + }); + Models.User.findById(req.session.user.id).then(user => { + if (rightsManager.check(user.role, OBJECT_POST, TASK_CREATE)) { + background_upload(req, res, function(err) { + if (err) { + res.json({ + message: err + }); + throw err; + } else { + var bgImage = req.files[0].path; + return res.json({ + message: DataEvent.SITE_BACKGROUND_UPLOADED, + url: bgImage.substr(7, bgImage.length) + }); + } + }); + } else { + res.json({ + message: "Nah. You can't do that. Talk to the admin, sport." + }); + } + }); }); -module.exports = router; \ No newline at end of file +module.exports = router; diff --git a/brain/api/mail/mailer.js b/brain/api/mail/mailer.js index 1899bc3..defb9b2 100644 --- a/brain/api/mail/mailer.js +++ b/brain/api/mail/mailer.js @@ -4,79 +4,71 @@ var nodemailer = require('nodemailer'); var mg = require('nodemailer-mailgun-transport'); const fs = require('fs-extra'); const pug = require('pug'); -router.post('/', function(req, res, next) -{ - fs.readJson('config/site-settings.json').then(settings => - { - let transport = '' - switch (settings.email.active) - { - case "option-smtp": - var auth = { - host: settings.email.smtp.domain, - port: 587, - secure: false, - auth: - { - type:"login", - email: settings.email.smtp, - password: settings.email.smtp.password - } - } - transport = nodemailer.createTransport((auth)); - break; - case "option-mg": - var auth = { - auth: - { - api_key: settings.email.mailgun['api-key'], - domain: settings.email.mailgun.domain - } - } - transport = nodemailer.createTransport(mg(auth)); - break - } - let render = pug.compileFile('themes/dash/email/base.pug'); - let html = render( - { - title: settings.title, - header: "a note from " + settings.title, - content: req.body.content, - footer: "powered by fipamo" - }) - transport.sendMail( - { - from: 'control@playvico.us', - to: 'are0h@protonmail.com', // An array if you have multiple recipients. - subject: 'Hey beautiful', - //You can use "html:" to send HTML email content. It's magic! - html: html - //You can use "text:" to send plain-text content. It's oldschool! - //text: 'Mailgun rocks, pow pow!' - }, function(err, info) - { - if (err) - { - console.log(err) - res.json( - { - message: "MAIL ERROR", - desc: err - }); - } - else - { - console.log(info) - res.json( - { - message: "MAIL SENT", - desc: info - }); - } - }); - }).catch(err => - { - console.error(err) - }) +router.post('/', function(req, res) { + fs.readJson('config/site-settings.json') + .then(settings => { + let transport = ''; + var auth = ''; + switch (settings.email.active) { + case 'option-smtp': + auth = { + host: settings.email.smtp.domain, + port: 587, + secure: false, + auth: { + type: 'login', + email: settings.email.smtp, + password: settings.email.smtp.password + } + }; + transport = nodemailer.createTransport(auth); + break; + case 'option-mg': + auth = { + auth: { + api_key: settings.email.mailgun['api-key'], + domain: settings.email.mailgun.domain + } + }; + transport = nodemailer.createTransport(mg(auth)); + break; + } + let render = pug.compileFile('themes/dash/email/base.pug'); + let html = render({ + title: settings.title, + header: 'a note from ' + settings.title, + content: req.body.content, + footer: 'powered by fipamo' + }); + transport.sendMail( + { + from: 'control@playvico.us', + to: 'are0h@protonmail.com', // An array if you have multiple recipients. + subject: 'Hey beautiful', + //You can use "html:" to send HTML email content. It's magic! + html: html + //You can use "text:" to send plain-text content. It's oldschool! + //text: 'Mailgun rocks, pow pow!' + }, + function(err, info) { + if (err) { + //console.log(err); + res.json({ + message: 'MAIL ERROR', + desc: err + }); + } else { + //console.log(info); + res.json({ + message: 'MAIL SENT', + desc: info + }); + } + } + ); + }) + .catch(() => { + //console.error(err); + }); }); -module.exports = router; \ No newline at end of file +module.exports = router; diff --git a/brain/models/FreshPosts.js b/brain/models/FreshPosts.js index 230bb0a..a23c1fe 100644 --- a/brain/models/FreshPosts.js +++ b/brain/models/FreshPosts.js @@ -1,33 +1,37 @@ -module.exports = function (sequelize, DataTypes) { - var FreshPost = sequelize.define('FreshPost', { - post: { - type: DataTypes.JSONB - } - }, { - timestamps: false, +module.exports = function(sequelize, DataTypes) { + var FreshPost = sequelize.define( + 'FreshPost', + { + post: { + type: DataTypes.JSONB + } + }, + { + timestamps: false, - // don't delete database entries but set the newly added attribute deletedAt - // to the current date (when deletion was done). paranoid will only work if - // timestamps are enabled - paranoid: false, + // don't delete database entries but set the newly added attribute deletedAt + // to the current date (when deletion was done). paranoid will only work if + // timestamps are enabled + paranoid: false, - // don't use camelcase for automatically added attributes but underscore style - // so updatedAt will be updated_at - underscored: true, + // don't use camelcase for automatically added attributes but underscore style + // so updatedAt will be updated_at + underscored: true, - // disable the modification of table names; By default, sequelize will automatically - // transform all passed model names (first parameter of define) into plural. - // if you don't want that, set the following - freezeTableName: false, + // disable the modification of table names; By default, sequelize will automatically + // transform all passed model names (first parameter of define) into plural. + // if you don't want that, set the following + freezeTableName: false, - // define the table's name - tableName: 'FreshPosts', + // define the table's name + tableName: 'FreshPosts', - // Enable optimistic locking. When enabled, sequelize will add a version count attriubte - // to the model and throw an OptimisticLockingError error when stale instances are saved. - // Set to true or a string with the attribute name you want to use to enable. - version: false - }); + // Enable optimistic locking. When enabled, sequelize will add a version count attriubte + // to the model and throw an OptimisticLockingError error when stale instances are saved. + // Set to true or a string with the attribute name you want to use to enable. + version: false + } + ); - return FreshPost; + return FreshPost; }; diff --git a/brain/models/index.js b/brain/models/index.js index 802761f..dcc27cc 100644 --- a/brain/models/index.js +++ b/brain/models/index.js @@ -10,25 +10,24 @@ const db = {}; let sequelize; if (config.use_env_variable) { - sequelize = new Sequelize(process.env[config.use_env_variable], config); + sequelize = new Sequelize(process.env[config.use_env_variable], config); } else { - sequelize = new Sequelize(config.database, config.username, config.password, config); + sequelize = new Sequelize(config.database, config.username, config.password, config); } -fs - .readdirSync(__dirname) - .filter(file => { - return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js'); - }) - .forEach(file => { - const model = sequelize['import'](path.join(__dirname, file)); - db[model.name] = model; - }); +fs.readdirSync(__dirname) + .filter(file => { + return file.indexOf('.') !== 0 && file !== basename && file.slice(-3) === '.js'; + }) + .forEach(file => { + const model = sequelize['import'](path.join(__dirname, file)); + db[model.name] = model; + }); Object.keys(db).forEach(modelName => { - if (db[modelName].associate) { - db[modelName].associate(db); - } + if (db[modelName].associate) { + db[modelName].associate(db); + } }); db.sequelize = sequelize; diff --git a/brain/routes/back/dash_nav.js b/brain/routes/back/dash_nav.js index f4ba32a..a9f9ac8 100644 --- a/brain/routes/back/dash_nav.js +++ b/brain/routes/back/dash_nav.js @@ -1,98 +1,80 @@ const express = require('express'); const router = express.Router(); const Models = require('../../models'); -const fs = require("fs-extra"); +const fs = require('fs-extra'); const _ = require('lodash'); var settings = []; //-------------------------- // SETTINGS //-------------------------- -router.get('/', function(req, res) -{ - fs.readJson('config/site-settings.json').then(obj => - { - settings = [] - settings = obj; - }).catch(err => - { - //console.error(err) - }) - if (req.session.user) - { - Models.User.findById(req.session.user.id).then((user) => - { - Models.FreshPost.findAll( - { - order: [ - ['id', 'DESC'] - ] - }).then(posts => - { - let pages = [] - if (settings.menu.length == 0) - { - for (let index = 0; index < posts.length; index++) - { - let item = posts[index].post; - if (item.page == true || item.page == "true") pages.push( - { - id: posts[index].id, - uuid: posts[index].post.uuid, - title: posts[index].post.title, - slug: posts[index].post.slug - }); - } - } - else - { - let newpages = [] - pages = settings.menu; - for (let index = 0; index < posts.length; index++) - { - let item = posts[index].post; - if (item.page == true || item.page == "true") newpages.push( - { - id: posts[index].id, - uuid: posts[index].post.uuid, - title: posts[index].post.title, - slug: posts[index].post.slug - }); - } - for (let i = 0; i < newpages.length; i++) - { - if (_.findIndex(pages, function(o) - { - return o.id == newpages[i].id; - }) != -1) - { - //console.log("FOUND") - } - else - { - pages.push( - { - id: newpages[i].id, - uuid: newpages[i].uuid, - title: newpages[i].title, - slug: newpages[i].slug - }); - } - } - } - res.render('dash/navigation', - { - pages: pages, - title: 'Dashboard | Global Nav' - }); - }).catch(err => - { - console.log("ERROR", err) - }) - }) - } - else - { - res.redirect('/@/dashboard'); - } +router.get('/', function(req, res) { + fs.readJson('config/site-settings.json') + .then(obj => { + settings = []; + settings = obj; + }) + .catch(() => { + //console.error(err) + }); + if (req.session.user) { + Models.User.findById(req.session.user.id).then(() => { + Models.FreshPost.findAll({ + order: [['id', 'DESC']] + }) + .then(posts => { + let pages = []; + if (settings.menu.length == 0) { + for (let index = 0; index < posts.length; index++) { + let item = posts[index].post; + if (item.page == true || item.page == 'true') + pages.push({ + id: posts[index].id, + uuid: posts[index].post.uuid, + title: posts[index].post.title, + slug: posts[index].post.slug + }); + } + } else { + let newpages = []; + pages = settings.menu; + for (let index = 0; index < posts.length; index++) { + let item = posts[index].post; + if (item.page == true || item.page == 'true') + newpages.push({ + id: posts[index].id, + uuid: posts[index].post.uuid, + title: posts[index].post.title, + slug: posts[index].post.slug + }); + } + for (let i = 0; i < newpages.length; i++) { + if ( + _.findIndex(pages, function(o) { + return o.id == newpages[i].id; + }) != -1 + ) { + //console.log("FOUND") + } else { + pages.push({ + id: newpages[i].id, + uuid: newpages[i].uuid, + title: newpages[i].title, + slug: newpages[i].slug + }); + } + } + } + res.render('dash/navigation', { + pages: pages, + title: 'Dashboard | Global Nav' + }); + }) + .catch(() => { + //console.log('ERROR', err); + }); + }); + } else { + res.redirect('/@/dashboard'); + } }); -module.exports = router; \ No newline at end of file +module.exports = router; diff --git a/brain/routes/back/dash_posts.js b/brain/routes/back/dash_posts.js index 2a4ca73..395cabb 100644 --- a/brain/routes/back/dash_posts.js +++ b/brain/routes/back/dash_posts.js @@ -11,123 +11,141 @@ const dateUtils = new DateUtils(); //-------------------------- // POSTS //-------------------------- -router.get('/:page?', function (req, res) { - var pageNum = req.params.page; - if (pageNum == "" || pageNum == null) pageNum = 1; - var offset = ((pageNum * 5) - 5); - if (req.session.user) { - Models.FreshPost.findAll({ - order: [ - ['id', 'DESC'] - ] - }).then(function (posts) { - let all = []; - let deleted = []; - let published = []; - let pages = []; - let featured = []; - for (let index = 0; index < posts.length; index++) { - let item = posts[index].post; - if (typeof item.deleted == 'undefined' || item.deleted == false) { - all.push(posts[index]); - if (item.published == 'true') published.push(posts[index]); - if (item.page == 'true') pages.push(posts[index]); - if (item.featured == 'true') featured.push(posts[index]); - } else { - deleted.push(posts[index]) - } - } - var count = Math.round(all.length / 6); - var pageItems = []; - var itemLimit = 6; - var rangeStart = (pageNum * itemLimit) - itemLimit; - for (var i = 0; i < itemLimit; i++) { - try { - if (all[i + rangeStart].id != null) { - pageItems.push(all[i + rangeStart]); - } - } catch (e) { - //console.log("NO POST", e) - } - } - res.render('dash/posts-index', { - title: 'Dashbord | Posts', - mode: 'admin', - welcome: "Your Posts", - items: pageItems, - page_info: { - all: all.length, - deleted:deleted.length, - published: published.length, - pages: pages.length, - featured: featured.length - }, - page_index: pageNum, - page_count: count, - user_status: true - }); - }).then(function (value) { - //console.log(value); - }).catch(function (err) { - //next(err); - }) - } else { - res.redirect('/@/dashboard'); - } +router.get('/:page?', function(req, res) { + var pageNum = req.params.page; + if (pageNum == '' || pageNum == null) pageNum = 1; + if (req.session.user) { + Models.FreshPost.findAll({ + order: [['id', 'DESC']] + }) + .then(function(posts) { + let all = []; + let deleted = []; + let published = []; + let pages = []; + let featured = []; + for (let index = 0; index < posts.length; index++) { + let item = posts[index].post; + if (typeof item.deleted == 'undefined' || item.deleted == false) { + all.push(posts[index]); + if (item.published == 'true') published.push(posts[index]); + if (item.page == 'true') pages.push(posts[index]); + if (item.featured == 'true') featured.push(posts[index]); + } else { + deleted.push(posts[index]); + } + } + var count = Math.round(all.length / 6); + var pageItems = []; + var itemLimit = 6; + var rangeStart = pageNum * itemLimit - itemLimit; + for (var i = 0; i < itemLimit; i++) { + try { + if (all[i + rangeStart].id != null) { + pageItems.push(all[i + rangeStart]); + } + } catch (e) { + //console.log("NO POST", e) + } + } + res.render('dash/posts-index', { + title: 'Dashbord | Posts', + mode: 'admin', + welcome: 'Your Posts', + items: pageItems, + page_info: { + all: all.length, + deleted: deleted.length, + published: published.length, + pages: pages.length, + featured: featured.length + }, + page_index: pageNum, + page_count: count, + user_status: true + }); + }) + .then(() => { + //console.log(value); + }) + .catch(() => { + //next(err); + }); + } else { + res.redirect('/@/dashboard'); + } }); //-------------------------- // BLOG POST ADD DISPLAY //-------------------------- -router.get('/add/new', function (req, res) { - if (req.session.user) { - res.render('dash/post-edit', { - title: 'Make New Post', - mode: 'admin', - date: dateUtils.getDate('year', new Date()) + "-" + dateUtils.getDate('month', new Date()) + "-" + dateUtils.getDate('day', new Date()), - status: ['false', 'false', 'false'], - edit: false - }); - } else { - res.redirect('/@/dashboard'); - } +router.get('/add/new', function(req, res) { + if (req.session.user) { + res.render('dash/post-edit', { + title: 'Make New Post', + mode: 'admin', + date: + dateUtils.getDate('year', new Date()) + + '-' + + dateUtils.getDate('month', new Date()) + + '-' + + dateUtils.getDate('day', new Date()), + status: ['false', 'false', 'false'], + edit: false + }); + } else { + res.redirect('/@/dashboard'); + } }); //-------------------------- // BLOG POST EDIT DISPLAY //-------------------------- -router.get('/edit/:id', function (req, res) { - if (req.session.user) { - Models.FreshPost.findOne({ - where: { - "post": { - [Op.contains]: { - uuid: req.params.id - } - } - } - }).then(item => { - let featured = 'null'; - if (item.post.feature != null || item.post.feature != '') featured = item.post.feature.substr(8, item.post.feature.length); - let pretty = hljs.highlight('markdown', item.post.plaintext).value; - let sexydate = dateUtils.getDate('year', item.post.created) + "-" + dateUtils.getDate('month', item.post.created) + "-" + dateUtils.getDate('day', item.post.created) - res.render('dash/post-edit', { - id: item.id, - title: 'Edit Post', - mode: 'admin', - post: item.post, - date: sexydate, - colored: pretty, - html: item.post.plaintext, - feature: featured, - status: [String(item.post.page), String(item.post.featured), String(item.post.published)], - edit: true - }); - }).then(function (value) { - //console.log("VALUE: " + value); - }).catch(function (err) { - //console.log(err); - }) - } else { - res.redirect('/@/dashboard'); - } +router.get('/edit/:id', function(req, res) { + if (req.session.user) { + Models.FreshPost.findOne({ + where: { + post: { + [Op.contains]: { + uuid: req.params.id + } + } + } + }) + .then(item => { + let featured = 'null'; + if (item.post.feature != null || item.post.feature != '') + featured = item.post.feature.substr(8, item.post.feature.length); + let pretty = hljs.highlight('markdown', item.post.plaintext).value; + let sexydate = + dateUtils.getDate('year', item.post.created) + + '-' + + dateUtils.getDate('month', item.post.created) + + '-' + + dateUtils.getDate('day', item.post.created); + res.render('dash/post-edit', { + id: item.id, + title: 'Edit Post', + mode: 'admin', + post: item.post, + date: sexydate, + colored: pretty, + html: item.post.plaintext, + feature: featured, + status: [ + String(item.post.page), + String(item.post.featured), + String(item.post.published) + ], + edit: true + }); + }) + .then(() => { + //console.log("VALUE: " + value); + }) + .catch(() => { + //console.log(err); + }); + } else { + res.redirect('/@/dashboard'); + } }); -module.exports = router; \ No newline at end of file +module.exports = router; diff --git a/brain/routes/back/dash_settings.js b/brain/routes/back/dash_settings.js index 26ccf3a..8250e42 100644 --- a/brain/routes/back/dash_settings.js +++ b/brain/routes/back/dash_settings.js @@ -2,77 +2,67 @@ const express = require('express'); const router = express.Router(); const FileHound = require('filehound'); const Models = require('../../models'); -const fs = require("fs-extra"); +const fs = require('fs-extra'); var settings = []; //-------------------------- // SETTINGS //-------------------------- -router.get('/', function(req, res) -{ - fs.readJson('config/site-settings.json').then(obj => - { - settings = obj; - }).catch(err => - { - //console.error(err) - }) - let themes = []; - FileHound.create().paths('themes').ext('json').find().then(files => - { - files.forEach(file => - { - fs.readJson(file).then(theme => - { - if (theme.name == settings.theme) - { - themes.push( - { - theme: theme, - current: "true" - }) - } - else - { - themes.push( - { - theme: theme, - current: "false" - }) - } - }).catch(err => - { - //console.error(err) - }) - }); - if (req.session.user) - { - let memberInfo = []; - Models.User.findById(req.session.user.id).then((user) => - { - memberInfo.push( - { - handle: user.handle, - email: user.email, - avi: user.avatar - }); - themes.sort(function(a, b) { - var textA = a.theme.name.toUpperCase(); - var textB = b.theme.name.toUpperCase(); - return (textA < textB) ? -1 : (textA > textB) ? 1 : 0; - }); - res.render('dash/settings', - { - title: 'Dashboard | Settings', - themes: themes, - settings: settings, - member: memberInfo[0] - }); - }) - } - else - { - res.redirect('/@/dashboard'); - } - }); +router.get('/', function(req, res) { + fs.readJson('config/site-settings.json') + .then(obj => { + settings = obj; + }) + .catch(() => { + //console.error(err) + }); + let themes = []; + FileHound.create() + .paths('themes') + .ext('json') + .find() + .then(files => { + files.forEach(file => { + fs.readJson(file) + .then(theme => { + if (theme.name == settings.theme) { + themes.push({ + theme: theme, + current: 'true' + }); + } else { + themes.push({ + theme: theme, + current: 'false' + }); + } + }) + .catch(() => { + //console.error(err) + }); + }); + if (req.session.user) { + let memberInfo = []; + Models.User.findById(req.session.user.id).then(user => { + memberInfo.push({ + handle: user.handle, + email: user.email, + avi: user.avatar + }); + themes.sort(function(a, b) { + var textA = a.theme.name.toUpperCase(); + var textB = b.theme.name.toUpperCase(); + return textA < textB ? -1 : textA > textB ? 1 : 0; + }); + res.render('dash/settings', { + title: 'Dashboard | Settings', + themes: themes, + settings: settings, + member: memberInfo[0] + }); + }); + } else { + res.redirect('/@/dashboard'); + } + }); }); -module.exports = router; \ No newline at end of file +module.exports = router; diff --git a/brain/routes/back/index.js b/brain/routes/back/index.js index 07f15ad..f2635bd 100644 --- a/brain/routes/back/index.js +++ b/brain/routes/back/index.js @@ -5,92 +5,76 @@ const bCrypt = require('bcrypt-nodejs'); //-------------------------- // Index //-------------------------- -router.get('/', function(req, res) -{ - var loggedIn = false - if (req.session.user) loggedIn = true; - Models.FreshPost.findAll( - { - order: [ - ['id', 'DESC'] - ] - }).then(function(posts) - { - let title = 'Fipamo Admin'; - (!loggedIn) ? welcome = "Hello." : welcome = "Welcome back, "+req.session.user.handle - let filtered = []; - for (let index = 0; index < posts.length; index++) - { - let item = posts[index].post; - if (typeof item.deleted == 'undefined' || item.deleted == false) - { - filtered.push(posts[index]) - } - else - { - continue - } - } - res.render('dash/index', - { - title: title, - welcome: welcome, - user_status: loggedIn, - items: filtered - }); - }).then(function(value) - { - //console.log(value); - }).catch(function(err) - { - //next(err); - }) +router.get('/', function(req, res) { + var loggedIn = false; + if (req.session.user) loggedIn = true; + Models.FreshPost.findAll({ + order: [['id', 'DESC']] + }) + .then(function(posts) { + let title = 'Fipamo Admin'; + let welcome = ''(!loggedIn) + ? (welcome = 'Hello.') + : (welcome = 'Welcome back, ' + req.session.user.handle); + let filtered = []; + for (let index = 0; index < posts.length; index++) { + let item = posts[index].post; + if (typeof item.deleted == 'undefined' || item.deleted == false) { + filtered.push(posts[index]); + } else { + continue; + } + } + res.render('dash/index', { + title: title, + welcome: welcome, + user_status: loggedIn, + items: filtered + }); + }) + .then(() => { + //console.log(value); + }) + .catch(() => { + //next(err); + }); }); //-------------------------- // Login //-------------------------- /* Handle Login POST */ -router.post('/login', function(req, res, next) -{ - Models.User.findOne( - { - where: - { - handle: req.body.handle - } - }).then(user => - { - if (!isValidPassword(user, req.body.password)) - { - return res.json( - { - message: 'CHECK YOUR PASSWORD' - }); - } - let session = req.session; - session.user = user; - res.redirect('/@/dashboard'); - }).catch(err => - { - return res.json( - { - message: 'NOT FOUND, HAWS' - }); - }) +router.post('/login', function(req, res) { + Models.User.findOne({ + where: { + handle: req.body.handle + } + }) + .then(user => { + if (!isValidPassword(user, req.body.password)) { + return res.json({ + message: 'CHECK YOUR PASSWORD' + }); + } + let session = req.session; + session.user = user; + res.redirect('/@/dashboard'); + }) + .catch(() => { + return res.json({ + message: 'NOT FOUND, HAWS' + }); + }); }); //-------------------------- // Logout //-------------------------- -router.post('/logout', function(req, res, next) -{ - req.logout(); - return res.json( - { - message: 'LOGGED OUT' - }); +router.post('/logout', function(req, res) { + req.logout(); + return res.json({ + message: 'LOGGED OUT' + }); }); module.exports = router; -var isValidPassword = function(user, password) -{ - return bCrypt.compareSync(password, user.password); -} \ No newline at end of file +var isValidPassword = function(user, password) { + return bCrypt.compareSync(password, user.password); +}; diff --git a/brain/tools/effects/Animate.js b/brain/tools/effects/Animate.js deleted file mode 100644 index f3cb3c1..0000000 --- a/brain/tools/effects/Animate.js +++ /dev/null @@ -1,23 +0,0 @@ -import EventEmitter from '../events/EventEmitter'; - -class Animate extends EventEmitter { - //-------------------------- - // constructor - //-------------------------- - constructor() { - super(); - } - //-------------------------- - // methods - //-------------------------- - object(properties) { - var animation = anime( - properties - ); - //animation.start(properties); - } - //-------------------------- - // event handlers - //-------------------------- -} -export default Animate diff --git a/brain/tools/effects/TextEffects.js b/brain/tools/effects/TextEffects.js deleted file mode 100644 index dcdd1a0..0000000 --- a/brain/tools/effects/TextEffects.js +++ /dev/null @@ -1,70 +0,0 @@ -class TexEffects { - //-------------------------- - // constructor - //-------------------------- - constructor() {} - //-------------------------- - // methods - //-------------------------- - scramble(obj, offset, complete) - { - var scrambleText = new ScrambleText(obj, { - timeOffset: offset, - chars: [ - '安', - '以', - '宇', - '衣', - '於', - '加', - '幾', - '久', - '計', - '己', - '左', - '之', - '寸', - '世', - '曽', - '太', - '知', - '川', - '天', - '止', - '奈', - '仁', - '奴', - '称', - '乃', - '波', - '比', - '不', - '部', - '保', - '末', - '美', - '武', - '女', - '毛', - '也', - '為', - '由', - '恵', - '与', - '良', - '利', - '留', - '礼', - '呂', - '和', - '遠', - '无' - ], - callback: complete - }).start(); - } - //-------------------------- - // event handlers - //-------------------------- -} -export default TexEffects diff --git a/brain/tools/events/EditorEvent.js b/brain/tools/events/EditorEvent.js index 9081147..2cd24c6 100644 --- a/brain/tools/events/EditorEvent.js +++ b/brain/tools/events/EditorEvent.js @@ -3,17 +3,12 @@ export const EDITOR_UPLOAD_POST_IMAGE = 'editorUploadImage'; export const EDITOR_SAVE = 'editorSave'; export const EDITOR_UPDATE = 'editorUpdate'; -class EditorEvent -{ - - //-------------------------- - // methods - //-------------------------- - - - - //-------------------------- - // event handlers - //-------------------------- +class EditorEvent { + //-------------------------- + // methods + //-------------------------- + //-------------------------- + // event handlers + //-------------------------- } -export default new EditorEvent +export default new EditorEvent(); diff --git a/brain/tools/events/EventEmitter.js b/brain/tools/events/EventEmitter.js index 6d03b31..56f5dfe 100644 --- a/brain/tools/events/EventEmitter.js +++ b/brain/tools/events/EventEmitter.js @@ -1,57 +1,52 @@ -class EventEmitter -{ +class EventEmitter { + //-------------------------- + // constructor + //-------------------------- + constructor() { + this.listeners = new Map(); + } + //-------------------------- + // methods + //-------------------------- + addListener(label, callback) { + this.listeners.has(label) || this.listeners.set(label, []); + this.listeners.get(label).push(callback); + } - //-------------------------- - // constructor - //-------------------------- - constructor() - { - this.listeners = new Map(); - } - //-------------------------- - // methods - //-------------------------- - addListener(label, callback) { - this.listeners.has(label) || this.listeners.set(label, []); - this.listeners.get(label).push(callback); - } + removeListener(label, callback) { + var isFunction = function(obj) { + return typeof obj == 'function' || false; + }; - removeListener(label, callback) { - var isFunction = function(obj) { - return typeof obj == 'function' || false; - }; + var listeners = this.listeners.get(label), + index; - var listeners = this.listeners.get(label), - index; + if (listeners && listeners.length) { + index = listeners.reduce((i, listener, index) => { + return isFunction(listener) && listener === callback ? (i = index) : i; + }, -1); - if (listeners && listeners.length) { - index = listeners.reduce((i, listener, index) => { - return (isFunction(listener) && listener === callback) - ? i = index - : i; - }, -1); + if (index > -1) { + listeners.splice(index, 1); + this.listeners.set(label, listeners); + return true; + } + } + return false; + } - if (index > -1) { - listeners.splice(index, 1); - this.listeners.set(label, listeners); - return true; - } - } - return false; - } - - emitEvent(label, ...args) { - var listeners = this.listeners.get(label); - if (listeners && listeners.length) { - listeners.forEach((listener) => { - listener(...args); - }); - return true; - } - return false; - } - //-------------------------- - // event handlers - //-------------------------- + emitEvent(label, ...args) { + var listeners = this.listeners.get(label); + if (listeners && listeners.length) { + listeners.forEach(listener => { + listener(...args); + }); + return true; + } + return false; + } + //-------------------------- + // event handlers + //-------------------------- } -export default EventEmitter +export default EventEmitter; diff --git a/brain/tools/ui/TextEditor.js b/brain/tools/ui/TextEditor.js index 74e280f..e326e08 100644 --- a/brain/tools/ui/TextEditor.js +++ b/brain/tools/ui/TextEditor.js @@ -1,160 +1,156 @@ import * as DataEvent from '../events/DataEvent'; import DateUtils from '../utilities/DateUtils'; -import { - position, - offset -} -from 'caret-pos'; +import { position } from 'caret-pos'; import EventEmitter from '../events/EventEmitter'; import * as EditorEvent from '../events/EditorEvent'; class TextEditor extends EventEmitter { - /** - * Text Editor UI Component - * @constructor - * @param {object} textEditor - Text area that will edit text - * @param {number} scrollLimit - YPos where editor position will become fixed - */ - //-------------------------- - // constructor - //-------------------------- - constructor(textEditor, scrollLimit) { - super(); - hljs.initHighlightingOnLoad(); - this.dateUtils = new DateUtils(); - this.textEditor = textEditor; - this.fixLimit = scrollLimit; - this.caretPos = null; - this.url = ''; - let self = this; - this.setInputs(); - window.addEventListener("scroll", f => { - var fixLimit = this.fixLimit; - if (window.pageYOffset >= fixLimit) { - document.getElementById('edit-control').style.position = "fixed" - } else { - document.getElementById('edit-control').style.position = "relative" - } - }); - this.refresh(); - } - //-------------------------- - // methods - //-------------------------- - setInputs() { - let self = this; - var editorButtons = document.querySelectorAll('.editor-button'); - for (var i = 0, length = editorButtons.length; i < length; i++) { - editorButtons[i].addEventListener('click', e => this.handleEditorOption(e), false); - } - - this.textEditor.addEventListener('input', e => { - let htmlTagRe = /<[a-z][\s\S]*>/g; - let text = this.textEditor.innerText; - if (e.inputType == "insertParagraph") return //cursor setting gets weird on return, so just back out + /** + * Text Editor UI Component + * @constructor + * @param {object} textEditor - Text area that will edit text + * @param {number} scrollLimit - YPos where editor position will become fixed + */ + //-------------------------- + // constructor + //-------------------------- + constructor(textEditor, scrollLimit) { + super(); + hljs.initHighlightingOnLoad(); + this.dateUtils = new DateUtils(); + this.textEditor = textEditor; + this.fixLimit = scrollLimit; + this.caretPos = null; + this.url = ''; + this.setInputs(); + window.addEventListener('scroll', () => { + var fixLimit = this.fixLimit; + if (window.pageYOffset >= fixLimit) { + document.getElementById('edit-control').style.position = 'fixed'; + } else { + document.getElementById('edit-control').style.position = 'relative'; + } + }); + this.refresh(); + } + //-------------------------- + // methods + //-------------------------- + setInputs() { + let self = this; + var editorButtons = document.querySelectorAll('.editor-button'); + for (var i = 0, length = editorButtons.length; i < length; i++) { + editorButtons[i].addEventListener('click', e => this.handleEditorOption(e), false); + } - if (text.search(htmlTagRe) > -1) { - let caret = position(this.textEditor).pos; - self.refresh() - position(this.textEditor, caret); - } - }) - } - refresh() { - var spiffed = hljs.highlight('markdown', this.textEditor.innerText).value; - spiffed = spiffed.replace(new RegExp('\r?\n', 'g'), '
'); - var temp = document.createElement("div"); - temp.innerText = spiffed; - this.textEditor.innerHTML = temp.innerText; - this.textEditor.style.maxWidth = '900px'; - } - notify(type, data) { - switch (type) { - case DataEvent.POST_UPDATED: - document.getElementById('submit-update').classList.add('icon-hide'); - document.getElementById('submit-good').classList.remove('icon-hide'); - document.getElementById('edit-update').classList.remove('submit-start'); - document.getElementById('edit-update').classList.add('submit-cool'); - setTimeout(f => { - document.getElementById('submit-update').classList.remove('icon-hide'); - document.getElementById('submit-good').classList.add('icon-hide'); - document.getElementById('edit-update').classList.add('submit-start'); - document.getElementById('edit-update').classList.remove('submit-cool'); - }, 2000); - break; - case DataEvent.POST_ADDED: - // do nothing - break; - case EditorEvent.EDITOR_UPLOAD_POST_IMAGE: - position(this.textEditor, this.caretPos); - var sel, range, pulled; - sel = window.getSelection(); //console.log(sel) - //console.log(note.message) - if (sel.rangeCount) { - range = sel.getRangeAt(0); - pulled = sel.getRangeAt(0).toString(); - range.deleteContents(); - range.insertNode(document.createTextNode("![image alt text](" + data + " 'image title')")); - } - this.refresh(); - break; - } + this.textEditor.addEventListener('input', e => { + let htmlTagRe = /<[a-z][\s\S]*>/g; + let text = this.textEditor.innerText; + if (e.inputType == 'insertParagraph') return; //cursor setting gets weird on return, so just back out - } - //-------------------------- - // event handlers - //-------------------------- - handleEditorOption(e) { - e.preventDefault(); - var self = this; - var sel, range, pulled; - sel = window.getSelection(); //console.log(sel) - if (sel.rangeCount) { - range = sel.getRangeAt(0); - pulled = sel.getRangeAt(0).toString(); - range.deleteContents(); - switch (e.target.id) { - case "edit-bold": - range.insertNode(document.createTextNode("**" + pulled + "**")); - break; - case "edit-italic": - range.insertNode(document.createTextNode("*" + pulled + "*")); - break; - case "edit-strikethrough": - range.insertNode(document.createTextNode("" + pulled + "")); - break; - case "edit-header1": - range.insertNode(document.createTextNode("# " + pulled)); - break; - case "edit-header2": - range.insertNode(document.createTextNode("## " + pulled)); - break; - case "edit-header3": - range.insertNode(document.createTextNode("### " + pulled)); - break; - case "edit-image": - this.caretPos = position(this.textEditor).pos; - this.emitEvent(EditorEvent.EDITOR_UPLOAD_POST_IMAGE); - break; - case "submit-save": - case "edit-save": - this.emitEvent(EditorEvent.EDITOR_SAVE); - break; - case "submit-update": - case "edit-update": - this.emitEvent(EditorEvent.EDITOR_UPDATE); - break - case "edit-link": - range.insertNode(document.createTextNode("[" + pulled + "](PASTE URL HERE)")); - break; - case "edit-delete": - this.emitEvent(EditorEvent.EDITOR_DELETE); - break - default: - //range.insertNode(document.createTextNode("[" + self.url + "](PASTE URL HERE)")); - break; - } - } - this.refresh() - } + if (text.search(htmlTagRe) > -1) { + let caret = position(this.textEditor).pos; + self.refresh(); + position(this.textEditor, caret); + } + }); + } + refresh() { + var spiffed = hljs.highlight('markdown', this.textEditor.innerText).value; + spiffed = spiffed.replace(new RegExp('\r?\n', 'g'), '
'); + var temp = document.createElement('div'); + temp.innerText = spiffed; + this.textEditor.innerHTML = temp.innerText; + this.textEditor.style.maxWidth = '900px'; + } + notify(type, data) { + switch (type) { + case DataEvent.POST_UPDATED: + document.getElementById('submit-update').classList.add('icon-hide'); + document.getElementById('submit-good').classList.remove('icon-hide'); + document.getElementById('edit-update').classList.remove('submit-start'); + document.getElementById('edit-update').classList.add('submit-cool'); + setTimeout(() => { + document.getElementById('submit-update').classList.remove('icon-hide'); + document.getElementById('submit-good').classList.add('icon-hide'); + document.getElementById('edit-update').classList.add('submit-start'); + document.getElementById('edit-update').classList.remove('submit-cool'); + }, 2000); + break; + case DataEvent.POST_ADDED: + // do nothing + break; + case EditorEvent.EDITOR_UPLOAD_POST_IMAGE: + position(this.textEditor, this.caretPos); + var sel, range; + //var pulled; + sel = window.getSelection(); //console.log(sel) + //console.log(note.message) + if (sel.rangeCount) { + range = sel.getRangeAt(0); + //pulled = sel.getRangeAt(0).toString(); + range.deleteContents(); + range.insertNode( + document.createTextNode('![image alt text](' + data + " 'image title')") + ); + } + this.refresh(); + break; + } + } + //-------------------------- + // event handlers + //-------------------------- + handleEditorOption(e) { + e.preventDefault(); + var sel, range, pulled; + sel = window.getSelection(); //console.log(sel) + if (sel.rangeCount) { + range = sel.getRangeAt(0); + pulled = sel.getRangeAt(0).toString(); + range.deleteContents(); + switch (e.target.id) { + case 'edit-bold': + range.insertNode(document.createTextNode('**' + pulled + '**')); + break; + case 'edit-italic': + range.insertNode(document.createTextNode('*' + pulled + '*')); + break; + case 'edit-strikethrough': + range.insertNode(document.createTextNode('' + pulled + '')); + break; + case 'edit-header1': + range.insertNode(document.createTextNode('# ' + pulled)); + break; + case 'edit-header2': + range.insertNode(document.createTextNode('## ' + pulled)); + break; + case 'edit-header3': + range.insertNode(document.createTextNode('### ' + pulled)); + break; + case 'edit-image': + this.caretPos = position(this.textEditor).pos; + this.emitEvent(EditorEvent.EDITOR_UPLOAD_POST_IMAGE); + break; + case 'submit-save': + case 'edit-save': + this.emitEvent(EditorEvent.EDITOR_SAVE); + break; + case 'submit-update': + case 'edit-update': + this.emitEvent(EditorEvent.EDITOR_UPDATE); + break; + case 'edit-link': + range.insertNode(document.createTextNode('[' + pulled + '](PASTE URL HERE)')); + break; + case 'edit-delete': + this.emitEvent(EditorEvent.EDITOR_DELETE); + break; + default: + //range.insertNode(document.createTextNode("[" + self.url + "](PASTE URL HERE)")); + break; + } + } + this.refresh(); + } } -export default TextEditor \ No newline at end of file +export default TextEditor; diff --git a/brain/tools/utilities/DBUtils.js b/brain/tools/utilities/DBUtils.js index 6ee2efb..3b4df9e 100644 --- a/brain/tools/utilities/DBUtils.js +++ b/brain/tools/utilities/DBUtils.js @@ -1,204 +1,177 @@ -"use strict"; -import DataUtils, -{ - REQUEST_TYPE_GET, - REQUEST_TYPE_PUT, - REQUEST_TYPE_POST, - REQUEST_TYPE_DELETE, - CONTENT_TYPE_JSON, - CONTENT_TYPE_FORM -} -from '../utilities/DataUtils'; +'use strict'; +import DataUtils, { REQUEST_TYPE_POST, CONTENT_TYPE_JSON } from '../utilities/DataUtils'; import Dexie from 'dexie'; import * as DataEvent from '../events/DataEvent'; export var COUNT; export var FINAL_KEY; -export default class DBUtils -{ - //-------------------------- - // constructor - //-------------------------- - constructor() - { - /** - * NOTE: DB ERRORS REPLICATE. - * WHEN FIXING A BUG, FIX DATA WITH JSON BACKUP - */ - this.dataUtils = new DataUtils(); - this.db = new Dexie("fipamo_posts"); - this.db.version(1).stores( - { - postList: 'id,post' - }); - this.db.postList.toArray(array => - { - COUNT = array.length; - FINAL_KEY = array[COUNT - 1].id; - }) - } - //-------------------------- - // methods - //-------------------------- - modify(id, postData) - { - let self = this; - let freshID; - return new Promise(function(resolve, reject) - { - if (id == null) - { - self.db.postList.put(postData).then(fresh => - { - freshID = fresh; - }).catch(e => - { - let err = { - message: "PUT ERROR", - error: e - } - }); - } - else - { - //console.log("UPDATED", postData); - self.db.postList.update(Number(id), - { - post: postData - }).then(updated => - {}).catch(e => - { - let err = { - message: "UPDATE ERROR", - error: e - } - }); - } - self.db.postList.toArray(array => - { - self.syncRemote(array, freshID).then(response => - { - resolve( - { - response - }) - }).catch(err => - { - reject( - { - err - }); - }); - }) - }) - } - syncLocal(array) - { - let self = this; - return new Promise(function(resolve, reject) - { - self.db.postList.clear().then(result => - { - self.db.postList.bulkAdd(array).then(key => - { - self.db.postList.toArray(array => - { - let event = DataEvent.LOCAL_DB_READY - resolve( - { - event - }) - }) - }).catch(Dexie.BulkError, e => - { - reject( - { - e - }) - }) - }) - }) - } - syncRemote(db, newPostId) - { - let self = this; - return new Promise(function(resolve, reject) - { - self.dataUtils.request('/api/post/sync', DataEvent.POSTS_SYNCED, REQUEST_TYPE_POST, CONTENT_TYPE_JSON, db).then((response) => - { - let bounce = { - message: response, - newPost: newPostId - } - resolve(bounce) - }).catch((err) => - { - reject(err); - }) - }) - } - getPost(id) - { - let self = this; - if (id == null) - { - return new Promise(function(resolve, reject) - { - self.db.postList.toArray(array => - { - resolve(array) - }).catch(err => - { - reject(err) - }) - }) - } - else - { - return new Promise(function(resolve, reject) - { - self.db.postList.get(Number(id)).then(obj => - { - resolve(obj) - }).catch(err => - { - reject(err) - }) - }) - } - } - archivePost(id, archive) - { - let self = this; - return new Promise(function(resolve, reject) - { - self.db.postList.update(Number(id), - { - post: archive - }).then(deleted => - { - self.db.postList.toArray(array => - { - self.syncRemote(array, null).then(response => - { - resolve( - { - response - }) - }).catch(err => - { - reject( - { - err - }); - }); - }) - }).catch(e => - { - console.log("ERROR", e) - }); - }) - } - //-------------------------- - // event handlers - //-------------------------- -} \ No newline at end of file +export default class DBUtils { + //-------------------------- + // constructor + //-------------------------- + constructor() { + /** + * NOTE: DB ERRORS REPLICATE. + * WHEN FIXING A BUG, FIX DATA WITH JSON BACKUP + */ + this.dataUtils = new DataUtils(); + this.db = new Dexie('fipamo_posts'); + this.db.version(1).stores({ + postList: 'id,post' + }); + this.db.postList.toArray(array => { + COUNT = array.length; + FINAL_KEY = array[COUNT - 1].id; + }); + } + //-------------------------- + // methods + //-------------------------- + modify(id, postData) { + let self = this; + let freshID; + return new Promise(function(resolve, reject) { + if (id == null) { + self.db.postList + .put(postData) + .then(fresh => { + freshID = fresh; + }) + .catch(e => { + let err = { + message: 'PUT ERROR', + error: e + }; + + return err; + }); + } else { + //console.log("UPDATED", postData); + self.db.postList + .update(Number(id), { + post: postData + }) + .then(() => {}) + .catch(e => { + let err = { + message: 'UPDATE ERROR', + error: e + }; + return err; + }); + } + self.db.postList.toArray(array => { + self.syncRemote(array, freshID) + .then(response => { + resolve({ + response + }); + }) + .catch(err => { + reject({ + err + }); + }); + }); + }); + } + syncLocal(array) { + let self = this; + return new Promise(function(resolve, reject) { + self.db.postList.clear().then(() => { + self.db.postList + .bulkAdd(array) + .then(() => { + self.db.postList.toArray(() => { + let event = DataEvent.LOCAL_DB_READY; + resolve({ + event + }); + }); + }) + .catch(Dexie.BulkError, e => { + reject({ + e + }); + }); + }); + }); + } + syncRemote(db, newPostId) { + let self = this; + return new Promise(function(resolve, reject) { + self.dataUtils + .request( + '/api/post/sync', + DataEvent.POSTS_SYNCED, + REQUEST_TYPE_POST, + CONTENT_TYPE_JSON, + db + ) + .then(response => { + let bounce = { + message: response, + newPost: newPostId + }; + resolve(bounce); + }) + .catch(err => { + reject(err); + }); + }); + } + getPost(id) { + let self = this; + if (id == null) { + return new Promise(function(resolve, reject) { + self.db.postList + .toArray(array => { + resolve(array); + }) + .catch(err => { + reject(err); + }); + }); + } else { + return new Promise(function(resolve, reject) { + self.db.postList + .get(Number(id)) + .then(obj => { + resolve(obj); + }) + .catch(err => { + reject(err); + }); + }); + } + } + archivePost(id, archive) { + let self = this; + return new Promise(function(resolve, reject) { + self.db.postList + .update(Number(id), { + post: archive + }) + .then(() => { + self.db.postList.toArray(array => { + self.syncRemote(array, null) + .then(response => { + resolve({ + response + }); + }) + .catch(err => { + reject({ + err + }); + }); + }); + }) + .catch(() => { + //console.log('ERROR', e); + }); + }); + } + //-------------------------- + // event handlers + //-------------------------- +} diff --git a/brain/tools/utilities/DOMUtils.js b/brain/tools/utilities/DOMUtils.js index f36907c..e63d0b9 100644 --- a/brain/tools/utilities/DOMUtils.js +++ b/brain/tools/utilities/DOMUtils.js @@ -1,31 +1,27 @@ -class DOMUtils -{ +class DOMUtils { + //-------------------------- + // constructor + //-------------------------- + constructor() {} + //-------------------------- + // methods + //-------------------------- + getWindowXY() { + var w = window, + d = document, + e = d.documentElement, + g = d.getElementsByTagName('body')[0], + x = w.innerWidth || e.clientWidth || g.clientWidth, + y = w.innerHeight || e.clientHeight || g.clientHeight; - //-------------------------- - // constructor - //-------------------------- - constructor() - {} - //-------------------------- - // methods - //-------------------------- - getWindowXY() - { - var w = window, - d = document, - e = d.documentElement, - g = d.getElementsByTagName('body')[0], - x = w.innerWidth || e.clientWidth || g.clientWidth, - y = w.innerHeight || e.clientHeight || g.clientHeight; - - var dimensions = { - windowHeight: y, - windowWidth: x - } - return dimensions; - } - //-------------------------- - // event handlers - //-------------------------- + var dimensions = { + windowHeight: y, + windowWidth: x + }; + return dimensions; + } + //-------------------------- + // event handlers + //-------------------------- } -export default DOMUtils +export default DOMUtils; diff --git a/brain/tools/utilities/DataUtils.js b/brain/tools/utilities/DataUtils.js index 4eaad81..4b82c4f 100644 --- a/brain/tools/utilities/DataUtils.js +++ b/brain/tools/utilities/DataUtils.js @@ -1,139 +1,123 @@ -export const REQUEST_TYPE_POST = "POST"; -export const REQUEST_TYPE_GET = "GET"; -export const REQUEST_TYPE_PUT = "PUT"; -export const REQUEST_TYPE_DELETE = "DELETE"; +export const REQUEST_TYPE_POST = 'POST'; +export const REQUEST_TYPE_GET = 'GET'; +export const REQUEST_TYPE_PUT = 'PUT'; +export const REQUEST_TYPE_DELETE = 'DELETE'; export const CONTENT_TYPE_JSON = 'json'; export const CONTENT_TYPE_FORM = 'x-www-form-urlencoded'; import EventEmitter from '../events/EventEmitter'; -import * as DataEvent from '../events/DataEvent'; -class DataUtils extends EventEmitter -{ - //-------------------------- - // constructor - //-------------------------- - constructor() - { - super(); - var self = this; - } - //-------------------------- - // methods - //-------------------------- - request(requestURL, eventType, requestType = REQUEST_TYPE_GET, contentType = CONTENT_TYPE_JSON, requestData = null) - { - var self = this; - return new Promise(function(resolve, reject) - { - var request = new XMLHttpRequest(); - request.upload.onprogress = self.handleLoadProgress; - request.open(requestType, requestURL, true); - request.onload = function(e) - { - if (request.status == 200) - { - resolve( - { - request, - eventType - }); - } - else - { - reject( - { - request, - eventType - }); - }; - }; - if (requestType == REQUEST_TYPE_PUT || requestType == REQUEST_TYPE_POST) - { - switch (contentType) - { - case CONTENT_TYPE_JSON: - request.setRequestHeader("Content-type", "application/" + contentType); - request.send(JSON.stringify(requestData)); - break; - case CONTENT_TYPE_FORM: - request.send(requestData); - break; - } - } - else - { - request.send(); - } - }) - } - imgLoad(url) - { - 'use strict'; - // Create new promise with the Promise() constructor; - // This has as its argument a function with two parameters, resolve and reject - return new Promise(function(resolve, reject) - { - // Standard XHR to load an image - var request = new XMLHttpRequest(); - request.open('GET', url); - request.responseType = 'blob'; - // When the request loads, check whether it was successful - request.onload = function() - { - if (request.status === 200) - { - // If successful, resolve the promise by passing back the request response - resolve(request.response); - } - else - { - // If it fails, reject the promise with a error message - reject(new Error('Image didn\'t load successfully; error code:' + request.statusText)); - } - }; - request.onerror = function() - { - // Also deal with the case when the entire request fails to begin with - // This is probably a network error, so reject the promise with an appropriate message - reject(new Error('There was a network error.')); - }; - // Send the request - request.send(); - }); - } - loadImage(src) - { - 'use strict'; - let self = this; - return new Promise(function(resolve, reject) - { - // Get a reference to the body element, and create a new image object - var body = document.querySelector('body'), - myImage = new Image(); - myImage.crossOrigin = ""; // or "anonymous" - // Call the function with the URL we want to load, but then chain the - // promise then() method on to the end of it. This contains two callbacks - self.imgLoad(src).then(function(response) - { - // The first runs when the promise resolves, with the request.reponse specified within the resolve() method. - var imageURL = window.URL.createObjectURL(response); - resolve(imageURL); - //$('background-content').setStyle('background-image', 'url('+imageURL+')') //myImage.src = imageURL; - //console.log(imageURL); - //body.appendChild(myImage); - // The second runs when the promise is rejected, and logs the Error specified with the reject() method. - }, function(Error) - { - reject(Error) - }); - }); - } - //-------------------------- - // event handlers - //-------------------------- - handleLoadProgress(e) - { - var percentComplete = Math.ceil((e.loaded / e.total) * 100); - //console.log(percentComplete); - } +class DataUtils extends EventEmitter { + //-------------------------- + // constructor + //-------------------------- + constructor() { + super(); + } + //-------------------------- + // methods + //-------------------------- + request( + requestURL, + eventType, + requestType = REQUEST_TYPE_GET, + contentType = CONTENT_TYPE_JSON, + requestData = null + ) { + var self = this; + return new Promise(function(resolve, reject) { + var request = new XMLHttpRequest(); + request.upload.onprogress = self.handleLoadProgress; + request.open(requestType, requestURL, true); + request.onload = () => { + if (request.status == 200) { + resolve({ + request, + eventType + }); + } else { + reject({ + request, + eventType + }); + } + }; + if (requestType == REQUEST_TYPE_PUT || requestType == REQUEST_TYPE_POST) { + switch (contentType) { + case CONTENT_TYPE_JSON: + request.setRequestHeader('Content-type', 'application/' + contentType); + request.send(JSON.stringify(requestData)); + break; + case CONTENT_TYPE_FORM: + request.send(requestData); + break; + } + } else { + request.send(); + } + }); + } + imgLoad(url) { + 'use strict'; + // Create new promise with the Promise() constructor; + // This has as its argument a function with two parameters, resolve and reject + return new Promise(function(resolve, reject) { + // Standard XHR to load an image + var request = new XMLHttpRequest(); + request.open('GET', url); + request.responseType = 'blob'; + // When the request loads, check whether it was successful + request.onload = function() { + if (request.status === 200) { + // If successful, resolve the promise by passing back the request response + resolve(request.response); + } else { + // If it fails, reject the promise with a error message + reject( + new Error( + "Image didn't load successfully; error code:" + request.statusText + ) + ); + } + }; + request.onerror = function() { + // Also deal with the case when the entire request fails to begin with + // This is probably a network error, so reject the promise with an appropriate message + reject(new Error('There was a network error.')); + }; + // Send the request + request.send(); + }); + } + loadImage(src) { + 'use strict'; + let self = this; + return new Promise(function(resolve, reject) { + // Get a reference to the body element, and create a new image object + var myImage = new Image(); + myImage.crossOrigin = ''; // or "anonymous" + // Call the function with the URL we want to load, but then chain the + // promise then() method on to the end of it. This contains two callbacks + self.imgLoad(src).then( + function(response) { + // The first runs when the promise resolves, with the request.reponse specified within the resolve() method. + var imageURL = window.URL.createObjectURL(response); + resolve(imageURL); + //$('background-content').setStyle('background-image', 'url('+imageURL+')') //myImage.src = imageURL; + //console.log(imageURL); + //body.appendChild(myImage); + // The second runs when the promise is rejected, and logs the Error specified with the reject() method. + }, + function(Error) { + reject(Error); + } + ); + }); + } + //-------------------------- + // event handlers + //-------------------------- + handleLoadProgress() { + //var percentComplete = Math.ceil((e.loaded / e.total) * 100); + //console.log(percentComplete); + } } -export default DataUtils; \ No newline at end of file +export default DataUtils; diff --git a/brain/tools/utilities/DateUtils.js b/brain/tools/utilities/DateUtils.js index d46b797..426a213 100644 --- a/brain/tools/utilities/DateUtils.js +++ b/brain/tools/utilities/DateUtils.js @@ -1,61 +1,102 @@ class DateUtils { + //-------------------------- + // constructor + //-------------------------- + constructor() {} - //-------------------------- - // constructor - //-------------------------- - constructor() {} + //-------------------------- + // methods + //-------------------------- + getMKtime() { + var time = + new Date( + new Date().getFullYear(), + new Date().getMonth(), + new Date().getDate(), + new Date().getHours(), + new Date().getMinutes(), + new Date().getSeconds(), + 0 + ).getTime() / 1000; + return time; + } - //-------------------------- - // methods - //-------------------------- - getMKtime() { - var time = new Date(new Date().getFullYear(), new Date().getMonth(), new Date().getDate(), new Date().getHours(), new Date().getMinutes(), new Date().getSeconds(), 0).getTime() / 1000; - return time; - } + convertMKtime(seconds) { + var date = new Date(seconds * 1000); + return date; + } - convertMKtime(seconds) { - var date = new Date(seconds * 1000); - return date; - } + getDate(type, rawdate) { + var day = + rawdate != null || rawdate != '' + ? String(new Date(rawdate).getUTCDate()) + : String(new Date().getUTCDate()); + var month = + rawdate != null || rawdate != '' + ? String(new Date(rawdate).getUTCMonth() + 1) + : String(new Date().getUTCMonth() + 1); + var year = + rawdate != null || rawdate != '' + ? String(new Date(rawdate).getUTCFullYear()) + : String(new Date().getUTCFullYear()); + var hour = + rawdate != null || rawdate != '' + ? String(new Date(rawdate).getUTCHours()) + : String(new Date().getUTCHours()); + var minute = + rawdate != null || rawdate != '' + ? String(new Date(rawdate).getUTCMinutes()) + : String(new Date().getUTCMinutes()); + var seconds = + rawdate != null || rawdate != '' + ? String(new Date(rawdate).getUTCSeconds()) + : String(new Date().getUTCSeconds()); + var millisecond = + rawdate != null || rawdate != '' + ? String(new Date(rawdate).getUTCMilliseconds()) + : String(new Date().getUTCMilliseconds()); + var offset = + rawdate != null || rawdate != '' + ? String(new Date(rawdate).getTimezoneOffset()) + : String(new Date().getTimezoneOffset()); + if (day.length == 1) day = String('0' + day); + if (month.length == 1) month = String('0' + month); + offset = String(offset / 60); + if (offset.length == 1) offset = String('0' + offset); + switch (type) { + case 'day': + return day; - getDate(type, rawdate) { - var day = ((rawdate != null || rawdate != '') ? String(new Date(rawdate).getUTCDate()) : String(new Date().getUTCDate())); - var month = ((rawdate != null || rawdate != '') ? String(new Date(rawdate).getUTCMonth() + 1) : String(new Date().getUTCMonth() + 1)); - var year = ((rawdate != null || rawdate != '') ? String(new Date(rawdate).getUTCFullYear()) : String(new Date().getUTCFullYear())); - var hour = ((rawdate != null || rawdate != '') ? String(new Date(rawdate).getUTCHours()) : String(new Date().getUTCHours())); - var minute = ((rawdate != null || rawdate != '') ? String(new Date(rawdate).getUTCMinutes()) : String(new Date().getUTCMinutes())); - var seconds = ((rawdate != null || rawdate != '') ? String(new Date(rawdate).getUTCSeconds()) : String(new Date().getUTCSeconds())); - var millisecond = ((rawdate != null || rawdate != '') ? String(new Date(rawdate).getUTCMilliseconds()) : String(new Date().getUTCMilliseconds())); - var offset = ((rawdate != null || rawdate != '') ? String(new Date(rawdate).getTimezoneOffset()) : String(new Date().getTimezoneOffset())); - if (day.length == 1) - day = String("0" + day); - if (month.length == 1) - month = String("0" + month); - offset = String(offset / 60); - if (offset.length == 1) - offset = String("0" + offset); - switch (type) { - case "day": - return day; - break; - case "month": - return month; - break; - case "year": - return year; - break; - case "stamp": - return String(year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + seconds + "." + millisecond + "-" + (offset)); - break - default: - return String(year + "-" + month + "-" + day); - break; - } - } + case 'month': + return month; + case 'year': + return year; + case 'stamp': + return String( + year + + '-' + + month + + '-' + + day + + ' ' + + hour + + ':' + + minute + + ':' + + seconds + + '.' + + millisecond + + '-' + + offset + ); + default: + return String(year + '-' + month + '-' + day); + } + } - //-------------------------- - // event handlers - //-------------------------- + //-------------------------- + // event handlers + //-------------------------- } -export default DateUtils \ No newline at end of file +export default DateUtils; diff --git a/brain/tools/utilities/RightsManager.js b/brain/tools/utilities/RightsManager.js index a014da6..1fd913d 100644 --- a/brain/tools/utilities/RightsManager.js +++ b/brain/tools/utilities/RightsManager.js @@ -1,162 +1,137 @@ export const roles = { - hnic: - { - "client_admin": - { - "create": true, - "read": true, - "update": true, - "delete": true - }, - "client_user": - { - "create": true, - "read": true, - "update": true, - "delete": true - }, - "client_project": - { - "create": true, - "read": true, - "update": true, - "delete": true - }, - "folio_project": - { - "create": true, - "read": true, - "update": true, - "delete": true - }, - "bookmark": - { - "create": true, - "read": true, - "update": true, - "delete": true - }, - "post": - { - "create": true, - "read": true, - "update": true, - "delete": true - }, - "settings": - { - "create": true, - "read": true, - "update": true, - "delete": true - } - }, - client: - { - "client_admin": - { - "create": false, - "read": true, - "update": false, - "delete": false - }, - "client_user": - { - "create": true, - "read": true, - "update": true, - "delete": true - }, - "client_project": - { - "create": true, - "read": true, - "update": true, - "delete": false - }, - "folio_project": - { - "create": false, - "read": false, - "update": false, - "delete": false - } - }, - user: - { - "client_admin": - { - "create": false, - "read": false, - "update": false, - "delete": false - }, - "client_user": - { - "create": false, - "read": true, - "update": false, - "delete": false - }, - "client_project": - { - "create": false, - "read": true, - "update": true, - "delete": false - }, - "folio_project": - { - "create": false, - "read": false, - "update": false, - "delete": false - }, - "bookmark": - { - "create": true, - "read": true, - "update": true, - "delete": true - }, - "post": - { - "create": false, - "read": false, - "update": false, - "delete": false - } - } + hnic: { + client_admin: { + create: true, + read: true, + update: true, + delete: true + }, + client_user: { + create: true, + read: true, + update: true, + delete: true + }, + client_project: { + create: true, + read: true, + update: true, + delete: true + }, + folio_project: { + create: true, + read: true, + update: true, + delete: true + }, + bookmark: { + create: true, + read: true, + update: true, + delete: true + }, + post: { + create: true, + read: true, + update: true, + delete: true + }, + settings: { + create: true, + read: true, + update: true, + delete: true + } + }, + client: { + client_admin: { + create: false, + read: true, + update: false, + delete: false + }, + client_user: { + create: true, + read: true, + update: true, + delete: true + }, + client_project: { + create: true, + read: true, + update: true, + delete: false + }, + folio_project: { + create: false, + read: false, + update: false, + delete: false + } + }, + user: { + client_admin: { + create: false, + read: false, + update: false, + delete: false + }, + client_user: { + create: false, + read: true, + update: false, + delete: false + }, + client_project: { + create: false, + read: true, + update: true, + delete: false + }, + folio_project: { + create: false, + read: false, + update: false, + delete: false + }, + bookmark: { + create: true, + read: true, + update: true, + delete: true + }, + post: { + create: false, + read: false, + update: false, + delete: false + } + } }; -export const TASK_CREATE = 'create' -export const TASK_UPDATE = 'update' -export const TASK_READ = 'read' -export const TASK_DELETE = 'delete' -export const OBJECT_CLIENT_ADMIN = 'client_admin' -export const OBJECT_CLIENT_USER = 'client_user' -export const OBJECT_PROJECT_CLIENT = 'client_project' -export const OBJECT_PROJECT_FOLIO = 'folio_project' -export const OBJECT_BOOKMARK = 'bookmark' -export const OBJECT_POST = 'post' -export const OBJECT_SETTINGS = 'settings' -export default class RightsManager -{ - //-------------------------- - // constructor - //-------------------------- - constructor() - { - var self = this; - } - //-------------------------- - // methods - //-------------------------- - check(role, object, task) - { - //console.log(role + " *** " + object + " *** " + task); - return roles[role][object][task]; - } - //-------------------------- - // event handlers - //-------------------------- -} \ No newline at end of file +export const TASK_CREATE = 'create'; +export const TASK_UPDATE = 'update'; +export const TASK_READ = 'read'; +export const TASK_DELETE = 'delete'; +export const OBJECT_CLIENT_ADMIN = 'client_admin'; +export const OBJECT_CLIENT_USER = 'client_user'; +export const OBJECT_PROJECT_CLIENT = 'client_project'; +export const OBJECT_PROJECT_FOLIO = 'folio_project'; +export const OBJECT_BOOKMARK = 'bookmark'; +export const OBJECT_POST = 'post'; +export const OBJECT_SETTINGS = 'settings'; +export default class RightsManager { + //-------------------------- + // constructor + //-------------------------- + constructor() {} + //-------------------------- + // methods + //-------------------------- + check(role, object, task) { + //console.log(role + " *** " + object + " *** " + task); + return roles[role][object][task]; + } + //-------------------------- + // event handlers + //-------------------------- +} diff --git a/brain/tools/utilities/StringUtils.js b/brain/tools/utilities/StringUtils.js index 2de506d..6676b91 100644 --- a/brain/tools/utilities/StringUtils.js +++ b/brain/tools/utilities/StringUtils.js @@ -1,65 +1,68 @@ -class StringUtils -{ +class StringUtils { + //-------------------------- + // constructor + //-------------------------- + constructor() {} + //-------------------------- + // methods + //-------------------------- + cleanString(string) { + var clean = string + .replace(/(^\-+|[^a-zA-Z0-9\/_| -]+|\-+$)/g, '') + .toLowerCase() + .replace(/[\/_| -]+/g, '-'); + return clean; + } - //-------------------------- - // constructor - //-------------------------- - constructor() - {} - //-------------------------- - // methods - //-------------------------- - cleanString(string) - { - var clean = string.replace(/(^\-+|[^a-zA-Z0-9\/_| -]+|\-+$)/g, '').toLowerCase().replace(/[\/_| -]+/g, '-'); - return clean; - } + decodeHTML(string, quote_style) { + var optTemp = 0, + i = 0, + noquotes = false; + if (typeof quote_style === 'undefined') { + quote_style = 2; + } + string = string + .toString() + .replace(/</g, '<') + .replace(/>/g, '>'); + var OPTS = { + ENT_NOQUOTES: 0, + ENT_HTML_QUOTE_SINGLE: 1, + ENT_HTML_QUOTE_DOUBLE: 2, + ENT_COMPAT: 2, + ENT_QUOTES: 3, + ENT_IGNORE: 4 + }; + if (quote_style === 0) { + noquotes = true; + } + if (typeof quote_style !== 'number') { + // Allow for a single string or an array of string flags + quote_style = [].concat(quote_style); + for (i = 0; i < quote_style.length; i++) { + // Resolve string input to bitwise e.g. 'PATHINFO_EXTENSION' becomes 4 + if (OPTS[quote_style[i]] === 0) { + noquotes = true; + } else if (OPTS[quote_style[i]]) { + optTemp = optTemp | OPTS[quote_style[i]]; + } + } + quote_style = optTemp; + } + if (quote_style & OPTS.ENT_HTML_QUOTE_SINGLE) { + string = string.replace(/�*39;/g, "'"); // PHP doesn't currently escape if more than one 0, but it should + // string = string.replace(/'|�*27;/g, "'"); // This would also be useful here, but not a part of PHP + } + if (!noquotes) { + string = string.replace(/"/g, '"'); + } + // Put this in last place to avoid escape being double-decoded + string = string.replace(/&/g, '&'); + return string; + } - decodeHTML(string, quote_style) { - var optTemp = 0, - i = 0, - noquotes = false; - if (typeof quote_style === 'undefined') { - quote_style = 2; - } - string = string.toString().replace(/</g, '<').replace(/>/g, '>'); - var OPTS = { - 'ENT_NOQUOTES': 0, - 'ENT_HTML_QUOTE_SINGLE': 1, - 'ENT_HTML_QUOTE_DOUBLE': 2, - 'ENT_COMPAT': 2, - 'ENT_QUOTES': 3, - 'ENT_IGNORE': 4 - }; - if (quote_style === 0) { - noquotes = true; - } - if (typeof quote_style !== 'number') { // Allow for a single string or an array of string flags - quote_style = [].concat(quote_style); - for (i = 0; i < quote_style.length; i++) { - // Resolve string input to bitwise e.g. 'PATHINFO_EXTENSION' becomes 4 - if (OPTS[quote_style[i]] === 0) { - noquotes = true; - } else if (OPTS[quote_style[i]]) { - optTemp = optTemp | OPTS[quote_style[i]]; - } - } - quote_style = optTemp; - } - if (quote_style & OPTS.ENT_HTML_QUOTE_SINGLE) { - string = string.replace(/�*39;/g, "'"); // PHP doesn't currently escape if more than one 0, but it should - // string = string.replace(/'|�*27;/g, "'"); // This would also be useful here, but not a part of PHP - } - if (!noquotes) { - string = string.replace(/"/g, '"'); - } - // Put this in last place to avoid escape being double-decoded - string = string.replace(/&/g, '&'); - return string; - } - - //-------------------------- - // event handlers - //-------------------------- + //-------------------------- + // event handlers + //-------------------------- } -export default StringUtils +export default StringUtils; diff --git a/init.js b/init.js index 23c5de8..8908cb1 100644 --- a/init.js +++ b/init.js @@ -5,7 +5,7 @@ */ var app = require('./brain/app'); -var debug = require('debug')('thetwelfthhouse:server'); +var debug = require('debug')('fipamo:server'); var http = require('http'); var models = require('./brain/models'); @@ -30,37 +30,35 @@ server.listen(port); server.on('error', onError); server.on('listening', onListening); - models.sequelize.sync().then(function() { - /** - * Listen on provided port, on all network interfaces. - */ - server.listen(port, function() { - debug('Express server listening on port ' + server.address().port); - }); - server.on('error', onError); - server.on('listening', onListening); + /** + * Listen on provided port, on all network interfaces. + */ + server.listen(port, function() { + debug('Express server listening on port ' + server.address().port); + }); + server.on('error', onError); + server.on('listening', onListening); }); - /** * Normalize a port into a number, string, or false. */ function normalizePort(val) { - var port = parseInt(val, 10); + var port = parseInt(val, 10); - if (isNaN(port)) { - // named pipe - return val; - } + if (isNaN(port)) { + // named pipe + return val; + } - if (port >= 0) { - // port number - return port; - } + if (port >= 0) { + // port number + return port; + } - return false; + return false; } /** @@ -68,27 +66,25 @@ function normalizePort(val) { */ function onError(error) { - if (error.syscall !== 'listen') { - throw error; - } - - var bind = typeof port === 'string' ? - 'Pipe ' + port : - 'Port ' + port - - // handle specific listen errors with friendly messages - switch (error.code) { - case 'EACCES': - console.error(bind + ' requires elevated privileges'); - process.exit(1); - break; - case 'EADDRINUSE': - console.error(bind + ' is already in use'); - process.exit(1); - break; - default: - throw error; - } + if (error.syscall !== 'listen') { + throw error; + } + + var bind = typeof port === 'string' ? 'Pipe ' + port : 'Port ' + port; + + // handle specific listen errors with friendly messages + switch (error.code) { + case 'EACCES': + console.error(bind + ' requires elevated privileges'); + process.exit(1); + break; + case 'EADDRINUSE': + console.error(bind + ' is already in use'); + process.exit(1); + break; + default: + throw error; + } } /** @@ -96,9 +92,7 @@ function onError(error) { */ function onListening() { - var addr = server.address(); - var bind = typeof addr === 'string' ? - 'pipe ' + addr : - 'port ' + addr.port; - debug('Listening on ' + bind); + var addr = server.address(); + var bind = typeof addr === 'string' ? 'pipe ' + addr : 'port ' + addr.port; + debug('Listening on ' + bind); } diff --git a/themes/dash/src/com/actions/Mailer.js b/themes/dash/src/com/actions/Mailer.js index bdfc398..11c3f7c 100644 --- a/themes/dash/src/com/actions/Mailer.js +++ b/themes/dash/src/com/actions/Mailer.js @@ -1,41 +1,39 @@ -import DataUtils, -{ - REQUEST_TYPE_GET, - REQUEST_TYPE_PUT, - REQUEST_TYPE_POST, - REQUEST_TYPE_DELETE, - CONTENT_TYPE_JSON, - CONTENT_TYPE_FORM -} -from '../../../../../brain//tools/utilities/DataUtils'; +import DataUtils, { + REQUEST_TYPE_POST, + CONTENT_TYPE_JSON +} from '../../../../../brain//tools/utilities/DataUtils'; import * as DataEvent from '../../../../../brain/tools/events/DataEvent'; -export default class Mailer -{ - //-------------------------- - // constructor - //-------------------------- - constructor() - { - this.dataUtils = new DataUtils(); - } - //-------------------------- - // methods - //-------------------------- - sendMail() - { - var self = this; - let mailData = { - content: "This is a test email" - } - self.dataUtils.request('/api/mail', DataEvent.SETTINGS_UPDATED, REQUEST_TYPE_POST, CONTENT_TYPE_JSON, mailData).then((response) => - { - console.log(response) - }).catch((err) => - { - console.log(err) - }) - } - //-------------------------- - // event handlers - //-------------------------- -} \ No newline at end of file +export default class Mailer { + //-------------------------- + // constructor + //-------------------------- + constructor() { + this.dataUtils = new DataUtils(); + } + //-------------------------- + // methods + //-------------------------- + sendMail() { + var self = this; + let mailData = { + content: 'This is a test email' + }; + self.dataUtils + .request( + '/api/mail', + DataEvent.SETTINGS_UPDATED, + REQUEST_TYPE_POST, + CONTENT_TYPE_JSON, + mailData + ) + .then(() => { + //console.log(response); + }) + .catch(() => { + //console.log(err); + }); + } + //-------------------------- + // event handlers + //-------------------------- +} diff --git a/themes/dash/src/com/actions/NavActions.js b/themes/dash/src/com/actions/NavActions.js index 5532ae8..dd3ea0f 100644 --- a/themes/dash/src/com/actions/NavActions.js +++ b/themes/dash/src/com/actions/NavActions.js @@ -1,71 +1,62 @@ -import DataUtils, -{ - REQUEST_TYPE_GET, - REQUEST_TYPE_PUT, - REQUEST_TYPE_POST, - REQUEST_TYPE_DELETE, - CONTENT_TYPE_JSON, - CONTENT_TYPE_FORM -} -from '../../../../../brain//tools/utilities/DataUtils'; -import StringUtils from '../../../../../brain//tools/utilities/StringUtils'; +import DataUtils, { + REQUEST_TYPE_POST, + CONTENT_TYPE_JSON +} from '../../../../../brain//tools/utilities/DataUtils'; import DateUtils from '../../../../../brain/tools/utilities/DateUtils'; import * as DataEvent from '../../../../../brain/tools/events/DataEvent'; import DBUtils from '../../../../../brain/tools/utilities/DBUtils'; -export default class NavActions -{ - //-------------------------- - // constructor - //-------------------------- - constructor() - { - this.dataUtils = new DataUtils(); - this.dateUtils = new DateUtils(); - this.dbutils = new DBUtils(); - } - //-------------------------- - // methods - //-------------------------- - save() - { - let self = this; - let navData = []; - let items = document.getElementById('nav-pages').children; - for (let index = 0; index < items.length; index++) - { - navData.push( - { - title: items[index].getElementsByTagName('label')[0].innerHTML, - id: items[index].id, - slug: items[index].getAttribute('data-slug'), - uuid: items[index].getAttribute('data-uuid') - }) - } - return new Promise(function(resolve, reject) - { - self.dataUtils.request('/api/settings/nav-sync', DataEvent.SETTINGS_UPDATED, REQUEST_TYPE_POST, CONTENT_TYPE_JSON, navData).then((response) => - { - resolve(response) - }).catch((err) => - { - reject(err); - }) - }) - } - removeItem(id) - { - let self = this; - this.dbutils.getPost(id).then(post => - { - post.post.page = "false"; - self.dbutils.modify(id, post.post).then(r => - { - document.getElementById('nav-pages').removeChild(document.getElementById(id)); - self.save() - }) - }) - } - //-------------------------- - // event handlers - //-------------------------- -} \ No newline at end of file +export default class NavActions { + //-------------------------- + // constructor + //-------------------------- + constructor() { + this.dataUtils = new DataUtils(); + this.dateUtils = new DateUtils(); + this.dbutils = new DBUtils(); + } + //-------------------------- + // methods + //-------------------------- + save() { + let self = this; + let navData = []; + let items = document.getElementById('nav-pages').children; + for (let index = 0; index < items.length; index++) { + navData.push({ + title: items[index].getElementsByTagName('label')[0].innerHTML, + id: items[index].id, + slug: items[index].getAttribute('data-slug'), + uuid: items[index].getAttribute('data-uuid') + }); + } + return new Promise(function(resolve, reject) { + self.dataUtils + .request( + '/api/settings/nav-sync', + DataEvent.SETTINGS_UPDATED, + REQUEST_TYPE_POST, + CONTENT_TYPE_JSON, + navData + ) + .then(response => { + resolve(response); + }) + .catch(err => { + reject(err); + }); + }); + } + removeItem(id) { + let self = this; + this.dbutils.getPost(id).then(post => { + post.post.page = 'false'; + self.dbutils.modify(id, post.post).then(() => { + document.getElementById('nav-pages').removeChild(document.getElementById(id)); + self.save(); + }); + }); + } + //-------------------------- + // event handlers + //-------------------------- +} diff --git a/themes/dash/src/com/actions/PostActions.js b/themes/dash/src/com/actions/PostActions.js index 375c246..97e1210 100644 --- a/themes/dash/src/com/actions/PostActions.js +++ b/themes/dash/src/com/actions/PostActions.js @@ -1,162 +1,155 @@ -import DataUtils, -{ - REQUEST_TYPE_GET, - REQUEST_TYPE_PUT, - REQUEST_TYPE_POST, - REQUEST_TYPE_DELETE, - CONTENT_TYPE_JSON, - CONTENT_TYPE_FORM -} -from '../../../../../brain//tools/utilities/DataUtils'; +import DataUtils, { + REQUEST_TYPE_POST, + CONTENT_TYPE_JSON +} from '../../../../../brain//tools/utilities/DataUtils'; import StringUtils from '../../../../../brain//tools/utilities/StringUtils'; import DateUtils from '../../../../../brain/tools/utilities/DateUtils'; import DBUtils from '../../../../../brain/tools/utilities/DBUtils'; var uuidv4 = require('uuid/v4'); import * as DataEvent from '../../../../../brain/tools/events/DataEvent'; -export default class PostActions -{ - //-------------------------- - // constructor - //-------------------------- - constructor() - { - this.dataUtils = new DataUtils(); - this.dateUtils = new DateUtils(); - this.dbUtils = new DBUtils(); - } - //-------------------------- - // methods - //-------------------------- - update(id, data, files, lastKey) - { - let self = this; - let freshData; - return new Promise(function(resolve, reject) - { - let txt = document.createElement("textarea"); - txt.innerHTML = document.getElementById('edit-post-text').innerHTML; - let html = txt.value; - html = html.replace(/<\/?span[^>]*>/g, ""); //removes highightjs styling - html = html.replace(/<\/?br[^>]*>/g, "\n"); //convert back to encoded line break for storage - data.title = document.getElementById('post_title').value; - data.slug = new StringUtils().cleanString(document.getElementById('post_title').value) - data.plaintext = html; - data.html = html; - data.created = document.getElementById('post-date').value; - data.tags = document.getElementById('post_tags').value; - data.page = document.getElementById('option-page').getAttribute('data-active') - data.featured = document.getElementById('option-feature').getAttribute('data-active') - data.published = document.getElementById('option-published').getAttribute('data-active') - if (files.length != 0) - { - for (var i = 0; i < files.length; i++) - { - var file = files[i]; - // Check the file type. - if (!file.type.match('image.*')) - { - continue; - } - data.feature = "/content/blog-images/" + self.dateUtils.getDate('year', new Date()) + "/" + self.dateUtils.getDate('month', new Date()) + "/" + file.name; - } - } - else - { - if (typeof data.feature == 'undefined') data.feature = "" - } - if (id == null) - { - freshData = { - id: lastKey + 1, - post: - { - uuid: uuidv4(), - title: data.title, - slug: data.slug, - plaintext: data.plaintext, - html: data.html, - feature: data.feature, - created: data.created, - tags: data.tags, - page: data.page, - featured: data.featured, - published: data.published, - deleted: "", - author: "user" - } - } - } - else - { - freshData = data; - } - self.dbUtils.modify(id, freshData).then((response) => - { - resolve(response) - if(id != null) (freshData.page == 'true') ? self.updateNav(true, id, freshData) : self.updateNav(false, id, freshData) - - }).catch((err) => - { - reject(err) - }) - }) - } - deletePost(id, body) - { - let self = this; - body.deleted = new Date().toString(); - return new Promise(function(resolve, reject) - { - self.dbUtils.archivePost(id, body).then(response => - { - console.log(response) - resolve(response) - }).catch(err => - { - console.log(err) - reject(error) - }) - }) - } - updateNav(add, id, post) - { - var self = this; - this.dataUtils.request('/api/settings/nav', DataEvent.SETTINGS_LOADED).then((response) => - { - let menu = JSON.parse(response.request['response']); - let item = { - id: id, - uuid: post.uuid, - title: post.title, - slug: post.slug - } - if (add) - { - menu.push(item) - } - else - { - for (let index = 0; index < menu.length; index++) - { - if (menu[index].id == id) - { - menu.splice(index, 1) - } - } - } - self.dataUtils.request('/api/settings/nav-sync', DataEvent.SETTINGS_UPDATED, REQUEST_TYPE_POST, CONTENT_TYPE_JSON, menu).then((response) => - { - console.log(response) - }).catch((err) => - { - console.log(err) - }) - }).catch((err) => - { - console.log(err); - }); - } - //-------------------------- - // event handlers - //-------------------------- -} \ No newline at end of file +export default class PostActions { + //-------------------------- + // constructor + //-------------------------- + constructor() { + this.dataUtils = new DataUtils(); + this.dateUtils = new DateUtils(); + this.dbUtils = new DBUtils(); + } + //-------------------------- + // methods + //-------------------------- + update(id, data, files, lastKey) { + let self = this; + let freshData; + return new Promise(function(resolve, reject) { + let txt = document.createElement('textarea'); + txt.innerHTML = document.getElementById('edit-post-text').innerHTML; + let html = txt.value; + html = html.replace(/<\/?span[^>]*>/g, ''); //removes highightjs styling + html = html.replace(/<\/?br[^>]*>/g, '\n'); //convert back to encoded line break for storage + data.title = document.getElementById('post_title').value; + data.slug = new StringUtils().cleanString(document.getElementById('post_title').value); + data.plaintext = html; + data.html = html; + data.created = document.getElementById('post-date').value; + data.tags = document.getElementById('post_tags').value; + data.page = document.getElementById('option-page').getAttribute('data-active'); + data.featured = document.getElementById('option-feature').getAttribute('data-active'); + data.published = document + .getElementById('option-published') + .getAttribute('data-active'); + if (files.length != 0) { + for (var i = 0; i < files.length; i++) { + var file = files[i]; + // Check the file type. + if (!file.type.match('image.*')) { + continue; + } + data.feature = + '/content/blog-images/' + + self.dateUtils.getDate('year', new Date()) + + '/' + + self.dateUtils.getDate('month', new Date()) + + '/' + + file.name; + } + } else { + if (typeof data.feature == 'undefined') data.feature = ''; + } + if (id == null) { + freshData = { + id: lastKey + 1, + post: { + uuid: uuidv4(), + title: data.title, + slug: data.slug, + plaintext: data.plaintext, + html: data.html, + feature: data.feature, + created: data.created, + tags: data.tags, + page: data.page, + featured: data.featured, + published: data.published, + deleted: '', + author: 'user' + } + }; + } else { + freshData = data; + } + self.dbUtils + .modify(id, freshData) + .then(response => { + resolve(response); + if (id != null) + freshData.page == 'true' + ? self.updateNav(true, id, freshData) + : self.updateNav(false, id, freshData); + }) + .catch(err => { + reject(err); + }); + }); + } + deletePost(id, body) { + let self = this; + body.deleted = new Date().toString(); + return new Promise(function(resolve, reject) { + self.dbUtils + .archivePost(id, body) + .then(response => { + //console.log(response); + resolve(response); + }) + .catch(err => { + //console.log(err); + reject(err); + }); + }); + } + updateNav(add, id, post) { + var self = this; + this.dataUtils + .request('/api/settings/nav', DataEvent.SETTINGS_LOADED) + .then(response => { + let menu = JSON.parse(response.request['response']); + let item = { + id: id, + uuid: post.uuid, + title: post.title, + slug: post.slug + }; + if (add) { + menu.push(item); + } else { + for (let index = 0; index < menu.length; index++) { + if (menu[index].id == id) { + menu.splice(index, 1); + } + } + } + self.dataUtils + .request( + '/api/settings/nav-sync', + DataEvent.SETTINGS_UPDATED, + REQUEST_TYPE_POST, + CONTENT_TYPE_JSON, + menu + ) + .then(() => { + //console.log(response); + }) + .catch(() => { + //console.log(err); + }); + }) + .catch(() => { + //console.log(err); + }); + } + //-------------------------- + // event handlers + //-------------------------- +} diff --git a/themes/dash/src/com/actions/SettingsActions.js b/themes/dash/src/com/actions/SettingsActions.js index 0b4cb5c..36828de 100644 --- a/themes/dash/src/com/actions/SettingsActions.js +++ b/themes/dash/src/com/actions/SettingsActions.js @@ -1,92 +1,88 @@ -import DataUtils, -{ - REQUEST_TYPE_GET, - REQUEST_TYPE_PUT, - REQUEST_TYPE_POST, - REQUEST_TYPE_DELETE, - CONTENT_TYPE_JSON, - CONTENT_TYPE_FORM -} -from '../../../../../brain//tools/utilities/DataUtils'; -import StringUtils from '../../../../../brain//tools/utilities/StringUtils'; +import DataUtils, { + REQUEST_TYPE_POST, + CONTENT_TYPE_JSON +} from '../../../../../brain//tools/utilities/DataUtils'; import DateUtils from '../../../../../brain/tools/utilities/DateUtils'; import * as DataEvent from '../../../../../brain/tools/events/DataEvent'; -export default class SettingsActions -{ - //-------------------------- - // constructor - //-------------------------- - constructor() - { - this.dataUtils = new DataUtils(); - this.dateUtils = new DateUtils(); - } - //-------------------------- - // methods - //-------------------------- - save() - { - let self = this; - let handle = document.getElementById('settings-handle').value; - let email = document.getElementById('settings-email').value; - let url = document.getElementById('settings-url').value; - let title = document.getElementById('settings-title').value; - let desc = document.getElementById('settings-desc').innerHTML; - let privacy = document.getElementById('privacy-toggle').getAttribute('data-private'); - let background = document.getElementById('background').src; - let selected = ""; - let selects = document.querySelectorAll('.theme-select'); - let smtpDomain = document.getElementById('smtp-domain').value; - let smtpEmail = document.getElementById('smtp-email').value; - let smtpPass = document.getElementById('smtp-pass').value; - let mgDomain = document.getElementById('mg-domain').value; - let mgKey = document.getElementById('mg-key').value; - let mailActive = ""; - let mailOptions = document.querySelectorAll('.mail-option'); - for (var i = 0, length = selects.length; i < length; i++) - { - if (selects[i].getAttribute('data-enabled') == "true") selected = selects[i].id; - } +export default class SettingsActions { + //-------------------------- + // constructor + //-------------------------- + constructor() { + this.dataUtils = new DataUtils(); + this.dateUtils = new DateUtils(); + } + //-------------------------- + // methods + //-------------------------- + save() { + let self = this; + let handle = document.getElementById('settings-handle').value; + let email = document.getElementById('settings-email').value; + let url = document.getElementById('settings-url').value; + let title = document.getElementById('settings-title').value; + let desc = document.getElementById('settings-desc').innerHTML; + let privacy = document.getElementById('privacy-toggle').getAttribute('data-private'); + let background = document.getElementById('background').src; + let selected = ''; + let selects = document.querySelectorAll('.theme-select'); + let smtpDomain = document.getElementById('smtp-domain').value; + let smtpEmail = document.getElementById('smtp-email').value; + let smtpPass = document.getElementById('smtp-pass').value; + let mgDomain = document.getElementById('mg-domain').value; + let mgKey = document.getElementById('mg-key').value; + let mailActive = ''; + let mailOptions = document.querySelectorAll('.mail-option'); + var i, count; + for (i = 0, count = selects.length; i < count; i++) { + if (selects[i].getAttribute('data-enabled') == 'true') selected = selects[i].id; + } - for (var i = 0, length = mailOptions.length; i < length; i++) - { - if (mailOptions[i].getAttribute('data-enabled') == "true") mailActive = mailOptions[i].id; - } - let settingsData = { - handle: handle, - email: email, - url: url, - title: title, - descriptions: desc, - background: background, - private: privacy, - theme: selected, - mailSettings:{ - activeProtocol: mailActive, - smtp:{ - domain: smtpDomain, - email: smtpEmail, - password:smtpPass - }, - mailgun:{ - domain: mgDomain, - key: mgKey - } - } - } - return new Promise(function(resolve, reject) - { - self.dataUtils.request('/api/settings/sync', DataEvent.SETTINGS_UPDATED, REQUEST_TYPE_POST, CONTENT_TYPE_JSON, settingsData).then((response) => - { - //console.log("RESPONSE", response) - resolve(response) - }).catch((err) => - { - reject(err); - }) - }) - } - //-------------------------- - // event handlers - //-------------------------- -} \ No newline at end of file + for (i = 0, count = mailOptions.length; i < count; i++) { + if (mailOptions[i].getAttribute('data-enabled') == 'true') + mailActive = mailOptions[i].id; + } + let settingsData = { + handle: handle, + email: email, + url: url, + title: title, + descriptions: desc, + background: background, + private: privacy, + theme: selected, + mailSettings: { + activeProtocol: mailActive, + smtp: { + domain: smtpDomain, + email: smtpEmail, + password: smtpPass + }, + mailgun: { + domain: mgDomain, + key: mgKey + } + } + }; + return new Promise(function(resolve, reject) { + self.dataUtils + .request( + '/api/settings/sync', + DataEvent.SETTINGS_UPDATED, + REQUEST_TYPE_POST, + CONTENT_TYPE_JSON, + settingsData + ) + .then(response => { + //console.log("RESPONSE", response) + resolve(response); + }) + .catch(err => { + reject(err); + }); + }); + } + //-------------------------- + // event handlers + //-------------------------- +} diff --git a/themes/dash/src/com/controllers/DashManager.js b/themes/dash/src/com/controllers/DashManager.js index e0ec2f7..b6c64b4 100644 --- a/themes/dash/src/com/controllers/DashManager.js +++ b/themes/dash/src/com/controllers/DashManager.js @@ -3,43 +3,39 @@ import SettingsIndex from './SettingsIndex'; import NaviIndex from './NavIndex'; export default class DashManager { - //-------------------------- - // constructor - //-------------------------- - constructor() { - this.currentDisplay = ''; - this.urlPieces = document.URL.split("/"); - this.chooseDisplay(this.urlPieces[5], this.urlPieces[6]); - } - //-------------------------- - // methods - //-------------------------- - start() { - let self = this; - - } + //-------------------------- + // constructor + //-------------------------- + constructor() { + this.currentDisplay = ''; + this.urlPieces = document.URL.split('/'); + this.chooseDisplay(this.urlPieces[5], this.urlPieces[6]); + } + //-------------------------- + // methods + //-------------------------- + start() {} - chooseDisplay(section, page) { - this.currentDisplay = ''; - switch (section) { - case 'posts': - this.currentDisplay = new PostIndex(page); - break; - case 'settings': - this.currentDisplay = new SettingsIndex(); - break; - case 'navigation': - this.currentDisplay = new NaviIndex(); - - default: - // just chill - break; - } - this.start(); + chooseDisplay(section, page) { + this.currentDisplay = ''; + switch (section) { + case 'posts': + this.currentDisplay = new PostIndex(page); + break; + case 'settings': + this.currentDisplay = new SettingsIndex(); + break; + case 'navigation': + this.currentDisplay = new NaviIndex(); + break; - } - //-------------------------- - // event handlers - //-------------------------- - -} \ No newline at end of file + default: + // just chill + break; + } + this.start(); + } + //-------------------------- + // event handlers + //-------------------------- +} diff --git a/themes/dash/src/com/controllers/NavIndex.js b/themes/dash/src/com/controllers/NavIndex.js index 586835a..769d809 100644 --- a/themes/dash/src/com/controllers/NavIndex.js +++ b/themes/dash/src/com/controllers/NavIndex.js @@ -1,66 +1,48 @@ -import NavActions from "../actions/NavActions"; -import DataUtils, -{ - REQUEST_TYPE_GET, - REQUEST_TYPE_PUT, - REQUEST_TYPE_POST, - REQUEST_TYPE_DELETE, - CONTENT_TYPE_JSON, - CONTENT_TYPE_FORM +import NavActions from '../actions/NavActions'; +import DBUtils from '../../../../../brain/tools/utilities/DBUtils'; +export default class NavIndex { + //-------------------------- + // constructor + //-------------------------- + constructor() { + this.start(); + //this.dataUtils = new DataUtils(); + this.dbutils = new DBUtils(); + } + //-------------------------- + // methods + //-------------------------- + start() { + Sortable.create(document.getElementById('nav-pages'), { + onUpdate: () => { + new NavActions() + .save() + .then(() => { + //console.log(r); + }) + .catch(() => { + //console.log(err); + }); + } + }); + var nav = document.querySelectorAll('.nav-btn'); + for (var i = 0, length = nav.length; i < length; i++) { + nav[i].addEventListener('click', e => this.handleNavButton(e), false); + } + } + //-------------------------- + // event handlers + //-------------------------- + handleNavButton(e) { + let id = ''; + switch (e.target.id) { + case 'remove-item': + id = e.target.getAttribute('data-id'); + new NavActions().removeItem(id); + break; + case 'edit-item': + window.location = '/@/dashboard/posts/edit/' + e.target.getAttribute('data-id'); + break; + } + } } -from "../../../../../brain/tools/utilities/DataUtils"; -import * as DataEvent from '../../../../../brain/tools/events/DataEvent'; -import DBUtils from "../../../../../brain/tools/utilities/DBUtils"; -export default class NavIndex -{ - //-------------------------- - // constructor - //-------------------------- - constructor() - { - this.start(); - this.dataUtils = new DataUtils(); - this.dbutils = new DBUtils(); - } - //-------------------------- - // methods - //-------------------------- - start() - { - let self = this; - let menu = Sortable.create(document.getElementById("nav-pages"), - { - onUpdate: e => - { - - new NavActions().save().then(r=>{ - console.log(r); - }).catch(err=>{ - console.log(err) - }) - } - }); - var nav = document.querySelectorAll('.nav-btn'); - for (var i = 0, length = nav.length; i < length; i++) - { - nav[i].addEventListener('click', e => this.handleNavButton(e), false); - } - } - //-------------------------- - // event handlers - //-------------------------- - handleNavButton(e) - { - let self = this; - switch (e.target.id) - { - case "remove-item": - let id = e.target.getAttribute('data-id'); - new NavActions().removeItem(id); - break - case "edit-item": - window.location = "/@/dashboard/posts/edit/" + e.target.getAttribute('data-id'); - break - } - } -} \ No newline at end of file diff --git a/themes/dash/src/com/controllers/PostEditor.js b/themes/dash/src/com/controllers/PostEditor.js index b38ac0e..9523dd0 100644 --- a/themes/dash/src/com/controllers/PostEditor.js +++ b/themes/dash/src/com/controllers/PostEditor.js @@ -1,253 +1,254 @@ //TOOLS -import DataUtils, -{ - REQUEST_TYPE_GET, - REQUEST_TYPE_PUT, - REQUEST_TYPE_POST, - REQUEST_TYPE_DELETE, - CONTENT_TYPE_JSON, - CONTENT_TYPE_FORM -} -from '../../../../../brain/tools/utilities/DataUtils'; +import DataUtils, { + REQUEST_TYPE_POST, + CONTENT_TYPE_FORM +} from '../../../../../brain/tools/utilities/DataUtils'; import * as DataEvent from '../../../../../brain/tools/events/DataEvent'; import PostActions from '../actions/PostActions'; import * as EditorEvent from '../../../../../brain/tools/events/EditorEvent'; import TinyDatePicker from 'tiny-date-picker'; import DateUtils from '../../../../../brain/tools/utilities/DateUtils'; import TextEditor from '../../../../../brain/tools/ui/TextEditor'; -import DBUtils, -{ - FINAL_KEY -} -from '../../../../../brain/tools/utilities/DBUtils'; -export default class PostEditor -{ - - //TODO - FIX POST FEATURE URLS IN DB +import DBUtils, { FINAL_KEY } from '../../../../../brain/tools/utilities/DBUtils'; +export default class PostEditor { + //TODO - FIX POST FEATURE URLS IN DB - //-------------------------- - // constructor - //-------------------------- - constructor() - { - let self = this; - this.dataUtils = new DataUtils(); - this.dateUtils = new DateUtils(); - this.urlPieces = document.URL.split("/"); - this.dbUtils = new DBUtils(); - this.post = []; - this.postID = null; - if (document.getElementById('post-edit-index').getAttribute('data-index')) - { - this.postID = document.getElementById('post-edit-index').getAttribute('data-index'); - this.dbUtils.getPost(this.postID).then(body => - { - self.post = body.post; - this.start() - }).catch(err => - { - //console.log(err) - }) - } - else - { - this.start() - } - if (document.getElementById('edit-post-text')) - { - this.editor = new TextEditor(document.getElementById('edit-post-text'), document.getElementById('header').offsetHeight + document.getElementById('post-header').offsetHeight + document.getElementById('post-feature').offsetHeight); - this.editor.addListener(EditorEvent.EDITOR_DELETE, f => this.handleEditorOptions(EditorEvent.EDITOR_DELETE), false) - this.editor.addListener(EditorEvent.EDITOR_UPLOAD_POST_IMAGE, f => this.handleEditorOptions(EditorEvent.EDITOR_UPLOAD_POST_IMAGE), false) - this.editor.addListener(EditorEvent.EDITOR_UPDATE, f => this.handleEditorOptions(EditorEvent.EDITOR_UPDATE), false) - this.editor.addListener(EditorEvent.EDITOR_SAVE, f => this.handleEditorOptions(EditorEvent.EDITOR_SAVE), false) - document.getElementById('post-image-upload').addEventListener('change', e => - { - self.handleImageUpload(e.target.id, e.target.files); - }, false); - TinyDatePicker(document.getElementById('post-date'), - { - mode: 'dp-below', - format(date) - { - return self.dateUtils.getDate('origin', date); - } - }); - } - } - //-------------------------- - // methods - //-------------------------- - start() - { - let self = this; - if (document.getElementById('featured-image-drop')) - { - document.getElementById('featured-image-drop').addEventListener('dragover', this.handleImageActions, false); - document.getElementById('featured-image-drop').addEventListener('drop', this.handleImageActions, false); - document.getElementById('featured-image-upload').addEventListener('change', e => this.handleImageActions(e), false); - if (document.getElementById('new-feature-upload')) - { - document.getElementById('new-feature-upload').addEventListener('click', e => - { - document.getElementById('featured-image-upload').click(); - }) - } - var optionButtons = document.querySelectorAll('.post-option-btn'); - for (var i = 0, length = optionButtons.length; i < length; i++) - { - optionButtons[i].addEventListener('click', e => this.handlePostOptions(e), false); - } - } - } - //-------------------------- - // event handlers - //-------------------------- - handlePostOptions(e) - { - let currentOption; - switch (e.target.id) - { - case "option-page-icon": - case "option-page": - currentOption = document.getElementById('option-page'); - break; - case "option-feature-icon": - case "option-feature": - currentOption = document.getElementById('option-feature'); - break; - case "option-published-icon": - case "option-published": - currentOption = document.getElementById('option-published'); - break; - } - let active = currentOption.getAttribute('data-active'); - (active == 'false') ? currentOption.setAttribute('data-active', 'true'): currentOption.setAttribute('data-active', 'false') - } - handleEditorOptions(e) - { - let self = this; - switch (e) - { - case EditorEvent.EDITOR_SAVE: - new PostActions().update(this.postID, this.post, PostEditor.uploadFiles, FINAL_KEY).then(response => - { - setTimeout(f => - { - self.dbUtils.getPost(Number(response.response.newPost)).then(r => - { - window.location = "/@/dashboard/posts/edit/" + r.post.uuid; - }) - }, 100); - }).catch(err => - { - //console.log("ERROR", err) - }) - break - case EditorEvent.EDITOR_UPDATE: - new PostActions().update(this.postID, this.post, PostEditor.uploadFiles, FINAL_KEY).then(response => - { - this.editor.notify(DataEvent.POST_UPDATED, this.postID); - }).catch(err => - { - //console.log("ERRORZ", err) - }) - break; - case EditorEvent.EDITOR_DELETE: - if (confirm('Aye! You know you\'re deleting this post, right?')) - { - new PostActions().deletePost(this.postID, this.post).then((response) => - { - setTimeout(f => - { - window.location = "/@/dashboard/posts/" - }, 100); - }).catch((err) => - { - console.log(err) - }); - } - else - { - // Do nothing! - } - break; - case EditorEvent.EDITOR_UPLOAD_POST_IMAGE: - document.getElementById('post-image-upload').click(); - break; - } - } - handleImageActions(e) - { - e.stopPropagation(); - e.preventDefault(); - var self = this; - switch (e.type) - { - case "dragover": - e.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy. - break; - case "change": - case "drop": - (e.type == "drop") ? PostEditor.uploadFiles = e.dataTransfer.files: PostEditor.uploadFiles = e.target.files; - for (var i = 0, f; f = PostEditor.uploadFiles[i]; i++) - { - // Only process image files. - if (!f.type.match('image.*')) - { - continue; - } - var reader = new FileReader(); - // Closure to capture the file information. - reader.onload = (function(theFile) - { - return function(f) - { - // Render thumbnail. - var image = document.createElement('img'); - image.src = f.target.result; - image.title = escape(theFile.name); - var span = document.createElement('div'); - span.innerHTML = ['' - ].join(''); - document.getElementById('featured-image-drop').innerHTML = ''; - document.getElementById('featured-image-drop').appendChild(image); - }; - })(f); - // Read in the image file as a data URL. - reader.readAsDataURL(f); - } - if (e.target.id == "featured-image-upload") this.handleImageUpload(e.target.id, PostEditor.uploadFiles); - break; - } - } - handleImageUpload(type, files) - { - let url = "" - let eventType = ""; - let self = this; - (type == "featured-image-upload") ? url = "/api/post/add-feature-image": url = "/api/post/add-post-image"; - (type == "featured-image-upload") ? eventType = DataEvent.FEATURE_IMAGE_ADDED: eventType = DataEvent.POST_IMAGE_ADDED - var imageData = new FormData(); - for (var i = 0; i < files.length; i++) - { - var file = files[i]; - // Check the file type. - if (!file.type.match('image.*')) - { - continue; - } - (type == "featured-image-upload") ? imageData.append('feature_image', file, file.name): imageData.append('post_image', file, file.name); - } - this.dataUtils.request(url, eventType, REQUEST_TYPE_POST, CONTENT_TYPE_FORM, imageData).then((response) => - { - let r = JSON.parse(response.request['response']); - if (r.message == DataEvent.POST_IMAGE_ADDED) self.editor.notify(EditorEvent.EDITOR_UPLOAD_POST_IMAGE, r.url); - }).catch((err) => - { - //console.log(err) - }) - } + //-------------------------- + // constructor + //-------------------------- + constructor() { + let self = this; + this.dataUtils = new DataUtils(); + this.dateUtils = new DateUtils(); + this.urlPieces = document.URL.split('/'); + this.dbUtils = new DBUtils(); + this.post = []; + this.postID = null; + if (document.getElementById('post-edit-index').getAttribute('data-index')) { + this.postID = document.getElementById('post-edit-index').getAttribute('data-index'); + this.dbUtils + .getPost(this.postID) + .then(body => { + self.post = body.post; + this.start(); + }) + .catch(); + } else { + this.start(); + } + if (document.getElementById('edit-post-text')) { + this.editor = new TextEditor( + document.getElementById('edit-post-text'), + document.getElementById('header').offsetHeight + + document.getElementById('post-header').offsetHeight + + document.getElementById('post-feature').offsetHeight + ); + this.editor.addListener( + EditorEvent.EDITOR_DELETE, + () => this.handleEditorOptions(EditorEvent.EDITOR_DELETE), + false + ); + this.editor.addListener( + EditorEvent.EDITOR_UPLOAD_POST_IMAGE, + () => this.handleEditorOptions(EditorEvent.EDITOR_UPLOAD_POST_IMAGE), + false + ); + this.editor.addListener( + EditorEvent.EDITOR_UPDATE, + () => this.handleEditorOptions(EditorEvent.EDITOR_UPDATE), + false + ); + this.editor.addListener( + EditorEvent.EDITOR_SAVE, + () => this.handleEditorOptions(EditorEvent.EDITOR_SAVE), + false + ); + document.getElementById('post-image-upload').addEventListener( + 'change', + e => { + self.handleImageUpload(e.target.id, e.target.files); + }, + false + ); + TinyDatePicker(document.getElementById('post-date'), { + mode: 'dp-below', + format(date) { + return self.dateUtils.getDate('origin', date); + } + }); + } + } + //-------------------------- + // methods + //-------------------------- + start() { + if (document.getElementById('featured-image-drop')) { + document + .getElementById('featured-image-drop') + .addEventListener('dragover', this.handleImageActions, false); + document + .getElementById('featured-image-drop') + .addEventListener('drop', this.handleImageActions, false); + document + .getElementById('featured-image-upload') + .addEventListener('change', e => this.handleImageActions(e), false); + if (document.getElementById('new-feature-upload')) { + document.getElementById('new-feature-upload').addEventListener('click', () => { + document.getElementById('featured-image-upload').click(); + }); + } + var optionButtons = document.querySelectorAll('.post-option-btn'); + for (var i = 0, length = optionButtons.length; i < length; i++) { + optionButtons[i].addEventListener('click', e => this.handlePostOptions(e), false); + } + } + } + //-------------------------- + // event handlers + //-------------------------- + handlePostOptions(e) { + let currentOption; + switch (e.target.id) { + case 'option-page-icon': + case 'option-page': + currentOption = document.getElementById('option-page'); + break; + case 'option-feature-icon': + case 'option-feature': + currentOption = document.getElementById('option-feature'); + break; + case 'option-published-icon': + case 'option-published': + currentOption = document.getElementById('option-published'); + break; + } + let active = currentOption.getAttribute('data-active'); + active == 'false' + ? currentOption.setAttribute('data-active', 'true') + : currentOption.setAttribute('data-active', 'false'); + } + handleEditorOptions(e) { + let self = this; + switch (e) { + case EditorEvent.EDITOR_SAVE: + new PostActions() + .update(this.postID, this.post, PostEditor.uploadFiles, FINAL_KEY) + .then(response => { + setTimeout(() => { + self.dbUtils.getPost(Number(response.response.newPost)).then(r => { + window.location = '/@/dashboard/posts/edit/' + r.post.uuid; + }); + }, 100); + }) + .catch(() => { + //console.log("ERROR", err) + }); + break; + case EditorEvent.EDITOR_UPDATE: + new PostActions() + .update(this.postID, this.post, PostEditor.uploadFiles, FINAL_KEY) + .then(() => { + this.editor.notify(DataEvent.POST_UPDATED, this.postID); + }) + .catch(() => { + //console.log("ERRORZ", err) + }); + break; + case EditorEvent.EDITOR_DELETE: + if (confirm("Aye! You know you're deleting this post, right?")) { + new PostActions() + .deletePost(this.postID, this.post) + .then(() => { + setTimeout(() => { + window.location = '/@/dashboard/posts/'; + }, 100); + }) + .catch(() => {}); + } else { + // Do nothing! + } + break; + case EditorEvent.EDITOR_UPLOAD_POST_IMAGE: + document.getElementById('post-image-upload').click(); + break; + } + } + handleImageActions(e) { + e.stopPropagation(); + e.preventDefault(); + switch (e.type) { + case 'dragover': + e.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy. + break; + case 'change': + case 'drop': + e.type == 'drop' + ? (PostEditor.uploadFiles = e.dataTransfer.files) + : (PostEditor.uploadFiles = e.target.files); + for (var i = 0, f; (f = PostEditor.uploadFiles[i]); i++) { + // Only process image files. + if (!f.type.match('image.*')) { + continue; + } + var reader = new FileReader(); + // Closure to capture the file information. + reader.onload = (function(theFile) { + return function(f) { + // Render thumbnail. + var image = document.createElement('img'); + image.src = f.target.result; + image.title = escape(theFile.name); + var span = document.createElement('div'); + span.innerHTML = [ + '' + ].join(''); + document.getElementById('featured-image-drop').innerHTML = ''; + document.getElementById('featured-image-drop').appendChild(image); + }; + })(f); + // Read in the image file as a data URL. + reader.readAsDataURL(f); + } + if (e.target.id == 'featured-image-upload') + this.handleImageUpload(e.target.id, PostEditor.uploadFiles); + break; + } + } + handleImageUpload(type, files) { + let url = ''; + let eventType = ''; + let self = this; + type == 'featured-image-upload' + ? (url = '/api/post/add-feature-image') + : (url = '/api/post/add-post-image'); + type == 'featured-image-upload' + ? (eventType = DataEvent.FEATURE_IMAGE_ADDED) + : (eventType = DataEvent.POST_IMAGE_ADDED); + var imageData = new FormData(); + for (var i = 0; i < files.length; i++) { + var file = files[i]; + // Check the file type. + if (!file.type.match('image.*')) { + continue; + } + type == 'featured-image-upload' + ? imageData.append('feature_image', file, file.name) + : imageData.append('post_image', file, file.name); + } + this.dataUtils + .request(url, eventType, REQUEST_TYPE_POST, CONTENT_TYPE_FORM, imageData) + .then(response => { + let r = JSON.parse(response.request['response']); + if (r.message == DataEvent.POST_IMAGE_ADDED) + self.editor.notify(EditorEvent.EDITOR_UPLOAD_POST_IMAGE, r.url); + }) + .catch(() => { + //console.log(err) + }); + } } -PostEditor.uploadFiles = []; \ No newline at end of file +PostEditor.uploadFiles = []; diff --git a/themes/dash/src/com/controllers/PostIndex.js b/themes/dash/src/com/controllers/PostIndex.js index 6af6afc..3d6157f 100644 --- a/themes/dash/src/com/controllers/PostIndex.js +++ b/themes/dash/src/com/controllers/PostIndex.js @@ -1,37 +1,30 @@ import PostEditor from './PostEditor'; -export default class PostIndex -{ - //-------------------------- - // constructor - //-------------------------- - constructor(page) - { - this.currentPage = null; - this.choosePage(page); - this.start(); - } - //-------------------------- - // methods - //-------------------------- - start() - { - let self = this; - } - choosePage(page) - { - this.currentPage = ''; - switch (page) - { - case "edit": - case "add": - this.currentPage = new PostEditor(); - break; - default: - //just chill - break; - } - } - //-------------------------- - // event handlers - //-------------------------- -} \ No newline at end of file +export default class PostIndex { + //-------------------------- + // constructor + //-------------------------- + constructor(page) { + this.currentPage = null; + this.choosePage(page); + this.start(); + } + //-------------------------- + // methods + //-------------------------- + start() {} + choosePage(page) { + this.currentPage = ''; + switch (page) { + case 'edit': + case 'add': + this.currentPage = new PostEditor(); + break; + default: + //just chill + break; + } + } + //-------------------------- + // event handlers + //-------------------------- +} diff --git a/themes/dash/src/com/controllers/SettingsIndex.js b/themes/dash/src/com/controllers/SettingsIndex.js index 92f3d08..e11bccc 100644 --- a/themes/dash/src/com/controllers/SettingsIndex.js +++ b/themes/dash/src/com/controllers/SettingsIndex.js @@ -1,171 +1,152 @@ -import SettingsActions from "../actions/SettingsActions"; -import DataUtils, -{ - REQUEST_TYPE_GET, - REQUEST_TYPE_PUT, - REQUEST_TYPE_POST, - REQUEST_TYPE_DELETE, - CONTENT_TYPE_JSON, - CONTENT_TYPE_FORM -} -from "../../../../../brain/tools/utilities/DataUtils"; +import SettingsActions from '../actions/SettingsActions'; +import DataUtils, { + REQUEST_TYPE_POST, + CONTENT_TYPE_FORM +} from '../../../../../brain/tools/utilities/DataUtils'; import * as DataEvent from '../../../../../brain/tools/events/DataEvent'; import Mailer from '../actions/Mailer'; -export default class SettingsIndex -{ - //-------------------------- - // constructor - //-------------------------- - constructor() - { - this.start(); - this.dataUtils = new DataUtils(); - this.mailer = new Mailer(); - } - //-------------------------- - // methods - //-------------------------- - start() - { - let self = this; - //handle save button - document.getElementById('save-toggle').addEventListener('click', f => new SettingsActions().save().then(response => - { - console.log(response); - }).catch(err => - { - console.log(err); - })); - //handle set up image uploads - document.getElementById('avatar').addEventListener('click', e => - { - document.getElementById('avatar-upload').click(); - }) - document.getElementById('background').addEventListener('click', e => - { - document.getElementById('background-upload').click(); - }) - document.getElementById('avatar-upload').addEventListener('change', e => - { - self.handleImageUpload(e.target.id, e.target.files); - }, false); - document.getElementById('background-upload').addEventListener('change', e => - { - self.handleImageUpload(e.target.id, e.target.files); - }, false); - //handle privacy toggle - document.getElementById("privacy-toggle").addEventListener("click", e => this.togglePrivacy(e)); - document.getElementById("send-mail").addEventListener("click", e => this.handleMailer(e)); - //handle theme toggle - let themeBtns = document.querySelectorAll('.theme-select'); - for (var i = 0, length = themeBtns.length; i < length; i++) - { - themeBtns[i].addEventListener('click', e => this.handleThemes(e)); - } - //handle mail options - let mailBtn = document.querySelectorAll('.mail-option'); - for (var i = 0, length = mailBtn.length; i < length; i++) - { - mailBtn[i].addEventListener('click', e => this.handleMailOptions(e)); - } - } - //-------------------------- - // event handlers - //-------------------------- - togglePrivacy(e) - { - e.stopPropagation(); - e.preventDefault(); - if (e.target.getAttribute('data-private') == "false") - { - e.target.setAttribute('data-private', 'true'); - e.target.innerHTML = "SITE IS PUBLIC" - } - else - { - e.target.setAttribute('data-private', 'false'); - e.target.innerHTML = "SITE IS PRIVATE" - } - } - handleMailer() - { - this.mailer.sendMail(); - } - handleThemes(e) - { - e.stopPropagation(); - e.preventDefault(); - let themes = document.querySelectorAll('.theme-select'); - for (var i = 0, length = themes.length; i < length; i++) - { - (e.target.id == themes[i].id) ? themes[i].setAttribute('data-enabled', 'true'): themes[i].setAttribute('data-enabled', 'false') - } - } - handleMailOptions(e) - { - e.preventDefault(); - e.stopPropagation(); - let smtp = document.getElementById('mail-smtp'); - let mailgun = document.getElementById('mail-mg') - let mail = document.querySelectorAll('.mail-option'); - for (var i = 0, length = mail.length; i < length; i++) - { - if (e.target.id == mail[i].id) - { - mail[i].setAttribute('data-enabled', 'true') - if (e.target.id == "option-smtp") - { - smtp.setAttribute('data-enabled', 'true') - mailgun.setAttribute('data-enabled', 'false') - } - else if (e.target.id == "option-none") - { - smtp.setAttribute('data-enabled', 'false') - mailgun.setAttribute('data-enabled', 'false') - } - else - { - smtp.setAttribute('data-enabled', 'false') - mailgun.setAttribute('data-enabled', 'true') - } - } - else - { - mail[i].setAttribute('data-enabled', 'false') - } - } - } - handleImageUpload(type, files) - { - let url = "" - let eventType = ""; - let self = this; - (type == "avatar-upload") ? url = "/api/settings/add-avatar": url = "/api/settings/add-feature-background"; - var imageData = new FormData(); - for (var i = 0; i < files.length; i++) - { - var file = files[i]; - // Check the file type. - if (!file.type.match('image.*')) - { - continue; - } - (type == "avatar-upload") ? imageData.append('avatar_upload', file, file.name): imageData.append('background_upload', file, file.name); - } - this.dataUtils.request(url, eventType, REQUEST_TYPE_POST, CONTENT_TYPE_FORM, imageData).then((response) => - { - let r = JSON.parse(response.request['response']); - if (r.message == DataEvent.AVATAR_UPLOADED) - { - document.getElementById('avatar').src = r.url; - } - else - { - document.getElementById('background').src = r.url; - } - }).catch((err) => - { - //console.log(err) - }) - } -} \ No newline at end of file +export default class SettingsIndex { + //-------------------------- + // constructor + //-------------------------- + constructor() { + this.start(); + this.dataUtils = new DataUtils(); + this.mailer = new Mailer(); + } + //-------------------------- + // methods + //-------------------------- + start() { + let self = this; + //handle save button + document.getElementById('save-toggle').addEventListener('click', () => + new SettingsActions() + .save() + .then(() => { + //console.log(response); + }) + .catch(() => { + //console.log(err); + }) + ); + //handle set up image uploads + document.getElementById('avatar').addEventListener('click', () => { + document.getElementById('avatar-upload').click(); + }); + document.getElementById('background').addEventListener('click', () => { + document.getElementById('background-upload').click(); + }); + document.getElementById('avatar-upload').addEventListener( + 'change', + e => { + self.handleImageUpload(e.target.id, e.target.files); + }, + false + ); + document.getElementById('background-upload').addEventListener( + 'change', + e => { + self.handleImageUpload(e.target.id, e.target.files); + }, + false + ); + //handle privacy toggle + document + .getElementById('privacy-toggle') + .addEventListener('click', e => this.togglePrivacy(e)); + document.getElementById('send-mail').addEventListener('click', e => this.handleMailer(e)); + //handle theme toggle + let themeBtns = document.querySelectorAll('.theme-select'); + for (var i = 0, length = themeBtns.length; i < length; i++) { + themeBtns[i].addEventListener('click', e => this.handleThemes(e)); + } + //handle mail options + let mailBtn = document.querySelectorAll('.mail-option'); + for (i = 0, length = mailBtn.length; i < length; i++) { + mailBtn[i].addEventListener('click', e => this.handleMailOptions(e)); + } + } + //-------------------------- + // event handlers + //-------------------------- + togglePrivacy(e) { + e.stopPropagation(); + e.preventDefault(); + if (e.target.getAttribute('data-private') == 'false') { + e.target.setAttribute('data-private', 'true'); + e.target.innerHTML = 'SITE IS PUBLIC'; + } else { + e.target.setAttribute('data-private', 'false'); + e.target.innerHTML = 'SITE IS PRIVATE'; + } + } + handleMailer() { + this.mailer.sendMail(); + } + handleThemes(e) { + e.stopPropagation(); + e.preventDefault(); + let themes = document.querySelectorAll('.theme-select'); + for (var i = 0, length = themes.length; i < length; i++) { + e.target.id == themes[i].id + ? themes[i].setAttribute('data-enabled', 'true') + : themes[i].setAttribute('data-enabled', 'false'); + } + } + handleMailOptions(e) { + e.preventDefault(); + e.stopPropagation(); + let smtp = document.getElementById('mail-smtp'); + let mailgun = document.getElementById('mail-mg'); + let mail = document.querySelectorAll('.mail-option'); + for (var i = 0, length = mail.length; i < length; i++) { + if (e.target.id == mail[i].id) { + mail[i].setAttribute('data-enabled', 'true'); + if (e.target.id == 'option-smtp') { + smtp.setAttribute('data-enabled', 'true'); + mailgun.setAttribute('data-enabled', 'false'); + } else if (e.target.id == 'option-none') { + smtp.setAttribute('data-enabled', 'false'); + mailgun.setAttribute('data-enabled', 'false'); + } else { + smtp.setAttribute('data-enabled', 'false'); + mailgun.setAttribute('data-enabled', 'true'); + } + } else { + mail[i].setAttribute('data-enabled', 'false'); + } + } + } + handleImageUpload(type, files) { + let url = ''; + let eventType = ''; + type == 'avatar-upload' + ? (url = '/api/settings/add-avatar') + : (url = '/api/settings/add-feature-background'); + var imageData = new FormData(); + for (var i = 0; i < files.length; i++) { + var file = files[i]; + // Check the file type. + if (!file.type.match('image.*')) { + continue; + } + type == 'avatar-upload' + ? imageData.append('avatar_upload', file, file.name) + : imageData.append('background_upload', file, file.name); + } + this.dataUtils + .request(url, eventType, REQUEST_TYPE_POST, CONTENT_TYPE_FORM, imageData) + .then(response => { + let r = JSON.parse(response.request['response']); + if (r.message == DataEvent.AVATAR_UPLOADED) { + document.getElementById('avatar').src = r.url; + } else { + document.getElementById('background').src = r.url; + } + }) + .catch(() => { + //console.log(err) + }); + } +} diff --git a/themes/dash/src/styles/dash.styl b/themes/dash/src/styles/dash.styl index ef161f8..5ccb7af 100644 --- a/themes/dash/src/styles/dash.styl +++ b/themes/dash/src/styles/dash.styl @@ -2,96 +2,73 @@ ------------------------------- -- Bulma ------------------------------- -**/ -//@import '/../../node_modules/bulma.styl/bulma.styl' -@import "../../../../node_modules/bulma.styl/stylus/utilities/_all" -@import "../../../../node_modules/bulma.styl/stylus/grid/columns" - - +* */ +@import '../../../../node_modules/bulma.styl/stylus/utilities/_all'; +@import '../../../../node_modules/bulma.styl/stylus/grid/columns'; /** ------------------------------- -- Colors ------------------------------- -**/ - -@import "main/_colors" - +* */ +@import 'main/_colors'; /** ------------------------------- -- Mixins ------------------------------- -**/ - -@import 'main/_mixins' - +* */ +@import 'main/_mixins'; /** ------------------------------- -- Normalize ------------------------------- -**/ -@import 'main/_normalize' - +* */ +@import 'main/_normalize'; /** ------------------------------- -- Typography ------------------------------- -**/ - -@import "main/_typography" - +* */ +@import 'main/_typography'; /** ------------------------------- -- Main Structure ------------------------------- -**/ - -@import "main/_structure" - +* */ +@import 'main/_structure'; /** ------------------------------- -- Index ------------------------------- -**/ - -@import "main/_index" - +* */ +@import 'main/_index'; /** ------------------------------- -- Settings ------------------------------- -**/ - -@import "main/_settings" - +* */ +@import 'main/_settings'; /** ------------------------------- -- Navigation ------------------------------- -**/ - -@import "main/_navigation" - +* */ +@import 'main/_navigation'; /** ------------------------------- -- Forms ------------------------------- -**/ - -@import 'main/_forms' - +* */ +@import 'main/_forms'; /** ------------------------------- -- Blog ------------------------------- -**/ - -@import 'main/_posts' - +* */ +@import 'main/_posts'; /** ------------------------------- -- Editor ------------------------------- -**/ - -@import 'main/_editor' -@import 'main/_editor-highlight' +* */ +@import 'main/_editor'; +@import 'main/_editor-highlight';