Skip to content

Commit

Permalink
enable creating and saving dashboards
Browse files Browse the repository at this point in the history
Enable a user to create their dashboard and save
it to the database. The user can also view the
dashboard.

Signed-off-by: ianmuchyri <[email protected]>
  • Loading branch information
ianmuchyri committed Feb 6, 2024
1 parent 0307e01 commit 8b990a5
Show file tree
Hide file tree
Showing 10 changed files with 240 additions and 109 deletions.
1 change: 1 addition & 0 deletions docker/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# SPDX-License-Identifier: Apache-2.0

version: "3.7"
name: magistrala

networks:
magistrala-base-net:
Expand Down
19 changes: 19 additions & 0 deletions ui/api/endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -2076,6 +2076,25 @@ func listDashboardsEndpoint(svc ui.Service) endpoint.Endpoint {
}
}

func dashboardsEndpoint(svc ui.Service) endpoint.Endpoint {
return func(_ context.Context, request interface{}) (interface{}, error) {
req := request.(dashboardsReq)
if err := req.validate(); err != nil {
return nil, err
}

res, err := svc.Dashboards(req.token)
if err != nil {
return nil, err
}

return uiRes{
code: http.StatusOK,
html: res,
}, nil
}
}

func updateDashboardEndpoint(svc ui.Service) endpoint.Endpoint {
return func(_ context.Context, request interface{}) (interface{}, error) {
req := request.(updateDashboardReq)
Expand Down
24 changes: 19 additions & 5 deletions ui/api/logging.go
Original file line number Diff line number Diff line change
Expand Up @@ -1633,7 +1633,7 @@ func (lm *loggingMiddleware) DeleteInvitation(token, userID, domainID string) (e
return lm.svc.DeleteInvitation(token, userID, domainID)
}

// View Dashboard adds logging middleware to view dashboard method.
// ViewDashboard adds logging middleware to view dashboard method.
func (lm *loggingMiddleware) ViewDashboard(token, dashboardID string) (b []byte, err error) {
defer func(begin time.Time) {
args := []any{
Expand All @@ -1651,7 +1651,7 @@ func (lm *loggingMiddleware) ViewDashboard(token, dashboardID string) (b []byte,
return lm.svc.ViewDashboard(token, dashboardID)
}

// Create Dashboard adds logging middleware to create dashboard method.
// CreateDashboard adds logging middleware to create dashboard method.
func (lm *loggingMiddleware) CreateDashboard(token string, dashboardReq ui.DashboardReq) (b []byte, err error) {
defer func(begin time.Time) {
args := []any{
Expand All @@ -1670,7 +1670,7 @@ func (lm *loggingMiddleware) CreateDashboard(token string, dashboardReq ui.Dashb
return lm.svc.CreateDashboard(token, dashboardReq)
}

// List Dashboards adds logging middleware to list dashboards method.
// ListDashboards adds logging middleware to list dashboards method.
func (lm *loggingMiddleware) ListDashboards(token string, page, limit uint64) (b []byte, err error) {
defer func(begin time.Time) {
args := []any{
Expand All @@ -1689,7 +1689,21 @@ func (lm *loggingMiddleware) ListDashboards(token string, page, limit uint64) (b
return lm.svc.ListDashboards(token, page, limit)
}

// Update Dashboard adds logging middleware to update dashboard method.
// Dashboards adds logging middleware to dashboards method.
func (lm *loggingMiddleware) Dashboards(token string) (b []byte, err error) {
defer func(begin time.Time) {
duration := slog.String("duration", time.Since(begin).String())
if err != nil {
lm.logger.Warn("Dashboards failed to complete successfully", slog.Any("error", err), duration)
return
}
lm.logger.Info("Dashboards completed successfully", duration)
}(time.Now())

return lm.svc.Dashboards(token)
}

// UpdateDashboard adds logging middleware to update dashboard method.
func (lm *loggingMiddleware) UpdateDashboard(token, dashboardID string, dashboardReq ui.DashboardReq) (err error) {
defer func(begin time.Time) {
args := []any{
Expand All @@ -1709,7 +1723,7 @@ func (lm *loggingMiddleware) UpdateDashboard(token, dashboardID string, dashboar
return lm.svc.UpdateDashboard(token, dashboardID, dashboardReq)
}

// Delete Dashboard adds logging middleware to delete dashboard method.
// DeleteDashboard adds logging middleware to delete dashboard method.
func (lm *loggingMiddleware) DeleteDashboard(token, dashboardID string) (err error) {
defer func(begin time.Time) {
args := []any{
Expand Down
20 changes: 15 additions & 5 deletions ui/api/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -929,7 +929,7 @@ func (mm *metricsMiddleware) DeleteInvitation(token, userID, domainID string) er
return mm.svc.DeleteInvitation(token, userID, domainID)
}

// View Dashboard adds metrics middleware to view dashboard method.
// ViewDashboard adds metrics middleware to view dashboard method.
func (mm *metricsMiddleware) ViewDashboard(token string, dashboardID string) (b []byte, err error) {
defer func(begin time.Time) {
mm.counter.With("method", "view_dashboard").Add(1)
Expand All @@ -939,7 +939,7 @@ func (mm *metricsMiddleware) ViewDashboard(token string, dashboardID string) (b
return mm.svc.ViewDashboard(token, dashboardID)
}

// Create Dashboard adds metrics middleware to create dashboard method.
// CreateDashboard adds metrics middleware to create dashboard method.
func (mm *metricsMiddleware) CreateDashboard(token string, dashboardReq ui.DashboardReq) (b []byte, err error) {
defer func(begin time.Time) {
mm.counter.With("method", "create_dashboard").Add(1)
Expand All @@ -949,7 +949,7 @@ func (mm *metricsMiddleware) CreateDashboard(token string, dashboardReq ui.Dashb
return mm.svc.CreateDashboard(token, dashboardReq)
}

// List Dashboards adds metrics middleware to list dashboards method.
// ListDashboards adds metrics middleware to list dashboards method.
func (mm *metricsMiddleware) ListDashboards(token string, page uint64, limit uint64) (b []byte, err error) {
defer func(begin time.Time) {
mm.counter.With("method", "list_dashboards").Add(1)
Expand All @@ -959,7 +959,17 @@ func (mm *metricsMiddleware) ListDashboards(token string, page uint64, limit uin
return mm.svc.ListDashboards(token, page, limit)
}

// Update Dashboard adds metrics middleware to update dashboard method.
// Dashboards adds metrics middleware to dashboards method.
func (mm *metricsMiddleware) Dashboards(token string) (b []byte, err error) {
defer func(begin time.Time) {
mm.counter.With("method", "dashboards").Add(1)
mm.latency.With("method", "dashboards").Observe(time.Since(begin).Seconds())
}(time.Now())

return mm.svc.Dashboards(token)
}

// UpdateDashboard adds metrics middleware to update dashboard method.
func (mm *metricsMiddleware) UpdateDashboard(token, dashboardID string, dashboardReq ui.DashboardReq) (err error) {
defer func(begin time.Time) {
mm.counter.With("method", "update_dashboard").Add(1)
Expand All @@ -969,7 +979,7 @@ func (mm *metricsMiddleware) UpdateDashboard(token, dashboardID string, dashboar
return mm.svc.UpdateDashboard(token, dashboardID, dashboardReq)
}

// Delete Dashboard adds metrics middleware to delete dashboard method.
// DeleteDashboard adds metrics middleware to delete dashboard method.
func (mm *metricsMiddleware) DeleteDashboard(token string, dashboardID string) (err error) {
defer func(begin time.Time) {
mm.counter.With("method", "delete_dashboard").Add(1)
Expand Down
11 changes: 11 additions & 0 deletions ui/api/requests.go
Original file line number Diff line number Diff line change
Expand Up @@ -1132,6 +1132,17 @@ func (req listDashboardsReq) validate() error {
return nil
}

type dashboardsReq struct {
token string
}

func (req dashboardsReq) validate() error {
if req.token == "" {
return errAuthorization
}
return nil
}

type updateDashboardReq struct {
token string
ID string `json:"id"`
Expand Down
36 changes: 25 additions & 11 deletions ui/api/transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,12 +170,18 @@ func MakeHandler(svc ui.Service, r *chi.Mux, instanceID string) http.Handler {
encodeResponse,
opts...,
).ServeHTTP)
r.Get("/", kithttp.NewServer(
r.Get("/list", kithttp.NewServer(
listDashboardsEndpoint(svc),
decodelistDashboardsRequest,
encodeResponse,
opts...,
).ServeHTTP)
r.Get("/", kithttp.NewServer(
dashboardsEndpoint(svc),
decodeDashboardRequest,
encodeResponse,
opts...,
).ServeHTTP)
r.Delete("/", kithttp.NewServer(
deleteDashboardEndpoint(svc),
decodeDeleteDashboardRequest,
Expand Down Expand Up @@ -820,17 +826,11 @@ func decodeCreateDashboardRequest(_ context.Context, r *http.Request) (interface
return nil, err
}

var data createDashboardReq
err = json.NewDecoder(r.Body).Decode(&data)
if err != nil {
return nil, err
}

req := createDashboardReq{
token: token,
Name: data.Name,
Description: data.Description,
Layout: data.Layout,
Name: r.PostFormValue("name"),
Description: r.PostFormValue("description"),
Layout: r.PostFormValue("layout"),
}

return req, nil
Expand Down Expand Up @@ -859,6 +859,19 @@ func decodelistDashboardsRequest(_ context.Context, r *http.Request) (interface{
return req, nil
}

func decodeDashboardRequest(_ context.Context, r *http.Request) (interface{}, error) {
token, err := tokenFromCookie(r, "token")
if err != nil {
return nil, err
}

req := dashboardsReq{
token: token,
}

return req, nil
}

func decodeUpdateDashboardRequest(_ context.Context, r *http.Request) (interface{}, error) {
token, err := tokenFromCookie(r, "token")
if err != nil {
Expand Down Expand Up @@ -905,7 +918,8 @@ func decodeViewDashboardRequest(_ context.Context, r *http.Request) (interface{}
return nil, err
}
req := viewDashboardReq{
token: token,
token: token,
DashboardID: chi.URLParam(r, "id"),
}

return req, nil
Expand Down
63 changes: 23 additions & 40 deletions ui/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,8 @@ type Service interface {
ViewDashboard(token, dashboardID string) ([]byte, error)
// List Dashboards retrieves all dashboards for a user.
ListDashboards(token string, page, limit uint64) ([]byte, error)
// Dashboards displays the dashboards page.
Dashboards(token string) ([]byte, error)
// Update a dashboard for a user.
UpdateDashboard(token, dashboardID string, dashboardReq DashboardReq) error
// Delete a dashboard for a user.
Expand Down Expand Up @@ -2046,23 +2048,6 @@ func (us *uiService) GetEntities(token, entity, entityName, domainID, permission
return []byte{}, errors.Wrap(err, ErrFailedRetreive)
}
items["data"] = domains.Domains
case "dashboards":
type Dashboard struct {
ID int
Name string
Description string
}

// Dummy data for dashboards (replace with your actual data retrieval logic)
dashboards := make([]Dashboard, 0)
for i := 1; i <= 28; i++ {
dashboards = append(dashboards, Dashboard{
ID: i,
Name: fmt.Sprintf("Dashboard %d", i),
Description: fmt.Sprintf("Description for Dashboard %d", i),
})
}
items["data"] = dashboards
}

jsonData, err := json.Marshal(items)
Expand Down Expand Up @@ -2381,17 +2366,14 @@ func (us *uiService) DeleteInvitation(token, userID, domainID string) error {
}

func (us *uiService) CreateDashboard(token string, dashboardReq DashboardReq) ([]byte, error) {
var btpl bytes.Buffer
charts := CreateItem()

userID, err := getUserID(token)
if err != nil {
return btpl.Bytes(), errors.Wrap(ErrFailedRetrieveUserID, err)
return []byte{}, errors.Wrap(ErrFailedRetrieveUserID, err)
}

dashboardID, err := us.idProvider.ID()
if err != nil {
return btpl.Bytes(), errors.Wrap(ErrFailedGenerateID, err)
return []byte{}, errors.Wrap(ErrFailedGenerateID, err)
}
dashboard := Dashboard{
ID: dashboardID,
Expand All @@ -2404,26 +2386,10 @@ func (us *uiService) CreateDashboard(token string, dashboardReq DashboardReq) ([

ds, err := us.drepo.Create(context.Background(), dashboard)
if err != nil {
return btpl.Bytes(), errors.Wrap(err, ErrFailedDashboardSave)
}

data := struct {
NavbarActive string
CollapseActive string
Charts []Item
Dashboard Dashboard
}{
dashboardsActive,
dashboardsActive,
charts,
ds,
return []byte{}, errors.Wrap(err, ErrFailedDashboardSave)
}

if err := us.tpls.ExecuteTemplate(&btpl, "dashboard", data); err != nil {
return []byte{}, errors.Wrap(err, ErrExecTemplate)
}

return btpl.Bytes(), nil
return us.ViewDashboard(token, ds.ID)
}

func (us *uiService) ViewDashboard(token, dashboardID string) ([]byte, error) {
Expand Down Expand Up @@ -2487,6 +2453,23 @@ func (us *uiService) ListDashboards(token string, page, limit uint64) ([]byte, e
return jsonData, nil
}

func (us *uiService) Dashboards(token string) ([]byte, error) {
data := struct {
NavbarActive string
CollapseActive string
}{
dashboardsActive,
dashboardsActive,
}

var btpl bytes.Buffer
if err := us.tpls.ExecuteTemplate(&btpl, "dashboards", data); err != nil {
return []byte{}, errors.Wrap(err, ErrExecTemplate)
}

return btpl.Bytes(), nil
}

func (us *uiService) UpdateDashboard(token, dashboardID string, dashboardReq DashboardReq) error {
userID, err := getUserID(token)
if err != nil {
Expand Down
Loading

0 comments on commit 8b990a5

Please sign in to comment.