diff --git a/cmd/ui/main.go b/cmd/ui/main.go
index 3d60b76c..62a5bd76 100644
--- a/cmd/ui/main.go
+++ b/cmd/ui/main.go
@@ -34,6 +34,7 @@ type config struct {
BootstrapURL string `env:"MG_BOOTSTRAP_URL" envDefault:"http://localhost:9013"`
DomainsURL string `env:"MG_DOMAINS_URL" envDefault:"http://localhost:8189"`
InvitationsURL string `env:"MG_INVITATIONS_URL" envDefault:"http://localhost:9020"`
+ EventsURL string `env:"MG_EVENTS_URL" envDefault:"http://localhost:9021"`
MsgContentType sdk.ContentType `env:"MG_UI_CONTENT_TYPE" envDefault:"application/senml+json"`
TLSVerification bool `env:"MG_UI_VERIFICATION_TLS" envDefault:"false"`
}
@@ -55,6 +56,7 @@ func main() {
BootstrapURL: cfg.BootstrapURL,
DomainsURL: cfg.DomainsURL,
InvitationsURL: cfg.InvitationsURL,
+ EventsURL: cfg.EventsURL,
}
logger, err := logger.New(os.Stdout, cfg.LogLevel)
diff --git a/docker/.env b/docker/.env
index 59441a4b..d2028942 100644
--- a/docker/.env
+++ b/docker/.env
@@ -14,6 +14,7 @@ MG_INVITATIONS_URL=http://localhost:9020
MG_DOMAINS_URL = http://localhost:8189
MG_BOOTSTRAP_URL=http://localhost:9013
MG_UI_HOST_URL=http://localhost:9095
+MG_EVENTS_URL=http://localhost:9021
MG_UI_VERIFICATION_TLS=false
MG_UI_CONTENT_TYPE = application/senml+json
MG_UI_INSTANCE_ID=
diff --git a/go.mod b/go.mod
index e1768538..00d963f8 100644
--- a/go.mod
+++ b/go.mod
@@ -45,3 +45,5 @@ require (
google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 // indirect
google.golang.org/protobuf v1.31.0 // indirect
)
+
+replace github.com/absmach/magistrala => /home/ian/work/Rodney/magistrala
diff --git a/go.sum b/go.sum
index 0574735e..c2e857f7 100644
--- a/go.sum
+++ b/go.sum
@@ -34,8 +34,6 @@ github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrd
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
github.com/absmach/agent v0.0.0-20231107115142-c8b509f24d50 h1:RyDGAkOtIuN34HEJ/UDTc0r7qZFO5jBx5cB3wmUtPJE=
github.com/absmach/agent v0.0.0-20231107115142-c8b509f24d50/go.mod h1:/S3WufAqHTSU6MEq6cN0g6m21RhPX8dxqubYh08vbU8=
-github.com/absmach/magistrala v0.11.1-0.20240103120656-b3e206321c9d h1:Q0HIBP9SSnp41CgGT1cmkd63mvf2/uqGCbaOZbIlSvI=
-github.com/absmach/magistrala v0.11.1-0.20240103120656-b3e206321c9d/go.mod h1:7D+27TxXQwMqTmlerdulb0QtvXpMcSgeGoyvzhxr8MQ=
github.com/absmach/mproxy v0.3.1-0.20231221215510-0ffbc4fc2337 h1:OW2WIn094hQCwrkXZ2KHgoOzsKAwqPaxZvRZ94VTc5U=
github.com/absmach/mproxy v0.3.1-0.20231221215510-0ffbc4fc2337/go.mod h1:HmXsnuSWIN0OKrcscIxBzDO/GRjvqYxUTnd6vpuo+MQ=
github.com/absmach/senml v1.0.5 h1:zNPRYpGr2Wsb8brAusz8DIfFqemy1a2dNbmMnegY3GE=
diff --git a/ui/api/endpoint.go b/ui/api/endpoint.go
index b09fe779..de5dad0a 100644
--- a/ui/api/endpoint.go
+++ b/ui/api/endpoint.go
@@ -756,6 +756,25 @@ func listThingMembersEndpoint(svc ui.Service) endpoint.Endpoint {
}
}
+func listEntityEventsEndpoint(svc ui.Service) endpoint.Endpoint {
+ return func(ctx context.Context, request interface{}) (response interface{}, err error) {
+ req := request.(listEntityEventsReq)
+ if err := req.validate(); err != nil {
+ return nil, err
+ }
+
+ res, err := svc.ListEntityEvents(req.token, req.entityType, req.entityID, req.page, req.limit)
+ if err != nil {
+ return nil, err
+ }
+
+ return uiRes{
+ html: res,
+ code: http.StatusOK,
+ }, nil
+ }
+}
+
func listChannelsByThingEndpoint(svc ui.Service) endpoint.Endpoint {
return func(_ context.Context, request interface{}) (interface{}, error) {
req := request.(listEntityByIDReq)
diff --git a/ui/api/errors.go b/ui/api/errors.go
index be74672c..7a71fcf6 100644
--- a/ui/api/errors.go
+++ b/ui/api/errors.go
@@ -45,4 +45,6 @@ var (
errMissingDomainID = errors.New("missing domain id")
errMissingRole = errors.New("missing role")
errMissingValue = errors.New("missing value")
+ errMissingType = errors.New("missing type")
+ errMissingID = errors.New("missing id")
)
diff --git a/ui/api/logging.go b/ui/api/logging.go
index d0fa1fb9..3ff7737b 100644
--- a/ui/api/logging.go
+++ b/ui/api/logging.go
@@ -498,6 +498,19 @@ func (lm *loggingMiddleware) ListChannelsByThing(token, thingID string, page, li
return lm.svc.ListChannelsByThing(token, thingID, page, limit)
}
+// ListEntityEvents adds logging middleware to list entity events method.
+func (lm *loggingMiddleware) ListEntityEvents(token, entityType, entityID string, page, limit uint64) (b []byte, err error) {
+ defer func(begin time.Time) {
+ message := fmt.Sprintf("Method list_entity_events for thing %s took %s to complete", entityID, time.Since(begin))
+ if err != nil {
+ lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err))
+ return
+ }
+ lm.logger.Info(fmt.Sprintf("%s without errors.", message))
+ }(time.Now())
+ return lm.svc.ListEntityEvents(token, entityType, entityID, page, limit)
+}
+
// CreateChannel adds logging middleware to create channel method.
func (lm *loggingMiddleware) CreateChannel(channel sdk.Channel, token string) (err error) {
defer func(begin time.Time) {
diff --git a/ui/api/metrics.go b/ui/api/metrics.go
index 4a2b8e7f..1fdda13a 100644
--- a/ui/api/metrics.go
+++ b/ui/api/metrics.go
@@ -370,6 +370,16 @@ func (mm *metricsMiddleware) ListChannelsByThing(token, thingID string, page, li
return mm.svc.ListChannelsByThing(token, thingID, page, limit)
}
+// ListEntityEvents adds metrics middleware to list entity events method.
+func (lm *metricsMiddleware) ListEntityEvents(token, entityType, entityID string, page, limit uint64) (b []byte, err error) {
+ defer func(begin time.Time) {
+ lm.counter.With("method", "list_entity_events").Add(1)
+ lm.latency.With("method", "list_entity_events").Observe(time.Since(begin).Seconds())
+ }(time.Now())
+
+ return lm.svc.ListEntityEvents(token, entityType, entityID, page, limit)
+}
+
// CreateChannel adds metrics middleware to create channel method.
func (mm *metricsMiddleware) CreateChannel(channel sdk.Channel, token string) (err error) {
defer func(begin time.Time) {
diff --git a/ui/api/requests.go b/ui/api/requests.go
index 666a6b44..bcb8931a 100644
--- a/ui/api/requests.go
+++ b/ui/api/requests.go
@@ -135,6 +135,33 @@ func (req listEntityByIDReq) validate() error {
return nil
}
+type listEntityEventsReq struct {
+ token string
+ entityID string
+ entityType string
+ page uint64
+ limit uint64
+}
+
+func (req listEntityEventsReq) validate() error {
+ if req.token == "" {
+ return errAuthorization
+ }
+ if req.entityID == "" {
+ return errMissingID
+ }
+ if req.entityType == "" {
+ return errMissingType
+ }
+ if req.page == 0 {
+ return errPageSize
+ }
+ if req.limit == 0 {
+ return errLimitSize
+ }
+ return nil
+}
+
type viewResourceReq struct {
token string
id string
diff --git a/ui/api/transport.go b/ui/api/transport.go
index d86ebd6f..334cadad 100644
--- a/ui/api/transport.go
+++ b/ui/api/transport.go
@@ -738,6 +738,13 @@ func MakeHandler(svc ui.Service, r *chi.Mux, instanceID string) http.Handler {
opts...,
).ServeHTTP)
})
+
+ r.Get("/events/{id}/{entity}", kithttp.NewServer(
+ listEntityEventsEndpoint(svc),
+ decodeListEntityEventsRequest,
+ encodeResponse,
+ opts...,
+ ).ServeHTTP)
})
r.Get("/health", magistrala.Health("ui", instanceID))
@@ -1829,6 +1836,32 @@ func decodeListEntityByIDRequest(_ context.Context, r *http.Request) (interface{
return req, nil
}
+func decodeListEntityEventsRequest(_ context.Context, r *http.Request) (interface{}, error) {
+ token, err := tokenFromCookie(r, "token")
+ if err != nil {
+ return nil, err
+ }
+ page, err := readNumQuery[uint64](r, pageKey, defPage)
+ if err != nil {
+ return nil, err
+ }
+
+ limit, err := readNumQuery[uint64](r, limitKey, defLimit)
+ if err != nil {
+ return nil, err
+ }
+
+ req := listEntityEventsReq{
+ token: token,
+ entityID: chi.URLParam(r, "id"),
+ entityType: chi.URLParam(r, "entity"),
+ page: page,
+ limit: limit,
+ }
+
+ return req, nil
+}
+
func decodeGetEntitiesRequest(_ context.Context, r *http.Request) (interface{}, error) {
token, err := tokenFromCookie(r, "token")
if err != nil {
diff --git a/ui/service.go b/ui/service.go
index f845189c..3ec62917 100644
--- a/ui/service.go
+++ b/ui/service.go
@@ -86,6 +86,7 @@ var (
"breadcrumb",
"metadatamodal",
"statusupdate",
+ "events",
"bootstrap",
"bootstraps",
@@ -223,9 +224,11 @@ type Service interface {
// UnshareThing unshares a thing with a user.
UnshareThing(token, thingID string, req sdk.UsersRelationRequest) error
// ListThingUsers retrieves users that share a thing.
- ListThingUsers(token, thingID, relation string, page, limit uint64) (b []byte, err error)
+ ListThingUsers(token, thingID, relation string, page, limit uint64) ([]byte, error)
// ListChannelsByThing retrieves a list of channels based on the given thing ID.
ListChannelsByThing(token, thingID string, page, limit uint64) ([]byte, error)
+ // ListEvents retrieves a list of events based on the given ID.
+ ListEntityEvents(token, entityType, entityID string, page, limit uint64) ([]byte, error)
// CreateChannel creates a new channel.
CreateChannel(channel sdk.Channel, token string) error
@@ -256,13 +259,13 @@ type Service interface {
// RemoveUserFromChannel removes a user from a channel.
RemoveUserFromChannel(token, channelID string, req sdk.UsersRelationRequest) error
// ListChannelUsers retrieves a list of users that are connected to a channel.
- ListChannelUsers(token, channelID, relation string, page, limit uint64) (b []byte, err error)
+ ListChannelUsers(token, channelID, relation string, page, limit uint64) ([]byte, error)
// AddUserGroupToChannel adds a userGroup to a channel.
AddUserGroupToChannel(token, channelID string, req sdk.UserGroupsRequest) error
// RemoveGroupFromChannel removes a userGroup from a channel.
RemoveUserGroupFromChannel(token, channelID string, req sdk.UserGroupsRequest) error
// ListChannelUserGroups retrieves a list of userGroups connected to a channel.
- ListChannelUserGroups(token, channelID string, page, limit uint64) (b []byte, err error)
+ ListChannelUserGroups(token, channelID string, page, limit uint64) ([]byte, error)
// CreateGroups creates new groups.
CreateGroups(token string, groups ...sdk.Group) error
@@ -283,7 +286,7 @@ type Service interface {
// DisableGroup updates the status of the group to disabled.
DisableGroup(token, id string) error
// ListUserGroupChannels retrieves a list of channels that a userGroup is connected to.
- ListUserGroupChannels(token, groupID string, page, limit uint64) (b []byte, err error)
+ ListUserGroupChannels(token, groupID string, page, limit uint64) ([]byte, error)
// Publish facilitates a thing publishin messages to a channel.
Publish(token, thKey string, msg *messaging.Message) error
@@ -1621,13 +1624,15 @@ func (gs *uiService) Publish(token, thKey string, msg *messaging.Message) error
func (us *uiService) ReadMessage(token, chID, thKey string, page, limit uint64) ([]byte, error) {
var msg sdk.MessagesPage
+ pgm := sdk.PageMetadata{}
+
user, err := us.sdk.UserProfile(token)
if err != nil {
return []byte{}, err
}
if chID != "" {
- msg, err = us.sdk.ReadMessages(chID, thKey)
+ msg, err = us.sdk.ReadMessages(pgm, chID, thKey)
if err != nil {
return []byte{}, err
}
@@ -2289,6 +2294,77 @@ func (us *uiService) DeleteInvitation(token, userID, domainID string) error {
return us.sdk.DeleteInvitation(userID, domainID, token)
}
+func (us *uiService) ListEntityEvents(token, entityType, entityID string, page, limit uint64) ([]byte, error) {
+ offset := (page - 1) * limit
+ pgm := sdk.PageMetadata{
+ Offset: offset,
+ Limit: limit,
+ Direction: "desc",
+ WithPayload: true,
+ }
+
+ var crumbs []breadcrumb
+ switch entityType {
+ case "thing":
+ crumbs = []breadcrumb{
+ {Name: thingsActive, URL: thingsEndpoint},
+ {Name: entityID, URL: thingsEndpoint + "/" + entityID},
+ {Name: "Events"},
+ }
+ case "channel":
+ crumbs = []breadcrumb{
+ {Name: channelsActive, URL: channelsEndpoint},
+ {Name: entityID, URL: channelsEndpoint + "/" + entityID},
+ {Name: "Events"},
+ }
+ entityType = "group"
+ case "user":
+ crumbs = []breadcrumb{
+ {Name: usersActive, URL: usersEndpoint},
+ {Name: entityID, URL: usersEndpoint + "/" + entityID},
+ {Name: "Events"},
+ }
+ case "group":
+ crumbs = []breadcrumb{
+ {Name: groupsActive, URL: groupsEndpoint},
+ {Name: entityID, URL: groupsEndpoint + "/" + entityID},
+ {Name: "Events"},
+ }
+ }
+
+ eventsPage, err := us.sdk.Events(pgm, entityID, entityType, token)
+ if err != nil {
+ return []byte{}, errors.Wrap(err, ErrFailedRetreive)
+ }
+
+ noOfPages := int(math.Ceil(float64(eventsPage.Total) / float64(limit)))
+
+ data := struct {
+ NavbarActive string
+ CollapseActive string
+ Events []sdk.Event
+ CurrentPage int
+ Pages int
+ Limit int
+ Breadcrumbs []breadcrumb
+ }{
+ thingsActive,
+ thingsActive,
+ eventsPage.Events,
+ int(page),
+ noOfPages,
+ int(limit),
+ crumbs,
+ }
+
+ var btpl bytes.Buffer
+ if err := us.tpls.ExecuteTemplate(&btpl, "events", data); err != nil {
+ return []byte{}, errors.Wrap(err, ErrExecTemplate)
+ }
+
+ return btpl.Bytes(), nil
+}
+
func parseTemplates(mfsdk sdk.SDK, templates []string) (tpl *template.Template, err error) {
tpl = template.New("mainflux")
tpl = tpl.Funcs(template.FuncMap{
diff --git a/ui/web/static/css/styles.css b/ui/web/static/css/styles.css
index 66591f26..1bcb310a 100644
--- a/ui/web/static/css/styles.css
+++ b/ui/web/static/css/styles.css
@@ -13,14 +13,14 @@ SPDX-License-Identifier: Apache-2.0 */
--sidebar-min: 7rem;
--border-radius: 5px;
- /* pills */
- --pill-color-1: #1d2231;
- --pill-color-2: #003366;
- --pill-color-3: #8390a2;
+ /* pills */
+ --pill-color-1: #1d2231;
+ --pill-color-2: #003366;
+ --pill-color-3: #8390a2;
- --codemirror-font: 'Inconsolata', monospace;
+ --codemirror-font: 'Inconsolata', monospace;
- --bs-breadcrumb-divider: '>';
+ --bs-breadcrumb-divider: '>';
}
* {
@@ -227,12 +227,12 @@ body.sidebar-toggled .main-content {
}
body .body-button {
- background: var(--main-color);
- border-radius: var(--border-radius);
- color: #fff;
- font-size: 1rem;
- border: 1px solid var(--main-color);
- margin-bottom: 0.5rem;
+ background: var(--main-color);
+ border-radius: var(--border-radius);
+ color: #fff;
+ font-size: 1rem;
+ border: 1px solid var(--main-color);
+ margin-bottom: 0.5rem;
}
.main-content .sendMessage-button {
@@ -243,10 +243,10 @@ body .body-button {
.main-content .sendMessage-button:hover,
body .body-button:hover {
- color: #fff;
- background: var(--main-color);
- transform: scale(1.03);
- font-weight: 700;
+ color: #fff;
+ background: var(--main-color);
+ transform: scale(1.03);
+ font-weight: 700;
}
.doc-button:hover {
@@ -537,11 +537,11 @@ button.edit-btn {
}
.domains-table .body-button {
- background: var(--main-color);
- border-radius: var(--border-radius);
- color: #fff;
- font-size: 1rem;
- border: 1px solid var(--main-color);
+ background: var(--main-color);
+ border-radius: var(--border-radius);
+ color: #fff;
+ font-size: 1rem;
+ border: 1px solid var(--main-color);
}
.domains-table .body-button:hover {
@@ -579,68 +579,68 @@ button.edit-btn {
}
.relation-pill {
- background: var(--pill-color-3);
+ background: var(--pill-color-3);
}
.enabled-pill {
- background: #f0f0f0;
- color: var(--main-color);
- padding: 0.5rem;
- border: var(--main-color) 1px solid;
+ background: #f0f0f0;
+ color: var(--main-color);
+ padding: 0.5rem;
+ border: var(--main-color) 1px solid;
}
.disabled-pill {
- background: #f0f0f0;
- color: #c20707;
- padding: 0.5rem;
- border: #c20707 1px solid;
+ background: #f0f0f0;
+ color: #c20707;
+ padding: 0.5rem;
+ border: #c20707 1px solid;
}
.modal-title {
- font-weight: 700;
- font-size: 1.25rem;
+ font-weight: 700;
+ font-size: 1.25rem;
}
.string,
.cm-s-default .cm-string {
- color: var(--main-color);
+ color: var(--main-color);
}
.key,
.cm-property {
- color: red !important;
+ color: red !important;
}
.number,
.cm-s-default .cm-number {
- color: darkorange;
+ color: darkorange;
}
.boolean,
.cm-s-default .cm-atom {
- color: green;
+ color: green;
}
.null {
- color: magenta;
+ color: magenta;
}
-.table-container .meta-div {
- overflow: auto;
- max-height: 6.8rem;
- max-width: 100%;
+.table-container .json-div {
+ overflow: auto;
+ max-height: 6.8rem;
+ max-width: 100%;
}
-.table-container .meta-div pre {
- margin-bottom: 0;
+.table-container .json-div pre {
+ margin-bottom: 0;
}
.table-container .meta-col {
- max-width: 50%;
+ max-width: 50%;
}
.metadata-field span {
- font-family: var(--codemirror-font) !important;
+ font-family: var(--codemirror-font) !important;
}
@media (max-width: 768px) {
@@ -716,18 +716,18 @@ button.edit-btn {
display: none;
}
- .table-container .tags-col,
- .table-container .meta-col,
- .table-container .created-col,
- .table-container .desc-col,
- .table-container .alias-col,
- .doc-button {
- display: none;
- }
-
- body .body-button {
- margin-left: 0.2rem;
- }
+ .table-container .tags-col,
+ .table-container .meta-col,
+ .table-container .created-col,
+ .table-container .desc-col,
+ .table-container .alias-col,
+ .doc-button {
+ display: none;
+ }
+
+ body .body-button {
+ margin-left: 0.2rem;
+ }
}
.highlight-list-item {
diff --git a/ui/web/static/js/formatjson.js b/ui/web/static/js/formatjson.js
index 88b865c3..0cc8e8cc 100644
--- a/ui/web/static/js/formatjson.js
+++ b/ui/web/static/js/formatjson.js
@@ -25,7 +25,7 @@ function syntaxHighlight(json) {
function attachFormatJsonWithPrettifyListener(config) {
document.addEventListener("DOMContentLoaded", function () {
- var meta = JSON.parse(config.metadata);
+ var meta = JSON.parse(config.data);
document.getElementById(config.id).innerHTML = syntaxHighlight(JSON.stringify(meta, null, 2));
});
}
diff --git a/ui/web/template/channel.html b/ui/web/template/channel.html
index 06d627f6..7f68deb0 100644
--- a/ui/web/template/channel.html
+++ b/ui/web/template/channel.html
@@ -26,6 +26,9 @@
Assign Groups
+
+ Events
+
@@ -148,7 +151,7 @@
attachFormatJsonWithPrettifyListener({
id: "meta-data",
- metadata: metadata,
+ data: metadata,
});
codeMirrorEditor({
diff --git a/ui/web/template/channels.html b/ui/web/template/channels.html
index 894bf3f0..e6f6b792 100644
--- a/ui/web/template/channels.html
+++ b/ui/web/template/channels.html
@@ -196,7 +196,7 @@ Add Channels
{{ $c.Name }} |
{{ $c.Description }} |
- |
@@ -213,7 +213,7 @@ Add Channels
diff --git a/ui/web/template/domain.html b/ui/web/template/domain.html
index cff1e943..95fd3863 100644
--- a/ui/web/template/domain.html
+++ b/ui/web/template/domain.html
@@ -163,7 +163,7 @@ Domain Information
attachFormatJsonWithPrettifyListener({
id: "meta-data",
- metadata: metadata,
+ data: metadata,
});
codeMirrorEditor({
diff --git a/ui/web/template/events.html b/ui/web/template/events.html
new file mode 100644
index 00000000..24813d30
--- /dev/null
+++ b/ui/web/template/events.html
@@ -0,0 +1,56 @@
+
+
+{{ define "events" }}
+
+
+
+ Events
+ {{ template "header" }}
+
+
+ {{ template "navbar" . }}
+
+
+
+
+ {{ template "breadcrumb" . }}
+
+ {{ template "tableheader" . }}
+
+
+
+ TimeStamp |
+ Operation |
+ Payload |
+
+
+
+ {{ range $i,$e := .Events }}
+
+ {{ .OccurredAt }} |
+ {{ .Operation }} |
+
+
+ |
+
+
+ {{ end }}
+
+
+ {{ template "tablefooter" . }}
+
+
+
+
+
+
+
+{{ end }}
diff --git a/ui/web/template/group.html b/ui/web/template/group.html
index e47b8bf8..10506c6b 100644
--- a/ui/web/template/group.html
+++ b/ui/web/template/group.html
@@ -23,6 +23,9 @@
Assign Channels
+
+ Events
+
@@ -144,7 +147,7 @@
attachFormatJsonWithPrettifyListener({
id: "meta-data",
- metadata: metadata,
+ data: metadata,
});
codeMirrorEditor({
diff --git a/ui/web/template/groups.html b/ui/web/template/groups.html
index 377ef3df..1f846b4d 100644
--- a/ui/web/template/groups.html
+++ b/ui/web/template/groups.html
@@ -188,7 +188,7 @@ Add Groups
{{ $g.Description }} |
- |
@@ -205,7 +205,7 @@ Add Groups
diff --git a/ui/web/template/thing.html b/ui/web/template/thing.html
index 3ce2fb38..cf0a48aa 100644
--- a/ui/web/template/thing.html
+++ b/ui/web/template/thing.html
@@ -23,6 +23,9 @@
Share
+
+ Events
+
@@ -170,7 +173,7 @@
attachFormatJsonWithPrettifyListener({
id: "meta-data",
- metadata: metadata,
+ data: metadata,
});
codeMirrorEditor({
diff --git a/ui/web/template/things.html b/ui/web/template/things.html
index 6937cf9c..785fb1de 100644
--- a/ui/web/template/things.html
+++ b/ui/web/template/things.html
@@ -218,7 +218,7 @@ Add Things
{{ end }}
- |
@@ -235,7 +235,7 @@ Add Things
diff --git a/ui/web/template/user.html b/ui/web/template/user.html
index d640cdab..2c61501b 100644
--- a/ui/web/template/user.html
+++ b/ui/web/template/user.html
@@ -230,7 +230,7 @@
attachFormatJsonWithPrettifyListener({
id: "meta-data",
- metadata: metadata,
+ data: metadata,
});
codeMirrorEditor({
diff --git a/ui/web/template/users.html b/ui/web/template/users.html
index 056a2e91..18292ba3 100644
--- a/ui/web/template/users.html
+++ b/ui/web/template/users.html
@@ -113,7 +113,12 @@ Add User
-