diff --git a/.gitignore b/.gitignore index 949bb40..c838d6f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ bower_components/ node_modules/ build/ +.sass-cache/ diff --git a/Gruntfile.js b/Gruntfile.js index be42044..cdce67d 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,7 +1,7 @@ module.exports = function (grunt) { grunt.loadTasks("tasks") - grunt.registerTask("default", ["lint", "copy", "cssmin", "requirejs"]) + grunt.registerTask("default", ["lint", "copy", "sass", "requirejs"]) grunt.registerTask("lint", ["eslint"]) grunt.registerTask("dev", ["default", "connect:server", "watch"]) } diff --git a/package.json b/package.json index b9112c7..4fa0602 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "grunt-contrib-copy": "^0.5.0", "grunt-contrib-cssmin": "^0.12.2", "grunt-contrib-requirejs": "^0.4.4", + "grunt-contrib-sass": "^0.9.2", "grunt-contrib-uglify": "^0.5.1", "grunt-contrib-watch": "^0.6.1", "grunt-eslint": "^10.0.0" diff --git a/scss/_leaflet.label.scss b/scss/_leaflet.label.scss new file mode 120000 index 0000000..b96f885 --- /dev/null +++ b/scss/_leaflet.label.scss @@ -0,0 +1 @@ +../bower_components/Leaflet.label/dist/leaflet.label.css \ No newline at end of file diff --git a/scss/_leaflet.scss b/scss/_leaflet.scss new file mode 120000 index 0000000..afb51f7 --- /dev/null +++ b/scss/_leaflet.scss @@ -0,0 +1 @@ +../bower_components/leaflet/dist/leaflet.css \ No newline at end of file diff --git a/scss/main.scss b/scss/main.scss new file mode 100644 index 0000000..0589d67 --- /dev/null +++ b/scss/main.scss @@ -0,0 +1,315 @@ +@import '_leaflet'; +@import '_leaflet.label'; + +.stroke-first { + paint-order: stroke; +} + +.tabs { + list-style: none; + display: flex; +} + +.tabs li { + flex: 1; + text-align: center; + padding: 0.5em; + cursor: pointer; +} + +.tabs li:hover { + background: rgba(0, 0, 0, 0.03); + color: #dc0067; +} + +.tabs .visible { + font-weight: bold; + border-bottom: 2pt solid black; +} + +.tab { + display: none; +} + +.tab.visible { + display: block; +} + +body { + margin: 0; + padding: 0; + font-family: 'Roboto Slab', serif; + font-size: 11pt; +} + +th.sort-header::selection { + background: transparent; +} + +th.sort-header { + cursor: pointer; +} + +table th.sort-header:after { + font-family: "ionicons"; + padding-left: 0.25em; + content: '\f10d'; + visibility: hidden; +} + +table th.sort-header:hover:after { + visibility: visible; +} + +table th.sort-up:after, table th.sort-down:after, table th.sort-down:hover:after { + visibility: visible; + opacity: 0.4; +} + +table th.sort-up:after { + content: '\f104'; +} + +table.attributes th { + text-align: left; + font-weight: bold; + vertical-align: top; + padding-right: 1em; + white-space: nowrap; +} + +table.attributes td { + text-align: left !important; + width: 100%; +} + +.infobox .clients { + font-family: "ionicons"; + color: #1566A9; + word-spacing: -0.2em; +} + +.infobox { + position: relative; + box-shadow: 0px 0.5px 3px rgba(0, 0, 0, 0.16), 0px 0.5px 2px rgba(0, 0, 0, 0.24); + background: rgba(0, 0, 0, 0.02); + padding: 0.25em 0; +} + +button { + -webkit-tap-highlight-color: transparent; + font-family: "ionicons"; + box-shadow: 0px 0.5px 3px rgba(0, 0, 0, 0.16), 0px 0.5px 2px rgba(0, 0, 0, 0.24); + border-radius: 0.9em; + background: rgba(255, 255, 255, 0.7); + border: none; + cursor: pointer; + height: 1.8em; + width: 1.8em; + font-size: 20pt; + transition: box-shadow 0.5s, color 0.5s; + outline: none; +} + +button:hover { + background: white; + color: #dc0067; + box-shadow: 0px 5px 20px rgba(0, 0, 0, 0.19), 0px 3px 6px rgba(0, 0, 0, 0.23); +} + +button:active { + box-shadow: inset 0px 5px 20px rgba(0, 0, 0, 0.19), inset 0px 3px 6px rgba(0, 0, 0, 0.23); +} + +button.close { + position: absolute; + right: 0.7em; + top: 0.7em; +} + +button.close:after { + content: "\f12a"; +} + +.sidebar h2, .sidebar h3 { + padding: 0 10pt; +} + +.sidebar p, .sidebar table, .sidebar pre, .sidebar ul { + padding: 0 10pt 1em; +} + +.sidebarhandle { + position: absolute; + right: -2.5em; + top: 0.7em; + z-index: 10; + transition: right 0.5s, box-shadow 0.5s, color 0.5s, transform 0.5s; +} + +.sidebarhandle:after { + padding-right: 0.125em; + content: "\f124"; +} + +.sidebar.hidden .sidebarhandle { + transform: scale(-1, 1); +} + +.hostname { +} + +.online { + color: #558020 !important; +} + +.offline { + color: #D43E2A !important; +} + +.sidebar { + z-index: 5; + width: 40em; + box-sizing: border-box; + position: absolute; + top: 0; + left: 0; + background: white; + box-shadow: 0px 5px 20px rgba(0, 0, 0, 0.19), 0px 3px 6px rgba(0, 0, 0, 0.23); + transition: left 0.5s; +} + +.sidebar.hidden { + left: -40em; +} + +.sidebar .container { + overflow: auto; + box-sizing: border-box; +} + +.sidebar .container, .map { + height: 100vh; +} + +.sidebar .icon { + padding: 0 0.25em; +} + +.sidebar table { + width: 100%; +} + +.sidebar table th { + text-align: left; +} + +.sidebar td:not(:first-child), .sidebar th:not(:first-child) { + text-align: right; +} + +.sidebar a { + color: #1566A9; +} + +.bar { + display: block; + height: 1.4em; + background: rgba(85, 128, 32, 0.5); + position: relative; +} + +.bar span { + display: inline-block; + height: 1.4em; + background: rgba(85, 128, 32, 0.8); +} + +.bar label { + font-weight: bold; + white-space: nowrap; + color: white; + position: absolute; + right: 0.5em; +} + +.map .node-alert { + -webkit-animation: blink 2s linear; + -webkit-animation-iteration-count: infinite; + animation: blink 2s linear; + animation-iteration-count: infinite; +} + +.proportion th { + font-weight: normal; + text-align: right !important; + font-size: 0.95em; +} + +.proportion td { + text-align: left !important; + width: 100%; +} + +.proportion td, .proportion th { + white-space: nowrap; +} + +.proportion span { + display: inline-block; + height: 1.4em; + background: black; + padding: 0 0.5em; + font-weight: bold; + min-width: 1.5em; + box-sizing: border-box; +} + +@-webkit-keyframes blink { + 0% { opacity: 1.0; } + 80% { opacity: 1.0; } + 90% { opacity: 0.0; } +} + +@keyframes blink { + 0% { opacity: 1.0; } + 80% { opacity: 1.0; } + 90% { opacity: 0.0; } +} + +@media screen and (max-width: 80em) { + .sidebar { + font-size: 0.8em; + } +} + +@media screen and (max-width: 60em) { + .sidebar .container { + overflow: visible; + height: auto; + padding-top: 1em; + } + + .sidebarhandle { + display: none; + } + + .map { + height: 60vh; + } + + .sidebar { + position: static; + margin-left: 0em !important; + width: auto; + height: auto; + } + + .sidebar.hidden { + width: auto; + } + + .sidebar.hidden .sidebar .container { + display: block; + } +} diff --git a/style.css b/style.css deleted file mode 100644 index cb58bc1..0000000 --- a/style.css +++ /dev/null @@ -1,312 +0,0 @@ -.stroke-first { - paint-order: stroke; -} - -.tabs { - list-style: none; - display: flex; -} - -.tabs li { - flex: 1; - text-align: center; - padding: 0.5em; - cursor: pointer; -} - -.tabs li:hover { - background: rgba(0, 0, 0, 0.03); - color: #dc0067; -} - -.tabs .visible { - font-weight: bold; - border-bottom: 2pt solid black; -} - -.tab { - display: none; -} - -.tab.visible { - display: block; -} - -body { - margin: 0; - padding: 0; - font-family: 'Roboto Slab', serif; - font-size: 11pt; -} - -th.sort-header::selection { - background: transparent; -} - -th.sort-header { - cursor: pointer; -} - -table th.sort-header:after { - font-family: "ionicons"; - padding-left: 0.25em; - content: '\f10d'; - visibility: hidden; -} - -table th.sort-header:hover:after { - visibility: visible; -} - -table th.sort-up:after, table th.sort-down:after, table th.sort-down:hover:after { - visibility: visible; - opacity: 0.4; -} - -table th.sort-up:after { - content: '\f104'; -} - -table.attributes th { - text-align: left; - font-weight: bold; - vertical-align: top; - padding-right: 1em; - white-space: nowrap; -} - -table.attributes td { - text-align: left !important; - width: 100%; -} - -.infobox .clients { - font-family: "ionicons"; - color: #1566A9; - word-spacing: -0.2em; -} - -.infobox { - position: relative; - box-shadow: 0px 0.5px 3px rgba(0, 0, 0, 0.16), 0px 0.5px 2px rgba(0, 0, 0, 0.24); - background: rgba(0, 0, 0, 0.02); - padding: 0.25em 0; -} - -button { - -webkit-tap-highlight-color: transparent; - font-family: "ionicons"; - box-shadow: 0px 0.5px 3px rgba(0, 0, 0, 0.16), 0px 0.5px 2px rgba(0, 0, 0, 0.24); - border-radius: 0.9em; - background: rgba(255, 255, 255, 0.7); - border: none; - cursor: pointer; - height: 1.8em; - width: 1.8em; - font-size: 20pt; - transition: box-shadow 0.5s, color 0.5s; - outline: none; -} - -button:hover { - background: white; - color: #dc0067; - box-shadow: 0px 5px 20px rgba(0, 0, 0, 0.19), 0px 3px 6px rgba(0, 0, 0, 0.23); -} - -button:active { - box-shadow: inset 0px 5px 20px rgba(0, 0, 0, 0.19), inset 0px 3px 6px rgba(0, 0, 0, 0.23); -} - -button.close { - position: absolute; - right: 0.7em; - top: 0.7em; -} - -button.close:after { - content: "\f12a"; -} - -.sidebar h2, .sidebar h3 { - padding: 0 10pt; -} - -.sidebar p, .sidebar table, .sidebar pre, .sidebar ul { - padding: 0 10pt 1em; -} - -.sidebarhandle { - position: absolute; - right: -2.5em; - top: 0.7em; - z-index: 10; - transition: right 0.5s, box-shadow 0.5s, color 0.5s, transform 0.5s; -} - -.sidebarhandle:after { - padding-right: 0.125em; - content: "\f124"; -} - -.sidebar.hidden .sidebarhandle { - transform: scale(-1, 1); -} - -.hostname { -} - -.online { - color: #558020 !important; -} - -.offline { - color: #D43E2A !important; -} - -.sidebar { - z-index: 5; - width: 40em; - box-sizing: border-box; - position: absolute; - top: 0; - left: 0; - background: white; - box-shadow: 0px 5px 20px rgba(0, 0, 0, 0.19), 0px 3px 6px rgba(0, 0, 0, 0.23); - transition: left 0.5s; -} - -.sidebar.hidden { - left: -40em; -} - -.sidebar .container { - overflow: auto; - box-sizing: border-box; -} - -.sidebar .container, .map { - height: 100vh; -} - -.sidebar .icon { - padding: 0 0.25em; -} - -.sidebar table { - width: 100%; -} - -.sidebar table th { - text-align: left; -} - -.sidebar td:not(:first-child), .sidebar th:not(:first-child) { - text-align: right; -} - -.sidebar a { - color: #1566A9; -} - -.bar { - display: block; - height: 1.4em; - background: rgba(85, 128, 32, 0.5); - position: relative; -} - -.bar span { - display: inline-block; - height: 1.4em; - background: rgba(85, 128, 32, 0.8); -} - -.bar label { - font-weight: bold; - white-space: nowrap; - color: white; - position: absolute; - right: 0.5em; -} - -.map .node-alert { - -webkit-animation: blink 2s linear; - -webkit-animation-iteration-count: infinite; - animation: blink 2s linear; - animation-iteration-count: infinite; -} - -.proportion th { - font-weight: normal; - text-align: right !important; - font-size: 0.95em; -} - -.proportion td { - text-align: left !important; - width: 100%; -} - -.proportion td, .proportion th { - white-space: nowrap; -} - -.proportion span { - display: inline-block; - height: 1.4em; - background: black; - padding: 0 0.5em; - font-weight: bold; - min-width: 1.5em; - box-sizing: border-box; -} - -@-webkit-keyframes blink { - 0% { opacity: 1.0; } - 80% { opacity: 1.0; } - 90% { opacity: 0.0; } -} - -@keyframes blink { - 0% { opacity: 1.0; } - 80% { opacity: 1.0; } - 90% { opacity: 0.0; } -} - -@media screen and (max-width: 80em) { - .sidebar { - font-size: 0.8em; - } -} - -@media screen and (max-width: 60em) { - .sidebar .container { - overflow: visible; - height: auto; - padding-top: 1em; - } - - .sidebarhandle { - display: none; - } - - .map { - height: 60vh; - } - - .sidebar { - position: static; - margin-left: 0em !important; - width: auto; - height: auto; - } - - .sidebar.hidden { - width: auto; - } - - .sidebar.hidden .sidebar .container { - display: block; - } -} diff --git a/style.css b/style.css new file mode 120000 index 0000000..6da54f6 --- /dev/null +++ b/style.css @@ -0,0 +1 @@ +build/style.css \ No newline at end of file diff --git a/tasks/build.js b/tasks/build.js index 4fc62ce..1846ec7 100644 --- a/tasks/build.js +++ b/tasks/build.js @@ -32,6 +32,16 @@ module.exports = function(grunt) { cwd: "bower_components/ionicons/" } }, + sass: { + dist: { + options: { + style: "compressed" + }, + files: { + "build/style.css": "scss/main.scss" + } + } + }, cssmin: { target: { files: { @@ -59,5 +69,5 @@ module.exports = function(grunt) { grunt.loadNpmTasks("grunt-contrib-copy") grunt.loadNpmTasks("grunt-contrib-requirejs") - grunt.loadNpmTasks("grunt-contrib-cssmin") + grunt.loadNpmTasks("grunt-contrib-sass") }