init prep for beta release

pull/32/head
Ro 4 years ago
parent 575fea388b
commit 9d00814809

6
.gitignore vendored

@ -8,10 +8,16 @@ public/*
!public/favicon.ico
!public/assets
public/assets/*
public/assets/css/*
!public/assets/css
!public/assets/css/dash.css
!public/assets/images
public/assets/images/*
!public/assets/images/global/
!public/assets/images/global/*
public/assets/scripts/*
!public/assets/scripts
!public/assets/scripts/dash.min.js
content/
.ftpconfig

@ -1,6 +1,6 @@
{
"name": "fipamo",
"version": "0.0.1",
"version": "beta-1.0.0",
"private": true,
"description": "The most chill blog framework ever.",
"repository": "https://code.playvicio.us/Are0h/Fipamo",
@ -8,11 +8,7 @@
"scripts": {
"start": "pm2 --node-args='-r esm' start init.js",
"stop": "pm2 stop init.js",
"dev": "nodemon -r esm init.js --ignore node_modules/ -e js",
"debug": "nodemon inspect -r esm init.js --ignore node_modules/ -e js",
"prettier-watch": "npx onchange '**/*.js' -- npx prettier --write {{changed}}",
"watch": "stylus -w -o public/assets/css src/styles/dash.styl & parcel watch src/com/Start.js --out-dir public/assets/scripts --out-file dash.min.js --public-url /assets/scripts",
"build-back-kit": "uglifyjs src/libraries/highlight.pack.js node_modules/sortablejs/Sortable.min.js node_modules/scramble-text/dist/ScrambleText.min.js node_modules/reframe.js/dist/reframe.min.js -c -o public/assets/scripts/dashkit.min.js"
"debug": "nodemon inspect -r esm init.js --ignore node_modules/ -e js"
},
"engines": {
"node": ">=10.16.0"
@ -52,17 +48,5 @@
"sortablejs": "^1.10.2",
"tiny-date-picker": "^3.2.8",
"uuid": "^3.4.0"
},
"devDependencies": {
"@babel/cli": "^7.10.1",
"@babel/core": "^7.10.2",
"@babel/preset-env": "^7.10.2",
"animejs": "^3.2.0",
"babel-preset-env": "^1.7.0",
"bulma.styl": "^0.6.11",
"parcel": "^1.12.4",
"prettier": "^2.0.5",
"scramble-text": "0.0.8",
"stylus": "^0.54.7"
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,79 +0,0 @@
import FipamoApi from '../libraries/FipamoAPI';
import DataUitls from './utils/DataUtils';
import * as DataEvent from './events/DataEvent';
import DashManager from './controllers/DashManager';
import Notfications from './ui/Notifications';
const api = new FipamoApi();
const data = new DataUitls();
const notify = new Notfications();
export default class Base {
//--------------------------
// constructor
//--------------------------
constructor() {
this.start();
}
//--------------------------
// methods
//--------------------------
start() {
if (document.getElementById('dash-form') || document.getElementById('dash-init')) {
if (document.getElementById('dash-form')) {
document
.getElementById('login-btn')
.addEventListener('click', e => this.handleLogin(e));
} else {
document
.getElementById('init-blog')
.addEventListener('click', e => this.handleSetup(e));
}
} else {
new DashManager();
}
}
//--------------------------
// event handlers
//--------------------------
handleLogin(e) {
e.stopPropagation();
e.preventDefault();
let authForm = data.formDataToJSON(document.getElementById('login'));
api.login(authForm)
.then(response => {
if (response.type === DataEvent.REQUEST_LAME) {
notify.alert(response.message, false);
} else {
e.target.innerHTML = response.message;
setTimeout(() => {
window.location = '/@/dashboard';
}, 500);
}
})
.catch(err => {
notify.alert(err, false);
});
}
handleSetup(e) {
e.stopPropagation();
e.preventDefault();
let setUpForm = data.formDataToJSON(document.getElementById('init-form'));
api.init(setUpForm)
.then(response => {
if (response.type === DataEvent.API_INIT_LAME) {
notify.alert(response.message, false);
} else {
notify.alert(response.message, true);
setTimeout(() => {
window.location = '/@/dashboard';
}, 700);
}
})
.catch(err => {
notify.alert(err, false);
});
}
}

@ -1,9 +0,0 @@
import Base from './Base';
document.addEventListener(
'DOMContentLoaded',
function () {
new Base();
},
false
);

@ -1,29 +0,0 @@
import FipamoAdminAPI from '../../libraries/FipamoAdminAPI';
import Notficaton from '../ui/Notifications';
const admin = new FipamoAdminAPI();
const notify = new Notficaton();
export default class Mailer {
//--------------------------
// constructor
//--------------------------
constructor() {}
//--------------------------
// methods
//--------------------------
sendMail() {
let mailData = {
content: 'This is a test email'
};
admin
.sendMail(mailData)
.then(result => {
notify.alert(result.message, true);
})
.catch(err => {
notify.alert(err.message, false);
});
}
//--------------------------
// event handlers
//--------------------------
}

@ -1,35 +0,0 @@
export default class NavActions {
//--------------------------
// constructor
//--------------------------
constructor() {}
//--------------------------
// methods
//--------------------------
syncMenu() {
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'),
path: items[index].getAttribute('data-path')
});
}
let data = { nav: navData, remove: null };
return new Promise(function (resolve) {
resolve(data);
});
}
removeItem(id) {
document.getElementById('nav-pages').removeChild(document.getElementById(id));
}
//--------------------------
// event handlers
//--------------------------
}

@ -1,77 +0,0 @@
import StringUtils from '../utils/StringUtils';
export default class PostActions {
//--------------------------
// constructor
//--------------------------
constructor() {}
//--------------------------
// methods
//--------------------------
collectInfo(image) {
return new Promise((resolve, reject) => {
let pageInfo = new FormData();
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
pageInfo.append(
'id',
document.getElementById('post-edit-index').getAttribute('data-index')
);
pageInfo.append(
'uuid',
document.getElementById('post-edit-index').getAttribute('data-uuid')
);
pageInfo.append(
'layout',
document.getElementById('post-edit-index').getAttribute('data-layout')
);
pageInfo.append(
'current_title',
document.getElementById('post-edit-index').getAttribute('data-slug')
);
pageInfo.append('content', html);
pageInfo.append('title', document.getElementById('post_title').value);
pageInfo.append(
'created',
document.getElementById('post-date').getAttribute('data-raw')
);
pageInfo.append(
'slug',
new StringUtils().cleanString(document.getElementById('post_title').value)
);
pageInfo.append('tags', document.getElementById('post_tags').value);
pageInfo.append(
'menu',
document.getElementById('option-menu-pin').getAttribute('data-active')
);
pageInfo.append(
'featured',
document.getElementById('option-feature').getAttribute('data-active')
);
pageInfo.append(
'published',
document.getElementById('option-published').getAttribute('data-active')
);
if (image != null || image != undefined) {
if (image.type.match('image.*')) {
pageInfo.append('feature_image', image, image.name);
} else {
reject('Not an image file');
}
} else {
//check to see if image exists
var imageURL = document.getElementById('featured-image').src;
imageURL != null || imageURL != undefined
? pageInfo.append('feature_image', imageURL)
: pageInfo.append('feature_image', null);
}
resolve(pageInfo);
});
}
//--------------------------
// event handlers
//--------------------------
}

@ -1,67 +0,0 @@
export default class SettingsActions {
//--------------------------
// constructor
//--------------------------
constructor() {}
//--------------------------
// methods
//--------------------------
getInfo() {
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').value;
//let privacy = document.getElementById('privacy-toggle').getAttribute('data-private');
let render = document.getElementById('render-toggle').getAttribute('data-render');
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 (i = 0, count = mailOptions.length; i < count; i++) {
if (mailOptions[i].getAttribute('data-enabled') == 'true')
mailActive = mailOptions[i].id;
}
let settingsData = {
global: {
base_url: url,
title: title,
descriptions: desc,
background: background,
private: false,
renderOnSave: render,
theme: selected
},
member: { handle: handle, email: email },
email: {
active: mailActive,
smtp: {
domain: smtpDomain,
email: smtpEmail,
password: smtpPass
},
mailgun: {
domain: mgDomain,
key: mgKey
}
}
};
return new Promise(function (resolve) {
resolve(settingsData);
});
}
//--------------------------
// event handlers
//--------------------------
}

