Fixed navigation

This commit is contained in:
Ziver Koc 2021-03-27 00:47:38 +01:00
parent 158bf98871
commit 87be302902
14 changed files with 3873 additions and 2340 deletions

View file

@ -75,10 +75,6 @@ public class TraderServer {
logger.info("Initializing HTTP Server.");
TraderPage.getRootNav().createSubNav("Sensors");
TraderPage.getRootNav().createSubNav("Events").setWeight(100);
TraderPage.getRootNav().createSubNav("Settings").setWeight(200);
http.setDefaultPage(new HttpFilePage(FileUtil.find(TraderContext.RESOURCE_WEB_ROOT)));
http.setPage("/", new HttpRedirectPage("/symbol_overview"));
http.setPage(AlertEndpoint.getInstance().getPath(), AlertEndpoint.getInstance());

View file

@ -16,18 +16,21 @@ import java.util.Map;
public abstract class TraderPage implements HttpPage {
private static final String TEMPLATE_MAIN = TraderContext.RESOURCE_WEB_ROOT + "/main.tmpl";
private static final String TEMPLATE_ALERT = TraderContext.RESOURCE_WEB_ROOT + "/main_alerts.tmpl";
private static final String TEMPLATE_NAVIGATION = TraderContext.RESOURCE_WEB_ROOT + "/main_nav.tmpl";
private static final String TEMPLATE_SUB_NAVIGATION = TraderContext.RESOURCE_WEB_ROOT + "/main_subnav.tmpl";
private static Navigation rootNav = Navigation.createRootNav();
private static Navigation userNav = Navigation.createRootNav();
private String pageId;
private boolean showSubNav;
private boolean showSubNav = true;
public TraderPage(String id){
this.pageId = id;
this.showSubNav = true;
}
public String getId(){
return pageId;
}
@ -38,25 +41,26 @@ public abstract class TraderPage implements HttpPage {
Map<String, Object> session, Map<String, String> cookie,
Map<String, String> request) throws IOException {
try {
List<UserMessageManager.UserMessage> messages = TraderContext.getMessageManager().getMessages();
for (UserMessageManager.UserMessage msg : messages) {
msg.decreaseTTL();
}
Templator navigationTemplate = new Templator(FileUtil.find(TEMPLATE_NAVIGATION));
navigationTemplate.set("rootNav", rootNav.createPagedNavInstance(header).getSubNavs());
navigationTemplate.set("userNav", userNav.createPagedNavInstance(header).getSubNavs());
Templator tmpl = new Templator(FileUtil.find(TEMPLATE_MAIN));
tmpl.set("rootNav", rootNav.createPagedNavInstance(header).getSubNavs());
tmpl.set("userNav", userNav.createPagedNavInstance(header).getSubNavs());
tmpl.set("content", httpRespond(session, cookie, request));
tmpl.set("alerts", AlertEndpoint.getInstance().generateAlerts());
tmpl.set("showSubNav", showSubNav);
Templator subNavigationTemplate = null;
if (showSubNav) {
subNavigationTemplate = new Templator(FileUtil.find(TEMPLATE_SUB_NAVIGATION));
List<Navigation> breadcrumb = Navigation.getBreadcrumb(Navigation.getPagedNavigation(header));
if (!breadcrumb.isEmpty())
tmpl.set("subNav", breadcrumb.get(1).createPagedNavInstance(header).getSubNavs());
subNavigationTemplate.set("sub_navigation", breadcrumb.get(1).createPagedNavInstance(header).getSubNavs());
}
out.print(tmpl.compile());
Templator main = new Templator(FileUtil.find(TEMPLATE_MAIN));
main.set("navigation", navigationTemplate);
main.set("sub_navigation", subNavigationTemplate);
main.set("alerts", AlertEndpoint.getInstance().generateAlerts());
main.set("content", httpRespond(session, cookie, request));
out.print(main.compile());
} catch (Exception e) {
throw new IOException(e);
}

View file

@ -13,7 +13,6 @@ import java.util.Map;
public class SymbolOverviewPage extends TraderPage {
private static final int HISTORY_LIMIT = 200;
private static final String OVERVIEW_TEMPLATE = TraderContext.RESOURCE_WEB_ROOT + "/symbol_overview.tmpl";
private static final String DETAIL_TEMPLATE = TraderContext.RESOURCE_WEB_ROOT + "/symbol_detail.tmpl";

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
@charset "UTF-8";
/*!
* Bootstrap v5.0.0-beta2 (https://getbootstrap.com/)
* Bootstrap v5.0.0-beta3 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors
* Copyright 2011-2021 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
@ -56,10 +56,6 @@ body {
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
[tabindex="-1"]:focus:not(:focus-visible) {
outline: 0 !important;
}
hr {
margin: 1rem 0;
color: inherit;
@ -130,7 +126,6 @@ p {
abbr[title],
abbr[data-bs-original-title] {
text-decoration: underline;
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
cursor: help;
@ -336,6 +331,9 @@ select {
select {
word-wrap: normal;
}
select:disabled {
opacity: 1;
}
[list]::-webkit-calendar-picker-indicator {
display: none;
@ -2184,10 +2182,6 @@ progress {
.form-control::-webkit-date-and-time-value {
height: 1.5em;
}
.form-control::-webkit-input-placeholder {
color: #6c757d;
opacity: 1;
}
.form-control::-moz-placeholder {
color: #6c757d;
opacity: 1;
@ -2359,7 +2353,6 @@ textarea.form-control-lg {
background-image: none;
}
.form-select:disabled {
color: #6c757d;
background-color: #e9ecef;
}
.form-select:-moz-focusring {
@ -2600,9 +2593,6 @@ textarea.form-control-lg {
transition: none;
}
}
.form-floating > .form-control::-webkit-input-placeholder {
color: transparent;
}
.form-floating > .form-control::-moz-placeholder {
color: transparent;
}
@ -2796,6 +2786,12 @@ textarea.form-control-lg {
margin-left: 0.5em;
}
.was-validated .input-group .form-control:valid, .input-group .form-control.is-valid,
.was-validated .input-group .form-select:valid,
.input-group .form-select.is-valid {
z-index: 3;
}
.invalid-feedback {
display: none;
width: 100%;
@ -2872,6 +2868,12 @@ textarea.form-control-lg {
margin-left: 0.5em;
}
.was-validated .input-group .form-control:invalid, .input-group .form-control.is-invalid,
.was-validated .input-group .form-select:invalid,
.input-group .form-select.is-invalid {
z-index: 3;
}
.btn {
display: inline-block;
font-weight: 400;
@ -3546,11 +3548,9 @@ textarea.form-control-lg {
left: auto /* rtl:ignore */;
}
}
.dropup .dropdown-menu {
.dropup .dropdown-menu[data-bs-popper] {
top: auto;
bottom: 100%;
}
.dropup .dropdown-menu[data-bs-popper] {
margin-top: 0;
margin-bottom: 0.125rem;
}
@ -3887,6 +3887,11 @@ textarea.form-control-lg {
text-align: center;
}
.nav-fill .nav-item .nav-link,
.nav-justified .nav-item .nav-link {
width: 100%;
}
.tab-content > .tab-pane {
display: none;
}
@ -4268,7 +4273,7 @@ textarea.form-control-lg {
text-decoration: none;
}
.card-link + .card-link {
margin-left: 1rem /* rtl:ignore */;
margin-left: 1rem;
}
.card-header {
@ -4381,8 +4386,8 @@ textarea.form-control-lg {
font-size: 1rem;
color: #212529;
text-align: left;
background-color: transparent;
border: 1px solid rgba(0, 0, 0, 0.125);
background-color: #fff;
border: 0;
border-radius: 0;
overflow-anchor: none;
transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, border-radius 0.15s ease;
@ -4392,12 +4397,10 @@ textarea.form-control-lg {
transition: none;
}
}
.accordion-button.collapsed {
border-bottom-width: 0;
}
.accordion-button:not(.collapsed) {
color: #0c63e4;
background-color: #e7f1ff;
box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.125);
}
.accordion-button:not(.collapsed)::after {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%230c63e4'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
@ -4433,47 +4436,53 @@ textarea.form-control-lg {
margin-bottom: 0;
}
.accordion-item:first-of-type .accordion-button {
.accordion-item {
margin-bottom: -1px;
background-color: #fff;
border: 1px solid rgba(0, 0, 0, 0.125);
}
.accordion-item:first-of-type {
border-top-left-radius: 0.25rem;
border-top-right-radius: 0.25rem;
}
.accordion-item:last-of-type .accordion-button.collapsed {
border-bottom-width: 1px;
.accordion-item:first-of-type .accordion-button {
border-top-left-radius: calc(0.25rem - 1px);
border-top-right-radius: calc(0.25rem - 1px);
}
.accordion-item:last-of-type {
margin-bottom: 0;
border-bottom-right-radius: 0.25rem;
border-bottom-left-radius: 0.25rem;
}
.accordion-item:last-of-type .accordion-button.collapsed {
border-bottom-right-radius: calc(0.25rem - 1px);
border-bottom-left-radius: calc(0.25rem - 1px);
}
.accordion-item:last-of-type .accordion-collapse {
border-bottom-width: 1px;
border-bottom-right-radius: 0.25rem;
border-bottom-left-radius: 0.25rem;
}
.accordion-collapse {
border: solid rgba(0, 0, 0, 0.125);
border-width: 0 1px;
}
.accordion-body {
padding: 1rem 1.25rem;
}
.accordion-flush .accordion-button {
.accordion-flush .accordion-collapse {
border-width: 0;
}
.accordion-flush .accordion-item {
border-right: 0;
border-left: 0;
border-radius: 0;
}
.accordion-flush .accordion-collapse {
border-width: 0;
.accordion-flush .accordion-item:first-child {
border-top: 0;
}
.accordion-flush .accordion-item:first-of-type .accordion-button {
border-top-width: 0;
border-top-left-radius: 0;
border-top-right-radius: 0;
.accordion-flush .accordion-item:last-child {
border-bottom: 0;
}
.accordion-flush .accordion-item:last-of-type .accordion-button.collapsed {
border-bottom-width: 0;
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
.accordion-flush .accordion-item .accordion-button {
border-radius: 0;
}
.breadcrumb {
@ -4767,6 +4776,15 @@ textarea.form-control-lg {
border-radius: 0.25rem;
}
.list-group-numbered {
list-style-type: none;
counter-reset: section;
}
.list-group-numbered > li::before {
content: counters(section, ".") ". ";
counter-increment: section;
}
.list-group-item-action {
width: 100%;
color: #495057;
@ -4787,6 +4805,7 @@ textarea.form-control-lg {
position: relative;
display: block;
padding: 0.5rem 1rem;
color: #212529;
text-decoration: none;
background-color: #fff;
border: 1px solid rgba(0, 0, 0, 0.125);
@ -5178,7 +5197,7 @@ textarea.form-control-lg {
position: fixed;
top: 0;
left: 0;
z-index: 1050;
z-index: 1060;
display: none;
width: 100%;
height: 100%;
@ -5242,7 +5261,7 @@ textarea.form-control-lg {
position: fixed;
top: 0;
left: 0;
z-index: 1040;
z-index: 1050;
width: 100vw;
height: 100vh;
background-color: #000;
@ -5465,7 +5484,7 @@ textarea.form-control-lg {
}
.tooltip {
position: absolute;
z-index: 1070;
z-index: 1080;
display: block;
margin: 0;
font-family: var(--bs-font-sans-serif);
@ -5567,7 +5586,7 @@ textarea.form-control-lg {
position: absolute;
top: 0;
left: 0 /* rtl:ignore */;
z-index: 1060;
z-index: 1070;
display: block;
max-width: 276px;
font-family: var(--bs-font-sans-serif);
@ -5972,6 +5991,86 @@ textarea.form-control-lg {
animation-duration: 1.5s;
}
}
.offcanvas {
position: fixed;
bottom: 0;
z-index: 1040;
display: flex;
flex-direction: column;
max-width: 100%;
visibility: hidden;
background-color: #fff;
background-clip: padding-box;
outline: 0;
transition: transform 0.3s ease-in-out;
}
@media (prefers-reduced-motion: reduce) {
.offcanvas {
transition: none;
}
}
.offcanvas-header {
display: flex;
justify-content: space-between;
padding: 1rem 1rem;
}
.offcanvas-header .btn-close {
padding: 0.5rem 0.5rem;
margin: -0.5rem -0.5rem -0.5rem auto;
}
.offcanvas-title {
margin-bottom: 0;
line-height: 1.5;
}
.offcanvas-body {
flex-grow: 1;
padding: 1rem 1rem;
overflow-y: auto;
}
.offcanvas-start {
top: 0;
left: 0;
width: 400px;
border-right: 1px solid rgba(0, 0, 0, 0.2);
transform: translateX(-100%);
}
.offcanvas-end {
top: 0;
right: 0;
width: 400px;
border-left: 1px solid rgba(0, 0, 0, 0.2);
transform: translateX(100%);
}
.offcanvas-bottom {
right: 0;
left: 0;
height: 30vh;
max-height: 100%;
border-top: 1px solid rgba(0, 0, 0, 0.2);
transform: translateY(100%);
}
.offcanvas.show {
transform: none;
}
.offcanvas-backdrop::before {
position: fixed;
top: 0;
left: 0;
z-index: 1039;
width: 100vw;
height: 100vh;
content: "";
background-color: rgba(0, 0, 0, 0.5);
}
.clearfix::after {
display: block;
clear: both;
@ -6424,10 +6523,6 @@ textarea.form-control-lg {
border-color: #fff !important;
}
.border-0 {
border-width: 0 !important;
}
.border-1 {
border-width: 1px !important;
}
@ -7098,6 +7193,10 @@ textarea.form-control-lg {
padding-left: 3rem !important;
}
.font-monospace {
font-family: var(--bs-font-monospace) !important;
}
.fs-1 {
font-size: calc(1.375rem + 1.5vw) !important;
}
@ -7150,16 +7249,20 @@ textarea.form-control-lg {
font-weight: bolder !important;
}
.text-lowercase {
text-transform: lowercase !important;
.lh-1 {
line-height: 1 !important;
}
.text-uppercase {
text-transform: uppercase !important;
.lh-sm {
line-height: 1.25 !important;
}
.text-capitalize {
text-transform: capitalize !important;
.lh-base {
line-height: 1.5 !important;
}
.lh-lg {
line-height: 2 !important;
}
.text-start {
@ -7174,6 +7277,45 @@ textarea.form-control-lg {
text-align: center !important;
}
.text-decoration-none {
text-decoration: none !important;
}
.text-decoration-underline {
text-decoration: underline !important;
}
.text-decoration-line-through {
text-decoration: line-through !important;
}
.text-lowercase {
text-transform: lowercase !important;
}
.text-uppercase {
text-transform: uppercase !important;
}
.text-capitalize {
text-transform: capitalize !important;
}
.text-wrap {
white-space: normal !important;
}
.text-nowrap {
white-space: nowrap !important;
}
/* rtl:begin:remove */
.text-break {
word-wrap: break-word !important;
word-break: break-word !important;
}
/* rtl:end:remove */
.text-primary {
color: #0d6efd !important;
}
@ -7230,22 +7372,6 @@ textarea.form-control-lg {
color: inherit !important;
}
.lh-1 {
line-height: 1 !important;
}
.lh-sm {
line-height: 1.25 !important;
}
.lh-base {
line-height: 1.5 !important;
}
.lh-lg {
line-height: 2 !important;
}
.bg-primary {
background-color: #0d6efd !important;
}
@ -7294,37 +7420,6 @@ textarea.form-control-lg {
background-image: var(--bs-gradient) !important;
}
.text-wrap {
white-space: normal !important;
}
.text-nowrap {
white-space: nowrap !important;
}
.text-decoration-none {
text-decoration: none !important;
}
.text-decoration-underline {
text-decoration: underline !important;
}
.text-decoration-line-through {
text-decoration: line-through !important;
}
/* rtl:begin:remove */
.text-break {
word-wrap: break-word !important;
word-break: break-word !important;
}
/* rtl:end:remove */
.font-monospace {
font-family: var(--bs-font-monospace) !important;
}
.user-select-all {
-webkit-user-select: all !important;
-moz-user-select: all !important;

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -8,6 +8,7 @@
<!-- CSS -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<link href="css/bootstrap-icons.css" rel="stylesheet">
<link href="css/bootstrap-switch.min.css" rel="stylesheet">
<link href="css/trader.css" rel="stylesheet">
@ -21,59 +22,26 @@
</head>
<body>
<header class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0 shadow">
<a class="navbar-brand col-md-3 col-lg-2 me-0 px-3" href="#">Trader</a>
<button class="navbar-toggler position-absolute d-md-none collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#sidebarMenu" aria-controls="sidebarMenu" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<input class="form-control form-control-dark w-100" type="text" placeholder="Search" aria-label="Search">
<ul class="navbar-nav px-3">
<li class="nav-item text-nowrap">
<a class="nav-link" href="#">Sign out</a>
</li>
</ul>
</header>
<main>
<nav class="navbar navbar-expand-md navbar-dark sticky-top bg-dark flex-md-nowrap p-0 shadow">
<div class="container-fluid">
<a class="navbar-brand col-md-3 col-lg-2 me-0 px-3" href="#">
Trader
</a>
<div class="container-fluid">
<div class="row">
<nav id="sidebarMenu" class="col-md-3 col-lg-2 d-md-block bg-light sidebar collapse">
<div class="position-sticky pt-3">
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">
<span data-feather="home"></span>
Dashboard
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">
<span data-feather="file"></span>
Orders
</a>
</li>
</ul>
{{navigation}}
</div>
</nav>
<h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted">
<span>Saved reports</span>
<a class="link-secondary" href="#" aria-label="Add a new report">
<span data-feather="plus-circle"></span>
</a>
</h6>
<ul class="nav flex-column mb-2">
<li class="nav-item">
<a class="nav-link" href="#">
<span data-feather="file-text"></span>
Current month
</a>
</li>
</ul>
</div>
</nav>
<div class="container-fluid">
<div class="row">
{{sub_navigation}}
<main class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
{{content}}
</main>
<main class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
{{content}}
</main>
</div>
</div>
</div>
</main>
</body>
</html>

View file

@ -0,0 +1,50 @@
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarsExample04">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse">
<ul class="navbar-nav me-auto mb-2 mb-md-0">
{{#rootNav}}
{{^.getSubNavs().length}}
<li class="nav-item">
<a class="nav-link {{#.isActive()}}active{{/.isActive()}}" href="{{.getURL()}}" >{{.getName()}}</a>
</li>
{{/.getSubNavs().length}}
{{#.getSubNavs().length}}
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle {{#.isActive()}}active{{/.isActive()}}" href="#" data-bs-toggle="dropdown">{{.getName()}}</a>
<ul class="dropdown-menu">
{{#.getSubNavs()}}
<li>
<a class="dropdown-item" href="{{.getURL()}}">{{.getName()}}</a>
</li>
{{/.getSubNavs()}}
</ul>
</li>
{{/.getSubNavs().length}}
{{/rootNav}}
</ul>
<!-- User navigation -->
<ul class="navbar-nav navbar-right">
<li class="nav-item dropdown">
<a class="nav-item dropdown-toggle" href="#" data-bs-toggle="dropdown">
<i class="bi bi-person"></i>
<strong>{{user.getUsername()}}</strong>
</a>
<ul class="dropdown-menu">
<li>
<div align="center">
<img src="{{user.getAvatarUrl()}}" />
</div>
</li>
<li class="divider"></li>
{{#userNav}}
<li>
<a class="dropdown-item" href="{{.getURL()}}">{{.getName()}}</a>
</li>
{{/userNav}}
</ul>
</li>
</ul>
</div>

View file

@ -0,0 +1,12 @@
<!-- Sub navigation -->
<nav id="sub-navbar" class="col-md-3 col-lg-2 d-md-block bg-light sidebar collapse">
<div class="position-sticky pt-3">
<ul class="nav flex-column">
{{#sub_navigation}}
<li class="nav-item">
<a class="nav-link {{#.isActive()}}active{{/.isActive()}}" href="{{.getURL()}}">{{.getName()}}</a>
</li>
{{/sub_navigation}}
</ul>
</div>
</nav>

View file

@ -2,7 +2,7 @@
<div class="col-md-12">
<div class="panel panel-default drop-shadow">
<div class="panel-heading">Symbols</div>
<div class="panel-heading"></div>
<div class="panel-body">
<table class="table table-hover table-condensed">