diff --git a/client/src/assets/components/_box.scss b/client/src/assets/components/_box.scss new file mode 100644 index 0000000..189bb06 --- /dev/null +++ b/client/src/assets/components/_box.scss @@ -0,0 +1,6 @@ +.box { + box-shadow: var(--box-shadow); + background-color: var(--box-bg-color); + color: var(--box-fg-color); + border-radius: var(--border-radius); +} diff --git a/client/src/assets/components/_button.scss b/client/src/assets/components/_button.scss index 77c3333..7db25cd 100644 --- a/client/src/assets/components/_button.scss +++ b/client/src/assets/components/_button.scss @@ -1,4 +1,5 @@ button { + font-family: var(--main-font); background: var(--button-bg-color); color: var(--button-fg-color); cursor: pointer; diff --git a/client/src/assets/components/_dashboard-header.scss b/client/src/assets/components/_dashboard-header.scss deleted file mode 100644 index 738d3db..0000000 --- a/client/src/assets/components/_dashboard-header.scss +++ /dev/null @@ -1,20 +0,0 @@ -.dashboard-head { - display: flex; - align-items: center; - margin-left: auto; - - .spacer { - margin: 0 1rem; - width: 1px; - background: var(--header-spacer-color); - height: 20px; - } - - .filter-button { - font-size: 125%; - cursor: pointer; - display: flex; - align-items: center; - margin-left: 0.5rem; - } -} diff --git a/client/src/assets/components/_form.scss b/client/src/assets/components/_form.scss new file mode 100644 index 0000000..b2eeec4 --- /dev/null +++ b/client/src/assets/components/_form.scss @@ -0,0 +1,44 @@ +form { + display: flex; + flex-direction: column; + + .input { + display: flex; + flex-direction: column; + margin-bottom: 0.5rem; + + label { + margin-bottom: 0.2rem; + } + } + + .actions { + text-align: right; + margin-top: 1rem; + + button { + padding: 0.5rem 1rem; + } + + button.cancel { + background-color: var(--button-cancel-bg-color); + color: var(--button-cancel-fg-color); + } + } +} + +form.horizontal { + flex-direction: row; + align-items: center; + + .input { + flex-direction: row; + margin-bottom: 0; + margin-right: 0.5rem; + align-items: baseline; + + label { + margin-right: 0.25rem; + } + } +} diff --git a/client/src/assets/components/_grid-sensors.scss b/client/src/assets/components/_grid-sensors.scss new file mode 100644 index 0000000..8ca5cfa --- /dev/null +++ b/client/src/assets/components/_grid-sensors.scss @@ -0,0 +1,160 @@ +.grid-sensors-container { + position: relative; + padding: 0.25rem; + flex: 1; + overflow: auto; + min-height: 0; +} + +.grid-sensors { + width: 100%; + height: 100%; + position: relative; + + .grid-box { + position: absolute; + transition: all 0.2s; + padding: 0.25rem; + box-sizing: border-box; + + .box { + position: relative; + display: flex; + flex-direction: column; + overflow: hidden; + + .body { + position: relative; + flex: 1; + } + + .box-loader { + position: absolute; + display: flex; + align-items: center; + justify-content: center; + left: 0; + right: 0; + top: 0; + bottom: 0; + background-color: var(--box-loader-bg-color); + color: var(--box-loader-fg-color); + font-size: 300%; + z-index: 2; + + .svg-icon { + animation-name: grid-loader-rotate; + animation-iteration-count: infinite; + animation-duration: 0.75s; + animation-timing-function: linear; + } + } + + .resize-h { + position: absolute; + right: 0; + top: 0; + bottom: 0; + width: 10px; + cursor: e-resize; + } + + .resize-v { + position: absolute; + right: 0; + left: 0; + bottom: 0; + height: 10px; + cursor: s-resize; + } + + .resize { + position: absolute; + right: 0; + bottom: 0; + width: 10px; + height: 10px; + cursor: se-resize; + } + + .header { + display: flex; + flex-grow: 0; + flex-shrink: 0; + overflow: hidden; + text-overflow: ellipsis; + + .drag-handle { + flex: 1; + cursor: move; + overflow: hidden; + text-overflow: ellipsis; + } + + .name { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + padding: 0.25rem 0.4rem; + } + + .actions { + margin-left: auto; + white-space: nowrap; + flex-shrink: 0; + display: flex; + align-items: center; + padding-right: 0.4rem; + opacity: 0; + transition: opacity 0.1s; + + .action { + margin-left: 0.25rem; + font-size: 110%; + cursor: pointer; + color: var(--box-action-fg-color); + } + } + } + + &:hover { + .header { + .actions { + opacity: 1; + } + } + } + + .dial { + text-align: center; + font-size: 150%; + display: flex; + align-items: center; + justify-content: center; + height: 100%; + } + } + } + + .grid-box.dragging { + transition: none; + } + + .box-preview { + position: absolute; + background-color: var(--box-preview-bg-color); + opacity: 0.5; + transition: all 0.2s; + z-index: 1; + border-radius: var(--border-radius); + } +} + +@keyframes grid-loader-rotate { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(-360deg); + } +} diff --git a/client/src/assets/components/_input.scss b/client/src/assets/components/_input.scss index d383198..56ea08a 100644 --- a/client/src/assets/components/_input.scss +++ b/client/src/assets/components/_input.scss @@ -1,5 +1,6 @@ select, input { + font-family: var(--main-font); padding: 0.15rem 0.4rem; box-sizing: border-box; border: 1px solid var(--input-border-color); @@ -18,3 +19,12 @@ input { padding: 0.1rem 0.25rem; } } + +.checkbox-label { + display: inline-flex; + align-items: center; +} + +.checkbox-label input[type="checkbox"] { + margin-top: 6px; +} diff --git a/client/src/assets/components/_user-layout.scss b/client/src/assets/components/_user-layout.scss new file mode 100644 index 0000000..20140ff --- /dev/null +++ b/client/src/assets/components/_user-layout.scss @@ -0,0 +1,105 @@ +main.layout { + height: 100%; + overflow: auto; + display: flex; + flex-direction: column; +} + +.menu { + position: fixed; + left: 0; + top: 0; + bottom: 0; + color: var(--box-fg-color); + width: 15rem; + transition: left 0.1s; + z-index: 2; + display: flex; + + .inner { + background-color: var(--box-bg-color); + flex: 1; + padding: 0.25em 0.5rem; + } + + .shadow { + width: 8px; + background: var(--menu-shadow); + flex-shrink: 0; + flex-grow: 0; + } + + .menu-close { + font-size: 150%; + cursor: pointer; + display: flex; + align-items: center; + } + + .menu-header { + display: flex; + align-items: center; + margin-bottom: 1rem; + + h2 { + font-size: 125%; + padding: 0; + margin: 0; + margin-left: 1rem; + font-weight: normal; + } + } + + nav { + display: flex; + flex-direction: column; + + a { + text-decoration: none; + } + } +} + +.menu-overlay { + background-color: var(--modal-overlay-bg-color); + z-index: 1; + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; +} + +header.header { + flex-grow: 0; + flex-shrink: 0; + + > .inner { + display: flex; + padding: 0.5rem 0.5rem; + background-color: var(--header-bg-color); + + > .menu-button { + display: flex; + align-items: center; + font-size: 125%; + cursor: pointer; + margin-right: 0.75rem; + } + } + + > .shadow { + position: absolute; + background: var(--header-shadow); + width: 100%; + height: 8px; + z-index: 1; + } +} + +section.content { + flex: 1; + overflow: auto; + display: flex; + flex-direction: column; +} diff --git a/client/src/assets/components/_filters-panel.scss b/client/src/assets/pages/_dashboard-page.scss similarity index 50% rename from client/src/assets/components/_filters-panel.scss rename to client/src/assets/pages/_dashboard-page.scss index 3584b77..46a1702 100644 --- a/client/src/assets/components/_filters-panel.scss +++ b/client/src/assets/pages/_dashboard-page.scss @@ -1,3 +1,31 @@ +.dashboard { + height: 100%; + overflow: auto; + display: flex; + flex-direction: column; +} + +.dashboard-head { + display: flex; + align-items: center; + margin-left: auto; + + .spacer { + margin: 0 1rem; + width: 1px; + background: var(--header-spacer-color); + height: 20px; + } + + .filter-button { + font-size: 125%; + cursor: pointer; + display: flex; + align-items: center; + margin-left: 0.5rem; + } +} + .filters-panel { position: fixed; right: 0; diff --git a/client/src/assets/pages/_login-page.scss b/client/src/assets/pages/_login-page.scss new file mode 100644 index 0000000..6c61e01 --- /dev/null +++ b/client/src/assets/pages/_login-page.scss @@ -0,0 +1,8 @@ +.login { + width: 300px; + margin: 2rem auto; +} + +.login .box { + padding: 1rem; +} diff --git a/client/src/assets/components/_sensors-page.scss b/client/src/assets/pages/_sensors-page.scss similarity index 78% rename from client/src/assets/components/_sensors-page.scss rename to client/src/assets/pages/_sensors-page.scss index 0f11f81..82d4d17 100644 --- a/client/src/assets/components/_sensors-page.scss +++ b/client/src/assets/pages/_sensors-page.scss @@ -97,29 +97,3 @@ } } } - -/* -@media screen and (max-width: 768px) { - .sensors-page .sensors-list { - grid-template-columns: repeat(1, 1fr); - } -} - -@media screen and (max-width: 900px) { - .sensors-page .sensors-list { - grid-template-columns: repeat(2, 1fr); - } -} - -@media screen and (max-width: 1200px) { - .sensors-page .sensors-list { - grid-template-columns: repeat(3, 1fr); - } -} - -@media screen and (max-width: 1980px) { - .sensors-page .sensors-list { - grid-template-columns: repeat(4, 1fr); - } -} -*/ diff --git a/client/src/assets/style.scss b/client/src/assets/style.scss index 8ecd5cd..87cd974 100644 --- a/client/src/assets/style.scss +++ b/client/src/assets/style.scss @@ -12,30 +12,20 @@ body { background: var(--main-bg-color); color: var(--main-fg-color); font-family: var(--main-font); + font-size: var(--font-size); } button, input, select { font-family: var(--main-font); + font-size: var(--font-size); } -@import "components/button"; -@import "components/input"; - a { color: var(--link-fg-color); } -.login { - width: 300px; - margin: 2rem auto; -} - -.login .box { - padding: 1rem; -} - #application { height: 100%; overflow: auto; @@ -43,367 +33,19 @@ a { flex-direction: column; } -main.layout { - height: 100%; - overflow: auto; - display: flex; - flex-direction: column; -} - -.menu { - position: fixed; - left: 0; - top: 0; - bottom: 0; - color: var(--box-fg-color); - width: 15rem; - transition: left 0.1s; - z-index: 2; - display: flex; -} - -.menu .inner { - background-color: var(--box-bg-color); - flex: 1; - padding: 0.25em 0.5rem; -} - -.menu .shadow { - width: 8px; - background: var(--menu-shadow); - flex-shrink: 0; - flex-grow: 0; -} - -.menu .menu-close { - font-size: 150%; - cursor: pointer; - display: flex; - align-items: center; -} - -.menu .menu-header { - display: flex; - align-items: center; - margin-bottom: 1rem; - - h2 { - font-size: 125%; - padding: 0; - margin: 0; - margin-left: 1rem; - font-weight: normal; - } -} - -.menu nav { - display: flex; - flex-direction: column; -} - -.menu nav a { - text-decoration: none; -} - -.menu-overlay { - background-color: var(--modal-overlay-bg-color); - z-index: 1; - position: fixed; - top: 0; - bottom: 0; - left: 0; - right: 0; -} - -header.header { - flex-grow: 0; - flex-shrink: 0; -} - -header.header > .inner { - display: flex; - padding: 0.5rem 0.5rem; - background-color: var(--header-bg-color); -} - -header.header > .shadow { - position: absolute; - background: var(--header-shadow); - width: 100%; - height: 8px; - z-index: 1; -} - -header.header > .inner > .menu-button { - display: flex; - align-items: center; - font-size: 125%; - cursor: pointer; - margin-right: 0.75rem; -} - -section.content { - flex: 1; - overflow: auto; - display: flex; - flex-direction: column; -} - -.sensors { - display: grid; - grid-template-columns: 1fr 1fr; - overflow: auto; - min-height: 0; - padding-top: 0.5rem; - padding-bottom: 0.5rem; -} - -@media only screen and (max-width: 1200px) { - .sensors { - grid-template-columns: 1fr; - } -} - -.box { - box-shadow: var(--box-shadow); - background-color: var(--box-bg-color); - color: var(--box-fg-color); - border-radius: var(--border-radius); -} - -@import "components/modal"; - -form { - display: flex; - flex-direction: column; -} - -form .input { - display: flex; - flex-direction: column; - margin-bottom: 0.5rem; -} - -form .input label { - margin-bottom: 0.2rem; -} - -form .actions { - text-align: right; - margin-top: 1rem; -} - -form .actions button { - padding: 0.5rem 1rem; -} - -form .actions button.cancel { - background-color: var(--button-cancel-bg-color); - color: var(--button-cancel-fg-color); -} - -form.horizontal { - flex-direction: row; - align-items: center; -} - -form.horizontal .input { - flex-direction: row; - margin-bottom: 0; - margin-right: 0.5rem; - align-items: baseline; -} - -form.horizontal .input label { - margin-right: 0.25rem; -} - -.checkbox-label { - display: inline-flex; - align-items: center; -} - -.checkbox-label input[type="checkbox"] { - margin-top: 6px; -} - -.grid-sensors-container { - position: relative; - padding: 0.25rem; - flex: 1; - overflow: auto; - min-height: 0; -} - -.grid-sensors { - width: 100%; - height: 100%; - position: relative; -} - -.grid-sensors .grid-box { - position: absolute; - transition: all 0.2s; - padding: 0.25rem; - box-sizing: border-box; -} - -.grid-sensors .grid-box.dragging { - transition: none; -} - -.grid-sensors .grid-box .box { - position: relative; - display: flex; - flex-direction: column; - overflow: hidden; -} - -.grid-sensors .grid-box .box .body { - position: relative; -} - -.grid-sensors .grid-box .box .box-loader { - position: absolute; - display: flex; - align-items: center; - justify-content: center; - left: 0; - right: 0; - top: 0; - bottom: 0; - background-color: var(--box-loader-bg-color); - color: var(--box-loader-fg-color); - font-size: 300%; - z-index: 2; -} - -.grid-sensors .grid-box .box .box-loader .svg-icon { - animation-name: rotate; - animation-iteration-count: infinite; - animation-duration: 0.75s; - animation-timing-function: linear; -} - -.grid-sensors .grid-box .box .resize-h { - position: absolute; - right: 0; - top: 0; - bottom: 0; - width: 10px; - cursor: e-resize; -} - -.grid-sensors .grid-box .box .resize-v { - position: absolute; - right: 0; - left: 0; - bottom: 0; - height: 10px; - cursor: s-resize; -} - -.grid-sensors .grid-box .box .resize { - position: absolute; - right: 0; - bottom: 0; - width: 10px; - height: 10px; - cursor: se-resize; -} - -.grid-sensors .grid-box .box .header { - display: flex; - flex-grow: 0; - flex-shrink: 0; - overflow: hidden; - text-overflow: ellipsis; -} - -.grid-sensors .grid-box .box .header .drag-handle { - flex: 1; - cursor: move; - overflow: hidden; - text-overflow: ellipsis; -} - -.grid-sensors .grid-box .box .header .name { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - padding: 0.25rem 0.4rem; -} - -.grid-sensors .grid-box .box .header .actions { - margin-left: auto; - white-space: nowrap; - flex-shrink: 0; - display: flex; - align-items: center; - padding-right: 0.4rem; - opacity: 0; - transition: opacity 0.1s; -} - -.grid-sensors .grid-box .box:hover .header .actions { - opacity: 1; -} - -.grid-sensors .grid-box .box .header .actions .action { - margin-left: 0.25rem; - font-size: 110%; - cursor: pointer; - color: var(--box-action-fg-color); -} - -.grid-sensors .grid-box .box .body { - flex: 1; -} - -.grid-sensors .grid-box .box .dial { - text-align: center; - font-size: 150%; - display: flex; - align-items: center; - justify-content: center; - height: 100%; -} - -.grid-sensors .box-preview { - position: absolute; - background-color: var(--box-preview-bg-color); - opacity: 0.5; - transition: all 0.2s; - z-index: 1; - border-radius: 0.5rem; -} - -.dashboard { - height: 100%; - overflow: auto; - display: flex; - flex-direction: column; -} - .svg-icon { height: 1em; stroke: currentColor; } -.flex-center { - display: flex; - align-items: center; -} +@import "components/button"; +@import "components/input"; +@import "components/modal"; +@import "components/form"; +@import "components/grid-sensors"; +@import "components/user-layout"; +@import "components/box"; -@keyframes rotate { - 0% { - transform: rotate(0deg); - } - 100% { - transform: rotate(-360deg); - } -} - -@import "components/dashboard-header"; -@import "components/filters-panel"; -@import "components/sensors-page"; +@import "pages/login-page"; +@import "pages/sensors-page"; +@import "pages/dashboard-page"; diff --git a/client/src/assets/themes/_basic.scss b/client/src/assets/themes/_basic.scss index f6bf1fd..0e35a06 100644 --- a/client/src/assets/themes/_basic.scss +++ b/client/src/assets/themes/_basic.scss @@ -1,5 +1,6 @@ :root { --main-font: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + --font-size: 14px; --border-radius: 0.15rem; --main-bg-color: #eee; --main-fg-color: #000; diff --git a/client/src/assets/themes/_console.scss b/client/src/assets/themes/_console.scss new file mode 100644 index 0000000..d9224fd --- /dev/null +++ b/client/src/assets/themes/_console.scss @@ -0,0 +1,67 @@ +:root { + --main-font: Consolas; + --border-radius: 0; + --main-bg-color: #000; + --main-fg-color: #fff; + --button-bg-color: #000; + --button-fg-color: #fff; + --button-hover-bg-color: #000; + --button-hover-fg-color: #fff; + --button-cancel-bg-color: transparent; + --button-cancel-fg-color: #000; + --button-remove-bg-color: transparent; + --button-remove-fg-color: #f00; + --header-bg-color: #000; + --header-spacer-color: #fff; + --header-shadow: none; + --box-bg-color: #000; + --box-fg-color: #fff; + --box-loader-bg-color: rgba(128, 128, 128, 0.3); + --box-loader-fg-color: #fff; + --box-action-fg-color: #666; + --box-preview-bg-color: #3988ff; + --box-shadow: none; + --modal-overlay-bg-color: rgba(0, 0, 0, 0.5); + --modal-bg-color: #000; + --modal-fg-color: #fff; + --confirm-overlay-bg-color: rgba(0, 0, 0, 0.7); + --graph-axis-fg-color: #777; + --graph-grid-color: rgb(30, 30, 30); + --link-fg-color: #3988ff; + --menu-shadow: none; + --filters-menu-shadow: none; + --input-border-color: var(--border-color); + --input-focus-border-color: var(--border-color); + --input-bg-color: #000; + --input-fg-color: #fff; + --border-color: #aaa; +} + +body, +select, +input, +button { + font-size: 14px; +} + +button, +.modal > .inner, +.box { + border: 1px solid var(--border-color) !important; +} + +header.header { + border-bottom: 1px solid var(--border-color); +} + +.menu > .inner { + border-right: 1px solid var(--border-color); +} + +.box .header { + border-bottom: 1px solid var(--border-color); +} + +.js-plotly-plot .plotly div { + font-family: var(--main-font); +} diff --git a/client/src/pages/dashboard/components/DashboardGrid/components/BoxGraphContent.tsx b/client/src/pages/dashboard/components/DashboardGrid/components/BoxGraphContent.tsx index b06d9de..0ae379c 100644 --- a/client/src/pages/dashboard/components/DashboardGrid/components/BoxGraphContent.tsx +++ b/client/src/pages/dashboard/components/DashboardGrid/components/BoxGraphContent.tsx @@ -38,6 +38,10 @@ export const BoxGraphContent = ({ box, data, refreshRef }: Props) => { useEffect(() => { if (bodyRef.current && values.data) { + const mainFont = getComputedStyle( + document.documentElement + ).getPropertyValue('--main-font') + const bgColor = getComputedStyle( document.documentElement ).getPropertyValue('--box-bg-color') @@ -120,6 +124,9 @@ export const BoxGraphContent = ({ box, data, refreshRef }: Props) => { pad: 5, }, height: box.h - 50, + font: { + family: mainFont, + }, }, { responsive: true,