@ -1,41 +0,0 @@
import PostIndex from './PostIndex';
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() {}
chooseDisplay(section, page) {
this.currentDisplay = '';
switch (section) {
case 'page':
this.currentDisplay = new PostIndex(page);
break;
case 'settings':
this.currentDisplay = new SettingsIndex();
break;
case 'navigation':
this.currentDisplay = new NaviIndex();
break;
default:
//just chill
break;
}
this.start();
}
//--------------------------
// event handlers
//--------------------------
}

@ -1,61 +0,0 @@
import FipamoAdminAPI from '../../libraries/FipamoAdminAPI';
import NavActions from '../actions/NavActions';
import * as DataEvent from '../events/DataEvent';
import Notifications from '../ui/Notifications';
const notify = new Notifications();
const admin = new FipamoAdminAPI();
export default class NavIndex {
//--------------------------
// constructor
//--------------------------
constructor() {
this.start();
}
//--------------------------
// methods
//--------------------------
start() {
Sortable.create(document.getElementById('nav-pages'), {
onUpdate: () => {
new NavActions().syncMenu().then(data => {
admin.syncNav(data).then(r => {
if (r.type == DataEvent.MENU_UPDATED) {
notify.alert(r.message, true);
} else {
notify.alert(r.message, true);
}
});
});
}
});
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);
new NavActions().syncMenu().then(data => {
data.remove = e.target.getAttribute('data-uuid');
admin.syncNav(data).then(r => {
if (r.type == DataEvent.MENU_UPDATED) {
notify.alert(r.message, true);
} else {
notify.alert(r.message, true);
}
});
});
break;
case 'edit-item':
window.location = '/@/dashboard/page/edit/' + e.target.getAttribute('data-id');
break;
}
}
}

@ -1,238 +0,0 @@
//TOOLS
import FipamoAdminAPI, {
TASK_PAGE_CREATE,
TASK_PAGE_EDIT,
TASK_PAGE_DELETE
} from '../../libraries/FipamoAdminAPI';
import * as DataEvent from '../events/DataEvent';
import PageActions from '../actions/PageActions';
import * as EditorEvent from '../events/EditorEvent';
//import TinyDatePicker from 'tiny-date-picker';
import TextEditor from '../ui/TextEditor';
import Notfications from '../ui/Notifications';
const admin = new FipamoAdminAPI();
const notify = new Notfications();
export default class PostEditor {
//--------------------------
// constructor
//--------------------------
constructor() {
let self = this;
this.urlPieces = document.URL.split('/');
this.post = [];
this.postID = null;
this.postUUID = null;
this.postLayout = null;
if (document.getElementById('post-edit-index').getAttribute('data-index')) {
this.postID = document.getElementById('post-edit-index').getAttribute('data-index');
this.postUUID = document.getElementById('post-edit-index').getAttribute('data-uuid');
this.postLayout = document
.getElementById('post-edit-index')
.getAttribute('data-layout');
}
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() {
//return self.dateUtils.getDate('origin', date);
}
});
*/
this.start();
}
}
//--------------------------
// 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-menu-pin':
currentOption = document.getElementById('option-menu-pin');
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) {
switch (e) {
case EditorEvent.EDITOR_SAVE:
case EditorEvent.EDITOR_UPDATE:
var task = '';
e === EditorEvent.EDITOR_SAVE ? (task = TASK_PAGE_CREATE) : (task = TASK_PAGE_EDIT);
new PageActions()
.collectInfo(document.getElementById('featured-image-upload').files[0])
.then(page => {
admin
.pageActions(task, page)
.then(r => {
if (
r.type === DataEvent.PAGE_ERROR ||
r.type === DataEvent.API_REQUEST_LAME
) {
notify.alert(r.message, false);
} else {
if (r.type === DataEvent.PAGE_UPDATED) {
notify.alert(r.message, true);
} else {
notify.alert(r.message, true);
window.location = '/@/dashboard/page/edit/' + r.id;
}
}
})
.catch(err => {
notify.alert(err, false);
});
});
break;
case EditorEvent.EDITOR_DELETE:
if (this.postLayout === 'index') {
notify.alert('Index cannot be deleted', false);
return;
}
if (confirm("AYE! You know you're deleting this post, right?")) {
let id = { id: this.postUUID };
admin
.pageActions(TASK_PAGE_DELETE, id)
.then(() => {
window.location = '/@/dashboard/page/list/';
})
.catch(err => {
notify.alert(err, false);
});
} 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 = [
'<img src="',
f.target.result,
'" title="',
escape(theFile.name),
'"/>'
].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);
}
}
}
handleImageUpload(type, files) {
let self = this;
admin
.imageUpload(type, files)
.then(r => {
if (r.type == DataEvent.POST_IMAGE_ADDED)
self.editor.notify(EditorEvent.EDITOR_UPLOAD_POST_IMAGE, r.url);
})
.catch(() => {
//console.log('ERROR', err);
});
}
}
PostEditor.uploadFiles = [];

@ -1,30 +0,0 @@
import PageEditor from './PageEditor';
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 PageEditor();
break;
default:
//just chill
break;
}
}
//--------------------------
// event handlers
//--------------------------
}

