Skip to content

Commit

Permalink
Add dashboard menu (in progress)
Browse files Browse the repository at this point in the history
Fix some CSS hell.
  • Loading branch information
hspaay committed Aug 28, 2024
1 parent 0c6623b commit c6fa74d
Show file tree
Hide file tree
Showing 22 changed files with 259 additions and 162 deletions.
2 changes: 1 addition & 1 deletion bindings/hiveoview/src/session/ClientSession.go
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ func (cs *ClientSession) SendNotify(ntype NotifyType, text string) {
func (cs *ClientSession) SendSSE(event string, content string) {
cs.mux.RLock()
defer cs.mux.RUnlock()
slog.Debug("sending sse event", "event", event, "nr clients", len(cs.sseClients))
slog.Info("sending sse event", "event", event, "nr clients", len(cs.sseClients))
for _, c := range cs.sseClients {
c <- SSEEvent{event, content}
}
Expand Down
26 changes: 1 addition & 25 deletions bindings/hiveoview/src/session/DashboardModel.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,27 +36,6 @@ type TileSource struct {
Title string `json:"title"`
}

// Affordance returns the event affordance of the tile source
//func (source *TileSource) Affordance() *things.EventAffordance {
// td := source.TD()
// aff := td.GetEvent(source.Key)
// if aff == nil {
// // return a dummy
// aff = &things.EventAffordance{
// Data: &things.DataSchema{},
// Title: "not found",
// }
// }
// return aff
//}

// Schema the dataschema of the tile source
//func (source *TileSource) Schema() *things.DataSchema {
// aff := source.Affordance()
// ds := aff.Data
// return ds
//}

// DashboardTile defines the configuration of a dashboard tile
type DashboardTile struct {
// ID of the tile, links to the ID in the layout
Expand Down Expand Up @@ -88,10 +67,7 @@ type DashboardModel struct {
// Tiles in this dashboard
Tiles map[string]DashboardTile `json:"tiles"`

// Next ID to use
NextTileID int `json:"nextTileID"`

// serialized layout
// Serialized layout from gridstack.js
// eg []{"id":,"x":,"y":,"w":,"h":}
GridLayout string `json:"layout"`
}
Expand Down
52 changes: 44 additions & 8 deletions bindings/hiveoview/src/views/app/appHead.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,41 @@ package app

import (
"github.com/hiveot/hub/bindings/hiveoview/src/session"
"github.com/hiveot/hub/lib/utils"
"net/http"
)

const AppHeadTemplate = "appHead.gohtml"

// dashboard paths
const RenderAddDashboardPath = "/dashboard/add"
const RenderConfirmDeleteDashboardPath = "/dashboard/{dashboardID}/confirmDelete"
const RenderDashboardPath = "/dashboard/{dashboardID}"
const RenderEditDashboardPath = "/dashboard/{dashboardID}/config"
const RenderNewTilePath = "/tile/{dashboardID}/new"

//const AppMenuTemplate = "appMenu.gohtml"
//const DashboardMenuTemplate = "dashboardMenu.gohtml"

// AppHeadDashboardData contains the rendering a dashboard menu
type AppHeadDashboardData struct {
// dashboard title
Title string
// paths
RenderDashboardPath string
RenderNewTilePath string
RenderConfirmDeleteDashboardPath string
RenderEditDashboardPath string
RenderAddDashboardPath string
}

// AppHeadTemplateData contains the rendering information for the application header
type AppHeadTemplateData struct {
Ready bool
Logo string
Title string
Status *ConnectStatus
Ready bool
Logo string
Title string
Status *ConnectStatus
AppHeadDashboards []AppHeadDashboardData
}

// RenderAppHead renders the app header fragment
Expand All @@ -22,11 +45,24 @@ func RenderAppHead(w http.ResponseWriter, r *http.Request) {
sess, _, _ := session.GetSessionFromContext(r)

data := AppHeadTemplateData{
Ready: true,
Logo: "/static/logo.svg",
Title: "HiveOT",
Status: GetConnectStatus(r),
Ready: true,
Logo: "/static/logo.svg",
Title: "HiveOT",
Status: GetConnectStatus(r),
AppHeadDashboards: []AppHeadDashboardData{},
}
// add the dashboard menus
dashboardID := "default" // todo: get from client data model
pathArgs := map[string]string{"dashboardID": dashboardID}
dashboardData := AppHeadDashboardData{
Title: dashboardID,
RenderDashboardPath: utils.Substitute(RenderDashboardPath, pathArgs),
RenderNewTilePath: utils.Substitute(RenderNewTilePath, pathArgs),
RenderConfirmDeleteDashboardPath: utils.Substitute(RenderConfirmDeleteDashboardPath, pathArgs),
RenderEditDashboardPath: utils.Substitute(RenderEditDashboardPath, pathArgs),
RenderAddDashboardPath: utils.Substitute(RenderAddDashboardPath, pathArgs),
}
data.AppHeadDashboards = append(data.AppHeadDashboards, dashboardData)
buff, err := RenderAppOrFragment(r, AppHeadTemplate, data)
sess.WritePage(w, buff, err)
}
32 changes: 20 additions & 12 deletions bindings/hiveoview/src/views/app/appHead.gohtml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

{{else}}

<nav class="container-fluid h-row">
<nav class="container-fluid h-row" style="height:60px">
<a href="/status"
hx-get="/status"
hx-swap="innerHTML"
Expand All @@ -24,17 +24,25 @@

<!-- === Tabs for selecting (not loading) application pages === -->
<!-- The h-navbar css highlights the li with class 'h-target', set by selectURLTargets() -->
<ul class="h-navbar">
<!-- TODO: use a link component which handles the onclick and stop propagation-->
{{/* The navigation buttons both select and reload the page*/}}
<li><a href="/dashboard"
hx-get="/dashboard"
hx-target="#dashboardPage"
hx-on::after-request="window.navigateTo(event,this.href)"
hx-swap="innerHTML"
>
Dashboard</a></li>
<li><a href="/directory"
<ul class="h-navbar" style="height:100%">
{{/* The navigation buttons both select and reload the page*/}}
{{range .AppHeadDashboards}}
<li class="h-row" style="height:100%">
<a href="{{.RenderDashboardPath}}"
hx-get="{{.RenderDashboardPath}}"
hx-target="#dashboardPage"
hx-on::after-request="window.navigateTo(event,this.href)"
hx-swap="innerHTML"
>
{{.Title}}
</a>

{{template "dashboardMenu.gohtml" .}}
</li>
{{end}}

<li style="height:100%">
<a href="/directory"
hx-get="/directory"
hx-target="#directoryPage"
hx-on::after-request="window.navigateTo(event,this.href)"
Expand Down
30 changes: 0 additions & 30 deletions bindings/hiveoview/src/views/app/appMenu.gohtml
Original file line number Diff line number Diff line change
Expand Up @@ -41,33 +41,3 @@
</ul>
</h-dropdown>

<style>

h-dropdown li {
display: flex;
flex-direction: row;
align-items: center;
gap: 7px;
width: 100%;

/*align-items: start;*/
/*margin: 0;*/
}

/*h-dropdown li:has(a.h-target) {*/
/* background-color: var(--pico-form-element-selected-background-color);*/
/*}*/
h-dropdown li.h-target {
background-color: var(--pico-form-element-selected-background-color);
}

.menu-checkbox {
width: 20px;
height: 20px;
margin-left: 0;
margin-top: 0;
margin-bottom: 0;
}

</style>

41 changes: 41 additions & 0 deletions bindings/hiveoview/src/views/dashboard/dashboardMenu.gohtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{{- /*gotype:AppHeadTemplateData*/ -}}

<!-- dropdown menu -->
<h-dropdown position="bottomright" >
<button slot="button" class="h-icon-button outline" style="border:none">
<iconify-icon icon="mdi:menu"></iconify-icon>
</button>

<ul class="h-shadow"
hx-params="none"
hx-swap="innerHTML"
hx-target="#dashboardDialog">

<li hx-get="{{.RenderNewTilePath}}"
hx-target="#dashboardDialog">
<iconify-icon icon='mdi:tab-plus'></iconify-icon>
Add Tile
</li>

<li class="h-horizontal-divider"></li>

<li hx-get="{{.RenderEditDashboardPath}}">
<iconify-icon icon='mdi:view-dashboard-edit'></iconify-icon>
Edit Dashboard
</li>

<li hx-get="{{.RenderAddDashboardPath}}">
<iconify-icon icon='mdi:plus'></iconify-icon>
Add Dashboard
</li>

<li hx-get="{{.RenderConfirmDeleteDashboardPath}}"
>
<iconify-icon icon="mdi:delete"></iconify-icon>
Delete Dashboard
</li>

</ul>
</h-dropdown>


Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<h-modal show showClose showCancel showSubmit>
<article>
<header class="h-row-centered">
<h3>Confirm Delete TD Document</h3>
<h4 style="margin-bottom:0">Confirm Delete TD Document</h4>
</header>

<form id="confirm-form">
Expand All @@ -21,7 +21,7 @@
</fieldset>
</form>

<footer class="h-row">
<footer>
{{- /*close-modal is handled by h-modal component*/ -}}
<button id="cancelBtn"
onclick="this.dispatchEvent(new Event('close-modal',{bubbles:true}))"
Expand All @@ -46,8 +46,8 @@
ev.stopImmediatePropagation()
let details = ev.detail
if (details.successful) {
modal = btn.parentElement.parentElement
modal.closeModal()
let closeEv = new Event('close-modal',{bubbles:true})
btn.dispatchEvent(closeEv)
}
}
</script>
11 changes: 7 additions & 4 deletions bindings/hiveoview/src/views/directory/SubmitDeleteTD.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ func SubmitDeleteTD(w http.ResponseWriter, r *http.Request) {
var hc hubclient.IHubClient

// get the hub client connection and read the existing TD
mySession, hc, err := session.GetSessionFromContext(r)
sess, hc, err := session.GetSessionFromContext(r)
if err != nil {
// TODO: redirect to login?
mySession.WriteError(w, err, http.StatusBadRequest)
sess.WriteError(w, err, http.StatusBadRequest)
return
}

Expand All @@ -40,16 +40,19 @@ func SubmitDeleteTD(w http.ResponseWriter, r *http.Request) {
slog.Info("Deleting TD", slog.String("thingID", thingID))
err = digitwin.DirectoryRemoveTD(hc, thingID)
}
cts := sess.GetConsumedThingsSession()
// reload the cached directory
cts.ReadDirectory(true)

// report the result
if err != nil {
mySession.WriteError(w, err, http.StatusInternalServerError)
sess.WriteError(w, err, http.StatusInternalServerError)
return
}

msgText := fmt.Sprintf("Thing '%s' successfully removed from the directory", td.Title)
slog.Info(msgText, "thingID", td.ID)
mySession.SendNotify(session.NotifySuccess, msgText)
sess.SendNotify(session.NotifySuccess, msgText)
// navigate back to the directory.
// http.Redirect doesn't work but using HX-Redirect header does.
// see also: https://www.reddit.com/r/htmx/comments/188oqx5/htmx_form_submission_issue_redirecting_on_success/
Expand Down
9 changes: 4 additions & 5 deletions bindings/hiveoview/src/views/thing/RenderActionRequest.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"github.com/hiveot/hub/api/go/digitwin"
"github.com/hiveot/hub/bindings/hiveoview/src/session"
"github.com/hiveot/hub/bindings/hiveoview/src/views/app"
"github.com/hiveot/hub/bindings/hiveoview/src/views/comps"
"github.com/hiveot/hub/lib/hubclient"
"github.com/hiveot/hub/lib/utils"
"github.com/hiveot/hub/wot/tdd"
Expand All @@ -28,8 +27,8 @@ type ActionRequestTemplateData struct {
Key string
// the action being viewed in case of an action
Action *tdd.ActionAffordance
Input *comps.SchemaValue
Output *comps.SchemaValue
Input *SchemaValue
Output *SchemaValue
// the message with the action
Msg hubclient.ThingMessage
// current delivery status
Expand Down Expand Up @@ -109,15 +108,15 @@ func RenderActionRequest(w http.ResponseWriter, r *http.Request) {
prevInputValue = fmt.Sprintf("%v", data.PrevValue.Input)
}
if data.Action.Input != nil {
data.Input = &comps.SchemaValue{
data.Input = &SchemaValue{
ThingID: thingID,
Key: key,
DataSchema: data.Action.Input,
Value: prevInputValue,
}
}
if data.Action.Output != nil {
data.Output = &comps.SchemaValue{
data.Output = &SchemaValue{
ThingID: thingID,
Key: key,
DataSchema: data.Action.Output,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package comps
package thing

import "github.com/hiveot/hub/wot/tdd"

Expand Down
12 changes: 6 additions & 6 deletions bindings/hiveoview/src/views/tile/RenderEditTile.gohtml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

<h-modal show showClose shadow>
<article>
<header class="h-row-centered" style="height: 60px">
<h3 style="margin:0">Edit Tile</h3>
</header>
<header class="h-row-centered" style="height: 60px">
<h3 style="margin:0">Edit Tile</h3>
</header>
<main>
<form id="edit-tile-form" style="overflow:auto">

Expand Down Expand Up @@ -59,7 +59,7 @@
</button>
<input name="sourceTitles" value="{{$v.Title}}"
style="margin:0"
title="{{$v.ThingID}}/{{$v.Key}}"/>
title="{{$v.ThingID}}/{{$v.Key}}"/>
<div class="h-row">{{$.GetValue $v.ThingID $v.Key}}</div>
<div class="h-row">{{$.GetUpdated $v.ThingID $v.Key}}</div>
</li>
Expand Down Expand Up @@ -113,8 +113,8 @@
ev.stopImmediatePropagation()
let details = ev.detail
if (details.successful) {
modal = btn.parentElement.parentElement
modal.closeModal()
let closeEv = new Event('close-modal',{bubbles:true})
btn.dispatchEvent(closeEv)
}
}
</script>
Loading

0 comments on commit c6fa74d

Please sign in to comment.