added avitar upload, created framework for dark and light theme, fixed inconsistent theme display bug

This commit is contained in:
Ro 2018-12-20 13:50:28 -05:00
parent e0ba70d475
commit 2749d0ab9f
212 changed files with 26202 additions and 87 deletions

View file

@ -23,7 +23,7 @@ const fs = require('fs-extra');
const Models = require('../../models'); const Models = require('../../models');
const dateUtils = new DateUtils(); const dateUtils = new DateUtils();
const rightsManager = new RightsManager(); const rightsManager = new RightsManager();
const uploadPath = "./content/blog-images/" + dateUtils.getDate('year', new Date()) + "/" + dateUtils.getDate('month', new Date()); const uploadPath = "./content/user-images/" + dateUtils.getDate('year', new Date()) + "/" + dateUtils.getDate('month', new Date());
const Sequelize = require('sequelize'); const Sequelize = require('sequelize');
const Op = Sequelize.Op; const Op = Sequelize.Op;
const _ = require('lodash'); const _ = require('lodash');
@ -47,11 +47,11 @@ var storage = multer.diskStorage(
var avatar_upload = multer( var avatar_upload = multer(
{ {
storage: storage storage: storage
}).array('avatar'); }).array('avatar_upload');
var background_upload = multer( var background_upload = multer(
{ {
storage: storage storage: storage
}).array('feature_background'); }).array('background_upload');
//** SYNC POSTS */ //** SYNC POSTS */
router.post("/sync", (req, res, next) => router.post("/sync", (req, res, next) =>
{ {
@ -138,11 +138,22 @@ router.post('/add-avatar', function(req, res, next)
} }
else else
{ {
var postImage = req.files[0].path; 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( return res.json(
{ {
message: DataEvent.POST_IMAGE_ADDED, message: DataEvent.AVATAR_UPLOADED,
url: postImage.substr(7, postImage.length) url: avatar.substr(7, avatar.length)
}); });
} }
}); });

View file