@ -1,172 +0,0 @@
import SettingsActions from '../actions/SettingsActions';
import FipamoAdminAPI from '../../libraries/FipamoAdminAPI';
import * as DataEvent from '../../../src/com/events/DataEvent';
import Mailer from '../actions/Mailer';
import Notifications from '../ui/Notifications';
const admin = new FipamoAdminAPI();
const notify = new Notifications();
const mailer = new Mailer();
export default class SettingsIndex {
//--------------------------
// constructor
//--------------------------
constructor() {
this.start();
}
//--------------------------
// methods
//--------------------------
start() {
let self = this;
//handle save button
document.getElementById('save-toggle').addEventListener('click', () =>
new SettingsActions()
.getInfo()
.then(data => {
admin.syncSettings(data).then(r => {
if (r.type == DataEvent.SETTINGS_UPDATED) {
notify.alert(r.message, true);
} else {
notify.alert(r.message, true);
}
});
})
.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('render-toggle')
.addEventListener('click', e => this.toggleRender(e));
document.getElementById('send-mail').addEventListener('click', e => this.handleMailer(e));
document
.getElementById('publish-pages')
.addEventListener('click', e => this.handlePublished(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';
}
}
toggleRender(e) {
e.stopPropagation();
e.preventDefault();
if (e.target.getAttribute('data-render') == 'false') {
e.target.setAttribute('data-render', 'true');
//e.target.innerHTML = 'RENDER PAGES ON SAVE';
} else {
e.target.setAttribute('data-render', 'false');
//e.target.innerHTML = "DON'T RENDER PAGES ON SAVE";
}
}
handleMailer() {
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) {
admin
.imageUpload(type, files)
.then(r => {
if (r.type == DataEvent.AVATAR_UPLOADED) {
notify.alert(r.message, true);
document.getElementById('avatar').src = r.url;
} else {
notify.alert(r.message, true);
document.getElementById('background').src = r.url;
}
})
.catch(() => {
//console.log(err)
});
}
handlePublished(e) {
e.preventDefault();
e.stopPropagation();
let task = { task: 'publish all pages' };
admin
.publishSite(task)
.then(r => {
notify.alert(r.message, true);
})
.catch(err => {
notify.alert(err, false);
});
}
}

@ -1,28 +0,0 @@
export const MEMBER_STATUS = "memberStatus";
export const LOGIN_STATUS = 'loginStatus';
export const SUPPORTER_FOUND = 'SUPPORTER FOUND';
export const SUPPORTER_LISTED = 'SUPPORTER LISTED';
export const SUPPORTER_NOT_FOUND = 'SUPPORTER NOT FOUND';
export const MEMBER_ADDED = 'MEMBER ADDED';
export const MEMBER_NOT_ADDED = 'MEMBER NOT ADDED';
export const MEMBER_LOGIN_GOOD = 'MEMBER LOGIN GOOD';
export const MEMBER_LOGIN_LAME = 'MEMBER LOGIN LAME';
export const MEMBER_EXISTS = 'USER ALREADY EXISTS';
export const MEMBER_LOGIN_MISSING = 'Missing credentials';
class AuthEvent
{
//--------------------------
// methods
//--------------------------
//--------------------------
// event handlers
//--------------------------
}
export default new AuthEvent

@ -1,44 +0,0 @@
export const REQUEST_GOOD = 'requestGood';
export const REQUEST_LAME = 'requestLame';
export const API_REQUEST_GOOD = 'apiUseAuthorized';
export const API_REQUEST_LAME = 'apiUseNotAuthorized';
export const IMG_REQUEST_GOOD = 'imgRequestGood';
export const IMG_REQUEST_LAME = 'imgRequestLame';
export const SETTINGS_LOADED = 'settingsLoaded';
export const POST_IMAGE_ADDED = 'postImageAdded';
export const FEATURE_IMAGE_ADDED = 'featureImageAdded';
export const PAGE_ERROR = 'postError';
export const PAGE_ADDED = 'postAdded';
export const PAGE_UPDATED = 'postUpdated';
export const PAGE_DELETED = 'postImageAdded';
export const PAGES_RENDERED = 'pagesRendered';
export const PAGES_NOT_RENDERED = 'pagesNotRendered';
export const TAG_PAGES_RENDERED = 'tagPagesRendered';
export const TAG_PAGES_NOT_RENDERED = 'tagPagesNotRendered';
export const SETTINGS_UPDATED = 'settingsUpdated';
export const SETTINGS_NOT_UPDATED = 'settingsNotUpdated';
export const MENU_ADD_ITEM = 'menuAddItem';
export const MENU_DELETE_ITEM = 'menuDeleteItem';
export const MENU_UPDATED = 'menuUpdated';
export const AVATAR_UPLOADED = 'avatarUploaded';
export const SITE_BACKGROUND_UPLOADED = 'siteBackgroundUploaded';
export const UPLOAD_PROGRESS = 'uploadProgress';
export const API_PAGE_WRITE = 'writingItDown';
export const API_PAGE_CREATE = 'writingNewEntry';
export const API_PAGE_DELETE = 'erasingPage';
export const API_SETTINGS_WRITE = 'savingSettings';
export const API_IMAGES_UPLOAD = 'uploadProfileImages';
export const API_RENDER_PAGES = 'renderPages';
export const API_INIT = 'blogInit';
export const API_INIT_GOOD = 'blogInitGood';
export const API_INIT_LAME = 'blogInitLame';
export const SEND_MAIL = 'sendMail';
class DataEvent {
//--------------------------
// methods
//--------------------------
//--------------------------
// event handlers
//--------------------------
}
export default new DataEvent();

@ -1,14 +0,0 @@
export const EDITOR_DELETE = 'editorDelete';
export const EDITOR_UPLOAD_POST_IMAGE = 'editorUploadImage';
export const EDITOR_SAVE = 'editorSave';
export const EDITOR_UPDATE = 'editorUpdate';
class EditorEvent {
//--------------------------
// methods
//--------------------------
//--------------------------
// event handlers
//--------------------------
}
export default new EditorEvent();

@ -1,52 +0,0 @@
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);
}
removeListener(label, callback) {
var isFunction = function(obj) {
return typeof obj == 'function' || false;
};
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 (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
//--------------------------
}
export default EventEmitter;

@ -1,61 +0,0 @@
import anime from 'animejs/lib/anime.es.js';
const notifcation = document.getElementById('notifications');
const message = document.getElementById('notifyMessage');
const messageText = document.getElementById('message-text');
export default class Notfications {
//--------------------------
// constructor
//--------------------------
constructor() {}
//--------------------------
// methods
//--------------------------
alert(text, status) {
messageText.innerHTML = text;
notifcation.style.display = 'flex';
var color = '';
status ? (color = '#32cd32') : (color = '#F64747');
anime({
targets: messageText,
backgroundColor: color,
easing: 'easeInOutQuint',
duration: 500,
complete: () => {
setTimeout(() => {
anime({
targets: messageText,
backgroundColor: '#374857',
easing: 'easeOutQuint',
duration: 500
});
}, 1000);
}
});
anime({
targets: message,
marginTop: '-20px',
easing: 'easeInOutQuint',
duration: 500,
opacity: 1,
complete: () => {
setTimeout(() => {
anime({
targets: message,
marginTop: '-125px',
easing: 'easeOutQuint',
duration: 500,
opacity: 0,
complete: () => {
notifcation.style.display = 'none';
}
});
}, 1000);
}
});
}
//--------------------------
// event handlers
//--------------------------
}

@ -1,158 +0,0 @@
import * as DataEvent from '../events/DataEvent';
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.textEditor = textEditor;
this.fixLimit = scrollLimit;
this.caretPos = null;
this.url = '';
this.setInputs();
window.addEventListener('scroll', () => {
//var fixLimit = this.fixLimit;
/**
* edit scroller needs work
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
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;
var spiffed = this.textEditor.innerText;
spiffed = spiffed.replace(new RegExp('\r?\n', 'g'), '<br>');
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('<del>' + pulled + '</del>'));
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;

@ -1,92 +0,0 @@
export default class DataUtils {
//--------------------------
// constructor
//--------------------------
constructor() {}
//--------------------------
// methods
//--------------------------
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);
}
);
});
}
/**
* Create a function to convert the serialize and convert the form data to JSON
* @param : $('#form_example');
* @return a JSON Stringify
*/
formDataToJSON(form) {
let object = {};
let formData = new FormData(form);
formData.forEach((value, key) => {
if (!object.hasOwnProperty(key)) {
object[key] = value;
return;
}
if (!Array.isArray(object[key])) {
object[key] = [object[key]];
}
object[key].push(value);
});
//let json = JSON.stringify(object);
return object;
}
//--------------------------
// event handlers
//--------------------------
}

@ -1,68 +0,0 @@
class StringUtils {
//--------------------------
// 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(/&lt;/g, '<')
.replace(/&gt;/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(/&#0*39;/g, "'"); // PHP doesn't currently escape if more than one 0, but it should
// string = string.replace(/&apos;|&#x0*27;/g, "'"); // This would also be useful here, but not a part of PHP
}
if (!noquotes) {
string = string.replace(/&quot;/g, '"');
}
// Put this in last place to avoid escape being double-decoded
string = string.replace(/&amp;/g, '&');
return string;
}
//--------------------------
// event handlers
//--------------------------
}
export default StringUtils;

@ -1,121 +0,0 @@
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';
export const API_STATUS = '/api/v1/auth/status';
export const API_INIT = '/api/v1/auth/init';
export const API_LOGIN = '/api/v1/auth/login';
export const API_GET_PAGES = '/api/v1/page/published';
export const API_GET_PAGE = '/api/v1/page/single';
import * as DataEvent from '../com/events/DataEvent';
export default class APIUtils {
//--------------------------
// constructor
//--------------------------
constructor() {}
//--------------------------
// public
//--------------------------
login(data) {
return new Promise((resolve, reject) => {
this._request(
API_LOGIN,
DataEvent.AUTH_STATUS,
REQUEST_TYPE_POST,
CONTENT_TYPE_JSON,
data
)
.then(result => {
resolve(result);
})
.catch(err => {
reject(err);
});
});
}
init(data) {
return new Promise((resolve, reject) => {
this._request(API_INIT, DataEvent.API_INIT, REQUEST_TYPE_POST, CONTENT_TYPE_JSON, data)
.then(result => {
resolve(result);
})
.catch(err => {
reject(err);
});
});
}
getPages(num) {
let pageNum = num;
if (pageNum === null || pageNum === '' || !pageNum) pageNum = 1;
return new Promise((resolve, reject) => {
this._request(API_GET_PAGES + '/' + pageNum, DataEvent.API_GET_PAGES, REQUEST_TYPE_GET)
.then(result => {
resolve(result);
})
.catch(err => {
reject(err);
});
});
}
getPage(id) {
return new Promise((resolve, reject) => {
this._request(API_GET_PAGE + '/' + id, DataEvent.API_GET_PAGES, REQUEST_TYPE_GET)
.then(result => {
resolve(result);
})
.catch(err => {
reject(err);
});
});
}
//--------------------------
// private
//--------------------------
_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) {
let response = JSON.parse(request['response']);
resolve(response);
} else {
let error = JSON.parse(request['response']);
reject(error);
}
};
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();
}
});
}
//--------------------------
// event handlers
//--------------------------
handleLoadProgress(e) {
this.percentComplete = Math.ceil((e.loaded / e.total) * 100);
//pass element to display request progress
}
}

