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."); 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.setDefaultPage(new HttpFilePage(FileUtil.find(TraderContext.RESOURCE_WEB_ROOT)));
http.setPage("/", new HttpRedirectPage("/symbol_overview")); http.setPage("/", new HttpRedirectPage("/symbol_overview"));
http.setPage(AlertEndpoint.getInstance().getPath(), AlertEndpoint.getInstance()); http.setPage(AlertEndpoint.getInstance().getPath(), AlertEndpoint.getInstance());

View file

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

View file

@ -13,7 +13,6 @@ import java.util.Map;
public class SymbolOverviewPage extends TraderPage { 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 OVERVIEW_TEMPLATE = TraderContext.RESOURCE_WEB_ROOT + "/symbol_overview.tmpl";
private static final String DETAIL_TEMPLATE = TraderContext.RESOURCE_WEB_ROOT + "/symbol_detail.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"; @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 The Bootstrap Authors
* Copyright 2011-2021 Twitter, Inc. * Copyright 2011-2021 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * 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); -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
} }
[tabindex="-1"]:focus:not(:focus-visible) {
outline: 0 !important;
}
hr { hr {
margin: 1rem 0; margin: 1rem 0;
color: inherit; color: inherit;
@ -130,7 +126,6 @@ p {
abbr[title], abbr[title],
abbr[data-bs-original-title] { abbr[data-bs-original-title] {
text-decoration: underline;
-webkit-text-decoration: underline dotted; -webkit-text-decoration: underline dotted;
text-decoration: underline dotted; text-decoration: underline dotted;
cursor: help; cursor: help;
@ -336,6 +331,9 @@ select {
select { select {
word-wrap: normal; word-wrap: normal;
} }
select:disabled {
opacity: 1;
}
[list]::-webkit-calendar-picker-indicator { [list]::-webkit-calendar-picker-indicator {
display: none; display: none;
@ -2184,10 +2182,6 @@ progress {
.form-control::-webkit-date-and-time-value { .form-control::-webkit-date-and-time-value {
height: 1.5em; height: 1.5em;
} }
.form-control::-webkit-input-placeholder {
color: #6c757d;
opacity: 1;
}
.form-control::-moz-placeholder { .form-control::-moz-placeholder {
color: #6c757d; color: #6c757d;
opacity: 1; opacity: 1;
@ -2359,7 +2353,6 @@ textarea.form-control-lg {
background-image: none; background-image: none;
} }
.form-select:disabled { .form-select:disabled {
color: #6c757d;
background-color: #e9ecef; background-color: #e9ecef;
} }
.form-select:-moz-focusring { .form-select:-moz-focusring {
@ -2600,9 +2593,6 @@ textarea.form-control-lg {
transition: none; transition: none;
} }
} }
.form-floating > .form-control::-webkit-input-placeholder {
color: transparent;
}
.form-floating > .form-control::-moz-placeholder { .form-floating > .form-control::-moz-placeholder {
color: transparent; color: transparent;
} }
@ -2796,6 +2786,12 @@ textarea.form-control-lg {
margin-left: 0.5em; 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 { .invalid-feedback {
display: none; display: none;
width: 100%; width: 100%;
@ -2872,6 +2868,12 @@ textarea.form-control-lg {
margin-left: 0.5em; 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 { .btn {
display: inline-block; display: inline-block;
font-weight: 400; font-weight: 400;
@ -3546,11 +3548,9 @@ textarea.form-control-lg {
left: auto /* rtl:ignore */; left: auto /* rtl:ignore */;
} }
} }
.dropup .dropdown-menu { .dropup .dropdown-menu[data-bs-popper] {
top: auto; top: auto;
bottom: 100%; bottom: 100%;
}
.dropup .dropdown-menu[data-bs-popper] {
margin-top: 0; margin-top: 0;
margin-bottom: 0.125rem; margin-bottom: 0.125rem;
} }
@ -3887,6 +3887,11 @@ textarea.form-control-lg {
text-align: center; text-align: center;
} }
.nav-fill .nav-item .nav-link,
.nav-justified .nav-item .nav-link {
width: 100%;
}
.tab-content > .tab-pane { .tab-content > .tab-pane {
display: none; display: none;
} }
@ -4268,7 +4273,7 @@ textarea.form-control-lg {
text-decoration: none; text-decoration: none;
} }
.card-link + .card-link { .card-link + .card-link {
margin-left: 1rem /* rtl:ignore */; margin-left: 1rem;
} }
.card-header { .card-header {
@ -4381,8 +4386,8 @@ textarea.form-control-lg {
font-size: 1rem; font-size: 1rem;
color: #212529; color: #212529;
text-align: left; text-align: left;
background-color: transparent; background-color: #fff;
border: 1px solid rgba(0, 0, 0, 0.125); border: 0;
border-radius: 0; border-radius: 0;
overflow-anchor: none; 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; 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; transition: none;
} }
} }
.accordion-button.collapsed {
border-bottom-width: 0;
}
.accordion-button:not(.collapsed) { .accordion-button:not(.collapsed) {
color: #0c63e4; color: #0c63e4;
background-color: #e7f1ff; background-color: #e7f1ff;
box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.125);
} }
.accordion-button:not(.collapsed)::after { .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"); 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; 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-left-radius: 0.25rem;
border-top-right-radius: 0.25rem; border-top-right-radius: 0.25rem;
} }
.accordion-item:last-of-type .accordion-button.collapsed { .accordion-item:first-of-type .accordion-button {
border-bottom-width: 1px; 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-right-radius: 0.25rem;
border-bottom-left-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 { .accordion-item:last-of-type .accordion-collapse {
border-bottom-width: 1px;
border-bottom-right-radius: 0.25rem; border-bottom-right-radius: 0.25rem;
border-bottom-left-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 { .accordion-body {
padding: 1rem 1.25rem; padding: 1rem 1.25rem;
} }
.accordion-flush .accordion-button { .accordion-flush .accordion-collapse {
border-width: 0;
}
.accordion-flush .accordion-item {
border-right: 0; border-right: 0;
border-left: 0; border-left: 0;
border-radius: 0; border-radius: 0;
} }
.accordion-flush .accordion-collapse { .accordion-flush .accordion-item:first-child {
border-width: 0; border-top: 0;
} }
.accordion-flush .accordion-item:first-of-type .accordion-button { .accordion-flush .accordion-item:last-child {
border-top-width: 0; border-bottom: 0;
border-top-left-radius: 0;
border-top-right-radius: 0;
} }
.accordion-flush .accordion-item:last-of-type .accordion-button.collapsed { .accordion-flush .accordion-item .accordion-button {
border-bottom-width: 0; border-radius: 0;
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
} }
.breadcrumb { .breadcrumb {
@ -4767,6 +4776,15 @@ textarea.form-control-lg {
border-radius: 0.25rem; 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 { .list-group-item-action {
width: 100%; width: 100%;
color: #495057; color: #495057;
@ -4787,6 +4805,7 @@ textarea.form-control-lg {
position: relative; position: relative;
display: block; display: block;
padding: 0.5rem 1rem; padding: 0.5rem 1rem;
color: #212529;
text-decoration: none; text-decoration: none;
background-color: #fff; background-color: #fff;
border: 1px solid rgba(0, 0, 0, 0.125); border: 1px solid rgba(0, 0, 0, 0.125);
@ -5178,7 +5197,7 @@ textarea.form-control-lg {
position: fixed; position: fixed;
top: 0; top: 0;
left: 0; left: 0;
z-index: 1050; z-index: 1060;
display: none; display: none;
width: 100%; width: 100%;
height: 100%; height: 100%;
@ -5242,7 +5261,7 @@ textarea.form-control-lg {
position: fixed; position: fixed;
top: 0; top: 0;
left: 0; left: 0;
z-index: 1040; z-index: 1050;
width: 100vw; width: 100vw;
height: 100vh; height: 100vh;
background-color: #000; background-color: #000;
@ -5465,7 +5484,7 @@ textarea.form-control-lg {
} }
.tooltip { .tooltip {
position: absolute; position: absolute;
z-index: 1070; z-index: 1080;
display: block; display: block;
margin: 0; margin: 0;
font-family: var(--bs-font-sans-serif); font-family: var(--bs-font-sans-serif);
@ -5567,7 +5586,7 @@ textarea.form-control-lg {
position: absolute; position: absolute;
top: 0; top: 0;
left: 0 /* rtl:ignore */; left: 0 /* rtl:ignore */;
z-index: 1060; z-index: 1070;
display: block; display: block;
max-width: 276px; max-width: 276px;
font-family: var(--bs-font-sans-serif); font-family: var(--bs-font-sans-serif);
@ -5972,6 +5991,86 @@ textarea.form-control-lg {
animation-duration: 1.5s; 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 { .clearfix::after {
display: block; display: block;
clear: both; clear: both;
@ -6424,10 +6523,6 @@ textarea.form-control-lg {
border-color: #fff !important; border-color: #fff !important;
} }
.border-0 {
border-width: 0 !important;
}
.border-1 { .border-1 {
border-width: 1px !important; border-width: 1px !important;
} }
@ -7098,6 +7193,10 @@ textarea.form-control-lg {
padding-left: 3rem !important; padding-left: 3rem !important;
} }
.font-monospace {
font-family: var(--bs-font-monospace) !important;
}
.fs-1 { .fs-1 {
font-size: calc(1.375rem + 1.5vw) !important; font-size: calc(1.375rem + 1.5vw) !important;
} }
@ -7150,16 +7249,20 @@ textarea.form-control-lg {
font-weight: bolder !important; font-weight: bolder !important;
} }
.text-lowercase { .lh-1 {
text-transform: lowercase !important; line-height: 1 !important;
} }
.text-uppercase { .lh-sm {
text-transform: uppercase !important; line-height: 1.25 !important;
} }
.text-capitalize { .lh-base {
text-transform: capitalize !important; line-height: 1.5 !important;
}
.lh-lg {
line-height: 2 !important;
} }
.text-start { .text-start {
@ -7174,6 +7277,45 @@ textarea.form-control-lg {
text-align: center !important; 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 { .text-primary {
color: #0d6efd !important; color: #0d6efd !important;
} }
@ -7230,22 +7372,6 @@ textarea.form-control-lg {
color: inherit !important; 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 { .bg-primary {
background-color: #0d6efd !important; background-color: #0d6efd !important;
} }
@ -7294,37 +7420,6 @@ textarea.form-control-lg {
background-image: var(--bs-gradient) !important; 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 { .user-select-all {
-webkit-user-select: all !important; -webkit-user-select: all !important;
-moz-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 --> <!-- CSS -->
<link href="css/bootstrap.min.css" rel="stylesheet"> <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/bootstrap-switch.min.css" rel="stylesheet">
<link href="css/trader.css" rel="stylesheet"> <link href="css/trader.css" rel="stylesheet">
@ -21,59 +22,26 @@
</head> </head>
<body> <body>
<header class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0 shadow"> <main>
<a class="navbar-brand col-md-3 col-lg-2 me-0 px-3" href="#">Trader</a> <nav class="navbar navbar-expand-md navbar-dark sticky-top bg-dark flex-md-nowrap p-0 shadow">
<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"> <div class="container-fluid">
<span class="navbar-toggler-icon"></span> <a class="navbar-brand col-md-3 col-lg-2 me-0 px-3" href="#">
</button> Trader
<input class="form-control form-control-dark w-100" type="text" placeholder="Search" aria-label="Search"> </a>
<ul class="navbar-nav px-3">
<li class="nav-item text-nowrap">
<a class="nav-link" href="#">Sign out</a>
</li>
</ul>
</header>
<div class="container-fluid"> {{navigation}}
<div class="row"> </div>
<nav id="sidebarMenu" class="col-md-3 col-lg-2 d-md-block bg-light sidebar collapse"> </nav>
<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>
<h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted"> <div class="container-fluid">
<span>Saved reports</span> <div class="row">
<a class="link-secondary" href="#" aria-label="Add a new report"> {{sub_navigation}}
<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>
<main class="col-md-9 ms-sm-auto col-lg-10 px-md-4"> <main class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
{{content}} {{content}}
</main> </main>
</div>
</div> </div>
</div> </main>
</body> </body>
</html> </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="col-md-12">
<div class="panel panel-default drop-shadow"> <div class="panel panel-default drop-shadow">
<div class="panel-heading">Symbols</div> <div class="panel-heading"></div>
<div class="panel-body"> <div class="panel-body">
<table class="table table-hover table-condensed"> <table class="table table-hover table-condensed">