Merged core back into main project
This commit is contained in:
parent
67bd4acdeb
commit
1ced194cd2
@ -26,7 +26,6 @@
|
||||
"winston": true,
|
||||
"ws": true,
|
||||
"Mongoose": true,
|
||||
"CORE_PATH": true,
|
||||
"ROOTPATH": true,
|
||||
"IS_DEBUG": true,
|
||||
"PROCNAME": true
|
||||
|
14
agent.js
14
agent.js
@ -7,17 +7,16 @@
|
||||
global.PROCNAME = 'AGENT'
|
||||
global.ROOTPATH = __dirname
|
||||
global.IS_DEBUG = process.env.NODE_ENV === 'development'
|
||||
if (IS_DEBUG) {
|
||||
global.CORE_PATH = ROOTPATH + '/../core/'
|
||||
} else {
|
||||
global.CORE_PATH = ROOTPATH + '/node_modules/requarks-core/'
|
||||
}
|
||||
|
||||
let appconf = require('./libs/config')()
|
||||
global.appconfig = appconf.config
|
||||
global.appdata = appconf.data
|
||||
|
||||
// ----------------------------------------
|
||||
// Load Winston
|
||||
// ----------------------------------------
|
||||
|
||||
global.winston = require(CORE_PATH + 'core-libs/winston')(IS_DEBUG)
|
||||
global.winston = require('./libs/logger')(IS_DEBUG)
|
||||
|
||||
// ----------------------------------------
|
||||
// Load global modules
|
||||
@ -25,9 +24,6 @@ global.winston = require(CORE_PATH + 'core-libs/winston')(IS_DEBUG)
|
||||
|
||||
winston.info('[AGENT] Background Agent is initializing...')
|
||||
|
||||
let appconf = require(CORE_PATH + 'core-libs/config')()
|
||||
global.appconfig = appconf.config
|
||||
global.appdata = appconf.data
|
||||
global.db = require('./libs/db').init()
|
||||
global.upl = require('./libs/uploads-agent').init()
|
||||
global.git = require('./libs/git').init()
|
||||
|
@ -1,31 +1,38 @@
|
||||
@charset "utf-8";
|
||||
|
||||
$primary: 'indigo';
|
||||
|
||||
@import 'core-client/scss/core';
|
||||
@import 'core-client/scss/components/alert';
|
||||
@import 'core-client/scss/components/button';
|
||||
@import 'core-client/scss/components/footer';
|
||||
@import 'core-client/scss/components/form';
|
||||
@import 'core-client/scss/components/grid';
|
||||
@import 'core-client/scss/components/hero';
|
||||
@import 'core-client/scss/components/markdown-content';
|
||||
@import 'core-client/scss/components/modal';
|
||||
@import 'core-client/scss/components/nav';
|
||||
@import 'core-client/scss/components/panel';
|
||||
@import 'core-client/scss/components/search';
|
||||
@import 'core-client/scss/components/sidebar';
|
||||
@import 'core-client/scss/components/table';
|
||||
@import 'core-client/scss/components/typography';
|
||||
@import "base/variables";
|
||||
@import "base/colors";
|
||||
@import "base/reset";
|
||||
@import "base/mixins";
|
||||
@import "base/fonts";
|
||||
@import "base/base";
|
||||
|
||||
@import './libs/twemoji-awesome';
|
||||
@import './libs/jquery-contextmenu';
|
||||
@import "libs/animate";
|
||||
|
||||
@import 'components/alert';
|
||||
@import 'components/button';
|
||||
@import 'components/footer';
|
||||
@import 'components/form';
|
||||
@import 'components/grid';
|
||||
@import 'components/hero';
|
||||
@import 'components/markdown-content';
|
||||
@import 'components/modal';
|
||||
@import 'components/nav';
|
||||
@import 'components/panel';
|
||||
@import 'components/search';
|
||||
@import 'components/sidebar';
|
||||
@import 'components/table';
|
||||
@import 'components/typography';
|
||||
|
||||
@import 'libs/twemoji-awesome';
|
||||
@import 'libs/jquery-contextmenu';
|
||||
@import 'node_modules/highlight.js/styles/tomorrow';
|
||||
@import 'node_modules/simplemde/dist/simplemde.min';
|
||||
|
||||
@import './components/_editor';
|
||||
@import 'components/_editor';
|
||||
|
||||
@import './layout/_header';
|
||||
//@import './layout/_content';
|
||||
@import 'layout/_header';
|
||||
|
||||
//@import './pages/_account';
|
||||
@import './pages/_welcome';
|
||||
@import 'pages/_welcome';
|
||||
|
107
client/scss/base/base.scss
Normal file
107
client/scss/base/base.scss
Normal file
@ -0,0 +1,107 @@
|
||||
html {
|
||||
box-sizing: border-box;
|
||||
font-family: $core-font-standard;
|
||||
}
|
||||
*, *:before, *:after {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
[v-cloak], .is-hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: mc('blue-grey','100');
|
||||
}
|
||||
|
||||
main {
|
||||
background-color: #FFF;
|
||||
}
|
||||
|
||||
a {
|
||||
color: mc('indigo', '600');
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
color: mc('indigo', '700');
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
// Container
|
||||
|
||||
.has-stickynav {
|
||||
padding-top: 50px;
|
||||
}
|
||||
|
||||
.container {
|
||||
position: relative;
|
||||
|
||||
@include desktop {
|
||||
margin: 0 auto;
|
||||
max-width: 960px;
|
||||
|
||||
// Modifiers
|
||||
&.is-fluid {
|
||||
margin: 0;
|
||||
max-width: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@include widescreen {
|
||||
max-width: 1200px;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
// Visibility
|
||||
|
||||
.is-hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.is-hidden-mobile {
|
||||
@include mobile {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.is-hidden-tablet {
|
||||
@include tablet {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.is-hidden-tablet-only {
|
||||
@include tablet-only {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.is-hidden-touch {
|
||||
@include touch {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.is-hidden-desktop {
|
||||
@include desktop {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.is-hidden-desktop-only {
|
||||
@include desktop-only {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.is-hidden-widescreen {
|
||||
@include widescreen {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
327
client/scss/base/colors.scss
Normal file
327
client/scss/base/colors.scss
Normal file
@ -0,0 +1,327 @@
|
||||
$material-colors: (
|
||||
'red': (
|
||||
'50': #ffebee,
|
||||
'100': #ffcdd2,
|
||||
'200': #ef9a9a,
|
||||
'300': #e57373,
|
||||
'400': #ef5350,
|
||||
'500': #f44336,
|
||||
'600': #e53935,
|
||||
'700': #d32f2f,
|
||||
'800': #c62828,
|
||||
'900': #b71c1c,
|
||||
'a100': #ff8a80,
|
||||
'a200': #ff5252,
|
||||
'a400': #ff1744,
|
||||
'a700': #d50000
|
||||
),
|
||||
|
||||
'pink': (
|
||||
'50': #fce4ec,
|
||||
'100': #f8bbd0,
|
||||
'200': #f48fb1,
|
||||
'300': #f06292,
|
||||
'400': #ec407a,
|
||||
'500': #e91e63,
|
||||
'600': #d81b60,
|
||||
'700': #c2185b,
|
||||
'800': #ad1457,
|
||||
'900': #880e4f,
|
||||
'a100': #ff80ab,
|
||||
'a200': #ff4081,
|
||||
'a400': #f50057,
|
||||
'a700': #c51162
|
||||
),
|
||||
|
||||
'purple': (
|
||||
'50': #f3e5f5,
|
||||
'100': #e1bee7,
|
||||
'200': #ce93d8,
|
||||
'300': #ba68c8,
|
||||
'400': #ab47bc,
|
||||
'500': #9c27b0,
|
||||
'600': #8e24aa,
|
||||
'700': #7b1fa2,
|
||||
'800': #6a1b9a,
|
||||
'900': #4a148c,
|
||||
'a100': #ea80fc,
|
||||
'a200': #e040fb,
|
||||
'a400': #d500f9,
|
||||
'a700': #aa00ff
|
||||
),
|
||||
|
||||
'deep-purple': (
|
||||
'50': #ede7f6,
|
||||
'100': #d1c4e9,
|
||||
'200': #b39ddb,
|
||||
'300': #9575cd,
|
||||
'400': #7e57c2,
|
||||
'500': #673ab7,
|
||||
'600': #5e35b1,
|
||||
'700': #512da8,
|
||||
'800': #4527a0,
|
||||
'900': #311b92,
|
||||
'a100': #b388ff,
|
||||
'a200': #7c4dff,
|
||||
'a400': #651fff,
|
||||
'a700': #6200ea
|
||||
),
|
||||
|
||||
'indigo': (
|
||||
'50': #e8eaf6,
|
||||
'100': #c5cae9,
|
||||
'200': #9fa8da,
|
||||
'300': #7986cb,
|
||||
'400': #5c6bc0,
|
||||
'500': #3f51b5,
|
||||
'600': #3949ab,
|
||||
'700': #303f9f,
|
||||
'800': #283593,
|
||||
'900': #1a237e,
|
||||
'a100': #8c9eff,
|
||||
'a200': #536dfe,
|
||||
'a400': #3d5afe,
|
||||
'a700': #304ffe
|
||||
),
|
||||
|
||||
'blue': (
|
||||
'50': #e3f2fd,
|
||||
'100': #bbdefb,
|
||||
'200': #90caf9,
|
||||
'300': #64b5f6,
|
||||
'400': #42a5f5,
|
||||
'500': #2196f3,
|
||||
'600': #1e88e5,
|
||||
'700': #1976d2,
|
||||
'800': #1565c0,
|
||||
'900': #0d47a1,
|
||||
'a100': #82b1ff,
|
||||
'a200': #448aff,
|
||||
'a400': #2979ff,
|
||||
'a700': #2962ff
|
||||
),
|
||||
|
||||
'light-blue': (
|
||||
'50': #e1f5fe,
|
||||
'100': #b3e5fc,
|
||||
'200': #81d4fa,
|
||||
'300': #4fc3f7,
|
||||
'400': #29b6f6,
|
||||
'500': #03a9f4,
|
||||
'600': #039be5,
|
||||
'700': #0288d1,
|
||||
'800': #0277bd,
|
||||
'900': #01579b,
|
||||
'a100': #80d8ff,
|
||||
'a200': #40c4ff,
|
||||
'a400': #00b0ff,
|
||||
'a700': #0091ea
|
||||
),
|
||||
|
||||
'cyan': (
|
||||
'50': #e0f7fa,
|
||||
'100': #b2ebf2,
|
||||
'200': #80deea,
|
||||
'300': #4dd0e1,
|
||||
'400': #26c6da,
|
||||
'500': #00bcd4,
|
||||
'600': #00acc1,
|
||||
'700': #0097a7,
|
||||
'800': #00838f,
|
||||
'900': #006064,
|
||||
'a100': #84ffff,
|
||||
'a200': #18ffff,
|
||||
'a400': #00e5ff,
|
||||
'a700': #00b8d4
|
||||
),
|
||||
|
||||
'teal': (
|
||||
'50': #e0f2f1,
|
||||
'100': #b2dfdb,
|
||||
'200': #80cbc4,
|
||||
'300': #4db6ac,
|
||||
'400': #26a69a,
|
||||
'500': #009688,
|
||||
'600': #00897b,
|
||||
'700': #00796b,
|
||||
'800': #00695c,
|
||||
'900': #004d40,
|
||||
'a100': #a7ffeb,
|
||||
'a200': #64ffda,
|
||||
'a400': #1de9b6,
|
||||
'a700': #00bfa5
|
||||
),
|
||||
|
||||
'green': (
|
||||
'50': #e8f5e9,
|
||||
'100': #c8e6c9,
|
||||
'200': #a5d6a7,
|
||||
'300': #81c784,
|
||||
'400': #66bb6a,
|
||||
'500': #4caf50,
|
||||
'600': #43a047,
|
||||
'700': #388e3c,
|
||||
'800': #2e7d32,
|
||||
'900': #1b5e20,
|
||||
'a100': #b9f6ca,
|
||||
'a200': #69f0ae,
|
||||
'a400': #00e676,
|
||||
'a700': #00c853
|
||||
),
|
||||
|
||||
'light-green': (
|
||||
'50': #f1f8e9,
|
||||
'100': #dcedc8,
|
||||
'200': #c5e1a5,
|
||||
'300': #aed581,
|
||||
'400': #9ccc65,
|
||||
'500': #8bc34a,
|
||||
'600': #7cb342,
|
||||
'700': #689f38,
|
||||
'800': #558b2f,
|
||||
'900': #33691e,
|
||||
'a100': #ccff90,
|
||||
'a200': #b2ff59,
|
||||
'a400': #76ff03,
|
||||
'a700': #64dd17
|
||||
),
|
||||
|
||||
'lime': (
|
||||
'50': #f9fbe7,
|
||||
'100': #f0f4c3,
|
||||
'200': #e6ee9c,
|
||||
'300': #dce775,
|
||||
'400': #d4e157,
|
||||
'500': #cddc39,
|
||||
'600': #c0ca33,
|
||||
'700': #afb42b,
|
||||
'800': #9e9d24,
|
||||
'900': #827717,
|
||||
'a100': #f4ff81,
|
||||
'a200': #eeff41,
|
||||
'a400': #c6ff00,
|
||||
'a700': #aeea00
|
||||
),
|
||||
|
||||
'yellow': (
|
||||
'50': #fffde7,
|
||||
'100': #fff9c4,
|
||||
'200': #fff59d,
|
||||
'300': #fff176,
|
||||
'400': #ffee58,
|
||||
'500': #ffeb3b,
|
||||
'600': #fdd835,
|
||||
'700': #fbc02d,
|
||||
'800': #f9a825,
|
||||
'900': #f57f17,
|
||||
'a100': #ffff8d,
|
||||
'a200': #ffff00,
|
||||
'a400': #ffea00,
|
||||
'a700': #ffd600
|
||||
),
|
||||
|
||||
'amber': (
|
||||
'50': #fff8e1,
|
||||
'100': #ffecb3,
|
||||
'200': #ffe082,
|
||||
'300': #ffd54f,
|
||||
'400': #ffca28,
|
||||
'500': #ffc107,
|
||||
'600': #ffb300,
|
||||
'700': #ffa000,
|
||||
'800': #ff8f00,
|
||||
'900': #ff6f00,
|
||||
'a100': #ffe57f,
|
||||
'a200': #ffd740,
|
||||
'a400': #ffc400,
|
||||
'a700': #ffab00
|
||||
),
|
||||
|
||||
'orange': (
|
||||
'50': #fff3e0,
|
||||
'100': #ffe0b2,
|
||||
'200': #ffcc80,
|
||||
'300': #ffb74d,
|
||||
'400': #ffa726,
|
||||
'500': #ff9800,
|
||||
'600': #fb8c00,
|
||||
'700': #f57c00,
|
||||
'800': #ef6c00,
|
||||
'900': #e65100,
|
||||
'a100': #ffd180,
|
||||
'a200': #ffab40,
|
||||
'a400': #ff9100,
|
||||
'a700': #ff6d00
|
||||
),
|
||||
|
||||
'deep-orange': (
|
||||
'50': #fbe9e7,
|
||||
'100': #ffccbc,
|
||||
'200': #ffab91,
|
||||
'300': #ff8a65,
|
||||
'400': #ff7043,
|
||||
'500': #ff5722,
|
||||
'600': #f4511e,
|
||||
'700': #e64a19,
|
||||
'800': #d84315,
|
||||
'900': #bf360c,
|
||||
'a100': #ff9e80,
|
||||
'a200': #ff6e40,
|
||||
'a400': #ff3d00,
|
||||
'a700': #dd2c00
|
||||
),
|
||||
|
||||
'brown': (
|
||||
'50': #efebe9,
|
||||
'100': #d7ccc8,
|
||||
'200': #bcaaa4,
|
||||
'300': #a1887f,
|
||||
'400': #8d6e63,
|
||||
'500': #795548,
|
||||
'600': #6d4c41,
|
||||
'700': #5d4037,
|
||||
'800': #4e342e,
|
||||
'900': #3e2723
|
||||
),
|
||||
|
||||
'grey': (
|
||||
'50': #fafafa,
|
||||
'100': #f5f5f5,
|
||||
'200': #eeeeee,
|
||||
'300': #e0e0e0,
|
||||
'400': #bdbdbd,
|
||||
'500': #9e9e9e,
|
||||
'600': #757575,
|
||||
'700': #616161,
|
||||
'800': #424242,
|
||||
'900': #212121
|
||||
),
|
||||
|
||||
'blue-grey': (
|
||||
'50': #eceff1,
|
||||
'100': #cfd8dc,
|
||||
'200': #b0bec5,
|
||||
'300': #90a4ae,
|
||||
'400': #78909c,
|
||||
'500': #607d8b,
|
||||
'600': #546e7a,
|
||||
'700': #455a64,
|
||||
'800': #37474f,
|
||||
'900': #263238,
|
||||
'1000': #11171a
|
||||
)
|
||||
);
|
||||
|
||||
@function material-color($color-name, $color-variant: '500') {
|
||||
$color: map-get(map-get($material-colors, $color-name),$color-variant);
|
||||
@if $color {
|
||||
@return $color;
|
||||
} @else {
|
||||
// Libsass still doesn't seem to support @error
|
||||
@warn "=> ERROR: COLOR NOT FOUND! <= | Your $color-name, $color-variant combination did not match any of the values in the $material-colors map.";
|
||||
}
|
||||
}
|
||||
|
||||
@function mc($color-name, $color-variant: '500') {
|
||||
@return material-color($color-name, $color-variant);
|
||||
}
|
2027
client/scss/base/fonts.scss
Normal file
2027
client/scss/base/fonts.scss
Normal file
File diff suppressed because it is too large
Load Diff
142
client/scss/base/mixins.scss
Normal file
142
client/scss/base/mixins.scss
Normal file
@ -0,0 +1,142 @@
|
||||
/**
|
||||
* Clearfix
|
||||
*
|
||||
* @return {string} Clearfix attribute
|
||||
*/
|
||||
@mixin clearfix {
|
||||
&:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Placeholder attribute for inputs
|
||||
*
|
||||
* @return {string} Placeholder attributes
|
||||
*/
|
||||
@mixin placeholder {
|
||||
&::-webkit-input-placeholder {@content};
|
||||
&::-moz-placeholder {@content}
|
||||
&:-ms-input-placeholder {@content}
|
||||
&:placeholder-shown {@content};
|
||||
}
|
||||
|
||||
/**
|
||||
* Spinner element
|
||||
*
|
||||
* @param {string} $color - Color
|
||||
* @param {string} $dur - Animation Duration
|
||||
* @param {int} $width - Width
|
||||
* @param {int} $height [$width] - height
|
||||
*
|
||||
* @return {string} Spinner element
|
||||
*/
|
||||
@mixin spinner($color,$dur,$width,$height:$width) {
|
||||
width: $width;
|
||||
height: $height;
|
||||
border-radius: 50%;
|
||||
box-shadow:0 0 0 1px rgba(0,0,0,0.1), 2px 1px 0 $color;
|
||||
@include prefix(animation, spin $dur linear infinite);
|
||||
@include keyframes(spin) {
|
||||
100%{
|
||||
@include prefix(transform, rotate(360deg));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefixes for keyframes
|
||||
*
|
||||
* @param {string} $animation-name - The animation name
|
||||
*
|
||||
* @return {string} Prefixed keyframes attributes
|
||||
*/
|
||||
@mixin keyframes($animation-name) {
|
||||
@-webkit-keyframes #{$animation-name} {
|
||||
@content;
|
||||
}
|
||||
@-moz-keyframes #{$animation-name} {
|
||||
@content;
|
||||
}
|
||||
@-o-keyframes #{$animation-name} {
|
||||
@content;
|
||||
}
|
||||
@keyframes #{$animation-name} {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefix function for browser compatibility
|
||||
*
|
||||
* @param {string} $property - Property name
|
||||
* @param {any} $value - Property value
|
||||
*
|
||||
* @return {string} Prefixed attributes
|
||||
*/
|
||||
@mixin prefix($property, $value) {
|
||||
-webkit-#{$property}: #{$value};
|
||||
-moz-#{$property}: #{$value};
|
||||
-ms-#{$property}: #{$value};
|
||||
-o-#{$property}: #{$value};
|
||||
#{$property}: #{$value};
|
||||
}
|
||||
|
||||
/**
|
||||
* Layout Mixins
|
||||
*/
|
||||
@mixin from($device) {
|
||||
@media screen and (min-width: $device) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin until($device) {
|
||||
@media screen and (max-width: $device - 1px) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin mobile {
|
||||
@media screen and (max-width: $tablet - 1px) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin tablet {
|
||||
@media screen and (min-width: $tablet) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin tablet-only {
|
||||
@media screen and (min-width: $tablet) and (max-width: $desktop - 1px) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin touch {
|
||||
@media screen and (max-width: $desktop - 1px) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin desktop {
|
||||
@media screen and (min-width: $desktop) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin desktop-only {
|
||||
@media screen and (min-width: $desktop) and (max-width: $widescreen - 1px) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin widescreen {
|
||||
@media screen and (min-width: $widescreen) {
|
||||
@content;
|
||||
}
|
||||
}
|
138
client/scss/base/reset.scss
Normal file
138
client/scss/base/reset.scss
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
HTML5 Reset :: style.css
|
||||
----------------------------------------------------------
|
||||
We have learned much from/been inspired by/taken code where offered from:
|
||||
Eric Meyer :: http://meyerweb.com
|
||||
HTML5 Doctor :: http://html5doctor.com
|
||||
and the HTML5 Boilerplate :: http://html5boilerplate.com
|
||||
-------------------------------------------------------------------------------*/
|
||||
|
||||
/* Let's default this puppy out
|
||||
-------------------------------------------------------------------------------*/
|
||||
|
||||
html, body, body div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp, small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, figure, footer, header, menu, nav, section, time, mark, audio, video, details, summary {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
font-size: 100%;
|
||||
font-weight: normal;
|
||||
vertical-align: baseline;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
main, article, aside, figure, footer, header, nav, section, details, summary {display: block;}
|
||||
|
||||
/* Handle box-sizing while better addressing child elements:
|
||||
http://css-tricks.com/inheriting-box-sizing-probably-slightly-better-best-practice/ */
|
||||
html {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
*,
|
||||
*:before,
|
||||
*:after {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
/* consider resetting the default cursor: https://gist.github.com/murtaugh/5247154 */
|
||||
|
||||
/* Responsive images and other embedded objects */
|
||||
/* if you don't have full control over `img` tags (if you have to overcome attributes), consider adding height: auto */
|
||||
img,
|
||||
object,
|
||||
embed {max-width: 100%;}
|
||||
|
||||
/*
|
||||
Note: keeping IMG here will cause problems if you're using foreground images as sprites.
|
||||
In fact, it *will* cause problems with Google Maps' controls at small size.
|
||||
If this is the case for you, try uncommenting the following:
|
||||
#map img {
|
||||
max-width: none;
|
||||
}
|
||||
*/
|
||||
|
||||
/* force a vertical scrollbar to prevent a jumpy page */
|
||||
html {overflow-y: scroll;}
|
||||
|
||||
/* we use a lot of ULs that aren't bulleted.
|
||||
you'll have to restore the bullets within content,
|
||||
which is fine because they're probably customized anyway */
|
||||
ul {list-style: none;}
|
||||
|
||||
blockquote, q {quotes: none;}
|
||||
|
||||
blockquote:before,
|
||||
blockquote:after,
|
||||
q:before,
|
||||
q:after {content: ''; content: none;}
|
||||
|
||||
a {margin: 0; padding: 0; font-size: 100%; vertical-align: baseline; background: transparent;}
|
||||
|
||||
del {text-decoration: line-through;}
|
||||
|
||||
abbr[title], dfn[title] {border-bottom: 1px dotted #000; cursor: help;}
|
||||
|
||||
/* tables still need cellspacing="0" in the markup */
|
||||
table {border-collapse: separate; border-spacing: 0;}
|
||||
th {font-weight: bold; vertical-align: bottom;}
|
||||
td {font-weight: normal; vertical-align: top;}
|
||||
|
||||
hr {display: block; height: 1px; border: 0; border-top: 1px solid #ccc; margin: 1em 0; padding: 0;}
|
||||
|
||||
input, select {vertical-align: middle;}
|
||||
|
||||
pre {
|
||||
white-space: pre; /* CSS2 */
|
||||
white-space: pre-wrap; /* CSS 2.1 */
|
||||
white-space: pre-line; /* CSS 3 (and 2.1 as well, actually) */
|
||||
word-wrap: break-word; /* IE */
|
||||
}
|
||||
|
||||
input[type="radio"] {vertical-align: text-bottom;}
|
||||
input[type="checkbox"] {vertical-align: bottom;}
|
||||
.ie7 input[type="checkbox"] {vertical-align: baseline;}
|
||||
.ie6 input {vertical-align: text-bottom;}
|
||||
|
||||
select, input, textarea {font: 99% sans-serif;}
|
||||
|
||||
table {font-size: inherit; font: 100%;}
|
||||
|
||||
small {font-size: 85%;}
|
||||
|
||||
strong {font-weight: bold;}
|
||||
|
||||
td, td img {vertical-align: top;}
|
||||
|
||||
/* Make sure sup and sub don't mess with your line-heights http://gist.github.com/413930 */
|
||||
sub, sup {font-size: 75%; line-height: 0; position: relative;}
|
||||
sup {top: -0.5em;}
|
||||
sub {bottom: -0.25em;}
|
||||
|
||||
/* standardize any monospaced elements */
|
||||
pre, code, kbd, samp {font-family: monospace, sans-serif;}
|
||||
|
||||
/* hand cursor on clickable elements */
|
||||
.clickable,
|
||||
label,
|
||||
input[type=button],
|
||||
input[type=submit],
|
||||
input[type=file],
|
||||
button {cursor: pointer;}
|
||||
|
||||
/* Webkit browsers add a 2px margin outside the chrome of form elements */
|
||||
button, input, select, textarea {margin: 0;}
|
||||
|
||||
/* make buttons play nice in IE */
|
||||
button,
|
||||
input[type=button] {width: auto; overflow: visible;}
|
||||
|
||||
/* scale images in IE7 more attractively */
|
||||
.ie7 img {-ms-interpolation-mode: bicubic;}
|
||||
|
||||
/* prevent BG image flicker upon hover
|
||||
(commented out as usage is rare, and the filter syntax messes with some pre-processors)
|
||||
.ie6 html {filter: expression(document.execCommand("BackgroundImageCache", false, true));}
|
||||
*/
|
||||
|
||||
/* let's clear some floats */
|
||||
.clearfix:after { content: " "; display: block; clear: both; }
|
25
client/scss/base/variables.scss
Normal file
25
client/scss/base/variables.scss
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
// --------------------------------------
|
||||
// FONTS
|
||||
// --------------------------------------
|
||||
|
||||
$core-font-standard: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||
$core-font-monospace: Consolas, "Liberation Mono", Menlo, Courier, monospace;
|
||||
|
||||
// --------------------------------------
|
||||
// LAYOUT
|
||||
// --------------------------------------
|
||||
|
||||
$tablet: 769px !default;
|
||||
$desktop: 980px !default;
|
||||
$widescreen: 1180px !default;
|
||||
|
||||
// --------------------------------------
|
||||
// COLORS
|
||||
// --------------------------------------
|
||||
|
||||
$color-text: mc('grey', '800');
|
||||
$color-link: mc('blue', '500');
|
||||
$color-link-hover: mc('blue', '700');
|
||||
$color-link-active: mc('purple', '500');
|
||||
$color-bg: #F4F5F9;
|
114
client/scss/components/alert.scss
Normal file
114
client/scss/components/alert.scss
Normal file
@ -0,0 +1,114 @@
|
||||
/*#alerts {
|
||||
position: fixed;
|
||||
top: 60px;
|
||||
right: 10px;
|
||||
width: 350px;
|
||||
z-index: 10;
|
||||
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;
|
||||
}
|
||||
|
||||
}*/
|
||||
|
||||
#alerts {
|
||||
position: fixed;
|
||||
top: 55px;
|
||||
right: 10px;
|
||||
width: 350px;
|
||||
z-index: 100;
|
||||
|
||||
> ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style-type: none;
|
||||
|
||||
> li {
|
||||
background-color: material-color('blue-grey', '800');
|
||||
box-shadow: 5px 5px 0 transparentize(material-color('blue-grey', '900'), 0.7);
|
||||
border: 1px solid material-color('blue-grey', '500');
|
||||
border-left-width: 5px;
|
||||
margin-top: 5px;
|
||||
padding: 8px 12px;
|
||||
animation-name: slideFromRight;
|
||||
animation-duration: 1s;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
|
||||
&:hover {
|
||||
background-color: material-color('blue-grey', '900');
|
||||
}
|
||||
|
||||
&.exit {
|
||||
animation-name: zoomOut;
|
||||
animation-duration: 1s;
|
||||
transform-origin: top center;
|
||||
}
|
||||
|
||||
> button {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
color: #FFF;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
padding: 0;
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
|
||||
&:before {
|
||||
content: 'X';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
> strong {
|
||||
display: block;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: #FFF;
|
||||
|
||||
> i {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
> span {
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: material-color('blue-grey', '100');
|
||||
}
|
||||
|
||||
&.error {
|
||||
border-color: material-color('red', '400');
|
||||
background-color: material-color('red', '600');
|
||||
> span {
|
||||
color: material-color('red', '50');
|
||||
}
|
||||
}
|
||||
&.success {
|
||||
border-color: material-color('green', '400');
|
||||
background-color: material-color('green', '700');
|
||||
> span {
|
||||
color: material-color('green', '50');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
122
client/scss/components/button.scss
Normal file
122
client/scss/components/button.scss
Normal file
@ -0,0 +1,122 @@
|
||||
.button {
|
||||
background-color: mc('orange','600');
|
||||
color: #FFF;
|
||||
border: 1px solid mc('orange','700');
|
||||
border-radius: 3px;
|
||||
display: inline-flex;
|
||||
height: 30px;
|
||||
align-items: center;
|
||||
padding: 0 15px;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
font-family: $core-font-standard;
|
||||
margin: 0;
|
||||
transition: all .4s ease;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
text-transform: uppercase;
|
||||
|
||||
span {
|
||||
font-weight: 600;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
line-height: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
i {
|
||||
margin-right: 8px;
|
||||
font-size: 14px;
|
||||
line-height: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
border-color: #FFF;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: mc('orange','800');
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
@each $color, $colorvalue in $material-colors {
|
||||
&.is-#{$color} {
|
||||
background-color: mc($color, '600');
|
||||
border-color: mc($color,'700');
|
||||
color: #FFF;
|
||||
|
||||
&.is-outlined {
|
||||
background-color: #FFF;
|
||||
color: mc($color,'700');
|
||||
}
|
||||
|
||||
&.is-inverted {
|
||||
background-color: rgba(mc($color, '800'), 0);
|
||||
border-color: mc($color, '500');
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: mc($color,'800');
|
||||
color: #FFF;
|
||||
animation: none;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
&.is-icon-only {
|
||||
i {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-featured {
|
||||
animation: btnInvertedPulse .6s ease alternate infinite;
|
||||
}
|
||||
|
||||
&.is-disabled, &:disabled {
|
||||
background-color: mc('grey', '300');
|
||||
border: 1px solid mc('grey','400');
|
||||
color: mc('grey', '500');
|
||||
cursor: default;
|
||||
transition: none;
|
||||
|
||||
&:hover {
|
||||
background-color: mc('grey', '300') !important;
|
||||
color: mc('grey', '500') !important;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.button-group {
|
||||
|
||||
.button {
|
||||
border-radius: 0;
|
||||
margin-left: 1px;
|
||||
|
||||
&:first-child {
|
||||
margin-left: 0;
|
||||
border-top-left-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-top-right-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@include keyframes(btnInvertedPulse) {
|
||||
0% {
|
||||
background-color: rgba(mc('grey', '500'), 0);
|
||||
}
|
||||
100% {
|
||||
background-color: rgba(mc('grey', '500'), 0.25);
|
||||
}
|
||||
}
|
26
client/scss/components/footer.scss
Normal file
26
client/scss/components/footer.scss
Normal file
@ -0,0 +1,26 @@
|
||||
.footer {
|
||||
background-color: mc('blue-grey','50');
|
||||
border-bottom: 5px solid mc('blue-grey','100');
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 25px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: mc('blue-grey','500');
|
||||
|
||||
ul {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style-type: none;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
li {
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
213
client/scss/components/form.scss
Normal file
213
client/scss/components/form.scss
Normal file
@ -0,0 +1,213 @@
|
||||
|
||||
.control {
|
||||
|
||||
& + .control {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
// ===============================================================
|
||||
// TEXTBOX
|
||||
// ===============================================================
|
||||
|
||||
input[type=text], input[type=password] {
|
||||
background-color: #FFF;
|
||||
display: flex;
|
||||
height: 30px;
|
||||
align-items: center;
|
||||
padding: 0 12px;
|
||||
border: 1px solid mc('grey', '400');
|
||||
border-radius: 3px;
|
||||
font-family: $core-font-standard;
|
||||
font-size: 14px;
|
||||
color: mc('grey', '700');
|
||||
transition: all .4s ease;
|
||||
box-shadow: inset 0 0 5px 0 rgba(0,0,0,0.1);
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
border-color: mc('light-blue', '500');
|
||||
box-shadow: inset 0 0 5px 0 rgba(mc('light-blue', '500'), 0.3);
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
background-color: mc('grey', '100');
|
||||
}
|
||||
|
||||
&.is-dirty.is-invalid {
|
||||
border-color: mc('red', '500');
|
||||
box-shadow: inset 0 0 5px 0 mc('red', '100');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
&.is-fullwidth {
|
||||
|
||||
input[type=text], input[type=password], select, textarea {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ===============================================================
|
||||
// DROPDOWN
|
||||
// ===============================================================
|
||||
|
||||
select {
|
||||
background-color: #FFF;
|
||||
display: flex;
|
||||
height: 30px;
|
||||
align-items: center;
|
||||
padding: 0 12px;
|
||||
border: 1px solid mc('grey', '400');
|
||||
border-radius: 3px;
|
||||
font-family: $core-font-standard;
|
||||
font-size: 14px;
|
||||
color: mc('grey', '700');
|
||||
transition: all .4s ease;
|
||||
box-shadow: inset 0 0 5px 0 rgba(0,0,0,0.1);
|
||||
cursor: pointer;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
border-color: mc('light-blue', '500');
|
||||
box-shadow: inset 0 0 5px 0 rgba(mc('light-blue', '500'), 0.3);
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
background-color: mc('grey', '100');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ===============================================================
|
||||
// CHECKBOX / RADIO BUTTONS
|
||||
// ===============================================================
|
||||
|
||||
input[type=radio], input[type=checkbox] {
|
||||
position: absolute;
|
||||
left: -9999px;
|
||||
opacity: 0;
|
||||
|
||||
& + label {
|
||||
position: relative;
|
||||
padding: 0 15px 0 25px;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
height: 25px;
|
||||
line-height: 25px;
|
||||
font-size: 14px;
|
||||
transition: .28s ease;
|
||||
@include prefix('user-select', none);
|
||||
|
||||
&:before, &:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
margin: 4px;
|
||||
border: 2px solid mc($primary, '600');
|
||||
margin: 4px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 50%;
|
||||
z-index: 0;
|
||||
transition: .28s ease;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
&:checked + label {
|
||||
|
||||
&:before, &:after {
|
||||
border-color: mc($primary, '600');
|
||||
}
|
||||
|
||||
&:after {
|
||||
@include prefix('transform', scale(0.5));
|
||||
background-color: mc($primary, '600');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
input[type=checkbox] + label {
|
||||
&:before, &:after {
|
||||
border-radius: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.help {
|
||||
font-size: 12px;
|
||||
|
||||
&.is-red {
|
||||
color: mc('red','600');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
& + label {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
> i:first-child {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.label {
|
||||
margin-bottom: 5px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.form-sections {
|
||||
|
||||
section {
|
||||
border-top: 1px solid mc('grey', '200');
|
||||
padding: 20px;
|
||||
@include prefix(animation-duration, .6s);
|
||||
|
||||
&:first-child {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.button + .button {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.desc {
|
||||
display: inline-block;
|
||||
padding: 10px 0 0 0px;
|
||||
font-size: 12px;
|
||||
color: mc('grey', '500');
|
||||
}
|
||||
|
||||
.section-block {
|
||||
padding-left: 20px;
|
||||
font-size: 14px;
|
||||
color: mc('blue-grey', '800');
|
||||
|
||||
h6 {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: mc('blue-grey', '600');
|
||||
margin-top: 15px;
|
||||
border-bottom: 1px dotted mc('blue-grey', '200');
|
||||
}
|
||||
|
||||
p {
|
||||
padding: 5px 0;
|
||||
|
||||
&.is-small {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
501
client/scss/components/grid.scss
Normal file
501
client/scss/components/grid.scss
Normal file
@ -0,0 +1,501 @@
|
||||
.column {
|
||||
flex-basis: 0;
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
padding: 10px;
|
||||
|
||||
.columns.is-mobile > &.is-narrow {
|
||||
flex: none;
|
||||
}
|
||||
|
||||
.columns.is-mobile > &.is-full {
|
||||
flex: none;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.columns.is-mobile > &.is-three-quarters {
|
||||
flex: none;
|
||||
width: 75%;
|
||||
}
|
||||
|
||||
.columns.is-mobile > &.is-two-thirds {
|
||||
flex: none;
|
||||
width: 66.6666%;
|
||||
}
|
||||
|
||||
.columns.is-mobile > &.is-half {
|
||||
flex: none;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.columns.is-mobile > &.is-one-third {
|
||||
flex: none;
|
||||
width: 33.3333%;
|
||||
}
|
||||
|
||||
.columns.is-mobile > &.is-one-quarter {
|
||||
flex: none;
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
.columns.is-mobile > &.is-offset-three-quarters {
|
||||
margin-left: 75%;
|
||||
}
|
||||
|
||||
.columns.is-mobile > &.is-offset-two-thirds {
|
||||
margin-left: 66.6666%;
|
||||
}
|
||||
|
||||
.columns.is-mobile > &.is-offset-half {
|
||||
margin-left: 50%;
|
||||
}
|
||||
|
||||
.columns.is-mobile > &.is-offset-one-third {
|
||||
margin-left: 33.3333%;
|
||||
}
|
||||
|
||||
.columns.is-mobile > &.is-offset-one-quarter {
|
||||
margin-left: 25%;
|
||||
}
|
||||
|
||||
@for $i from 1 through 12 {
|
||||
.columns.is-mobile > &.is-#{$i} {
|
||||
flex: none;
|
||||
width: $i / 12 * 100%;
|
||||
}
|
||||
|
||||
.columns.is-mobile > &.is-offset-#{$i} {
|
||||
margin-left: $i / 12 * 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@include mobile {
|
||||
&.is-narrow-mobile {
|
||||
flex: none;
|
||||
}
|
||||
|
||||
&.is-full-mobile {
|
||||
flex: none;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&.is-three-quarters-mobile {
|
||||
flex: none;
|
||||
width: 75%;
|
||||
}
|
||||
|
||||
&.is-two-thirds-mobile {
|
||||
flex: none;
|
||||
width: 66.6666%;
|
||||
}
|
||||
|
||||
&.is-half-mobile {
|
||||
flex: none;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
&.is-one-third-mobile {
|
||||
flex: none;
|
||||
width: 33.3333%;
|
||||
}
|
||||
|
||||
&.is-one-quarter-mobile {
|
||||
flex: none;
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
&.is-offset-three-quarters-mobile {
|
||||
margin-left: 75%;
|
||||
}
|
||||
|
||||
&.is-offset-two-thirds-mobile {
|
||||
margin-left: 66.6666%;
|
||||
}
|
||||
|
||||
&.is-offset-half-mobile {
|
||||
margin-left: 50%;
|
||||
}
|
||||
|
||||
&.is-offset-one-third-mobile {
|
||||
margin-left: 33.3333%;
|
||||
}
|
||||
|
||||
&.is-offset-one-quarter-mobile {
|
||||
margin-left: 25%;
|
||||
}
|
||||
|
||||
@for $i from 1 through 12 {
|
||||
&.is-#{$i}-mobile {
|
||||
flex: none;
|
||||
width: $i / 12 * 100%;
|
||||
}
|
||||
|
||||
&.is-offset-#{$i}-mobile {
|
||||
margin-left: $i / 12 * 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@include tablet {
|
||||
&.is-narrow,
|
||||
&.is-narrow-tablet {
|
||||
flex: none;
|
||||
}
|
||||
|
||||
&.is-full,
|
||||
&.is-full-tablet {
|
||||
flex: none;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&.is-three-quarters,
|
||||
&.is-three-quarters-tablet {
|
||||
flex: none;
|
||||
width: 75%;
|
||||
}
|
||||
|
||||
&.is-two-thirds,
|
||||
&.is-two-thirds-tablet {
|
||||
flex: none;
|
||||
width: 66.6666%;
|
||||
}
|
||||
|
||||
&.is-half,
|
||||
&.is-half-tablet {
|
||||
flex: none;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
&.is-one-third,
|
||||
&.is-one-third-tablet {
|
||||
flex: none;
|
||||
width: 33.3333%;
|
||||
}
|
||||
|
||||
&.is-one-quarter,
|
||||
&.is-one-quarter-tablet {
|
||||
flex: none;
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
&.is-offset-three-quarters,
|
||||
&.is-offset-three-quarters-tablet {
|
||||
margin-left: 75%;
|
||||
}
|
||||
|
||||
&.is-offset-two-thirds,
|
||||
&.is-offset-two-thirds-tablet {
|
||||
margin-left: 66.6666%;
|
||||
}
|
||||
|
||||
&.is-offset-half,
|
||||
&.is-offset-half-tablet {
|
||||
margin-left: 50%;
|
||||
}
|
||||
|
||||
&.is-offset-one-third,
|
||||
&.is-offset-one-third-tablet {
|
||||
margin-left: 33.3333%;
|
||||
}
|
||||
|
||||
&.is-offset-one-quarter,
|
||||
&.is-offset-one-quarter-tablet {
|
||||
margin-left: 25%;
|
||||
}
|
||||
|
||||
@for $i from 1 through 12 {
|
||||
&.is-#{$i},
|
||||
&.is-#{$i}-tablet {
|
||||
flex: none;
|
||||
width: $i / 12 * 100%;
|
||||
}
|
||||
|
||||
&.is-offset-#{$i},
|
||||
&.is-offset-#{$i}-tablet {
|
||||
margin-left: $i / 12 * 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@include desktop {
|
||||
&.is-narrow-desktop {
|
||||
flex: none;
|
||||
}
|
||||
|
||||
&.is-full-desktop {
|
||||
flex: none;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&.is-three-quarters-desktop {
|
||||
flex: none;
|
||||
width: 75%;
|
||||
}
|
||||
|
||||
&.is-two-thirds-desktop {
|
||||
flex: none;
|
||||
width: 66.6666%;
|
||||
}
|
||||
|
||||
&.is-half-desktop {
|
||||
flex: none;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
&.is-one-third-desktop {
|
||||
flex: none;
|
||||
width: 33.3333%;
|
||||
}
|
||||
|
||||
&.is-one-quarter-desktop {
|
||||
flex: none;
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
&.is-offset-three-quarters-desktop {
|
||||
margin-left: 75%;
|
||||
}
|
||||
|
||||
&.is-offset-two-thirds-desktop {
|
||||
margin-left: 66.6666%;
|
||||
}
|
||||
|
||||
&.is-offset-half-desktop {
|
||||
margin-left: 50%;
|
||||
}
|
||||
|
||||
&.is-offset-one-third-desktop {
|
||||
margin-left: 33.3333%;
|
||||
}
|
||||
|
||||
&.is-offset-one-quarter-desktop {
|
||||
margin-left: 25%;
|
||||
}
|
||||
|
||||
@for $i from 1 through 12 {
|
||||
&.is-#{$i}-desktop {
|
||||
flex: none;
|
||||
width: $i / 12 * 100%;
|
||||
}
|
||||
|
||||
&.is-offset-#{$i}-desktop {
|
||||
margin-left: $i / 12 * 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@include widescreen {
|
||||
&.is-narrow-widescreen {
|
||||
flex: none;
|
||||
}
|
||||
|
||||
&.is-full-widescreen {
|
||||
flex: none;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&.is-three-quarters-widescreen {
|
||||
flex: none;
|
||||
width: 75%;
|
||||
}
|
||||
|
||||
&.is-two-thirds-widescreen {
|
||||
flex: none;
|
||||
width: 66.6666%;
|
||||
}
|
||||
|
||||
&.is-half-widescreen {
|
||||
flex: none;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
&.is-one-third-widescreen {
|
||||
flex: none;
|
||||
width: 33.3333%;
|
||||
}
|
||||
|
||||
&.is-one-quarter-widescreen {
|
||||
flex: none;
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
&.is-offset-three-quarters-widescreen {
|
||||
margin-left: 75%;
|
||||
}
|
||||
|
||||
&.is-offset-two-thirds-widescreen {
|
||||
margin-left: 66.6666%;
|
||||
}
|
||||
|
||||
&.is-offset-half-widescreen {
|
||||
margin-left: 50%;
|
||||
}
|
||||
|
||||
&.is-offset-one-third-widescreen {
|
||||
margin-left: 33.3333%;
|
||||
}
|
||||
|
||||
&.is-offset-one-quarter-widescreen {
|
||||
margin-left: 25%;
|
||||
}
|
||||
|
||||
@for $i from 1 through 12 {
|
||||
&.is-#{$i}-widescreen {
|
||||
flex: none;
|
||||
width: $i / 12 * 100%;
|
||||
}
|
||||
|
||||
&.is-offset-#{$i}-widescreen {
|
||||
margin-left: $i / 12 * 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.columns {
|
||||
margin-left: -10px;
|
||||
margin-right: -10px;
|
||||
margin-top: -10px;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: -10px;
|
||||
}
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
// Modifiers
|
||||
&.is-centered {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
&.is-gapless {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
margin-top: 0;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
& > .column {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-stretched {
|
||||
flex-grow: 1;
|
||||
align-items: stretch;
|
||||
align-self: stretch;
|
||||
}
|
||||
|
||||
&.is-grid {
|
||||
// Responsiveness
|
||||
@include tablet {
|
||||
flex-wrap: wrap;
|
||||
|
||||
& > .column {
|
||||
max-width: 33.3333%;
|
||||
padding: 10px;
|
||||
width: 33.3333%;
|
||||
|
||||
& + .column {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.is-mobile {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
&.is-multiline {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
&.is-vcentered {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
// Responsiveness
|
||||
@include tablet {
|
||||
&:not(.is-desktop) {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@include desktop {
|
||||
// Modifiers
|
||||
&.is-desktop {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tile {
|
||||
align-items: stretch;
|
||||
flex-basis: auto;
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
min-height: min-content;
|
||||
|
||||
// Modifiers
|
||||
&.is-ancestor {
|
||||
margin-left: -10px;
|
||||
margin-right: -10px;
|
||||
margin-top: -10px;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: -10px;
|
||||
}
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-child {
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
&.is-parent {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
&.is-vertical {
|
||||
flex-direction: column;
|
||||
|
||||
& > .tile.is-child:not(:last-child) {
|
||||
margin-bottom: 20px !important;
|
||||
}
|
||||
}
|
||||
|
||||
// Responsiveness
|
||||
@include tablet {
|
||||
&:not(.is-child) {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
@for $i from 1 through 12 {
|
||||
&.is-#{$i} {
|
||||
flex: none;
|
||||
width: $i / 12 * 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.column.is-white {
|
||||
background-color: #FFF;
|
||||
}
|
68
client/scss/components/hero.scss
Normal file
68
client/scss/components/hero.scss
Normal file
@ -0,0 +1,68 @@
|
||||
.hero {
|
||||
padding: 20px;
|
||||
background-color: mc('grey', '50');
|
||||
border-bottom: 1px solid mc('grey', '200');
|
||||
position: relative;
|
||||
|
||||
h1 {
|
||||
font-size: 28px;
|
||||
color: mc($primary, '500');
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 18px;
|
||||
color: mc('grey', '500');
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.hero-menu {
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
bottom: -1px;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
|
||||
li {
|
||||
display: flex;
|
||||
margin-left: 1px;
|
||||
|
||||
a, button {
|
||||
background-color: mc('light-blue', '500');
|
||||
color: #FFF;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-items: center;
|
||||
padding: 0 15px;
|
||||
height: 32px;
|
||||
border: 1px solid mc('light-blue', '600');
|
||||
font-family: $core-font-standard;
|
||||
font-size: 13px;
|
||||
transition: all 0.4s ease;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
text-transform: uppercase;
|
||||
|
||||
i {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
@each $color, $colorvalue in $material-colors {
|
||||
&.is-#{$color} {
|
||||
background-color: mc($color, '600');
|
||||
border-color: mc($color, '600');
|
||||
|
||||
&:hover {
|
||||
background-color: mc($color, '800');
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
62
client/scss/components/list.scss
Normal file
62
client/scss/components/list.scss
Normal file
@ -0,0 +1,62 @@
|
||||
.list {
|
||||
background-color: #FFF;
|
||||
min-height: 25px;
|
||||
|
||||
.list-header {
|
||||
background-color: mc('grey','100');
|
||||
height: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 20px;
|
||||
text-transform: uppercase;
|
||||
font-size: 13px;
|
||||
color: mc($primary,'500');
|
||||
text-shadow: 1px 1px 0 #FFF;
|
||||
|
||||
span {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
i {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.list-row {
|
||||
border-top: 1px solid mc('grey','100');
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 10px 20px;
|
||||
|
||||
&:first-child {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.list-item {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.list-icon {
|
||||
margin-right: 15px;
|
||||
color: mc('grey','500');
|
||||
}
|
||||
.list-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
strong {
|
||||
color: mc('grey','700');
|
||||
}
|
||||
span {
|
||||
color: mc('grey','600');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
355
client/scss/components/markdown-content.scss
Normal file
355
client/scss/components/markdown-content.scss
Normal file
@ -0,0 +1,355 @@
|
||||
.mkcontent {
|
||||
font-size: 14px;
|
||||
color: mc('grey', '700');
|
||||
padding: 0 0 20px 0;
|
||||
|
||||
h1, h2, h3 {
|
||||
font-weight: 400;
|
||||
margin: 10px 0 0;
|
||||
padding: 7px 20px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
h1 {
|
||||
background-color: mc('indigo', '50');
|
||||
border-bottom: 2px solid mc('indigo', '100');
|
||||
font-size: 18px;
|
||||
color: mc('indigo', '500');
|
||||
|
||||
&:first-child {
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
/*& + h2 {
|
||||
margin-top: 1px;
|
||||
border-top: none;
|
||||
}*/
|
||||
|
||||
& + p {
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
h2 {
|
||||
background-color: lighten(mc('teal', '50'), 5%);
|
||||
border: 1px solid mc('teal', '100');
|
||||
border-right-width: 5px;
|
||||
border-top-left-radius: 3px;
|
||||
border-bottom-left-radius: 3px;
|
||||
font-size: 16px;
|
||||
color: mc('teal', '900');
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.indent-h2 {
|
||||
border-right: 5px solid mc('teal', '100');
|
||||
margin-left: 20px;
|
||||
padding-top: 1px;
|
||||
padding-bottom: 20px;
|
||||
overflow: hidden;
|
||||
|
||||
& + h1, & + h2 {
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
h3:first-child {
|
||||
margin-top: 0;
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
h3 {
|
||||
background-color: lighten(mc('blue', '50'), 3%);
|
||||
border: 1px solid mc('blue', '100');
|
||||
border-right-width: 5px;
|
||||
border-top-left-radius: 3px;
|
||||
border-bottom-left-radius: 3px;
|
||||
font-size: 14px;
|
||||
color: mc('blue', '700');
|
||||
margin-left: 20px;
|
||||
margin-right: 1px;
|
||||
padding: 5px 20px;
|
||||
}
|
||||
|
||||
.indent-h3 {
|
||||
border-right: 5px solid mc('teal', '100');
|
||||
margin-left: 20px;
|
||||
margin-right: 1px;
|
||||
padding-bottom: 10px;
|
||||
|
||||
& + h1, & + h2, & + h3 {
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: underline;
|
||||
font-weight: 400;
|
||||
|
||||
&:hover {
|
||||
color: mc('blue', '700');
|
||||
}
|
||||
|
||||
&.toc-anchor {
|
||||
font-size: 80%;
|
||||
color: mc('indigo', '300');
|
||||
border-bottom: none;
|
||||
text-decoration: none;
|
||||
|
||||
&:visited {
|
||||
color: mc('indigo', '300') !important;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
&.external-link {
|
||||
position: relative;
|
||||
padding-left: 5px;
|
||||
//display: inline-flex;
|
||||
//align-items: center;
|
||||
|
||||
&:before {
|
||||
content: $icon-open;
|
||||
display: inline-block;
|
||||
font-family: 'core-icons';
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
text-decoration: none;
|
||||
color: mc('grey', '500');
|
||||
font-size: 14px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
&:hover:before {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ul {
|
||||
padding: 10px 0 10px 40px;
|
||||
list-style-type: square;
|
||||
|
||||
li {
|
||||
padding: 1px 0;
|
||||
|
||||
> ul {
|
||||
padding: 5px 0 5px 15px;
|
||||
list-style-type: disc;
|
||||
}
|
||||
|
||||
p {
|
||||
padding: 0;
|
||||
|
||||
&:first-child {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ol {
|
||||
padding: 10px 40px;
|
||||
list-style-type: decimal;
|
||||
|
||||
li {
|
||||
padding: 1px 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
p {
|
||||
padding: 10px 20px;
|
||||
|
||||
&:first-child {
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
&.is-gapless {
|
||||
padding: 0 20px;
|
||||
|
||||
& + p {
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
& + h1 {
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
table {
|
||||
width: auto;
|
||||
border-collapse: collapse;
|
||||
margin: 10px 20px;
|
||||
font-size: 14px;
|
||||
|
||||
th {
|
||||
background-color: mc('blue', '500');
|
||||
color: #FFF;
|
||||
border: 1px solid mc('blue', '500');
|
||||
padding: 5px 15px;
|
||||
|
||||
&:first-child {
|
||||
border-left-color: mc('blue', '500');
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-right-color: mc('blue', '500');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
td {
|
||||
border: 1px solid mc('grey', '500');
|
||||
padding: 5px 15px;
|
||||
}
|
||||
|
||||
tr:nth-child(even) {
|
||||
background-color: mc('grey', '100');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
code {
|
||||
font-weight: 500;
|
||||
color: mc('purple', '500');
|
||||
background-color: lighten(mc('purple', '50'), 5%);
|
||||
padding: 0 5px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
pre {
|
||||
background-color: mc('grey', '50');
|
||||
border-top: 1px solid mc('grey', '100');
|
||||
box-shadow: inset 0 0 5px 0 rgba(mc('grey', '500'), 0.3);
|
||||
padding: 20px;
|
||||
font-family: $core-font-monospace;
|
||||
white-space: pre;
|
||||
|
||||
> code {
|
||||
box-shadow: inset 0 0 5px 0 mc('grey', '100');
|
||||
border-radius: 5px;
|
||||
font-weight: 400;
|
||||
background-color: none;
|
||||
color: mc('grey', '700');
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
& + p {
|
||||
padding-top: 1em;
|
||||
}
|
||||
|
||||
& + h1, & + h2, & + h3 {
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.align-right {
|
||||
float:right;
|
||||
margin: 0 0 10px 10px;
|
||||
max-width: 30vw;
|
||||
}
|
||||
.align-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
img.pagelogo {
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
top: 20px;
|
||||
max-width: 200px;
|
||||
max-height: 100px;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
strong {
|
||||
color: mc('grey', '700');
|
||||
}
|
||||
|
||||
.twa {
|
||||
font-size: 120%;
|
||||
}
|
||||
|
||||
hr {
|
||||
margin: 20px;
|
||||
border-top: 1px dotted mc('grey', '500');
|
||||
}
|
||||
|
||||
blockquote {
|
||||
background-color: mc('teal', '50');
|
||||
border: 1px solid mc('teal', '100');
|
||||
border-bottom-width: 2px;
|
||||
box-shadow: inset 0px 0px 0px 1px rgba(255,255,255,1);
|
||||
border-radius: 5px;
|
||||
padding: 0 10px;
|
||||
margin: 10px 20px;
|
||||
|
||||
p {
|
||||
padding: 10px 0;
|
||||
color: mc('teal', '800');
|
||||
|
||||
&:first-child {
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
strong {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
&.is-danger {
|
||||
background-color: mc('red', '100');
|
||||
border-color: mc('red', '200');
|
||||
p {
|
||||
color: mc('red', '900');
|
||||
}
|
||||
}
|
||||
|
||||
&.is-warning {
|
||||
background-color: mc('amber', '50');
|
||||
border-color: mc('amber', '200');
|
||||
p {
|
||||
color: darken(mc('amber', '900'), 10%);
|
||||
}
|
||||
}
|
||||
|
||||
&.is-success {
|
||||
background-color: mc('green', '50');
|
||||
border-color: mc('green', '200');
|
||||
p {
|
||||
color: darken(mc('green', '900'), 10%);
|
||||
}
|
||||
}
|
||||
|
||||
&.is-info {
|
||||
background-color: mc('blue', '50');
|
||||
border-color: mc('blue', '200');
|
||||
p {
|
||||
color: darken(mc('blue', '900'), 10%);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
356
client/scss/components/modal.scss
Normal file
356
client/scss/components/modal.scss
Normal file
@ -0,0 +1,356 @@
|
||||
.modal {
|
||||
align-items: flex-start;
|
||||
display: none;
|
||||
|
||||
&.is-active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
&.is-superimposed {
|
||||
.modal-background {
|
||||
z-index: 20;
|
||||
}
|
||||
.modal-container {
|
||||
z-index: 21;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
.modal-background {
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
position: fixed;
|
||||
background-color: rgba(0,0,0,0.85);
|
||||
animation: .4s ease fadeIn;
|
||||
z-index: 10;
|
||||
}
|
||||
.modal-container {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 11;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.modal-content {
|
||||
animation: .3s ease zoomIn;
|
||||
width: 600px;
|
||||
background-color: #FFF;
|
||||
|
||||
&.is-expanded {
|
||||
align-self: stretch;
|
||||
width: 100%;
|
||||
margin: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
> section {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
header {
|
||||
background-color: mc('teal', '600');
|
||||
color: #FFF;
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
height: 40px;
|
||||
align-items: center;
|
||||
font-weight: 400;
|
||||
font-size: 16px;
|
||||
padding: 0 20px;
|
||||
position: relative;
|
||||
|
||||
@each $color, $colorvalue in $material-colors {
|
||||
&.is-#{$color} {
|
||||
background-color: mc($color, '600');
|
||||
}
|
||||
}
|
||||
|
||||
.modal-notify {
|
||||
position: absolute;
|
||||
display: none;
|
||||
align-items: center;
|
||||
height: 40px;
|
||||
right: 20px;
|
||||
top: 0;
|
||||
|
||||
&.is-active {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 12px;
|
||||
letter-spacing: 1px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
i {
|
||||
margin-left: 15px;
|
||||
display: inline-block;
|
||||
@include spinner(#FFF, .5s, 20px);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
section {
|
||||
padding: 20px;
|
||||
border-top: 1px dotted mc('grey', '300');
|
||||
|
||||
&:first-of-type {
|
||||
border-top: none;
|
||||
padding-top: 20px;
|
||||
}
|
||||
&:last-of-type {
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
&.is-gapless {
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
&.modal-loading {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
> i {
|
||||
display: block;
|
||||
@include spinner(mc('blue','500'), .4s, 32px);
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
> span {
|
||||
color: mc('grey', '600');
|
||||
}
|
||||
|
||||
> em {
|
||||
font-size: 12px;
|
||||
color: mc('grey', '500');
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
&.modal-instructions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
color: mc('grey', '800');
|
||||
|
||||
img {
|
||||
height: 100px;
|
||||
|
||||
& + * {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
i.is-huge {
|
||||
font-size: 72px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
> span {
|
||||
color: mc('grey', '800');
|
||||
}
|
||||
|
||||
> em {
|
||||
font-size: 12px;
|
||||
color: mc('grey', '600');
|
||||
font-style: normal;
|
||||
margin-top: 10px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.bullets {
|
||||
list-style-type: square;
|
||||
padding: 5px 0 0 30px;
|
||||
font-size: 14px;
|
||||
color: mc('grey', '800');
|
||||
}
|
||||
|
||||
.note {
|
||||
display: block;
|
||||
margin-top: 10px;
|
||||
font-size: 14px;
|
||||
color: mc('grey', '800');
|
||||
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
ul {
|
||||
color: mc('grey', '800');
|
||||
padding-left: 10px;
|
||||
|
||||
li {
|
||||
margin-top: 5px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
> i {
|
||||
margin-right: 8px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
footer {
|
||||
padding: 20px;
|
||||
text-align: right;
|
||||
|
||||
.button {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.modal-toolbar {
|
||||
background-color: mc('teal', '700');
|
||||
padding: 7px 20px;
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
justify-content: center;
|
||||
|
||||
@each $color, $colorvalue in $material-colors {
|
||||
&.is-#{$color} {
|
||||
background-color: mc($color, '700');
|
||||
|
||||
.button {
|
||||
border-color: mc($color, '900');
|
||||
background-color: mc($color, '900');
|
||||
|
||||
&:hover {
|
||||
border-color: mc($color, '900');
|
||||
background-color: mc($color, '800');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// BUTTONS
|
||||
|
||||
.button {
|
||||
border: 1px solid mc('teal', '900');
|
||||
background-color: mc('teal', '900');
|
||||
transition: all .4s ease;
|
||||
color: #FFF;
|
||||
border-radius: 0;
|
||||
|
||||
&:first-child {
|
||||
border-top-left-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-top-right-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
border-color: mc('teal', '900');
|
||||
background-color: mc('teal', '800');
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.button + .button {
|
||||
margin-left: 1px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.modal-sidebar {
|
||||
|
||||
background-color: mc('teal', '50');
|
||||
padding: 0;
|
||||
//padding: 7px 20px;
|
||||
|
||||
@each $color, $colorvalue in $material-colors {
|
||||
&.is-#{$color} {
|
||||
background-color: mc($color, '50');
|
||||
|
||||
.model-sidebar-header {
|
||||
background-color: mc($color, '100');
|
||||
color: mc($color, '800');
|
||||
}
|
||||
|
||||
.model-sidebar-list > li a {
|
||||
&:hover {
|
||||
background-color: mc($color, '200');
|
||||
}
|
||||
&.is-active {
|
||||
background-color: mc($color, '500');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.model-sidebar-header {
|
||||
padding: 7px 20px;
|
||||
}
|
||||
|
||||
.model-sidebar-content {
|
||||
padding: 7px 20px;
|
||||
}
|
||||
|
||||
.model-sidebar-list {
|
||||
|
||||
> li {
|
||||
padding: 0;
|
||||
|
||||
a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 34px;
|
||||
padding: 0 20px;
|
||||
cursor: pointer;
|
||||
color: mc('grey', '800');
|
||||
|
||||
&:hover {
|
||||
background-color: mc('teal', '200');
|
||||
}
|
||||
|
||||
&.is-active {
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
i {
|
||||
margin-right: 7px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.modal-content .card-footer-item.featured {
|
||||
animation: flash 4s ease 0 infinite;
|
||||
}
|
182
client/scss/components/nav.scss
Normal file
182
client/scss/components/nav.scss
Normal file
@ -0,0 +1,182 @@
|
||||
|
||||
.nav {
|
||||
align-items: stretch;
|
||||
background-color: mc($primary, '500');
|
||||
display: flex;
|
||||
min-height: 50px;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
box-shadow: 0 2px 3px rgba(mc($primary, '500'), 0.2);
|
||||
z-index: 2;
|
||||
color: #FFF;
|
||||
|
||||
@each $color, $colorvalue in $material-colors {
|
||||
&.is-#{$color} {
|
||||
background-color: mc($color, '500');
|
||||
box-shadow: 0 2px 3px rgba(mc($color, '500'), 0.2);
|
||||
|
||||
.nav-item {
|
||||
|
||||
.button {
|
||||
border: 1px solid mc($color, '900');
|
||||
background-color: mc($color, '800');
|
||||
|
||||
&.is-outlined {
|
||||
background-color: mc($color, '600');
|
||||
border-color: mc($color, '800');
|
||||
color: mc($color, '100');
|
||||
}
|
||||
|
||||
&:hover {
|
||||
border-color: mc($color, '900');
|
||||
background-color: mc($color, '900');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.nav-left {
|
||||
align-items: stretch;
|
||||
display: flex;
|
||||
flex-basis: 0;
|
||||
flex-grow: 1;
|
||||
justify-content: flex-start;
|
||||
overflow: hidden;
|
||||
overflow-x: auto;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.nav-center {
|
||||
align-items: stretch;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.nav-right {
|
||||
@include tablet {
|
||||
align-items: stretch;
|
||||
display: flex;
|
||||
flex-basis: 0;
|
||||
flex-grow: 1;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 0 10px;
|
||||
|
||||
// LINKS
|
||||
|
||||
@at-root .nav-item a, a.nav-item {
|
||||
color: mc($primary, '50');
|
||||
transition: color .4s ease;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: mc($primary, '200');
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// LOGO
|
||||
|
||||
img {
|
||||
max-height: 34px;
|
||||
}
|
||||
|
||||
// HEADERS
|
||||
|
||||
h1 {
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
letter-spacing: 0.5px;
|
||||
text-transform: uppercase;
|
||||
transition: color .4s ease;
|
||||
color: #FFF;
|
||||
padding-left: 10px;
|
||||
|
||||
i {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: mc('indigo', '100');
|
||||
}
|
||||
}
|
||||
|
||||
@at-root h2.nav-item, .nav-item h2 {
|
||||
color: mc($primary, '50');
|
||||
}
|
||||
|
||||
// BUTTONS
|
||||
|
||||
.button {
|
||||
border: 1px solid mc($primary, '900');
|
||||
background-color: mc($primary, '800');
|
||||
transition: all .4s ease;
|
||||
color: #FFF;
|
||||
border-radius: 0;
|
||||
|
||||
&:first-child {
|
||||
border-top-left-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-top-right-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
}
|
||||
|
||||
&.is-outlined {
|
||||
background-color: mc($primary, '600');
|
||||
border-color: mc($primary, '800');
|
||||
color: mc($primary, '100');
|
||||
}
|
||||
|
||||
&:hover {
|
||||
border-color: mc($primary, '900');
|
||||
background-color: mc($primary, '900');
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.button + .button {
|
||||
margin-left: 1px;
|
||||
}
|
||||
|
||||
// INPUTS
|
||||
|
||||
.control {
|
||||
|
||||
input[type=text] {
|
||||
background-color: mc($primary, '800');
|
||||
border-color: mc($primary, '400');
|
||||
color: mc($primary, '50');
|
||||
|
||||
&:focus {
|
||||
border-color: mc($primary, '200');
|
||||
box-shadow: inset 0 0 5px 0 rgba(mc($primary, '900'), 0.5);
|
||||
}
|
||||
|
||||
@include placeholder {
|
||||
color: mc($primary, '200');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
112
client/scss/components/panel.scss
Normal file
112
client/scss/components/panel.scss
Normal file
@ -0,0 +1,112 @@
|
||||
|
||||
.panel-aside {
|
||||
background-color: mc('blue-grey', '800');
|
||||
border: 1px solid mc('blue-grey', '800');
|
||||
border-bottom-left-radius: 8px;
|
||||
padding: 20px;
|
||||
color: mc('blue-grey','100');
|
||||
|
||||
label {
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.panel {
|
||||
background-color: #FFF;
|
||||
box-shadow: 0 0 12px 0 rgba(mc('grey','800'), .10), 1px 6px 8px 0 rgba(mc('grey','800'), .10);
|
||||
padding: 0 0 1px 0;
|
||||
border-radius: 4px;
|
||||
|
||||
.panel-title {
|
||||
border-bottom: 1px solid darken($color-bg, 5%);
|
||||
padding: 0 15px;
|
||||
color: $color-text;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 40px;
|
||||
|
||||
&.is-featured {
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
background-color: mc('indigo', '300');
|
||||
border-bottom-color: mc('indigo', '400');
|
||||
color: #FFF;
|
||||
|
||||
> i::before {
|
||||
@include spinner(#FFF, 0.4s, 18px);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
> span {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
> i {
|
||||
display: flex;
|
||||
width: 18px;
|
||||
align-items: center;
|
||||
|
||||
&::before {
|
||||
content: " ";
|
||||
@include spinner(mc($primary,'500'), 0.4s, 18px);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.panel-content {
|
||||
padding: 0 15px;
|
||||
|
||||
&.is-text {
|
||||
padding: 25px;
|
||||
|
||||
p + p, p + h3 {
|
||||
margin-top: 25px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin-bottom: 15px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
ul li {
|
||||
color: mc('grey', '700');
|
||||
}
|
||||
|
||||
strong {
|
||||
font-weight: 500;
|
||||
color: mc($primary,'800');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.panel-footer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
height: 50px;
|
||||
background-color: $color-bg;
|
||||
padding: 0 15px;
|
||||
margin: 0 1px;
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
position: relative;
|
||||
|
||||
.button + .button {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+ .panel {
|
||||
margin-top: 25px;
|
||||
}
|
||||
|
||||
}
|
57
client/scss/components/search.scss
Normal file
57
client/scss/components/search.scss
Normal file
@ -0,0 +1,57 @@
|
||||
.searchresults {
|
||||
position: fixed;
|
||||
top: 45px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: 0 auto;
|
||||
width: 500px;
|
||||
z-index: 1;
|
||||
background-color: mc($primary, '700');
|
||||
border-bottom: 5px solid mc($primary, '800');
|
||||
box-shadow: 0 0 5px mc($primary, '500');
|
||||
color: #FFF;
|
||||
|
||||
&.slideInDown {
|
||||
@include prefix(animation-duration, .6s);
|
||||
}
|
||||
|
||||
.searchresults-label {
|
||||
color: mc($primary, '200');
|
||||
padding: 15px 10px 10px;
|
||||
font-size: 13px;
|
||||
text-transform: uppercase;
|
||||
border-bottom: 1px dotted mc($primary, '400');
|
||||
}
|
||||
|
||||
.searchresults-list {
|
||||
|
||||
> li {
|
||||
display: flex;
|
||||
font-size: 14px;
|
||||
transition: background-color .3s linear;
|
||||
|
||||
&:nth-child(odd) {
|
||||
background-color: mc($primary, '600');
|
||||
}
|
||||
|
||||
&.is-active, &:hover {
|
||||
background-color: mc($primary, '400');
|
||||
color: #FFF;
|
||||
border-left: 5px solid mc($primary, '200');
|
||||
}
|
||||
|
||||
a {
|
||||
color: mc($primary, '50');
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 30px;
|
||||
padding: 0 20px;
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
83
client/scss/components/sidebar.scss
Normal file
83
client/scss/components/sidebar.scss
Normal file
@ -0,0 +1,83 @@
|
||||
|
||||
.sidebar {
|
||||
background-color: mc('blue-grey', '900');
|
||||
color: mc('blue-grey', '50');
|
||||
width: 250px;
|
||||
max-width: 250px;
|
||||
min-height: 80vh;
|
||||
|
||||
aside {
|
||||
|
||||
&:last-child {
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
.sidebar-label {
|
||||
padding: 0 0 5px 0;
|
||||
color: mc('blue-grey', '400');
|
||||
font-size: 13px;
|
||||
letter-spacing: 1px;
|
||||
text-transform: uppercase;
|
||||
border-bottom: 1px solid mc('blue-grey', '700');
|
||||
margin: 25px 10px 15px 10px;
|
||||
|
||||
i {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.sidebar-menu {
|
||||
|
||||
li {
|
||||
display: block;
|
||||
|
||||
a {
|
||||
display: flex;
|
||||
min-height: 30px;
|
||||
align-items: center;
|
||||
padding: 5px 20px;
|
||||
color: mc('blue-grey', '50');
|
||||
font-size: 14px;
|
||||
transition: all .4s ease;
|
||||
line-height: 14px;
|
||||
|
||||
i {
|
||||
margin-right: 7px;
|
||||
color: mc('blue-grey', '300');
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: mc('blue-grey', '400');
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
> ul {
|
||||
border-top: 1px solid lighten(mc('blue-grey', '900'), 3%);
|
||||
border-bottom: 1px solid lighten(mc('blue-grey', '900'), 2%);
|
||||
background-color: darken(mc('blue-grey', '900'), 2%);
|
||||
margin-bottom: 10px;
|
||||
padding: 10px 0;
|
||||
|
||||
li {
|
||||
padding-left: 10px;
|
||||
//border-left: 5px solid mc('blue-grey', '800');
|
||||
|
||||
a {
|
||||
min-height: 24px;
|
||||
color: mc('blue-grey', '100');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
90
client/scss/components/table.scss
Normal file
90
client/scss/components/table.scss
Normal file
@ -0,0 +1,90 @@
|
||||
.table {
|
||||
border-spacing: collapse;
|
||||
padding: 1px;
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
|
||||
thead {
|
||||
background-color: mc('blue-grey', '500');
|
||||
color: #FFF;
|
||||
|
||||
th {
|
||||
padding: 5px 10px;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
border-left: 1px solid mc('blue-grey', '200');
|
||||
|
||||
&:first-child {
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@each $color, $colorvalue in $material-colors {
|
||||
&.is-#{$color} {
|
||||
background-color: mc($color, '500');
|
||||
|
||||
th {
|
||||
border-left-color: mc($color, '200');
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
tbody {
|
||||
|
||||
tr {
|
||||
background-color: mc('blue-grey', '100');
|
||||
|
||||
&:nth-child(odd) {
|
||||
background-color: mc('blue-grey', '50');
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 5px 10px;
|
||||
border-left: 1px solid #FFF;
|
||||
vertical-align: middle;
|
||||
|
||||
&:first-child {
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.is-centered {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.has-icons i {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.is-icon {
|
||||
font-size: 14px;
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
.has-action-icons {
|
||||
i {
|
||||
cursor: pointer;
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.table-actions {
|
||||
text-align: right;
|
||||
|
||||
.button {
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
}
|
||||
|
||||
}
|
16
client/scss/components/typography.scss
Normal file
16
client/scss/components/typography.scss
Normal file
@ -0,0 +1,16 @@
|
||||
|
||||
h1 {
|
||||
font-size: 28px;
|
||||
}
|
||||
h2 {
|
||||
font-size: 18px;
|
||||
}
|
||||
h3 {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
@each $color, $colorvalue in $material-colors {
|
||||
i.is-#{$color} {
|
||||
color: mc($color, '600');
|
||||
}
|
||||
}
|
3486
client/scss/libs/animate.scss
vendored
Normal file
3486
client/scss/libs/animate.scss
vendored
Normal file
File diff suppressed because it is too large
Load Diff
52
client/scss/pages/_error.scss
Normal file
52
client/scss/pages/_error.scss
Normal file
@ -0,0 +1,52 @@
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-height: 100vh;
|
||||
width: 100vw;
|
||||
padding: 25px 0;
|
||||
margin: 0;
|
||||
color: #FFF;
|
||||
|
||||
&.is-notexist {
|
||||
background-color: mc('blue-grey', '900');
|
||||
}
|
||||
|
||||
&.is-forbidden {
|
||||
background-color: darken(mc('blue-grey', '900'), 5%);
|
||||
}
|
||||
|
||||
&.is-error {
|
||||
background-color: darken(mc('blue-grey', '900'), 10%);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.container {
|
||||
text-align: center;
|
||||
|
||||
h1 {
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-bottom: 50px;
|
||||
}
|
||||
|
||||
a.button {
|
||||
margin: 0 5px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
text-align: left;
|
||||
margin-top: 50px;
|
||||
}
|
||||
|
||||
pre {
|
||||
margin-top: 10px;
|
||||
text-align: left;
|
||||
color: mc('blue-grey', '200');
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
}
|
306
client/scss/pages/_login.scss
Normal file
306
client/scss/pages/_login.scss
Normal file
@ -0,0 +1,306 @@
|
||||
|
||||
body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-family: $core-font-standard;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #FFF;
|
||||
transition: color 0.4s ease;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
color: mc('orange','600');
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#bg {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 1;
|
||||
background-color: #000;
|
||||
|
||||
> div {
|
||||
background-size: cover;
|
||||
background-position: center center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transition: opacity 3s ease, visibility 3s;
|
||||
animation: bg 30s linear infinite;
|
||||
|
||||
&:nth-child(1) {
|
||||
animation-delay: 10s;
|
||||
}
|
||||
|
||||
&:nth-child(2) {
|
||||
animation-delay: 20s;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#root {
|
||||
position: fixed;
|
||||
top: 15vh;
|
||||
left: 10vw;
|
||||
z-index: 2;
|
||||
color: #FFF;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
h1 {
|
||||
font-size: 4rem;
|
||||
font-weight: bold;
|
||||
color: #FFF;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
animation: headerIntro 3s ease;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.5rem;
|
||||
font-weight: normal;
|
||||
color: rgba(255,255,255,0.7);
|
||||
padding: 0;
|
||||
margin: 0 0 25px 0;
|
||||
animation: headerIntro 3s ease;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.25rem;
|
||||
font-weight: normal;
|
||||
color: #FB8C00;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
animation: shake 1s ease;
|
||||
|
||||
> .fa {
|
||||
margin-right: 7px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 0.8rem;
|
||||
font-weight: normal;
|
||||
color: rgba(255,255,255,0.7);
|
||||
padding: 0;
|
||||
margin: 0 0 15px 0;
|
||||
animation: fadeIn 3s ease;
|
||||
}
|
||||
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
input[type=text], input[type=password] {
|
||||
width: 350px;
|
||||
max-width: 80vw;
|
||||
border: 1px solid rgba(255,255,255,0.3);
|
||||
border-radius: 3px;
|
||||
background-color: rgba(0,0,0,0.2);
|
||||
padding: 0 15px;
|
||||
height: 40px;
|
||||
margin: 0 0 10px 0;
|
||||
color: #FFF;
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
transition: all 0.4s ease;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
border-color: mc('orange','600');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: mc('orange','600');
|
||||
color: #FFF;
|
||||
border: 1px solid lighten(mc('orange','600'), 10%);
|
||||
border-radius: 3px;
|
||||
height: 40px;
|
||||
width: 125px;
|
||||
padding: 0;
|
||||
font-weight: bold;
|
||||
margin: 15px 0 0 0;
|
||||
transition: all 0.4s ease;
|
||||
cursor: pointer;
|
||||
|
||||
span {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
border-color: #FFF;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: darken(mc('orange','600'), 10%);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#social {
|
||||
margin-top: 25px;
|
||||
|
||||
> span {
|
||||
display: block;
|
||||
font-weight: bold;
|
||||
color: rgba(255,255,255,0.7);
|
||||
}
|
||||
|
||||
button {
|
||||
margin-right: 5px;
|
||||
width: auto;
|
||||
padding: 0 15px;
|
||||
|
||||
> i {
|
||||
margin-right: 10px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
&.ms {
|
||||
background-color: mc('blue','600');
|
||||
border-color: lighten(mc('blue','600'), 10%);
|
||||
|
||||
&:focus {
|
||||
border-color: #FFF;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: darken(mc('blue','600'), 10%);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
&.google {
|
||||
background-color: mc('light-blue','600');
|
||||
border-color: lighten(mc('light-blue','600'), 10%);
|
||||
|
||||
&:focus {
|
||||
border-color: #FFF;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: darken(mc('light-blue','600'), 10%);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
&.facebook {
|
||||
background-color: mc('indigo','600');
|
||||
border-color: lighten(mc('indigo','600'), 10%);
|
||||
|
||||
&:focus {
|
||||
border-color: #FFF;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: darken(mc('indigo','600'), 10%);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
&.github {
|
||||
background-color: mc('blue-grey','700');
|
||||
border-color: lighten(mc('blue-grey','700'), 10%);
|
||||
|
||||
&:focus {
|
||||
border-color: #FFF;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: darken(mc('blue-grey','700'), 10%);
|
||||
}
|
||||
}
|
||||
|
||||
&.slack {
|
||||
background-color: mc('purple','700');
|
||||
border-color: lighten(mc('purple','700'), 10%);
|
||||
|
||||
&:focus {
|
||||
border-color: #FFF;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: darken(mc('purple','700'), 10%);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#copyright {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
position: absolute;
|
||||
left: 10vw;
|
||||
bottom: 10vh;
|
||||
z-index: 2;
|
||||
color: rgba(255,255,255,0.5);
|
||||
font-weight: bold;
|
||||
|
||||
.icon {
|
||||
font-size: 1.2rem;
|
||||
margin: 0 8px;
|
||||
}
|
||||
|
||||
a {
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@include keyframes(bg) {
|
||||
0% {
|
||||
@include prefix(transform, scale(1,1));
|
||||
visibility: visible;
|
||||
opacity: 0;
|
||||
},
|
||||
5% {
|
||||
opacity: 0.5;
|
||||
},
|
||||
33% {
|
||||
opacity: 0.5;
|
||||
},
|
||||
38% {
|
||||
@include prefix(transform, scale(1.2, 1.2));
|
||||
opacity: 0;
|
||||
},
|
||||
39% {
|
||||
visibility: hidden;
|
||||
}
|
||||
100% {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@include keyframes(headerIntro) {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
243
libs/auth.js
Normal file
243
libs/auth.js
Normal file
@ -0,0 +1,243 @@
|
||||
'use strict'
|
||||
|
||||
/* global appconfig, appdata, db, winston */
|
||||
|
||||
const LocalStrategy = require('passport-local').Strategy
|
||||
const GoogleStrategy = require('passport-google-oauth20').Strategy
|
||||
const WindowsLiveStrategy = require('passport-windowslive').Strategy
|
||||
const FacebookStrategy = require('passport-facebook').Strategy
|
||||
const GitHubStrategy = require('passport-github2').Strategy
|
||||
const SlackStrategy = require('passport-slack').Strategy
|
||||
const LdapStrategy = require('passport-ldapauth').Strategy
|
||||
const fs = require('fs')
|
||||
|
||||
module.exports = function (passport) {
|
||||
// Serialization user methods
|
||||
|
||||
passport.serializeUser(function (user, done) {
|
||||
done(null, user._id)
|
||||
})
|
||||
|
||||
passport.deserializeUser(function (id, done) {
|
||||
db.User.findById(id).then((user) => {
|
||||
if (user) {
|
||||
done(null, user)
|
||||
} else {
|
||||
done(new Error('User not found.'), null)
|
||||
}
|
||||
return true
|
||||
}).catch((err) => {
|
||||
done(err, null)
|
||||
})
|
||||
})
|
||||
|
||||
// Local Account
|
||||
|
||||
if (!appdata.capabilities.manyAuthProviders || (appconfig.auth.local && appconfig.auth.local.enabled)) {
|
||||
passport.use('local',
|
||||
new LocalStrategy({
|
||||
usernameField: 'email',
|
||||
passwordField: 'password'
|
||||
},
|
||||
(uEmail, uPassword, done) => {
|
||||
db.User.findOne({ email: uEmail, provider: 'local' }).then((user) => {
|
||||
if (user) {
|
||||
return user.validatePassword(uPassword).then(() => {
|
||||
return done(null, user) || true
|
||||
}).catch((err) => {
|
||||
return done(err, null)
|
||||
})
|
||||
} else {
|
||||
return done(new Error('INVALID_LOGIN'), null)
|
||||
}
|
||||
}).catch((err) => {
|
||||
done(err, null)
|
||||
})
|
||||
}
|
||||
))
|
||||
}
|
||||
|
||||
// Google ID
|
||||
|
||||
if (appdata.capabilities.manyAuthProviders && appconfig.auth.google && appconfig.auth.google.enabled) {
|
||||
passport.use('google',
|
||||
new GoogleStrategy({
|
||||
clientID: appconfig.auth.google.clientId,
|
||||
clientSecret: appconfig.auth.google.clientSecret,
|
||||
callbackURL: appconfig.host + '/login/google/callback'
|
||||
},
|
||||
(accessToken, refreshToken, profile, cb) => {
|
||||
db.User.processProfile(profile).then((user) => {
|
||||
return cb(null, user) || true
|
||||
}).catch((err) => {
|
||||
return cb(err, null) || true
|
||||
})
|
||||
}
|
||||
))
|
||||
}
|
||||
|
||||
// Microsoft Accounts
|
||||
|
||||
if (appdata.capabilities.manyAuthProviders && appconfig.auth.microsoft && appconfig.auth.microsoft.enabled) {
|
||||
passport.use('windowslive',
|
||||
new WindowsLiveStrategy({
|
||||
clientID: appconfig.auth.microsoft.clientId,
|
||||
clientSecret: appconfig.auth.microsoft.clientSecret,
|
||||
callbackURL: appconfig.host + '/login/ms/callback'
|
||||
},
|
||||
function (accessToken, refreshToken, profile, cb) {
|
||||
db.User.processProfile(profile).then((user) => {
|
||||
return cb(null, user) || true
|
||||
}).catch((err) => {
|
||||
return cb(err, null) || true
|
||||
})
|
||||
}
|
||||
))
|
||||
}
|
||||
|
||||
// Facebook
|
||||
|
||||
if (appdata.capabilities.manyAuthProviders && appconfig.auth.facebook && appconfig.auth.facebook.enabled) {
|
||||
passport.use('facebook',
|
||||
new FacebookStrategy({
|
||||
clientID: appconfig.auth.facebook.clientId,
|
||||
clientSecret: appconfig.auth.facebook.clientSecret,
|
||||
callbackURL: appconfig.host + '/login/facebook/callback',
|
||||
profileFields: ['id', 'displayName', 'email']
|
||||
},
|
||||
function (accessToken, refreshToken, profile, cb) {
|
||||
db.User.processProfile(profile).then((user) => {
|
||||
return cb(null, user) || true
|
||||
}).catch((err) => {
|
||||
return cb(err, null) || true
|
||||
})
|
||||
}
|
||||
))
|
||||
}
|
||||
|
||||
// GitHub
|
||||
|
||||
if (appdata.capabilities.manyAuthProviders && appconfig.auth.github && appconfig.auth.github.enabled) {
|
||||
passport.use('github',
|
||||
new GitHubStrategy({
|
||||
clientID: appconfig.auth.github.clientId,
|
||||
clientSecret: appconfig.auth.github.clientSecret,
|
||||
callbackURL: appconfig.host + '/login/github/callback',
|
||||
scope: [ 'user:email' ]
|
||||
},
|
||||
(accessToken, refreshToken, profile, cb) => {
|
||||
db.User.processProfile(profile).then((user) => {
|
||||
return cb(null, user) || true
|
||||
}).catch((err) => {
|
||||
return cb(err, null) || true
|
||||
})
|
||||
}
|
||||
))
|
||||
}
|
||||
|
||||
// Slack
|
||||
|
||||
if (appdata.capabilities.manyAuthProviders && appconfig.auth.slack && appconfig.auth.slack.enabled) {
|
||||
passport.use('slack',
|
||||
new SlackStrategy({
|
||||
clientID: appconfig.auth.slack.clientId,
|
||||
clientSecret: appconfig.auth.slack.clientSecret,
|
||||
callbackURL: appconfig.host + '/login/slack/callback'
|
||||
},
|
||||
(accessToken, refreshToken, profile, cb) => {
|
||||
db.User.processProfile(profile).then((user) => {
|
||||
return cb(null, user) || true
|
||||
}).catch((err) => {
|
||||
return cb(err, null) || true
|
||||
})
|
||||
}
|
||||
))
|
||||
}
|
||||
|
||||
// LDAP
|
||||
|
||||
if (appdata.capabilities.manyAuthProviders && appconfig.auth.ldap && appconfig.auth.ldap.enabled) {
|
||||
passport.use('ldapauth',
|
||||
new LdapStrategy({
|
||||
server: {
|
||||
url: appconfig.auth.ldap.url,
|
||||
bindDn: appconfig.auth.ldap.bindDn,
|
||||
bindCredentials: appconfig.auth.ldap.bindCredentials,
|
||||
searchBase: appconfig.auth.ldap.searchBase,
|
||||
searchFilter: appconfig.auth.ldap.searchFilter,
|
||||
searchAttributes: ['displayName', 'name', 'cn', 'mail'],
|
||||
tlsOptions: (appconfig.auth.ldap.tlsEnabled) ? {
|
||||
ca: [
|
||||
fs.readFileSync(appconfig.auth.ldap.tlsCertPath)
|
||||
]
|
||||
} : {}
|
||||
},
|
||||
usernameField: 'email',
|
||||
passReqToCallback: false
|
||||
},
|
||||
(profile, cb) => {
|
||||
profile.provider = 'ldap'
|
||||
profile.id = profile.dn
|
||||
db.User.processProfile(profile).then((user) => {
|
||||
return cb(null, user) || true
|
||||
}).catch((err) => {
|
||||
return cb(err, null) || true
|
||||
})
|
||||
}
|
||||
))
|
||||
}
|
||||
|
||||
// Create users for first-time
|
||||
|
||||
db.onReady.then(() => {
|
||||
db.User.findOne({ provider: 'local', email: 'guest' }).then((c) => {
|
||||
if (c < 1) {
|
||||
// Create root admin account
|
||||
|
||||
winston.info('[AUTH] No administrator account found. Creating a new one...')
|
||||
db.User.hashPassword('admin123').then((pwd) => {
|
||||
return db.User.create({
|
||||
provider: 'local',
|
||||
email: appconfig.admin,
|
||||
name: 'Administrator',
|
||||
password: pwd,
|
||||
rights: [{
|
||||
role: 'admin',
|
||||
path: '/',
|
||||
exact: false,
|
||||
deny: false
|
||||
}]
|
||||
})
|
||||
}).then(() => {
|
||||
winston.info('[AUTH] Administrator account created successfully!')
|
||||
}).then(() => {
|
||||
if (appdata.capabilities.guest) {
|
||||
// Create guest account
|
||||
|
||||
return db.User.create({
|
||||
provider: 'local',
|
||||
email: 'guest',
|
||||
name: 'Guest',
|
||||
password: '',
|
||||
rights: [{
|
||||
role: 'read',
|
||||
path: '/',
|
||||
exact: false,
|
||||
deny: !appconfig.public
|
||||
}]
|
||||
}).then(() => {
|
||||
winston.info('[AUTH] Guest account created successfully!')
|
||||
})
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}).catch((err) => {
|
||||
winston.error('[AUTH] An error occured while creating administrator/guest account:')
|
||||
winston.error(err)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
return true
|
||||
})
|
||||
}
|
58
libs/config.js
Normal file
58
libs/config.js
Normal file
@ -0,0 +1,58 @@
|
||||
'use strict'
|
||||
|
||||
/* global winston */
|
||||
|
||||
const fs = require('fs')
|
||||
const yaml = require('js-yaml')
|
||||
const _ = require('lodash')
|
||||
|
||||
/**
|
||||
* Load Application Configuration
|
||||
*
|
||||
* @param {Object} confPaths Path to the configuration files
|
||||
* @return {Object} Application Configuration
|
||||
*/
|
||||
module.exports = (confPaths) => {
|
||||
confPaths = _.defaults(confPaths, {
|
||||
config: './config.yml',
|
||||
data: './app/data.yml'
|
||||
})
|
||||
|
||||
let appconfig = {}
|
||||
let appdata = {}
|
||||
|
||||
try {
|
||||
appconfig = yaml.safeLoad(fs.readFileSync(confPaths.config, 'utf8'))
|
||||
appdata = yaml.safeLoad(fs.readFileSync(confPaths.data, 'utf8'))
|
||||
} catch (ex) {
|
||||
winston.error(ex)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
// Merge with defaults
|
||||
|
||||
appconfig = _.defaultsDeep(appconfig, appdata.defaults.config)
|
||||
|
||||
// List authentication strategies
|
||||
|
||||
if (appdata.capabilities.manyAuthProviders) {
|
||||
appconfig.authStrategies = {
|
||||
list: _.filter(appconfig.auth, ['enabled', true]),
|
||||
socialEnabled: (_.chain(appconfig.auth).omit('local').reject({ enabled: false }).value().length > 0)
|
||||
}
|
||||
if (appconfig.authStrategies.list.length < 1) {
|
||||
winston.error(new Error('You must enable at least 1 authentication strategy!'))
|
||||
process.exit(1)
|
||||
}
|
||||
} else {
|
||||
appconfig.authStrategies = {
|
||||
list: { local: { enabled: true } },
|
||||
socialEnabled: false
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
config: appconfig,
|
||||
data: appdata
|
||||
}
|
||||
}
|
120
libs/rights.js
Normal file
120
libs/rights.js
Normal file
@ -0,0 +1,120 @@
|
||||
'use strict'
|
||||
|
||||
/* global db */
|
||||
|
||||
const _ = require('lodash')
|
||||
|
||||
/**
|
||||
* Rights
|
||||
*/
|
||||
module.exports = {
|
||||
|
||||
guest: {
|
||||
provider: 'local',
|
||||
email: 'guest',
|
||||
name: 'Guest',
|
||||
password: '',
|
||||
rights: [
|
||||
{
|
||||
role: 'read',
|
||||
path: '/',
|
||||
deny: false,
|
||||
exact: false
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
/**
|
||||
* Initialize Rights module
|
||||
*
|
||||
* @return {void} Void
|
||||
*/
|
||||
init () {
|
||||
let self = this
|
||||
|
||||
db.onReady.then(() => {
|
||||
db.User.findOne({ provider: 'local', email: 'guest' }).then((u) => {
|
||||
if (u) {
|
||||
self.guest = u
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Check user permissions for this request
|
||||
*
|
||||
* @param {object} req The request object
|
||||
* @return {object} List of permissions for this request
|
||||
*/
|
||||
check (req) {
|
||||
let self = this
|
||||
|
||||
let perm = {
|
||||
read: false,
|
||||
write: false,
|
||||
manage: false
|
||||
}
|
||||
let rt = []
|
||||
let p = _.chain(req.originalUrl).toLower().trim().value()
|
||||
|
||||
// Load User Rights
|
||||
|
||||
if (_.isArray(req.user.rights)) {
|
||||
rt = req.user.rights
|
||||
}
|
||||
|
||||
// Is admin?
|
||||
|
||||
if (_.find(rt, { role: 'admin' })) {
|
||||
perm.read = true
|
||||
perm.write = true
|
||||
perm.manage = true
|
||||
} else if (self.checkRole(p, rt, 'write')) {
|
||||
perm.read = true
|
||||
perm.write = true
|
||||
} else if (self.checkRole(p, rt, 'read')) {
|
||||
perm.read = true
|
||||
}
|
||||
|
||||
return perm
|
||||
},
|
||||
|
||||
/**
|
||||
* Check for a specific role based on list of user rights
|
||||
*
|
||||
* @param {String} p Base path
|
||||
* @param {array<object>} rt The user rights
|
||||
* @param {string} role The minimum role required
|
||||
* @return {boolean} True if authorized
|
||||
*/
|
||||
checkRole (p, rt, role) {
|
||||
// Check specific role on path
|
||||
|
||||
let filteredRights = _.filter(rt, (r) => {
|
||||
if (r.role === role || (r.role === 'write' && role === 'read')) {
|
||||
if ((!r.exact && _.startsWith(p, r.path)) || (r.exact && p === r.path)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
// Check for deny scenario
|
||||
|
||||
let isValid = false
|
||||
|
||||
if (filteredRights.length > 1) {
|
||||
isValid = !_.chain(filteredRights).sortBy((r) => {
|
||||
return r.path.length + ((r.deny) ? 0.5 : 0)
|
||||
}).last().get('deny').value()
|
||||
} else if (filteredRights.length === 1 && filteredRights[0].deny === false) {
|
||||
isValid = true
|
||||
}
|
||||
|
||||
// Deny by default
|
||||
|
||||
return isValid
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
'use strict'
|
||||
|
||||
/* global appdata, rights */
|
||||
|
||||
const moment = require('moment-timezone')
|
||||
|
||||
/**
|
||||
@ -14,13 +16,24 @@ module.exports = (req, res, next) => {
|
||||
// Is user authenticated ?
|
||||
|
||||
if (!req.isAuthenticated()) {
|
||||
return res.redirect('/login')
|
||||
if (!appdata.capabilities.guest || req.app.locals.appconfig.public !== true) {
|
||||
return res.redirect('/login')
|
||||
} else {
|
||||
req.user = rights.guest
|
||||
res.locals.isGuest = true
|
||||
}
|
||||
} else if (appdata.capabilities.guest) {
|
||||
res.locals.isGuest = false
|
||||
}
|
||||
|
||||
// Check permissions
|
||||
|
||||
if (!rights.check(req, 'read')) {
|
||||
return res.render('error-forbidden')
|
||||
if (appdata.capabilities.rights) {
|
||||
res.locals.rights = rights.check(req)
|
||||
|
||||
if (!res.locals.rights.read) {
|
||||
return res.render('error-forbidden')
|
||||
}
|
||||
}
|
||||
|
||||
// Set i18n locale
|
||||
|
@ -1,5 +1,7 @@
|
||||
'use strict'
|
||||
|
||||
/* global app */
|
||||
|
||||
/**
|
||||
* Security Middleware
|
||||
*
|
||||
|
12
package.json
12
package.json
@ -73,7 +73,7 @@
|
||||
"i18next-node-fs-backend": "^0.1.3",
|
||||
"image-size": "^0.5.1",
|
||||
"jimp": "github:ngpixel/jimp",
|
||||
"js-yaml": "^3.8.1",
|
||||
"js-yaml": "^3.8.2",
|
||||
"klaw": "^1.3.1",
|
||||
"levelup": "^1.3.5",
|
||||
"lodash": "^4.17.3",
|
||||
@ -95,13 +95,18 @@
|
||||
"multer": "^1.2.1",
|
||||
"ora": "^1.2.0",
|
||||
"passport": "^0.3.2",
|
||||
"passport-facebook": "^2.1.1",
|
||||
"passport-github2": "^0.1.10",
|
||||
"passport-google-oauth20": "^1.0.0",
|
||||
"passport-ldapauth": "^1.0.0",
|
||||
"passport-local": "^1.0.0",
|
||||
"passport-slack": "0.0.7",
|
||||
"passport-windowslive": "^1.0.2",
|
||||
"passport.socketio": "^3.7.0",
|
||||
"pm2": "^2.4.3",
|
||||
"pug": "^2.0.0-beta11",
|
||||
"read-chunk": "^2.0.0",
|
||||
"remove-markdown": "^0.1.0",
|
||||
"requarks-core": "^0.2.2",
|
||||
"request": "^2.81.0",
|
||||
"search-index-adder": "github:ngpixel/search-index-adder",
|
||||
"search-index-searcher": "github:ngpixel/search-index-searcher",
|
||||
@ -116,7 +121,7 @@
|
||||
"through2": "^2.0.3",
|
||||
"validator": "^7.0.0",
|
||||
"validator-as-promised": "^1.0.2",
|
||||
"winston": "^2.3.0"
|
||||
"winston": "^2.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-cli": "latest",
|
||||
@ -165,7 +170,6 @@
|
||||
"winston",
|
||||
"ws",
|
||||
"Mongoose",
|
||||
"CORE_PATH",
|
||||
"ROOTPATH",
|
||||
"IS_DEBUG",
|
||||
"PROCNAME",
|
||||
|
@ -9,7 +9,6 @@
|
||||
global.PROCNAME = 'SERVER'
|
||||
global.ROOTPATH = __dirname
|
||||
global.IS_DEBUG = process.env.NODE_ENV === 'development'
|
||||
global.CORE_PATH = (IS_DEBUG) ? ROOTPATH + '/../core/' : ROOTPATH + '/node_modules/requarks-core/'
|
||||
|
||||
if (IS_DEBUG) {
|
||||
try { require('newrelic') } catch (err) {}
|
||||
@ -17,7 +16,7 @@ if (IS_DEBUG) {
|
||||
|
||||
process.env.VIPS_WARNING = false
|
||||
|
||||
let appconf = require(CORE_PATH + 'core-libs/config')()
|
||||
let appconf = require('./libs/config')()
|
||||
global.appconfig = appconf.config
|
||||
global.appdata = appconf.data
|
||||
|
||||
@ -63,7 +62,7 @@ const session = require('express-session')
|
||||
const SessionMongoStore = require('connect-mongo')(session)
|
||||
const socketio = require('socket.io')
|
||||
|
||||
var mw = autoload(CORE_PATH + '/core-middlewares')
|
||||
var mw = autoload(path.join(ROOTPATH, '/middlewares'))
|
||||
var ctrl = autoload(path.join(ROOTPATH, '/controllers'))
|
||||
|
||||
// ----------------------------------------
|
||||
@ -90,8 +89,8 @@ app.use(express.static(path.join(ROOTPATH, 'assets')))
|
||||
// Passport Authentication
|
||||
// ----------------------------------------
|
||||
|
||||
require(CORE_PATH + 'core-libs/auth')(passport)
|
||||
global.rights = require(CORE_PATH + 'core-libs/rights')
|
||||
require('./libs/auth')(passport)
|
||||
global.rights = require('./libs/rights')
|
||||
rights.init()
|
||||
|
||||
var sessionStore = new SessionMongoStore({
|
||||
|
Loading…
Reference in New Issue
Block a user