@ -1,247 +0,0 @@
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 TASK_PAGE_CREATE = 'createNewPage';
export const TASK_PAGE_EDIT = 'editPage';
export const TASK_PAGE_DELETE = 'deletePage';
export const CONTENT_TYPE_JSON = 'json';
export const CONTENT_TYPE_FORM = 'x-www-form-urlencoded';
export const API_STATUS = '/api/v1/auth/status';
export const API_GET_NAV = '/api/settings/nav';
export const API_NEW_PAGE = '/api/v1/page/write/new';
export const API_EDIT_PAGE = '/api/v1/page/write';
export const API_DELETE_PAGE = '/api/v1/page/delete';
export const API_IMAGE_UPLOAD = '/api/v1/page/add-post-image';
export const API_SETTINGS_SYNC = '/api/v1/settings/sync';
export const API_UPLOAD_AVATAR = '/api/v1/settings/add-avatar';
export const API_UPLOAD_BACKGROUND = '/api/v1/settings/add-feature-background';
export const API_PUBLISH_PAGES = '/api/v1/settings/publish-pages';
export const API_NAV_SYNC = '/api/v1/settings/nav-sync';
export const API_SEND_MAIL = '/api/v1/mailer';
import * as DataEvent from '../com/events/DataEvent';
export default class APIUtils {
//--------------------------
// constructor
//--------------------------
constructor() {
this.percentComplete = 0;
this.token = null;
//checks backend to see if user is logged in
//and requests encrypted token for api calls
this._request(API_STATUS).then(response => {
if (response.type === DataEvent.API_REQUEST_GOOD) {
this.token = response.token;
} else {
//don't set token
}
});
}
//--------------------------
// public
//--------------------------
syncSettings(data) {
return new Promise((resolve, reject) => {
this._request(
API_SETTINGS_SYNC,
DataEvent.API_SETTINGS_WRITE,
REQUEST_TYPE_POST,
CONTENT_TYPE_JSON,
data
)
.then(result => {
resolve(result);
})
.catch(err => {
reject(err);
});
});
}
imageUpload(type, files) {
return new Promise((resolve, reject) => {
let url = '';
switch (type) {
case 'avatar-upload':
url = API_UPLOAD_AVATAR;
break;
case 'background-upload':
url = API_UPLOAD_BACKGROUND;
break;
default:
url = API_IMAGE_UPLOAD;
break;
}
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;
}
if (type === 'avatar-upload') {
imageData.append('avatar_upload', file, file.name);
} else if (type === 'background-upload') {
imageData.append('background_upload', file, file.name);
} else {
imageData.append('post_image', file, file.name);
}
}
this._request(
url,
DataEvent.API_IMAGES_UPLOAD,
REQUEST_TYPE_POST,
CONTENT_TYPE_FORM,
imageData
)
.then(r => {
resolve(r);
})
.catch(err => {
reject(err);
});
});
}
publishSite(data) {
return new Promise((resolve, reject) => {
this._request(
API_PUBLISH_PAGES,
DataEvent.API_RENDER_PAGES,
REQUEST_TYPE_POST,
CONTENT_TYPE_JSON,
data
)
.then(result => {
resolve(result);
})
.catch(err => {
reject(err);
});
});
}
pageActions(task, data) {
let url, event, content;
switch (task) {
case TASK_PAGE_CREATE:
url = API_NEW_PAGE;
event = DataEvent.API_PAGE_WRITE;
content = CONTENT_TYPE_FORM;
break;
case TASK_PAGE_EDIT:
url = API_EDIT_PAGE;
event = DataEvent.API_PAGE_WRITE;
content = CONTENT_TYPE_FORM;
break;
case TASK_PAGE_DELETE:
url = API_DELETE_PAGE;
event = DataEvent.API_PAGE_DELETE;
content = CONTENT_TYPE_JSON;
break;
default:
break;
}
return new Promise((resolve, reject) => {
this._request(url, event, REQUEST_TYPE_POST, content, data)
.then(result => {
resolve(result);
})
.catch(err => {
reject(err);
});
});
}
syncNav(data) {
return new Promise((resolve, reject) => {
this._request(
API_NAV_SYNC,
DataEvent.API_SETTINGS_WRITE,
REQUEST_TYPE_POST,
CONTENT_TYPE_JSON,
data
)
.then(result => {
resolve(result);
})
.catch(err => {
reject(err);
});
});
}
sendMail(message) {
return new Promise((resolve, reject) => {
this._request(
API_SEND_MAIL,
DataEvent.SEND_MAIL,
REQUEST_TYPE_POST,
CONTENT_TYPE_JSON,
message
)
.then(result => {
resolve(result);
})
.catch(err => {
reject(err);
});
});
}
//--------------------------
// private
//--------------------------
_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) {
let response = JSON.parse(request['response']);
resolve(response);
} else {
let error = JSON.parse(request['response']);
reject(error);
}
};
if (requestType == REQUEST_TYPE_PUT || requestType == REQUEST_TYPE_POST) {
if (
eventType === DataEvent.API_PAGE_WRITE ||
eventType === DataEvent.API_IMAGES_UPLOAD ||
eventType === DataEvent.API_SETTINGS_WRITE ||
eventType === DataEvent.API_PAGE_DELETE ||
eventType === DataEvent.API_RENDER_PAGES
)
request.setRequestHeader('x-access-token', self.token);
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();
}
});
}
//--------------------------
// event handlers
//--------------------------
handleLoadProgress(e) {
this.percentComplete = Math.ceil((e.loaded / e.total) * 100);
//pass element to display request progress
}
}

@ -1,81 +0,0 @@
/**
-------------------------------
-- Bulma
-------------------------------
* */
@import '../../node_modules/bulma.styl/stylus/utilities/_all'
@import '../../node_modules/bulma.styl/stylus/grid/columns'
/**
-------------------------------
-- Colors
-------------------------------
* */
@import 'main/_colors'
/**
-------------------------------
-- Mixins
-------------------------------
* */
@import 'main/_mixins'
/**
-------------------------------
-- Normalize
-------------------------------
* */
@import 'main/_normalize'
/**
-------------------------------
-- Typography
-------------------------------
* */
@import 'main/_typography'
/**
-------------------------------
-- Main Structures
-------------------------------
* */
@import 'main/_structure'
/**
-------------------------------
-- Index
-------------------------------
* */
@import 'main/_index'
/**
-------------------------------
-- Settings
-------------------------------
* */
@import 'main/_settings'
/**
-------------------------------
-- Error
-------------------------------
* */
@import 'main/_error'
/**
-------------------------------
-- Navigation
-------------------------------
* */
@import 'main/_navigation'
/**
-------------------------------
-- Forms
-------------------------------
* */
@import 'main/_forms'
/**
-------------------------------
-- Blog
-------------------------------
* */
@import 'main/_posts'
/**
-------------------------------
-- Editor
-------------------------------
* */
@import 'main/_calendar'
@import 'main/_editor'
@import 'main/_editor-highlight'