@ -3,7 +3,6 @@ const router = express.Router();
const FileHound = require('filehound'); const FileHound = require('filehound');
const Models = require('../../models'); const Models = require('../../models');
const fs = require("fs-extra"); const fs = require("fs-extra");
var themes = [];
var settings = []; var settings = [];
//-------------------------- //--------------------------
// SETTINGS // SETTINGS
@ -17,49 +16,63 @@ router.get('/', function(req, res)
{ {
//console.error(err) //console.error(err)
}) })
let themes = [];
FileHound.create().paths('themes').ext('json').find().then(files => FileHound.create().paths('themes').ext('json').find().then(files =>
{ {
themes = []; files.forEach(file =>
for (let index = 0; index < files.length; index++)
{ {
fs.readJson(files[index]).then(theme => fs.readJson(file).then(theme =>
{ {
(theme.name == settings.theme) ? themes.push( if (theme.name == settings.theme)
{ {
theme: theme, themes.push(
current: "true" {
}): themes.push( theme: theme,
current: "true"
})
}
else
{ {
theme: theme, themes.push(
current: "false" {
}) theme: theme,
current: "false"
})
}
}).catch(err => }).catch(err =>
{ {
//console.error(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');
} }
}); });
if (req.session.user)
{
let memberInfo = [];
memberInfo.push(
{
handle: req.session.user.handle,
email: req.session.user.email,
avi: req.session.user.avatar
});
console.log("THEMES", themes);
res.render('dash/settings',
{
title: 'Dashboard | Settings',
themes: themes,
settings: settings,
member: memberInfo[0]
});
}
else
{
res.redirect('/@/dashboard');
}
}); });
module.exports = router; module.exports = router;

View file

@ -19,6 +19,7 @@ export const POST_DELETED = 'postImageAdded';
export const POSTS_SYNCED = 'postsSynced'; export const POSTS_SYNCED = 'postsSynced';
export const LOCAL_DB_READY = 'localDBReady'; export const LOCAL_DB_READY = 'localDBReady';
export const SETTINGS_UPDATED = 'settingsUpdated'; export const SETTINGS_UPDATED = 'settingsUpdated';
export const AVATAR_UPLOADED = 'avatarUploaded';
class DataEvent class DataEvent
{ {

View file

@ -4,7 +4,7 @@
"private": true, "private": true,
"description": "The most chill blog framework ever.", "description": "The most chill blog framework ever.",
"repository": "https://code.playvicio.us/Are0h/Fipamo", "repository": "https://code.playvicio.us/Are0h/Fipamo",
"theme": "default", "theme": "default-light",
"scripts": { "scripts": {
"start": "forever start -r esm init.js", "start": "forever start -r esm init.js",
"stop": "forever stop init.js", "stop": "forever stop init.js",

View file

@ -1 +1,22 @@
{"url":"http://fipamo.local","title":"This is Fipamo, bro","description":"The most chill blog framework ever.","theme":"default","private":"false","email":{"smtp":{"domain":"","email":"","password":""},"mailgun":{"domain":"","api-key":""}}} {
"url": "http://fipamo.local",
"title": "This is Fipamo, bro",
"description": "The most chill blog framework ever.",
"theme": "default-light",
"private": "false",
"feautred-url":"",
"email":
{
"smtp":
{
"domain": "",
"email": "",
"password": ""
},
"mailgun":
{
"domain": "",
"api-key": ""
}
}
}

View file

@ -1897,9 +1897,10 @@ svg.icons {
} }
#settings-index #settings-index-wrapper #member-avatar-drop img { #settings-index #settings-index-wrapper #member-avatar-drop img {
width: 200px; width: 200px;
border: 1px solid #f2f1ef; border: 5px solid #f2f1ef;
border-radius: 100px; border-radius: 150px;
overflow: hidden; overflow: hidden;
cursor: pointer;
} }
#settings-index #settings-index-wrapper #member-avatar-drop input { #settings-index #settings-index-wrapper #member-avatar-drop input {
visibility: hidden; visibility: hidden;
@ -1913,7 +1914,7 @@ svg.icons {
#settings-index #settings-index-wrapper #member-settings label, #settings-index #settings-index-wrapper #member-settings label,
#settings-index #settings-index-wrapper #site-settings label, #settings-index #settings-index-wrapper #site-settings label,
#settings-index #settings-index-wrapper #theme-settings label { #settings-index #settings-index-wrapper #theme-settings label {
font-family: "Apercu-Mono"; font-family: 'Apercu-Mono';
color: #f2f1ef; color: #f2f1ef;
} }
#settings-index #settings-index-wrapper #member-settings input, #settings-index #settings-index-wrapper #member-settings input,
@ -1934,9 +1935,9 @@ svg.icons {
margin-top: 10px; margin-top: 10px;
padding: 10px; padding: 10px;
} }
#settings-index #settings-index-wrapper #theme-settings a { #settings-index #settings-index-wrapper #theme-settings a[data-enabled='false'] {
width: 310px; width: 310px;
margin-right: 5px; margin: 0 5px 5px 0;
height: 25px; height: 25px;
padding: 10px; padding: 10px;
display: inline-block; display: inline-block;
@ -1944,6 +1945,21 @@ svg.icons {
color: #b2cce5; color: #b2cce5;
border-radius: 3px; border-radius: 3px;
} }
#settings-index #settings-index-wrapper #theme-settings a[data-enabled='true'] {
width: 310px;
margin: 0 5px 5px 0;
height: 25px;
padding: 10px;
display: inline-block;
background: #b2cce5;
color: #374857;
border-radius: 3px;
}
#settings-index #settings-index-wrapper #theme-settings a[data-enabled='true'] svg {
fill: #374857;
display: inline-block;
float: right;
}
/** /**
------------------------------- -------------------------------
-- Forms -- Forms
@ -1972,7 +1988,7 @@ textarea {
button, button,
input[type=submit] { input[type=submit] {
background: #fc6399; background: #fc6399;
color: #f2f1ef; color: #161d23;
font: 1em 'Apercu-Mono'; font: 1em 'Apercu-Mono';
border-radius: 3px; border-radius: 3px;
position: relative; position: relative;

File diff suppressed because one or more lines are too long

View file

@ -197,7 +197,7 @@ exports.default = _default;
Object.defineProperty(exports, "__esModule", { Object.defineProperty(exports, "__esModule", {
value: true value: true
}); });
exports.default = exports.SETTINGS_UPDATED = exports.LOCAL_DB_READY = exports.POSTS_SYNCED = exports.POST_DELETED = exports.POST_UPDATED = exports.POST_ADDED = exports.POST_ERROR = exports.FEATURE_IMAGE_ADDED = exports.POST_IMAGE_ADDED = exports.PROJECTS_SORTED = exports.PROJECT_ADDED = exports.PROJECT_UPDATED = exports.ARCHIVES_ENTRY_LOADED = exports.ARCHIVES_PAGE_LOADED = exports.ARCHIVES_JSON_LOADED = exports.HTML_LOADED = exports.SETTINGS_LOADED = exports.IMG_REQUEST_LAME = exports.IMG_REQUEST_GOOD = exports.REQUEST_LAME = exports.REQUEST_GOOD = void 0; exports.default = exports.AVATAR_UPLOADED = exports.SETTINGS_UPDATED = exports.LOCAL_DB_READY = exports.POSTS_SYNCED = exports.POST_DELETED = exports.POST_UPDATED = exports.POST_ADDED = exports.POST_ERROR = exports.FEATURE_IMAGE_ADDED = exports.POST_IMAGE_ADDED = exports.PROJECTS_SORTED = exports.PROJECT_ADDED = exports.PROJECT_UPDATED = exports.ARCHIVES_ENTRY_LOADED = exports.ARCHIVES_PAGE_LOADED = exports.ARCHIVES_JSON_LOADED = exports.HTML_LOADED = exports.SETTINGS_LOADED = exports.IMG_REQUEST_LAME = exports.IMG_REQUEST_GOOD = exports.REQUEST_LAME = exports.REQUEST_GOOD = void 0;
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
@ -243,6 +243,8 @@ var LOCAL_DB_READY = 'localDBReady';
exports.LOCAL_DB_READY = LOCAL_DB_READY; exports.LOCAL_DB_READY = LOCAL_DB_READY;
var SETTINGS_UPDATED = 'settingsUpdated'; var SETTINGS_UPDATED = 'settingsUpdated';
exports.SETTINGS_UPDATED = SETTINGS_UPDATED; exports.SETTINGS_UPDATED = SETTINGS_UPDATED;
var AVATAR_UPLOADED = 'avatarUploaded';
exports.AVATAR_UPLOADED = AVATAR_UPLOADED;
var DataEvent = function DataEvent() { var DataEvent = function DataEvent() {
_classCallCheck(this, DataEvent); _classCallCheck(this, DataEvent);
@ -8388,6 +8390,12 @@ exports.default = void 0;
var _SettingsActions = _interopRequireDefault(require("../actions/SettingsActions")); var _SettingsActions = _interopRequireDefault(require("../actions/SettingsActions"));
var _DataUtils = _interopRequireWildcard(require("../../../../../brain/tools/utilities/DataUtils"));
var DataEvent = _interopRequireWildcard(require("../../../../../brain/tools/events/DataEvent"));
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
@ -8406,6 +8414,7 @@ function () {
_classCallCheck(this, SettingsIndex); _classCallCheck(this, SettingsIndex);
this.start(); this.start();
this.dataUtils = new _DataUtils.default();
} //-------------------------- } //--------------------------
// methods // methods
//-------------------------- //--------------------------
@ -8414,6 +8423,7 @@ function () {
_createClass(SettingsIndex, [{ _createClass(SettingsIndex, [{
key: "start", key: "start",
value: function start() { value: function start() {
var self = this;
document.getElementById('save-toggle').addEventListener('click', function (f) { document.getElementById('save-toggle').addEventListener('click', function (f) {
return new _SettingsActions.default().save().then(function (response) { return new _SettingsActions.default().save().then(function (response) {
console.log(response); console.log(response);
@ -8421,17 +8431,52 @@ function () {
console.log(err); console.log(err);
}); });
}); });
document.getElementById('avatar').addEventListener('click', function (e) {
document.getElementById('avatar-upload').click();
});
document.getElementById('avatar-upload').addEventListener('change', function (e) {
self.handleImageUpload(e.target.id, e.target.files);
}, false);
} //-------------------------- } //--------------------------
// event handlers // event handlers
//-------------------------- //--------------------------
}, {
key: "handleImageUpload",
value: function handleImageUpload(type, files) {
var url = "";
var eventType = "";
var self = this;
type == "avatar-upload" ? url = "/api/settings/add-avatar" : url = "/api/settings/add-feature-background"; //(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 == "avatar-upload" ? imageData.append('avatar_upload', file, file.name) : imageData.append('background_upload', file, file.name);
}
this.dataUtils.request(url, eventType, _DataUtils.REQUEST_TYPE_POST, _DataUtils.CONTENT_TYPE_FORM, imageData).then(function (response) {
var r = JSON.parse(response.request['response']);
if (r.message == DataEvent.AVATAR_UPLOADED) {
document.getElementById('avatar').src = r.url;
}
}).catch(function (err) {//console.log(err)
});
}
}]); }]);
return SettingsIndex; return SettingsIndex;
}(); }();
exports.default = SettingsIndex; exports.default = SettingsIndex;
},{"../actions/SettingsActions":"actions/SettingsActions.js"}],"controllers/DashManager.js":[function(require,module,exports) { },{"../actions/SettingsActions":"actions/SettingsActions.js","../../../../../brain/tools/utilities/DataUtils":"../../../../brain/tools/utilities/DataUtils.js","../../../../../brain/tools/events/DataEvent":"../../../../brain/tools/events/DataEvent.js"}],"controllers/DashManager.js":[function(require,module,exports) {
"use strict"; "use strict";
Object.defineProperty(exports, "__esModule", { Object.defineProperty(exports, "__esModule", {

File diff suppressed because one or more lines are too long

View file

@ -10,7 +10,7 @@
a#menu(href="") a#menu(href="")
svg(viewBox="0 0 20 20" class="icons") svg(viewBox="0 0 20 20" class="icons")
use(xlink:href='/dash/assets/images/sprite.svg#entypo-list') use(xlink:href='/dash/assets/images/sprite.svg#entypo-list')
label Menu label Navigation
#dash-recent #dash-recent
#recent-list #recent-list
h3 Recent h3 Recent

View file

@ -3,8 +3,8 @@ block main-content
#settings-index #settings-index
#settings-index-wrapper #settings-index-wrapper
#member-avatar-drop #member-avatar-drop
img(src=member.avi) img#avatar(src=member.avi, for="avatar-upload")
input(id="avatar-upload" type="file" name="avatar-image-upload") input(id="avatar-upload" type="file" name="avatar-upload")
#member-settings #member-settings
input(type='text', name='handle' id='settings-handle', placeholder='handle', value=member.handle, autofocus) input(type='text', name='handle' id='settings-handle', placeholder='handle', value=member.handle, autofocus)
input(type='text', name='email' id='settings-email', placeholder='email', value=member.email, autofocus) input(type='text', name='email' id='settings-email', placeholder='email', value=member.email, autofocus)
@ -24,6 +24,8 @@ block main-content
-if(themes[index].current == "true") -if(themes[index].current == "true")
a.theme-select(href="#" id=themes[index].theme.name, data-enabled="true") a.theme-select(href="#" id=themes[index].theme.name, data-enabled="true")
= themes[index].theme["display-name"] = themes[index].theme["display-name"]
svg(viewBox="0 0 20 20" class="icons")
use(xlink:href='/dash/assets/images/sprite.svg#entypo-check')
-else -else
a.theme-select(href="#" id=themes[index].theme.name, data-enabled="false") a.theme-select(href="#" id=themes[index].theme.name, data-enabled="false")
= themes[index].theme["display-name"] = themes[index].theme["display-name"]

View file

@ -1,4 +1,15 @@
import SettingsActions from "../actions/SettingsActions"; 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 * as DataEvent from '../../../../../brain/tools/events/DataEvent';
export default class SettingsIndex export default class SettingsIndex
{ {
//-------------------------- //--------------------------
@ -7,12 +18,14 @@ export default class SettingsIndex
constructor() constructor()
{ {
this.start(); this.start();
this.dataUtils = new DataUtils();
} }
//-------------------------- //--------------------------
// methods // methods
//-------------------------- //--------------------------
start() start()
{ {
let self = this;
document.getElementById('save-toggle').addEventListener('click', f => new SettingsActions().save().then(response => document.getElementById('save-toggle').addEventListener('click', f => new SettingsActions().save().then(response =>
{ {
console.log(response); console.log(response);
@ -20,8 +33,47 @@ export default class SettingsIndex
{ {
console.log(err); console.log(err);
})); }));
document.getElementById('avatar').addEventListener('click', e =>
{
document.getElementById('avatar-upload').click();
})
document.getElementById('avatar-upload').addEventListener('change', e =>
{
self.handleImageUpload(e.target.id, e.target.files);
}, false);
} }
//-------------------------- //--------------------------
// event handlers // event handlers
//-------------------------- //--------------------------
handleImageUpload(type, files)
{
let url = ""
let eventType = "";
let self = this;
(type == "avatar-upload") ? url = "/api/settings/add-avatar": url = "/api/settings/add-feature-background";
//(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 == "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;
}
}).catch((err) =>
{
//console.log(err)
})
}
} }

View file

@ -18,7 +18,7 @@ textarea
button, input[type=submit] button, input[type=submit]
background $highlight background $highlight
color $white color $primary - 60%
font 1em 'Apercu-Mono' font 1em 'Apercu-Mono'
border-radius 3px border-radius 3px
position relative position relative

View file

@ -2,47 +2,69 @@
width 100% width 100%
max-width 900px max-width 900px
margin 0 auto margin 0 auto
#settings-index-wrapper #settings-index-wrapper
padding 0.75rem padding 0.75rem
button
margin-top: 5px; button
width: 320px margin-top 5px
height 45px width 320px
height 45px
#member-avatar-drop #member-avatar-drop
img img
width: 200px width 200px
border: 1px solid $white border 5px solid $white
border-radius: 100px; border-radius 150px
overflow hidden overflow hidden
cursor pointer
input input
visibility hidden visibility hidden
#member-settings, #site-settings, #theme-settings #member-settings, #site-settings, #theme-settings
label label
font-family: "Apercu-Mono" font-family 'Apercu-Mono'
color: $white color $white
width: 80%
margin-bottom: 40px width 80%
margin-bottom 40px
input input
width: 44%; width 44%
margin-right: 5px; margin-right 5px
height 30px height 30px
padding: 10px padding 10px
textarea textarea
background: $primary - 60% background $primary - 60%
width: 91.5% width 91.5%
height 100px; height 100px
color: $secondary color $secondary
margin-top: 10px margin-top 10px
padding: 10px; padding 10px
#theme-settings #theme-settings
a a[data-enabled='false']
width: 310px; width 310px
margin-right: 5px; margin 0 5px 5px 0
height 25px height 25px
padding: 10px padding 10px
display inline-block
background $primary - 60%
color $secondary
border-radius 3px
a[data-enabled='true']
width 310px
margin 0 5px 5px 0
height 25px
padding 10px
display inline-block
background $secondary
color $primary
border-radius 3px
svg
fill $primary
display inline-block display inline-block
background: $primary - 60% float right
color $secondary
border-radius 3px

View file

Before

Width:  |  Height:  |  Size: 284 KiB

After

Width:  |  Height:  |  Size: 284 KiB

View file

Before

Width:  |  Height:  |  Size: 279 KiB

After

Width:  |  Height:  |  Size: 279 KiB

View file

Before

Width:  |  Height:  |  Size: 362 KiB

After

Width:  |  Height:  |  Size: 362 KiB

View file

Before

Width:  |  Height:  |  Size: 377 KiB

After

Width:  |  Height:  |  Size: 377 KiB

View file

Before

Width:  |  Height:  |  Size: 367 KiB

After

Width:  |  Height:  |  Size: 367 KiB

View file

Before

Width:  |  Height:  |  Size: 390 KiB

After

Width:  |  Height:  |  Size: 390 KiB

View file

Before

Width:  |  Height:  |  Size: 434 KiB

After

Width:  |  Height:  |  Size: 434 KiB

View file

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 78 KiB

View file

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 71 KiB

View file

Before

Width:  |  Height:  |  Size: 690 KiB

After

Width:  |  Height:  |  Size: 690 KiB

View file

Before

Width:  |  Height:  |  Size: 1.8 MiB

After

Width:  |  Height:  |  Size: 1.8 MiB

View file

Before

Width:  |  Height:  |  Size: 342 KiB

After

Width:  |  Height:  |  Size: 342 KiB

View file

Before

Width:  |  Height:  |  Size: 202 KiB

After

Width:  |  Height:  |  Size: 202 KiB

View file

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Some files were not shown because too many files have changed in this diff Show more