Added alerts functionality + modal UI

This commit is contained in:
NGPixel 2016-08-23 21:09:09 -04:00
parent aa740dea7a
commit 52c9821189
13 changed files with 206 additions and 14 deletions

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
"use strict";jQuery(document).ready(function(e){e("a").smoothScroll({speed:400,offset:-20});new Sticky(".stickyscroll")}); "use strict";function _classCallCheck(e,s){if(!(e instanceof s))throw new TypeError("Cannot call a class as a function")}var _createClass=function(){function e(e,s){for(var t=0;t<s.length;t++){var n=s[t];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(s,t,n){return t&&e(s.prototype,t),n&&e(s,n),s}}(),Alerts=function(){function e(){_classCallCheck(this,e);var s=this;s.mdl=new Vue({el:"#alerts",data:{children:[]},methods:{acknowledge:function(e){s.close(e)}}}),s.uidNext=1}return _createClass(e,[{key:"push",value:function(e){var s=this,t=_.defaults(e,{_uid:s.uidNext,class:"is-info",message:"---",sticky:!1,title:"---"});s.mdl.children.push(t),t.sticky||_.delay(function(){s.close(t._uid)},5e3),s.uidNext++}},{key:"pushError",value:function(e,s){this.push({class:"is-danger",message:s,sticky:!1,title:e})}},{key:"pushSuccess",value:function(e,s){this.push({class:"is-success",message:s,sticky:!1,title:e})}},{key:"close",value:function(e){var s=this,t=_.findIndex(s.mdl.children,["_uid",e]),n=_.nth(s.mdl.children,t);t>=0&&n&&(n.class+=" exit",s.mdl.children.$set(t,n),_.delay(function(){s.mdl.children.$remove(n)},500))}}]),e}();jQuery(document).ready(function(e){e("a").smoothScroll({speed:400,offset:-20});var s=(new Sticky(".stickyscroll"),new Alerts);alertsData&&_.forEach(alertsData,function(e){s.push(e)})});

View File

@ -9,4 +9,11 @@ jQuery( document ).ready(function( $ ) {
var sticky = new Sticky('.stickyscroll'); var sticky = new Sticky('.stickyscroll');
var alerts = new Alerts();
if(alertsData) {
_.forEach(alertsData, (alertRow) => {
alerts.push(alertRow);
});
}
}); });

View File

@ -0,0 +1,115 @@
"use strict";
/**
* Alerts
*/
class Alerts {
/**
* Constructor
*
* @class
*/
constructor() {
let self = this;
self.mdl = new Vue({
el: '#alerts',
data: {
children: []
},
methods: {
acknowledge: (uid) => {
self.close(uid);
}
}
});
self.uidNext = 1;
}
/**
* Show a new Alert
*
* @param {Object} options Alert properties
* @return {null} Void
*/
push(options) {
let self = this;
let nAlert = _.defaults(options, {
_uid: self.uidNext,
class: 'is-info',
message: '---',
sticky: false,
title: '---'
});
self.mdl.children.push(nAlert);
if(!nAlert.sticky) {
_.delay(() => {
self.close(nAlert._uid);
}, 5000);
}
self.uidNext++;
}
/**
* Shorthand method for pushing errors
*
* @param {String} title The title
* @param {String} message The message
*/
pushError(title, message) {
this.push({
class: 'is-danger',
message,
sticky: false,
title
});
}
/**
* Shorthand method for pushing success messages
*
* @param {String} title The title
* @param {String} message The message
*/
pushSuccess(title, message) {
this.push({
class: 'is-success',
message,
sticky: false,
title
});
}
/**
* Close an alert
*
* @param {Integer} uid The unique ID of the alert
*/
close(uid) {
let self = this;
let nAlertIdx = _.findIndex(self.mdl.children, ['_uid', uid]);
let nAlert = _.nth(self.mdl.children, nAlertIdx);
if(nAlertIdx >= 0 && nAlert) {
nAlert.class += ' exit';
self.mdl.children.$set(nAlertIdx, nAlert);
_.delay(() => {
self.mdl.children.$remove(nAlert);
}, 500);
}
}
}

View File

@ -5,6 +5,9 @@ $warning: #f68b39;
@import 'bulma'; @import 'bulma';
@import './libs/twemoji-awesome'; @import './libs/twemoji-awesome';
@import './libs/animate.min.css';
@import './components/_alerts';
@import './layout/_header'; @import './layout/_header';
@import './layout/_footer'; @import './layout/_footer';

View File

@ -0,0 +1,24 @@
#alerts {
position: fixed;
top: 60px;
right: 10px;
width: 350px;
z-index: 2;
text-shadow: 1px 1px 0 rgba(0,0,0,0.1);
.notification {
animation: 0.5s ease slideInRight;
margin-top: 5px;
&.exit {
animation: 0.5s ease fadeOutRight;
}
}
h3 {
font-size: 16px;
font-size: 500;
}
}

View File