@ -1,245 +0,0 @@
// TINY DATE
.dp-modal
position fixed
top 0
left 0
right 0
bottom 0
// background rgba(255, 255, 255, 0.75)
background-opacity($primary - 70%, 0.75)
z-index 2000
.dp
position relative
background $primary // #FFF
box-shadow 2px 2px 16px rgba(0, 0, 0, 0.25)
line-height 1.4
border-radius 4px
max-height 400px
z-index 5000
padding-top 6px
overflow hidden
-webkit-tap-highlight-color transparent
.dp:before
content ' '
height 6px
position absolute
top 0
left 0
right 0
background $highlight
// background linear-gradient(-90deg, #3B99FC 0%, #8AEFC8 100%)
.dp-permanent .dp
padding-top 0
border 1px solid #EEE
box-shadow none
.dp-permanent .dp:before
display none
.dp-cal
min-height 300px
.dp-below
position absolute
font-size 0.8em
width 400px
max-width 90vw
.dp-permanent
position relative
font-size 0.8em
width 400px
max-width 100vw
.dp-permanent .dp
z-index 0
.dp-modal .dp
position absolute
top 50%
left 50%
max-width 600px
width calc(100% - 4em)
transform translate(-50%, -50%)
animation slide-up 0.3s forwards
.dp-months
padding 24px
.dp-years
box-sizing border-box
max-height 400px
padding 8px 0
overflow auto !important /* HACK for Chrome on Android */
.dp-cal-month, .dp-cal-year, .dp-day, .dp-month, .dp-year
box-sizing border-box
text-align center
text-decoration none
position relative
color $white
border-radius 2px
border 0
background transparent
.dp-cal-header
position relative
text-align center
padding-bottom 16px
background $primary - 10%
.dp-next, .dp-prev
position absolute
width 30px
height 30px
overflow hidden
top 14px
color $primary - 50%
border-radius 2px
border 0
background transparent
.dp-next:focus, .dp-prev:focus, .dp-next:hover, .dp-prev:hover
outline none
color inherit
.dp-prev
left 24px
.dp-next
right 24px
.dp-prev:before, .dp-next:before
content ''
border 2px solid
width 10px
height 10px
display inline-block
transform rotate(-45deg)
transition border-color 0.2s
margin 9px 0 40px 4px
.dp-prev:before
border-right 0
border-bottom 0
.dp-next:before
border-left 0
border-top 0
margin-left 0
margin-right 4px
.dp-cal-month, .dp-cal-year
display inline-block
font-size 1.4em
padding 16px 8px 8px
outline none
.dp-cal-footer
text-align center
background $primary - 10%
.dp-day-today:after
content ''
height 0
width 0
border 7px solid $highlight
border-bottom-color transparent
border-left-color transparent
position absolute
top 0
right 0
.dp-close, .dp-clear, .dp-today
box-sizing border-box
display inline-block
width 33%
padding 8px
text-decoration none
color $primary - 50%
border 0
background transparent
.dp-permanent .dp-close, .dp-permanent .dp-clear
display none
.dp-close:active, .dp-clear:active, .dp-today:active, .dp-next:active, .dp-prev:active, .dp-cal-month:active, .dp-cal-year:active
background $highlight
color $white
@media screen and (min-device-width: 1200px)
.dp-close:hover, .dp-close:focus, .dp-clear:hover, .dp-clear:focus, .dp-today:hover, .dp-today:focus, .dp-next:hover, .dp-next:focus, .dp-prev:hover, .dp-prev:focus, .dp-cal-month:focus, .dp-cal-month:hover, .dp-cal-year:hover, .dp-cal-year:focus
background $highlight
color $white
.dp-col-header, .dp-day
width 14.28571429%
display inline-block
padding 8px
text-align center
.dp-col-header
color #AAA
text-transform uppercase
font-weight 300
font-size 0.8em
padding 8px 0
.dp-month
width 33%
display inline-block
padding 8px
.dp-year
display block
padding 8px 40px
width 100%
.dp-edge-day
color #AAA
.dp-day:hover, .dp-month:hover, .dp-year:hover, .dp-current:focus, .dp-current, .dp-day:focus, .dp-month:focus, .dp-year:focus
outline none
background $primary - 40%
color $white
.dp-selected:hover, .dp-selected:focus, .dp-selected
background $highlight
color $primary - 60%
.dp-day-disabled
background transparent
color #DDD
.dp-day-disabled:focus, .dp-day-disabled:hover
background #DDD
.dp-focuser
position absolute
z-index 0
top 50%
left 50%
/**
-------------------------------
-- Responsive
-------------------------------
* */
@media (max-width: 480px), (max-height: 480px)
.dp-modal .dp
font-size 0.9em
width auto
width 100%
.dp-day-of-week, .dp-day
padding 8px
@keyframes slide-up
0%
transform translate(-50%, 100%)
100%
transform translate(-50%, -50%)

@ -1,19 +0,0 @@
$primary = #374857;
//$primary = #200317; deep sexy purple
$secondary = #b2cce5;
$tertiary = #f5ab35;
$highlight = #fc6399;
$white = #f2f1ef;
$grey = #abb7b7;
$black = #32302f;
//editor colors
$eventCool = #32cd32
$eventLame = #F64747
$editorPrimary = #fde3a7;
$editorSecondary = #ffa07a;
$editorTertiary = #89c4f4;
$editorString = #f6dd74;
//Bulma overrides

@ -1,46 +0,0 @@
.hljs
display block
overflow-x auto
padding 0.5em
background $primary - 5%
.hljs, .hljs-subst
color #ebdbb2
.hljs-deletion, .hljs-formula, .hljs-keyword .hljs-selector-tag
color $editorPrimary
font-style italic
.hljs-link
color $highlight
.hljs-built_in, .hljs-emphasis, .hljs-name, .hljs-quote, .hljs-strong, .hljs-title, .hljs-variable
color $editorSecondary
.hljs-attr, .hljs-params, .hljs-template-tag, .hljs-type
color $editorTertiary
.hljs-builtin-name, .hljs-doctag, .hljs-literal, .hljs-number
color #8f3f71
.hljs-code, .hljs-meta, .hljs-regexp, .hljs-selector-id, .hljs-template-variable
color $tertiary
.hljs-addition, .hljs-meta-string, .hljs-section, .hljs-selector-attr, .hljs-selector-class, .hljs-string, .hljs-symbol
color $editorString
.hljs-attribute, .hljs-bullet, .hljs-class, .hljs-function, .hljs-function .hljs-keyword, .hljs-meta-keyword, .hljs-selector-pseudo, .hljs-tag
color $primary + 50%
.hljs-comment
color #928374
.hljs-link_label, .hljs-literal, .hljs-number
color #d3869b
.hljs-comment, .hljs-emphasis
font-style italic
.hljs-section, .hljs-strong, .hljs-tag
font-weight normal

@ -1,95 +0,0 @@
#edit-control
// margin 10px
top 1px
border-radius 3px
// background-opacity($primary - 10%, 0.50)
width 100%
max-width 880px
margin-top 30px
z-index 2000
button:nth-child(1)
border-radius 3px 0 0 3px
button:nth-child(10)
border-radius 0 3px 3px 0
button
background $secondary
width 10%
height 39px
object-transitions(0.3s)
margin 0
border-radius 0
display inline-block
vertical-align top
text-align center
button:hover
background: $secondary - 20%
#option-update
padding 5px 5px 1px 5px
display inline-block
vertical-align top
text-align center
.icon-hide
display none
visibility hidden
.submit-start
background $white
svg
fill $eventCool
.submit-cool
background $eventCool
svg
fill $white
.submit-delete
background $eventLame !important
svg
fill $white !important
#option-date
height 30px
padding-top 6px
svg
margin -13px 5px 0 0
display inline-block
vertical-align top
fill $white
.content-editor-btn-icon
padding 5px 5px 1px 5px
// border-radius 20px
color $primary
svg
fill $primary
.content-editor-btn-text
padding 5px
// border-radius 20px
color $primary
#option-bold
font-weight bold
text-decoration none
#option-italic
font-weight bold
text-decoration none
font-style italic
#option-strikethrough
font-weight bold
text-decoration line-through
font-style italic

