mirror of
https://github.com/mentos1386/zdravko.git
synced 2024-11-21 15:26:29 +00:00
feat: sidebar design
This commit is contained in:
parent
b07297cf31
commit
cfc5668c48
10 changed files with 77 additions and 32 deletions
|
@ -20,7 +20,7 @@ trigger: |
|
|||
}
|
||||
|
||||
# Example monitor code
|
||||
monitor: |
|
||||
check: |
|
||||
import http from 'k6/http';
|
||||
|
||||
export const options = {
|
||||
|
|
|
@ -15,8 +15,8 @@ type IndexData struct {
|
|||
*components.Base
|
||||
Checks map[string]ChecksAndStatus
|
||||
ChecksLength int
|
||||
TimeRange string
|
||||
Status models.CheckStatus
|
||||
TimeRange string
|
||||
Status models.CheckStatus
|
||||
}
|
||||
|
||||
type Check struct {
|
||||
|
@ -33,11 +33,11 @@ type HistoryItem struct {
|
|||
|
||||
type History struct {
|
||||
List []HistoryItem
|
||||
Uptime int
|
||||
Uptime float64
|
||||
}
|
||||
|
||||
type ChecksAndStatus struct {
|
||||
Status models.CheckStatus
|
||||
Status models.CheckStatus
|
||||
Checks []*Check
|
||||
}
|
||||
|
||||
|
@ -47,8 +47,8 @@ func getDateString(date time.Time) string {
|
|||
|
||||
func getHistory(history []*models.CheckHistory, period time.Duration, buckets int) *History {
|
||||
historyMap := map[string]models.CheckStatus{}
|
||||
numOfSuccess := 0
|
||||
numTotal := 0
|
||||
numOfSuccess := 0.0
|
||||
numTotal := 0.0
|
||||
|
||||
for i := 0; i < buckets; i++ {
|
||||
dateString := getDateString(time.Now().Add(period * time.Duration(-i)).Truncate(period))
|
||||
|
@ -88,9 +88,9 @@ func getHistory(history []*models.CheckHistory, period time.Duration, buckets in
|
|||
}
|
||||
}
|
||||
|
||||
uptime := 0
|
||||
uptime := 0.0
|
||||
if numTotal > 0 {
|
||||
uptime = 100 * numOfSuccess / numTotal
|
||||
uptime = 100.0 * numOfSuccess / numTotal
|
||||
}
|
||||
|
||||
return &History{
|
||||
|
@ -160,7 +160,7 @@ func (h *BaseHandler) Index(c echo.Context) error {
|
|||
checksByGroup := map[string]ChecksAndStatus{}
|
||||
for _, check := range checksWithHistory {
|
||||
checksByGroup[check.Group] = ChecksAndStatus{
|
||||
Status: statusByGroup[check.Group],
|
||||
Status: statusByGroup[check.Group],
|
||||
Checks: append(checksByGroup[check.Group].Checks, check),
|
||||
}
|
||||
}
|
||||
|
@ -172,7 +172,7 @@ func (h *BaseHandler) Index(c echo.Context) error {
|
|||
NavbarActive: GetPageByTitle(Pages, "Status"),
|
||||
Navbar: Pages,
|
||||
},
|
||||
Checks: checksByGroup,
|
||||
Checks: checksByGroup,
|
||||
TimeRange: timeRange,
|
||||
Status: overallStatus,
|
||||
})
|
||||
|
|
|
@ -15,18 +15,37 @@ type SettingsSidebarGroup struct {
|
|||
|
||||
type Settings struct {
|
||||
*components.Base
|
||||
SettingsGroupName string
|
||||
SettingsSidebarActive *components.Page
|
||||
SettingsSidebar []SettingsSidebarGroup
|
||||
User *AuthenticatedUser
|
||||
SettingsBreadcrumbs []*components.Page
|
||||
}
|
||||
|
||||
func findGroupForPage(groups []SettingsSidebarGroup, page *components.Page) *SettingsSidebarGroup {
|
||||
for _, group := range groups {
|
||||
for _, p := range group.Pages {
|
||||
if p == page {
|
||||
return &group
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewSettings(user *AuthenticatedUser, page *components.Page, breadCrumbs []*components.Page) *Settings {
|
||||
groupName := ""
|
||||
group := findGroupForPage(SettingsSidebar, page)
|
||||
if group != nil {
|
||||
groupName = group.Group
|
||||
}
|
||||
|
||||
return &Settings{
|
||||
Base: &components.Base{
|
||||
NavbarActive: GetPageByTitle(Pages, "Settings"),
|
||||
Navbar: Pages,
|
||||
},
|
||||
SettingsGroupName: groupName,
|
||||
SettingsSidebarActive: page,
|
||||
SettingsSidebar: SettingsSidebar,
|
||||
SettingsBreadcrumbs: breadCrumbs,
|
||||
|
@ -35,7 +54,7 @@ func NewSettings(user *AuthenticatedUser, page *components.Page, breadCrumbs []*
|
|||
}
|
||||
|
||||
var SettingsPages = []*components.Page{
|
||||
{Path: "/settings", Title: "Overview", Breadcrumb: "Overview"},
|
||||
{Path: "/settings", Title: "Home", Breadcrumb: "Home"},
|
||||
{Path: "/settings/incidents", Title: "Incidents", Breadcrumb: "Incidents"},
|
||||
{Path: "/settings/targets", Title: "Targets", Breadcrumb: "Targets"},
|
||||
{Path: "/settings/targets/create", Title: "Targets Create", Breadcrumb: "Create"},
|
||||
|
@ -57,7 +76,7 @@ var SettingsSidebar = []SettingsSidebarGroup{
|
|||
{
|
||||
Group: "Overview",
|
||||
Pages: []*components.Page{
|
||||
GetPageByTitle(SettingsPages, "Overview"),
|
||||
GetPageByTitle(SettingsPages, "Home"),
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -91,7 +110,7 @@ var SettingsSidebar = []SettingsSidebarGroup{
|
|||
},
|
||||
}
|
||||
|
||||
type SettingsOverview struct {
|
||||
type SettingsHome struct {
|
||||
*Settings
|
||||
WorkerGroupsCount int
|
||||
ChecksCount int
|
||||
|
@ -99,7 +118,7 @@ type SettingsOverview struct {
|
|||
History []*services.CheckHistoryWithCheck
|
||||
}
|
||||
|
||||
func (h *BaseHandler) SettingsOverviewGET(c echo.Context) error {
|
||||
func (h *BaseHandler) SettingsHomeGET(c echo.Context) error {
|
||||
cc := c.(AuthenticatedContext)
|
||||
ctx := c.Request().Context()
|
||||
|
||||
|
@ -118,11 +137,11 @@ func (h *BaseHandler) SettingsOverviewGET(c echo.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
return c.Render(http.StatusOK, "settings_overview.tmpl", SettingsOverview{
|
||||
return c.Render(http.StatusOK, "settings_home.tmpl", SettingsHome{
|
||||
Settings: NewSettings(
|
||||
cc.Principal.User,
|
||||
GetPageByTitle(SettingsPages, "Overview"),
|
||||
[]*components.Page{GetPageByTitle(SettingsPages, "Overview")},
|
||||
GetPageByTitle(SettingsPages, "Home"),
|
||||
[]*components.Page{GetPageByTitle(SettingsPages, "Home")},
|
||||
),
|
||||
WorkerGroupsCount: workerGroups,
|
||||
ChecksCount: checks,
|
||||
|
|
|
@ -52,7 +52,7 @@ func Routes(
|
|||
// Settings
|
||||
settings := e.Group("/settings")
|
||||
settings.Use(h.Authenticated)
|
||||
settings.GET("", h.SettingsOverviewGET)
|
||||
settings.GET("", h.SettingsHomeGET)
|
||||
|
||||
settings.GET("/triggers", h.SettingsTriggersGET)
|
||||
settings.GET("/triggers/:id", h.SettingsTriggersDescribeGET)
|
||||
|
|
|
@ -64,11 +64,11 @@ code {
|
|||
@apply bg-blue-700 text-white;
|
||||
}
|
||||
|
||||
.monitors .time-range > a {
|
||||
.checks .time-range > a {
|
||||
@apply font-medium text-sm px-2.5 py-1 rounded-lg;
|
||||
@apply text-black bg-gray-100 hover:bg-gray-300 focus:outline-none focus:ring-2 focus:ring-gray-400;
|
||||
}
|
||||
.monitors .time-range > a.active {
|
||||
.checks .time-range > a.active {
|
||||
@apply bg-white hover:bg-gray-300 shadow;
|
||||
}
|
||||
|
||||
|
|
|
@ -1404,7 +1404,7 @@ code {
|
|||
color: rgb(255 255 255 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.monitors .time-range > a {
|
||||
.checks .time-range > a {
|
||||
border-radius: 0.5rem;
|
||||
padding-left: 0.625rem;
|
||||
padding-right: 0.625rem;
|
||||
|
@ -1419,12 +1419,12 @@ code {
|
|||
color: rgb(0 0 0 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.monitors .time-range > a:hover {
|
||||
.checks .time-range > a:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(209 213 219 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.monitors .time-range > a:focus {
|
||||
.checks .time-range > a:focus {
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: 2px;
|
||||
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
||||
|
@ -1434,7 +1434,7 @@ code {
|
|||
--tw-ring-color: rgb(156 163 175 / var(--tw-ring-opacity));
|
||||
}
|
||||
|
||||
.monitors .time-range > a.active {
|
||||
.checks .time-range > a.active {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
|
||||
--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
|
||||
|
@ -1442,7 +1442,7 @@ code {
|
|||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||
}
|
||||
|
||||
.monitors .time-range > a.active:hover {
|
||||
.checks .time-range > a.active:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(209 213 219 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
@ -1772,6 +1772,17 @@ code {
|
|||
--tw-ring-color: rgb(252 165 165 / var(--tw-ring-opacity));
|
||||
}
|
||||
|
||||
.has-\[\.active\]\:bg-white:has(.active) {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.has-\[\.active\]\:shadow-md:has(.active) {
|
||||
--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
|
||||
--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.sm\:w-auto {
|
||||
width: auto;
|
||||
|
|
|
@ -14,13 +14,15 @@
|
|||
class="sidebar gap-2 flex flex-row flex-wrap justify-center lg:flex-col lg:w-48 h-fit text-sm font-medium text-gray-900"
|
||||
>
|
||||
{{ range .SettingsSidebar }}
|
||||
<li class="flex items-center gap-1 lg:flex-col lg:items-start">
|
||||
<li
|
||||
class="flex items-center gap-2 p-2 lg:flex-col lg:items-start rounded-lg has-[.active]:shadow-md has-[.active]:bg-white"
|
||||
>
|
||||
<p
|
||||
class="text-xs font-semibold text-gray-600 uppercase tracking-wider"
|
||||
>
|
||||
{{ .Group }}
|
||||
</p>
|
||||
<ul class="flex flex-row flex-wrap gap-1 lg:flex-col">
|
||||
<ul class="flex flex-row flex-wrap gap-1 lg:flex-col w-full">
|
||||
{{ range .Pages }}
|
||||
<li>
|
||||
<a
|
||||
|
@ -67,6 +69,19 @@
|
|||
class="mx-8 lg:mx-0 grid justify-center lg:justify-start"
|
||||
>
|
||||
<ol class="inline-flex items-center">
|
||||
<li class="inline-flex items-center">
|
||||
<p
|
||||
class="inline-flex items-center text-sm font-medium text-gray-700"
|
||||
>
|
||||
{{ .SettingsGroupName }}
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="feather h-4 w-4 mx-1 text-gray-400 overflow-visible"
|
||||
>
|
||||
<use href="/static/icons/feather-sprite.svg#chevron-right" />
|
||||
</svg>
|
||||
</p>
|
||||
</li>
|
||||
{{ range .SettingsBreadcrumbs }}
|
||||
<li class="inline-flex items-center">
|
||||
<a
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
<p
|
||||
class="mb-8 text-l font-normal text-gray-700 lg:text-l sm:px-8 lg:px-40"
|
||||
>
|
||||
Create a check to check your services and get notified when they
|
||||
are down.
|
||||
Create a check to check your services and get notified when they are
|
||||
down.
|
||||
</p>
|
||||
<div class="flex flex-col gap-4 sm:flex-row sm:justify-center">
|
||||
<a
|
||||
|
@ -138,7 +138,7 @@
|
|||
<h4>{{ .Name }}</h4>
|
||||
</div>
|
||||
<div class="justify-self-end text-sm">
|
||||
{{ .History.Uptime }}% uptime
|
||||
{{ printf "%.2f" .History.Uptime }}% uptime
|
||||
</div>
|
||||
<div
|
||||
class="grid gap-px col-span-2 grid-flow-col h-8 rounded overflow-hidden"
|
||||
|
|
|
@ -46,7 +46,7 @@ func NewTemplates() *Templates {
|
|||
"404.tmpl": load("pages/404.tmpl"),
|
||||
"index.tmpl": load("pages/index.tmpl"),
|
||||
"incidents.tmpl": load("pages/incidents.tmpl"),
|
||||
"settings_overview.tmpl": loadSettings("pages/settings_overview.tmpl"),
|
||||
"settings_home.tmpl": loadSettings("pages/settings_home.tmpl"),
|
||||
"settings_triggers.tmpl": loadSettings("pages/settings_triggers.tmpl"),
|
||||
"settings_triggers_create.tmpl": loadSettings("pages/settings_triggers_create.tmpl"),
|
||||
"settings_triggers_describe.tmpl": loadSettings("pages/settings_triggers_describe.tmpl"),
|
Loading…
Reference in a new issue