@ -71,6 +71,16 @@ p code {
border-radius: 4px; border-radius: 4px;
} }
.modal {
align-items: flex-start;
}
.modal-background {
animation: 0.4s ease fadeIn;
}
.modal-content {
animation: 0.4s ease slideInDown;
}
.card-header { .card-header {
background-color: $turquoise; background-color: $turquoise;
} }
@ -81,3 +91,7 @@ p code {
font-size: 16px; font-size: 16px;
padding: 10px 20px; padding: 10px 20px;
} }
.modal-content .card-footer-item {
font-weight: 500;
}

11
client/scss/libs/animate.min.css vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -15,7 +15,7 @@ router.get('/', (req, res) => {
let pageData = mark.parse(contents); let pageData = mark.parse(contents);
if(!pageData.title) { if(!pageData.title) {
pageData.title = 'Redis'; pageData.title = 'Redis';
pageData.subtitle = 'An open source, in-memory data structure store, used as database, cache and message broker.' pageData.subtitle = 'An open source, in-memory data structure store, used as database, cache and message broker.';
} }
res.render('pages/view', { pageData }); res.render('pages/view', { pageData });
}); });

View File

@ -103,7 +103,7 @@ gulp.task("scripts-app", function () {
.pipe(babel()) .pipe(babel())
.pipe(uglify()) .pipe(uglify())
.pipe(plumber.stop()) .pipe(plumber.stop())
.pipe(gulp.dest("./assets/js")) .pipe(gulp.dest("./assets/js"));
}); });

View File

@ -21,11 +21,13 @@ var mkdown = md({
html: true, html: true,
linkify: true, linkify: true,
typography: true, typography: true,
highlight: function (str, lang) { highlight(str, lang) {
if (lang && hljs.getLanguage(lang)) { if (lang && hljs.getLanguage(lang)) {
try { try {
return '<pre class="hljs"><code>' + hljs.highlight(lang, str, true).value + '</code></pre>'; return '<pre class="hljs"><code>' + hljs.highlight(lang, str, true).value + '</code></pre>';
} catch (__) {} } catch (err) {
return '<pre><code>' + str + '</code></pre>';
}
} }
return '<pre class="hljs"><code>' + hljs.highlightAuto(str).value + '</code></pre>'; return '<pre class="hljs"><code>' + hljs.highlightAuto(str).value + '</code></pre>';
} }
@ -72,17 +74,17 @@ const parseTree = (content) => {
for (let i = 0; i < tokens.length; i++) { for (let i = 0; i < tokens.length; i++) {
if (tokens[i].type !== "heading_close") { if (tokens[i].type !== "heading_close") {
continue continue;
} }
const heading = tokens[i - 1] const heading = tokens[i - 1];
const heading_close = tokens[i] const heading_close = tokens[i];
if (heading.type === "inline") { if (heading.type === "inline") {
let content = ""; let content = "";
let anchor = ""; let anchor = "";
if (heading.children && heading.children[0].type === "link_open") { if (heading.children && heading.children[0].type === "link_open") {
content = heading.children[1].content content = heading.children[1].content;
anchor = slug(content, {lower: true}); anchor = slug(content, {lower: true});
} else { } else {
content = heading.content content = heading.content
@ -93,7 +95,7 @@ const parseTree = (content) => {
content, content,
anchor, anchor,
level: +heading_close.tag.substr(1, 1) level: +heading_close.tag.substr(1, 1)
}) });
} }
} }

View File

@ -35,14 +35,14 @@
"bluebird": "^3.4.1", "bluebird": "^3.4.1",
"body-parser": "^1.15.2", "body-parser": "^1.15.2",
"bulma": "^0.1.2", "bulma": "^0.1.2",
"cheerio": "^0.20.0", "cheerio": "^0.22.0",
"compression": "^1.6.2", "compression": "^1.6.2",
"connect-flash": "^0.1.1", "connect-flash": "^0.1.1",
"connect-loki": "^1.0.5", "connect-loki": "^1.0.6",
"connect-redis": "^3.1.0", "connect-redis": "^3.1.0",
"cookie-parser": "^1.4.3", "cookie-parser": "^1.4.3",
"express": "^4.14.0", "express": "^4.14.0",
"express-brute": "^0.7.0-beta.0", "express-brute": "^1.0.0",
"express-session": "^1.14.0", "express-session": "^1.14.0",
"express-validator": "^2.20.8", "express-validator": "^2.20.8",
"highlight.js": "^9.6.0", "highlight.js": "^9.6.0",

View File

@ -0,0 +1,16 @@
#alerts
ul
template(v-for="aItem in children", track-by='_uid')
.notification(v-bind:class='aItem.class')
button.delete(v-on:click='acknowledge(aItem._uid)')
h3 {{ aItem.title }}
span {{ aItem.message }}
if appflash.length > 0
script(type='text/javascript')
| var alertsData =
!= JSON.stringify(appflash)
| ;
else
script(type='text/javascript')
| var alertsData = [];