@ -1,22 +0,0 @@
#error-index
width 100%
max-width 900px
margin 0 auto;
padding: 10px
height 100%
z-index 10
position relative
label#title
font-size 100px
color $highlight
font-weight: 500
label#message
font-size 50px
color $tertiary
font-weight: 500
label#error
font-size 25px
color $eventLame
font-weight: 500

@ -1,57 +0,0 @@
form
display inline-block
input[type=email], input[type=password], input[type=text]
border 0
border-radius 3px
padding 5px
font 1em $monoType
display inline-block
background-color $primary - 60%
color $secondary
textarea
border 0
border-radius 3px
color $type02
font 1em $monoType
button, input[type=submit]
background $highlight
color $primary - 60%
font 1em $monoType
border-radius 3px
position relative
cursor pointer
border 0
input.large
font-size 1.4em
padding 10px
select
font 1em $monoType
border 1px solid $secondary
-webkit-appearance none
-moz-appearance none
appearance none
// background: url(http://www.stackoverflow.com/favicon.ico) 96% / 15% no-repeat #000;
color $primary
::-webkit-input-placeholder
font 1em $monoType
color $secondary
:-moz-placeholder
/* Firefox 18- */
font 1em $monoType
color $secondary
::-moz-placeholder
/* Firefox 19+ */
font 1em $monoType
color $secondary
:-ms-input-placeholder
font 1em $monoType
color $secondary

@ -1,252 +0,0 @@
#dash-index-content
width 100%
height 100%
margin 0 auto
#dash-index
width 100%
height 100%
z-index 10
position relative
#dash-index-wrapper
width 100%
height 100%
margin 0 auto
.dash-init
width 100%
max-width 900px
margin 0 auto
color $secondary
label
color $primary
form
background $white
padding 15px
h1
color $primary
p
color $primary - 60%
border-top 1px solid $primary
border-bottom 1px solid $primary
padding 10px 0 10px 0
input.large[type=email], input[type=password], input[type=text]
margin-bottom 15px
margin-top 5px
button
height 30px
width 120px
margin 0 auto
display block
#dash-login
width 100%
max-width 900px
margin 0 auto
#dash-form
width 300px
padding 0.75em
background $primary
border-radius 3px
input
width 290px
margin 0 0 10px 0
height 30px
button
width 300px
#dash-menu
padding 10px
width 90%
max-width 900px
margin 50px auto
a
display inline-block
vertical-align top
background $primary - 60%
width 30%
padding 5px
border-radius 3px
color $white
margin 0 10px 10px 0
&:hover
background $primary - 50%
svg
display inline-block
vertical-align top
fill $white
label
display inline-block
margin-top 5px
width 85%
text-align center
cursor pointer
#dash-recent
width 100%
max-width 900px
height 100%
padding 5px 0 0 0
margin 0 auto
#recent-list
padding 0.75em
position relative
.recent-header
height 50px
h3
vertical-align top
display inline-block
width 50%
.index-menu
width 50%
text-align right
vertical-align top
display inline-block
margin 24px 0 24px 0
right 10px
color $white
a
text-decoration-color $highlight
a.post-link
font-size 1.5em
font-weight 300
display inline-block
border-radius 3px
vertical-align top
text-decoration none
position relative
label
font-size 1.4em
font-weight 700
color $white
padding 5px
vertical-align top
display inline-block
word-wrap break-word
width 100%
text-align center
text-drop-shadow($black, 1, 2px, 2px, 0)
span
vertical-align top
margin 0 auto
width 300px
display block
font-family $monoType
font-size 0.5em
padding 7px
color $white
text-align: center
//background $primary - 60%
border-radius 0 0 3px 3px
div
width 100%
position absolute
bottom 0
border-radius 0 0 3px 3px
//background-opacity($black, .35)
background: linear-gradient(to bottom, rgba(0,0,0,0) 0%,rgba(0,0,0,0.65) 100%);
#options
display block
vertical-align: top
width 300px
position relative
text-align: center
margin 0 auto
background none
.item-options
border-radius 3px
margin 5px
display inline-block
.item-options[data-active='false']
width 65px
background $primary - 60%
color $white
.item-options[data-active='true']
width 70px
background $tertiary + 50%
color $primary - 60%
a:nth-child(3)
width 100%
margin-bottom 20px
height 500px
a:nth-child(4)
width 49%
height 275px
margin 0 15px 15px 0
a:nth-child(5)
width 49%
height 550px
a:nth-child(6)
width 49%
height 550px
margin -260px 15px 0 0
a:nth-child(7)
width 49%
height 275px
margin 15px 0 0 0
/**
-------------------------------
-- Responsive
-------------------------------
* */
@media only screen and (max-width: 768px)
#dash-index-content
#dash-index
#dash-index-wrapper
#dash-recent
#recent-list
a:nth-child(4), a:nth-child(6)
width 48.9%
@media only screen and (max-width: 640px)
#dash-index-content
#dash-index
#dash-index-wrapper
#dash-recent
#recent-list
a:nth-child(4), a:nth-child(6)
width 48.5%
@media only screen and (max-width: 480px)
#dash-index-content
#dash-index
#dash-index-wrapper
#dash-recent
#recent-list
.recent-header
h3
width 40%
.index-menu
width 60%
a:nth-child(3), a:nth-child(4), a:nth-child(5), a:nth-child(6), a:nth-child(7)
width 100%
margin 15px 0 0 0
height 400px

@ -1,11 +0,0 @@
text-drop-shadow(rgb-value, opacity, offsetX, offsetY, blur)
text-shadow offsetX offsetY blur rgba(rgb-value, opacity)
object-transitions(rate)
-moz-transition all rate linear
-webkit-transition all rate linear
-o-transition all rate linear
transition all rate linear
background-opacity(rgb-value, opacity)
background rgba(rgb-value, opacity)

@ -1,62 +0,0 @@
#nav-index
width 100%
max-width 900px
margin 0 auto
#nav-index-wrapper
padding 0.75rem
#nav-pages
.nav-item
display block
width 98%
background $primary
border-radius 3px
color $white
height 30px
padding 10px
margin 0 0 10px 0
font-size 1.5em
cursor move
label
display inline-block
vertical-align middle
padding 0
margin -15px 0 0 10px
cursor move
#nav-btns
float right
button
font-size 0.8em
margin 0 0 0 10px
@media only screen and (max-width: 375px)
#nav-index
#nav-index-wrapper
#nav-pages
.nav-item
width 94.5%
font-size 1em
label
width 47%
vertical-align top
margin-top 0px
line-height 1em
@media only screen and (max-width: 320px)
#nav-index
#nav-index-wrapper
#nav-pages
.nav-item
width 94.5%
font-size 1em
label
width 37%
vertical-align top
margin-top 0px
line-height 1em

@ -1,196 +0,0 @@
html
line-height 1.15
-ms-text-size-adjust 100%
-webkit-text-size-adjust 100%
body
margin 0
article,
aside,
footer,
header,
nav,
section
display block
h1
font-size 2em
margin 0.67em 0
figcaption,
figure,
main
display block
figure
margin 1em 40px
hr
box-sizing content-box
height 0
overflow visible
pre
font-family monospace, monospace
font-size 1em
a
background-color transparent
-webkit-text-decoration-skip objects
a:active,
a:hover
outline-width 0
abbr[title]
border-bottom none
text-decoration underline
text-decoration underline dotted
b,
strong
font-weight inherit
font-weight bolder
code,
kbd,
samp
font-family monospace, monospace
font-size 1em
dfn
font-style italic
mark
background-color #ff0
color #000
small
font-size 80%
sub,
sup
font-size 60%
line-height 0
position relative
vertical-align baseline
sub
bottom -0.25em
sup
top -0.55em
background lightness($primary, 80%)
color $primary
border-radius: 2px;
padding 0 2px 0 2px
margin: 0 2px 0 0
audio,
video
display inline-block
audio
&:not([controls])
display none
height 0
img
border-style none
svg
&:not(:root)
overflow hidden
button,
input,
optgroup,
select,
textarea
font-family sans-serif
font-size 100%
line-height 1.15
margin 0
button,
input
overflow visible
button,
select
text-transform none
button, html [type="button"],
[type="reset"],
[type="submit"]
-webkit-appearance button
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner,
button::-moz-focus-inner
border-style none
padding 0
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring,
button:-moz-focusring
outline 1px dotted ButtonText
fieldset
border 1px solid #c0c0c0
margin 0 2px
padding 0.35em 0.625em 0.75em
legend
box-sizing border-box
color inherit
display table
max-width 100%
padding 0
white-space normal
progress
display inline-block
vertical-align baseline
textarea
overflow auto
[type="checkbox"],
[type="radio"]
box-sizing border-box
padding 0
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button
height auto
[type="search"]
-webkit-appearance textfield
outline-offset -2px
[type="search"]::-webkit-search-cancel-button,
[type="search"]::-webkit-search-decoration
-webkit-appearance none
::-webkit-file-upload-button
-webkit-appearance button
font inherit
details,
menu
display block
summary
display list-item
canvas
display inline-block
template
display none
[hidden]
display none

@ -1,388 +0,0 @@
#post-index
width 100%
max-width 900px
margin 0 auto
#post-index-wrapper
padding 0.75rem
overflow hidden
#post-index-menu
color $white
a
text-decoration-color $highlight
a.add-new-post
display inline-block
background $highlight
border-radius 3px
padding 3px
color $white
text-align center
margin-bottom 10px
float right
.current-filter
color $highlight
text-decoration-color $secondary
#posts-list
margin 20px 0 0 0
a.page-link
background $white
display inline-block
vertical-align top
width 100%
text-decoration none
margin 0 0 20px 0
border-radius 3px
overflow hidden
color $primary - 60%
label
font-size 2em
font-weight 500
padding 10px
display inline-block
vertical-align top
width 100%
span
display inline-block
vertical-align top
font-size 0.8em
font-family $monoType
width 50%
padding 0 0 0 10px
div.page-bg
width 100%
height 350px
background-color $highlight
position relative
#meta
width 100%
background: linear-gradient(to bottom, rgba(0,0,0,0) 0%,rgba(0,0,0,0.65) 100%);
border-radius 3px
margin auto
bottom 0
position absolute
padding 0 0 20px 0
span
color $white
text-align center
margin 0 auto
display block
label
font-size 1.4em
font-weight 700
color $white
padding 5px
vertical-align top
display inline-block
word-wrap break-word
width 100%
text-align center
text-drop-shadow($black, 1, 2px, 2px, 0)
#options
margin 0 auto
width: 275px
.meta-options
border-radius 3px
margin 5px
display inline-block
text-align: center
padding 2px
.meta-options[data-active='false']
width 70px
background $primary - 60%
color $white
.meta-options[data-active='true']
width 75px
background $tertiary + 50%
color $primary - 60%
p
padding 5px 10px 5px 10px
font-size 1.2em
font-weight 400
.paginate
width 260px
display block
margin 0 auto
a
display inline-block
vertical-align: top
span.count
text-align center
padding 5px
margin-top -2px
display inline-block
width 200px
font-size: 1.5em
color $tertiary
#post-edit-index
width 100%
overflow hidden
#post-edit-index-wrapper
width 100%
#post-header
// width 100%
background $highlight
#post-header-wrapper
max-width 900px
margin 0 auto
padding 0.75rem
label
color: $white
font-size: 0.8em
font-family $monoType
font-weight 600
span
color color $primary - 60%
font-size 1.5em
#post-title
#post_title
background $highlight + 10%
font-family $baseType
width 97.6%
height 80px
font-size 2em
color $primary - 60%
padding 5px
margin 0 0 5px 0
#calendar-icon
background $primary - 15%
border-radius 3px 0 0 3px
display inline-block
padding 5.2px
color $secondary
#post-meta
#post_tags
background $highlight + 10%
font-family $baseType
width 97.6%
height 80px
color $primary - 60%
padding 5px
margin 0 0 5px 0
#post-options
display inline-block
vertical-align top
width 100%
padding 0
button:nth-child(1)
border-radius 3px 0 0 3px
button:nth-child(4)
border-radius 0 3px 3px 0
button
width 33.3%
height 39px
object-transitions(0.3s)
margin 0
border-radius 0
display inline-block
vertical-align top
text-align center
button[data-active='false']
background $primary - 60%
svg
fill $white
button[data-active='true']
background $tertiary + 50%
svg
fill $primary - 60%
#featured-image-upload, #post-image-upload
display none
#post-feature
width 100%
#featured-image-drop
display flex
align-items center
justify-content center
width 100%
min-height 200px
background $primary - 50%
color $primary
vertical-align middle
font-family $monoType
label
cursor pointer
img
width 100%
margin 0
padding 0
#featured-new-image-btn
position absolute
margin 20px
#new-feature-upload
padding-top 4px
background $white
svg
fill $highlight
#edit-post
width 100%
max-width 880px
margin 0 auto
#edit-post-wrapper
//width 98.7%
max-width 900px
border-radius 5px
//background $primary - 10%
margin: 40px 0 40px 0
overflow hidden
pre
margin 0
code
font-family $monoType
padding 5px
border-radius 5px
line-height 1.6em
font-size 1.25em
color $editorPrimary
word-wrap normal
white-space pre-wrap
line-break normal
-webkit-line-break normal
-o-line-break normal
-moz-line-break normal
display inline-block
width 100%
max-width 900px
min-height 200px
/**
-------------------------------
-- Responsive
-------------------------------
* */
@media only screen and (max-width: 800px)
#post-edit-index
#post-edit-index-wrapper
#post-header
#post-title
#post-date
width 37.6%
@media only screen and (max-width: 768px)
#post-edit-index
#post-edit-index-wrapper
#post-header
#post-title
#post-date
width 43.1%
#post-meta
#edit-control
max-width 100%
button
width 9.91%
@media only screen and (max-width: 640px)
#post-edit-index
#post-edit-index-wrapper
#post-header
#post-title
#post-date
width 42%
@media only screen and (max-width: 480px)
#post-index
#post-index-wrapper
#post-index-menu
a
font-size 0.95em
label
display none
visibility hidden
#post-edit-index
#post-edit-index-wrapper
#post-header
#post-title
#post-options
margin 5px 0 0 0
width 100%
padding 0
#post-date
width 89.2%
#post-meta
#edit-control
button
width 9.91%
@media only screen and (max-width: 320px)
#post-index
#post-index-wrapper
#post-index-menu
a
font-size 0.95em
label
display none
visibility hidden
#post-edit-index
#post-edit-index-wrapper
#post-header
#post-title
#post_title
width 96.4%
#post-options
margin 5px 0 0 0
width 100%
padding 0
#post-date
width 83.1%
#post-meta
#post_tags
width 96.4%
#edit-control
.content-editor-btn-icon
svg.icons
width 20px
.post-sumbit-btn
svg.icons
width 20px
button
width 10%

@ -1,165 +0,0 @@
#settings-actions
position fixed
width 40%
margin-top -85px
left 50%
margin-left -20%
#buttons
width 155px
margin 0 auto
button
//width 30%
margin 5px
svg
fill $white
button[data-render='false']
background $primary - 60%
svg
fill $white
button[data-render='true']
background $tertiary + 50%
svg
fill $primary - 60%
#site-background
margin 0 0 10px 0
img
width 100%
// border 5px solid $white
border-radius 0
overflow hidden
cursor pointer
label
position absolute
color $white
margin 5px
background $primary - 60%
padding 5px
border-radius 3px
input
visibility hidden
display none
#settings-index
width 94%
max-width 900px
margin 0 auto
#settings-index-wrapper
padding 0.75rem
button
margin-top 5px
width 100%
height 45px
#member-settings, #site-settings, #option-settings
background $primary
padding 5px
border-radius 5px 0 5px 0
label
font-family $monoType
color $white
input
width 95%
margin 0 5px 10px 0
height 30px
padding 10px
width 100%
margin 20px auto
#member-avatar-drop
display inline-block
margin 0 0 10px 0
img
width 100%
// border 5px solid $white
border-radius 5px
overflow hidden
cursor pointer
display block
margin-bottom 2px
input
visibility hidden
display none
#privacy-toggle
width 50%
#render-toggle
width 50%
#member-info
vertical-align top
display inline-block
width 100%
input
width 95%
margin 0 5px 10px 0
textarea
background $primary - 60%
width 95%
height 155px
color $secondary
padding 10px
#option-settings
#theme-settings
a
width 95%
margin 0 5px 5px 0
height 25px
padding 10px
display inline-block
a[data-enabled='false']
background $primary - 60%
color $secondary
border-radius 3px
a[data-enabled='true']
background $secondary
color $primary
border-radius 3px
svg
fill $primary
display inline-block
float right
#mail-settings
min-height 240px
a.mail-option
float right
font-family $monoType
font-size 0.9em
border-radius 3px
text-decoration none
margin 0 0 0 5px
// padding: 1px
a.mail-option[data-enabled='true']
color $highlight
a.mail-option[data-enabled='false']
color $white
input
// width 94%
margin 0 5px 5px 0
vertical-align top
div[data-enabled='false']
display none
visibility hidden

@ -1,150 +0,0 @@
html, body
background-color $primary - 60%
font 400 1em $baseType
height 100%
a
font 300 1em $baseType
color $secondary
text-decoration underline
object-transitions(0.1s)
&:hover
color $secondary + 10%
svg.icons
width 25px
fill $secondary
#notifications
position fixed
z-index 2000
height 10%
width 100%
display none
align-items center
justify-content center
padding 0
margin 0
#notifyMessage
margin-top: 0px;
padding-top -125px
height 50px;
width 500px
display: flex;
align-items center
justify-content center
opacity: 0
.notify-icon
background $black
padding 8px 5px 5px 5px
border-radius 5px 0 0 5px
height 30px
width 30px
text-align center
border 2px solid $white
p
color $white
background $highlight
width 400px
height 28px
padding 15px 0 0 5px
border-radius 0 5px 5px 0
border 2px solid $white
text-align center
.icons
fill $white
.blog-container
width 100%
.main-container
margin 0 auto
z-index 10
position relative
section
header
width 100%
max-width 900px
margin 0 auto
#wrapper
padding 0.75rem
#left, #right
width 50%
display inline-block
vertical-align top
#the-logo
width 40px
#right
text-align right
color $white
a
text-decoration-color $highlight
font-weight: 400
label#the-title
font-size 1.2em
font-weight 400
color $tertiary
text-decoration none
display block
line-height 0.8
// word-break: break-all;
#dash-menu
text-align right
/* Mozilla based browsers */
::-moz-selection
background-color $highlight
color $white
/* Works in Safari */
::selection
background-color $highlight
color $white
/* Works in Opera */
::-o-selection
background-color $highlight
color $white
::-ms-selection
background-color $highlight
color $white
/* Works in Internet Explorer */
::-webkit-selection
background-color $highlight
color $white
/**
-------------------------------
-- Responsive
-------------------------------
* */
@media only screen and (max-width: 800px)
.main-container
section
header
#wrapper
#left, #right
display inline-block
@media only screen and (max-width: 480px)
.main-container
section
header
#wrapper
#left
width 30%
#right
width 70%

@ -1,119 +0,0 @@
@font-face
font-weight 300
font-style normal
font-family 'Apercu'
src url('fonts/Apercu-Light.eot'),
url('fonts/Apercu-Light.eot?#iefix') format('embedded-opentype'),
url('fonts/Apercu-Light.woff2') format('woff2'),
url('fonts/Apercu-Light.woff') format('woff'),
url('fonts/Apercu-Light.ttf') format('truetype'),
url('fonts/Apercu-Light.svg?#Apercu') format('svg')
@font-face
font-weight 300
font-style italic
font-family 'Apercu'
src url('fonts/Apercu-LightItalic.eot'),
url('fonts/Apercu-LightItalic.eot?#iefix') format('embedded-opentype'),
url('fonts/Apercu-LightItalic.woff2') format('woff2'),
url('fonts/Apercu-LightItalic.woff') format('woff'),
url('fonts/Apercu-LightItalic.ttf') format('truetype'),
url('fonts/Apercu-LightItalic.svg?#Apercu') format('svg')
@font-face
font-weight 400
font-style normal
font-family 'Apercu'
src url('fonts/Apercu.eot'),
url('fonts/Apercu.eot?#iefix') format('embedded-opentype'),
url('fonts/Apercu.woff2') format('woff2'),
url('fonts/Apercu.woff') format('woff'),
url('fonts/Apercu.ttf') format('truetype'),
url('fonts/Apercu.svg?#Apercu') format('svg')
@font-face
font-weight 400
font-style italic
font-family 'Apercu'
src url('fonts/Apercu-Italic.eot'),
url('fonts/Apercu-Italic.eot?#iefix') format('embedded-opentype'),
url('fonts/Apercu-Italic.woff2') format('woff2'),
url('fonts/Apercu-Italic.woff') format('woff'),
url('fonts/Apercu-Italic.ttf') format('truetype'),
url('fonts/Apercu-Italic.svg?#Apercu') format('svg')
@font-face
font-weight 500
font-style normal
font-family 'Apercu'
src url('fonts/Apercu-Medium.eot'),
url('fonts/Apercu-Medium.eot?#iefix') format('embedded-opentype'),
url('fonts/Apercu-Medium.woff2') format('woff2'),
url('fonts/Apercu-Medium.woff') format('woff'),
url('fonts/Apercu-Medium.ttf') format('truetype'),
url('fonts/Apercu-Medium.svg?#Apercu') format('svg')
@font-face
font-weight 500
font-style italic
font-family 'Apercu'
src url('fonts/Apercu-MediumItalic.eot'),
url('fonts/Apercu-MediumItalic.eot?#iefix') format('embedded-opentype'),
url('fonts/Apercu-MediumItalic.woff2') format('woff2'),
url('fonts/Apercu-MediumItalic.woff') format('woff'),
url('fonts/Apercu-MediumItalic.ttf') format('truetype'),
url('fonts/Apercu-MediumItalic.svg?#Apercu') format('svg')
@font-face
font-weight 600
font-style normal
font-weight bold
font-family 'Apercu'
src url('fonts/Apercu-Bold.eot'),
url('fonts/Apercu-Bold.eot?#iefix') format('embedded-opentype'),
url('fonts/Apercu-Bold.woff2') format('woff2'),
url('fonts/Apercu-Bold.woff') format('woff'),
url('fonts/Apercu-Bold.ttf') format('truetype'),
url('fonts/Apercu-Bold.svg?#Apercu') format('svg')
@font-face
font-weight 600
font-style italic
font-weight bold
font-family 'Apercu'
src url('fonts/Apercu-BoldItalic.eot'),
url('fonts/Apercu-BoldItalic.eot?#iefix') format('embedded-opentype'),
url('fonts/Apercu-BoldItalic.woff2') format('woff2'),
url('fonts/Apercu-BoldItalic.woff') format('woff'),
url('fonts/Apercu-BoldItalic.ttf') format('truetype'),
url('fonts/Apercu-Bold.svg?#Apercu') format('svg')
@font-face
font-weight 400
font-style normal
font-family 'Apercu-Mono'
src url('fonts/Apercu-Mono.eot'),
url('fonts/Apercu-Mono.eot?#iefix') format('embedded-opentype'),
url('fonts/Apercu-Mono.woff2') format('woff2'),
url('fonts/Apercu-Mono.woff') format('woff'),
url('fonts/Apercu-Mono.ttf') format('truetype'),
url('fonts/Apercu-Mono.svg?#Apercu') format('svg')
$baseType = Helvetica, Arial, sans-serif;
$monoType = 'Andale Mono'
h1, h2, h3
color $white
h1
font-size 2em
font-weight 400
h2
font-size 1.75em
font-weight 400
h3
font-size 1.5em
font-weight 300
Loading…
Cancel
Save