commit
e4704d806e
|
|
@ -80,6 +80,8 @@ func (h *Handler) CwmpHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
h.pub(NATS_CWMP_SUBJECT_PREFIX+sn+".info", tmp)
|
h.pub(NATS_CWMP_SUBJECT_PREFIX+sn+".info", tmp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cpe.ConnectionRequestURL = Inform.GetConnectionRequest() // Update connection request URL, in case the CPE changed IP
|
||||||
|
|
||||||
log.Printf("Received an Inform from device %s withEventCodes %s", addr, Inform.GetEvents())
|
log.Printf("Received an Inform from device %s withEventCodes %s", addr, Inform.GetEvents())
|
||||||
|
|
||||||
expiration := time.Now().AddDate(0, 0, 1)
|
expiration := time.Now().AddDate(0, 0, 1)
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,11 @@ func (a *Api) StartApi() {
|
||||||
iot := r.PathPrefix("/api/device").Subrouter()
|
iot := r.PathPrefix("/api/device").Subrouter()
|
||||||
iot.HandleFunc("/alias", a.setDeviceAlias).Methods("PUT")
|
iot.HandleFunc("/alias", a.setDeviceAlias).Methods("PUT")
|
||||||
iot.HandleFunc("/auth", a.deviceAuth).Methods("GET", "POST", "DELETE")
|
iot.HandleFunc("/auth", a.deviceAuth).Methods("GET", "POST", "DELETE")
|
||||||
|
iot.HandleFunc("/message/{type}", a.addTemplate).Methods("POST")
|
||||||
|
iot.HandleFunc("/message", a.updateTemplate).Methods("PUT")
|
||||||
|
iot.HandleFunc("/message", a.getTemplate).Methods("GET")
|
||||||
|
iot.HandleFunc("/message", a.deleteTemplate).Methods("DELETE")
|
||||||
|
iot.HandleFunc("/cwmp/{sn}/generic", a.cwmpGenericMsg).Methods("PUT")
|
||||||
iot.HandleFunc("/cwmp/{sn}/getParameterNames", a.cwmpGetParameterNamesMsg).Methods("PUT")
|
iot.HandleFunc("/cwmp/{sn}/getParameterNames", a.cwmpGetParameterNamesMsg).Methods("PUT")
|
||||||
iot.HandleFunc("/cwmp/{sn}/getParameterValues", a.cwmpGetParameterValuesMsg).Methods("PUT")
|
iot.HandleFunc("/cwmp/{sn}/getParameterValues", a.cwmpGetParameterValuesMsg).Methods("PUT")
|
||||||
iot.HandleFunc("/cwmp/{sn}/getParameterAttributes", a.cwmpGetParameterAttributesMsg).Methods("PUT")
|
iot.HandleFunc("/cwmp/{sn}/getParameterAttributes", a.cwmpGetParameterAttributesMsg).Methods("PUT")
|
||||||
|
|
@ -61,6 +66,7 @@ func (a *Api) StartApi() {
|
||||||
iot.HandleFunc("/cwmp/{sn}/deleteObject", a.cwmpDeleteObjectMsg).Methods("PUT")
|
iot.HandleFunc("/cwmp/{sn}/deleteObject", a.cwmpDeleteObjectMsg).Methods("PUT")
|
||||||
iot.HandleFunc("", a.retrieveDevices).Methods("GET")
|
iot.HandleFunc("", a.retrieveDevices).Methods("GET")
|
||||||
iot.HandleFunc("/filterOptions", a.filterOptions).Methods("GET")
|
iot.HandleFunc("/filterOptions", a.filterOptions).Methods("GET")
|
||||||
|
iot.HandleFunc("/{sn}/{mtp}/generic", a.deviceGenericMessage).Methods("PUT")
|
||||||
iot.HandleFunc("/{sn}/{mtp}/get", a.deviceGetMsg).Methods("PUT")
|
iot.HandleFunc("/{sn}/{mtp}/get", a.deviceGetMsg).Methods("PUT")
|
||||||
iot.HandleFunc("/{sn}/{mtp}/add", a.deviceCreateMsg).Methods("PUT")
|
iot.HandleFunc("/{sn}/{mtp}/add", a.deviceCreateMsg).Methods("PUT")
|
||||||
iot.HandleFunc("/{sn}/{mtp}/del", a.deviceDeleteMsg).Methods("PUT")
|
iot.HandleFunc("/{sn}/{mtp}/del", a.deviceDeleteMsg).Methods("PUT")
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,31 @@ import (
|
||||||
|
|
||||||
var errDeviceModelNotFound = errors.New("device model not found")
|
var errDeviceModelNotFound = errors.New("device model not found")
|
||||||
|
|
||||||
|
func (a *Api) cwmpGenericMsg(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
|
sn := getSerialNumberFromRequest(r)
|
||||||
|
|
||||||
|
payload, err := io.ReadAll(r.Body)
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
w.Write(utils.Marshall(err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(payload) == 0 {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
w.Write(utils.Marshall("Empty payload"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
data, _, err := cwmpInteraction[cwmp.SoapEnvelope](sn, payload, w, a.nc)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Write(data)
|
||||||
|
}
|
||||||
|
|
||||||
func (a *Api) cwmpGetParameterNamesMsg(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) cwmpGetParameterNamesMsg(w http.ResponseWriter, r *http.Request) {
|
||||||
sn := getSerialNumberFromRequest(r)
|
sn := getSerialNumberFromRequest(r)
|
||||||
|
|
||||||
|
|
@ -125,7 +150,7 @@ func (a *Api) cwmpDeleteObjectMsg(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Write(data)
|
w.Write(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func cwmpInteraction[T cwmp.SetParameterValuesResponse | cwmp.DeleteObjectResponse | cwmp.GetParameterAttributesResponse | cwmp.GetParameterNamesResponse | cwmp.GetParameterValuesResponse | cwmp.AddObjectResponse](
|
func cwmpInteraction[T cwmp.SetParameterValuesResponse | cwmp.SoapEnvelope | cwmp.DeleteObjectResponse | cwmp.GetParameterAttributesResponse | cwmp.GetParameterNamesResponse | cwmp.GetParameterValuesResponse | cwmp.AddObjectResponse](
|
||||||
sn string, payload []byte, w http.ResponseWriter, nc *nats.Conn,
|
sn string, payload []byte, w http.ResponseWriter, nc *nats.Conn,
|
||||||
) ([]byte, T, error) {
|
) ([]byte, T, error) {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/gorilla/mux"
|
||||||
"github.com/leandrofars/oktopus/internal/bridge"
|
"github.com/leandrofars/oktopus/internal/bridge"
|
||||||
"github.com/leandrofars/oktopus/internal/db"
|
"github.com/leandrofars/oktopus/internal/db"
|
||||||
"github.com/leandrofars/oktopus/internal/entity"
|
"github.com/leandrofars/oktopus/internal/entity"
|
||||||
|
|
@ -367,3 +368,141 @@ func (a *Api) filterOptions(w http.ResponseWriter, r *http.Request) {
|
||||||
w.WriteHeader(resp.Code)
|
w.WriteHeader(resp.Code)
|
||||||
w.Write(utils.Marshall(resp.Msg))
|
w.Write(utils.Marshall(resp.Msg))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *Api) updateTemplate(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
|
name := r.URL.Query().Get("name")
|
||||||
|
if name == "" {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
utils.MarshallEncoder("No name provided", w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
payload, err := io.ReadAll(r.Body)
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
utils.MarshallEncoder("Error to decode payload: "+err.Error(), w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
payloadLen := len(payload)
|
||||||
|
if payloadLen == 0 {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
utils.MarshallEncoder("No payload provided", w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = a.db.UpdateTemplate(name, string(payload))
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
json.NewEncoder(w).Encode(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusNoContent)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Api) addTemplate(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
|
name := r.URL.Query().Get("name")
|
||||||
|
if name == "" {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
utils.MarshallEncoder("No name provided", w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
payload, err := io.ReadAll(r.Body)
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
utils.MarshallEncoder("Error to decode payload: "+err.Error(), w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
payloadLen := len(payload)
|
||||||
|
if payloadLen == 0 {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
utils.MarshallEncoder("No payload provided", w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
switch vars["type"] {
|
||||||
|
case "cwmp":
|
||||||
|
err = a.db.AddTemplate(name, "cwmp", string(payload))
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
json.NewEncoder(w).Encode(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.WriteHeader(http.StatusNoContent)
|
||||||
|
return
|
||||||
|
case "usp":
|
||||||
|
err = a.db.AddTemplate(name, "usp", string(payload))
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
json.NewEncoder(w).Encode(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.WriteHeader(http.StatusNoContent)
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
utils.MarshallEncoder("Invalid template type", w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Api) getTemplate(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
|
name := r.URL.Query().Get("name")
|
||||||
|
msgType := r.URL.Query().Get("type")
|
||||||
|
|
||||||
|
if name == "" {
|
||||||
|
|
||||||
|
var filter bson.D
|
||||||
|
if msgType == "" {
|
||||||
|
filter = bson.D{}
|
||||||
|
} else {
|
||||||
|
filter = bson.D{{"type", msgType}}
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := a.db.AllTemplates(filter)
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
json.NewEncoder(w).Encode("Error to get all templates: " + err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
json.NewEncoder(w).Encode(result)
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
t, err := a.db.FindTemplate(bson.D{{"name", name}})
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
json.NewEncoder(w).Encode("error to find message: " + err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
w.Write([]byte(t.Value))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Api) deleteTemplate(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
|
name := r.URL.Query().Get("name")
|
||||||
|
if name == "" {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
json.NewEncoder(w).Encode("needs template name!")
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
err := a.db.DeleteTemplate(name)
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
json.NewEncoder(w).Encode("error to delete template: " + err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.WriteHeader(http.StatusNoContent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -135,16 +135,6 @@ func (a *Api) changePassword(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
userToChangePasswd := mux.Vars(r)["user"]
|
|
||||||
if userToChangePasswd != "" && userToChangePasswd != email {
|
|
||||||
rUser, _ := a.db.FindUser(email)
|
|
||||||
if rUser.Level != db.AdminUser {
|
|
||||||
w.WriteHeader(http.StatusForbidden)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
email = userToChangePasswd
|
|
||||||
}
|
|
||||||
|
|
||||||
var user db.User
|
var user db.User
|
||||||
err = json.NewDecoder(r.Body).Decode(&user)
|
err = json.NewDecoder(r.Body).Decode(&user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -154,6 +144,12 @@ func (a *Api) changePassword(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
user.Email = email
|
user.Email = email
|
||||||
|
|
||||||
|
if len(user.Password) < 8 {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
w.Write([]byte("Password must be at least 8 characters long"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if err := user.HashPassword(user.Password); err != nil {
|
if err := user.HashPassword(user.Password); err != nil {
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
|
|
@ -164,6 +160,7 @@ func (a *Api) changePassword(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusNoContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Api) registerAdminUser(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) registerAdminUser(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
|
@ -12,6 +13,7 @@ import (
|
||||||
"github.com/leandrofars/oktopus/internal/usp/usp_utils"
|
"github.com/leandrofars/oktopus/internal/usp/usp_utils"
|
||||||
"github.com/leandrofars/oktopus/internal/utils"
|
"github.com/leandrofars/oktopus/internal/utils"
|
||||||
"github.com/nats-io/nats.go"
|
"github.com/nats-io/nats.go"
|
||||||
|
"google.golang.org/protobuf/encoding/protojson"
|
||||||
"google.golang.org/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -59,6 +61,16 @@ func sendUspMsg(msg usp_msg.Msg, sn string, w http.ResponseWriter, nc *nats.Conn
|
||||||
}
|
}
|
||||||
|
|
||||||
body := receivedMsg.Body.GetResponse()
|
body := receivedMsg.Body.GetResponse()
|
||||||
|
if body == nil {
|
||||||
|
errorMsg := receivedMsg.Body.GetError()
|
||||||
|
if errorMsg == nil {
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
log.Println("No response body or error")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
w.Write(utils.Marshall(errorMsg))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
switch body.RespType.(type) {
|
switch body.RespType.(type) {
|
||||||
case *usp_msg.Response_GetResp:
|
case *usp_msg.Response_GetResp:
|
||||||
|
|
@ -86,6 +98,44 @@ func sendUspMsg(msg usp_msg.Msg, sn string, w http.ResponseWriter, nc *nats.Conn
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *Api) deviceGenericMessage(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
|
sn := getSerialNumberFromRequest(r)
|
||||||
|
mtp, err := getMtpFromRequest(r, w)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if mtp == "" {
|
||||||
|
var ok bool
|
||||||
|
mtp, ok = deviceStateOK(w, a.nc, sn)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
payload, err := io.ReadAll(r.Body)
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
w.Write(utils.Marshall(err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var msg usp_msg.Msg
|
||||||
|
|
||||||
|
err = protojson.Unmarshal(payload, &msg)
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
w.Write(utils.Marshall(err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = sendUspMsg(msg, sn, w, a.nc, mtp)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (a *Api) deviceGetMsg(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) deviceGetMsg(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
sn := getSerialNumberFromRequest(r)
|
sn := getSerialNumberFromRequest(r)
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,10 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Database struct {
|
type Database struct {
|
||||||
client *mongo.Client
|
client *mongo.Client
|
||||||
users *mongo.Collection
|
users *mongo.Collection
|
||||||
ctx context.Context
|
template *mongo.Collection
|
||||||
|
ctx context.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDatabase(ctx context.Context, mongoUri string) Database {
|
func NewDatabase(ctx context.Context, mongoUri string) Database {
|
||||||
|
|
@ -43,6 +44,16 @@ func NewDatabase(ctx context.Context, mongoUri string) Database {
|
||||||
log.Fatalln(err)
|
log.Fatalln(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
db.template = client.Database("general").Collection("templates")
|
||||||
|
indexField = bson.M{"name": 1}
|
||||||
|
_, err = db.template.Indexes().CreateOne(ctx, mongo.IndexModel{
|
||||||
|
Keys: indexField,
|
||||||
|
Options: options.Index().SetUnique(true),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
|
||||||
db.ctx = ctx
|
db.ctx = ctx
|
||||||
|
|
||||||
return db
|
return db
|
||||||
|
|
|
||||||
72
backend/services/controller/internal/db/template.go
Normal file
72
backend/services/controller/internal/db/template.go
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
package db
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Template struct {
|
||||||
|
Name string `json:"name" bson:"name"`
|
||||||
|
Type string `json:"type" bson:"type"`
|
||||||
|
Value string `json:"value" bson:"value"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var ErrorTemplateExists = errors.New("message already exists")
|
||||||
|
var ErrorTemplateNotExists = errors.New("message don't exist")
|
||||||
|
|
||||||
|
func (d *Database) FindTemplate(filter interface{}) (Template, error) {
|
||||||
|
var result Template
|
||||||
|
err := d.template.FindOne(d.ctx, filter).Decode(&result)
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Database) AllTemplates(filter interface{}) ([]Template, error) {
|
||||||
|
var results []Template
|
||||||
|
|
||||||
|
cursor, err := d.template.Find(d.ctx, filter)
|
||||||
|
if err != nil {
|
||||||
|
return results, err
|
||||||
|
}
|
||||||
|
if err = cursor.All(d.ctx, &results); err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
return results, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Database) AddTemplate(name, tr string, t string) error {
|
||||||
|
opts := options.FindOneAndReplace().SetUpsert(true)
|
||||||
|
err := d.template.FindOneAndReplace(d.ctx, bson.D{{"name", name}}, Template{Name: name, Type: tr, Value: t}, opts).Err()
|
||||||
|
if err != nil {
|
||||||
|
if err == mongo.ErrNoDocuments {
|
||||||
|
log.Printf("New message %s added to database", name)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.Printf("Message %s already existed, and got replaced for new payload", name)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Database) UpdateTemplate(name, t string) error {
|
||||||
|
result, err := d.template.UpdateOne(d.ctx, bson.D{{"name", name}}, bson.D{{"$set", bson.D{{"value", t}}}})
|
||||||
|
if err == nil {
|
||||||
|
if result.MatchedCount == 0 {
|
||||||
|
return ErrorTemplateNotExists
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Database) DeleteTemplate(name string) error {
|
||||||
|
result, err := d.template.DeleteOne(d.ctx, bson.D{{"name", name}})
|
||||||
|
if err == nil {
|
||||||
|
if result.DeletedCount == 0 {
|
||||||
|
return ErrorTemplateNotExists
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
@ -82,6 +82,13 @@ func (d *Database) CreateDevice(device Device) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ------------------------- Do not overwrite alias ------------------------- */
|
||||||
|
if deviceExistent.Alias != "" {
|
||||||
|
device.Alias = deviceExistent.Alias
|
||||||
|
}
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
callback := func(sessCtx mongo.SessionContext) (interface{}, error) {
|
callback := func(sessCtx mongo.SessionContext) (interface{}, error) {
|
||||||
|
|
|
||||||
|
|
@ -211,6 +211,8 @@ export const AuthProvider = (props) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const signOut = () => {
|
const signOut = () => {
|
||||||
|
router.push("/auth/login")
|
||||||
|
localStorage.removeItem("token")
|
||||||
dispatch({
|
dispatch({
|
||||||
type: HANDLERS.SIGN_OUT
|
type: HANDLERS.SIGN_OUT
|
||||||
});
|
});
|
||||||
|
|
|
||||||
91
frontend/src/contexts/backend-context.js
Normal file
91
frontend/src/contexts/backend-context.js
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
import { createContext, useContext, } from 'react';
|
||||||
|
import { useRouter } from 'next/router';
|
||||||
|
import { useAlertContext } from './error-context';
|
||||||
|
|
||||||
|
export const BackendContext = createContext({ undefined });
|
||||||
|
|
||||||
|
export const BackendProvider = (props) => {
|
||||||
|
const { children } = props;
|
||||||
|
|
||||||
|
const { setAlert } = useAlertContext();
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
var myHeaders = new Headers();
|
||||||
|
myHeaders.append("Content-Type", "application/json");
|
||||||
|
myHeaders.append("Authorization", localStorage.getItem("token"));
|
||||||
|
|
||||||
|
const httpRequest = async (path, method, body, headers, encoding) => {
|
||||||
|
|
||||||
|
var requestOptions = {
|
||||||
|
method: method,
|
||||||
|
redirect: 'follow',
|
||||||
|
};
|
||||||
|
|
||||||
|
if (body) {
|
||||||
|
requestOptions.body = body
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("headers:", headers)
|
||||||
|
if (headers) {
|
||||||
|
requestOptions.headers = headers
|
||||||
|
}else {
|
||||||
|
requestOptions.headers = myHeaders
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}${path}`, requestOptions)
|
||||||
|
console.log("status:", response.status)
|
||||||
|
if (response.status != 200) {
|
||||||
|
if (response.status == 401) {
|
||||||
|
router.push("/auth/login")
|
||||||
|
}
|
||||||
|
if (response.status == 204 || response.status == 201) {
|
||||||
|
return {status : response.status, result: null}
|
||||||
|
}
|
||||||
|
const data = await response.text()
|
||||||
|
// setAlert({
|
||||||
|
// severity: "error",
|
||||||
|
// title: "Error",
|
||||||
|
// message: `Status: ${response.status}, Content: ${data}`,
|
||||||
|
// })
|
||||||
|
setAlert({
|
||||||
|
severity: "error",
|
||||||
|
// title: "Error",
|
||||||
|
message: `${data}`,
|
||||||
|
})
|
||||||
|
return {status : response.status, result: null}
|
||||||
|
}
|
||||||
|
if (encoding) {
|
||||||
|
console.log("encoding:", encoding)
|
||||||
|
if (encoding == "text") {
|
||||||
|
const data = await response.text()
|
||||||
|
return {status: response.status, result: data}
|
||||||
|
}else if (encoding == "blob") {
|
||||||
|
const data = await response.blob()
|
||||||
|
return {status: response.status, result: data}
|
||||||
|
}else if (encoding == "json") {
|
||||||
|
const data = await response.json()
|
||||||
|
return {status: response.status, result: data}
|
||||||
|
}else{
|
||||||
|
return {status: response.status, result: response}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const data = await response.json()
|
||||||
|
return {status: response.status, result: data}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<BackendContext.Provider
|
||||||
|
value={{
|
||||||
|
httpRequest,
|
||||||
|
setAlert,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</BackendContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const BackendConsumer = BackendContext.Consumer;
|
||||||
|
|
||||||
|
export const useBackendContext = () => useContext(BackendContext);
|
||||||
32
frontend/src/contexts/error-context.js
Normal file
32
frontend/src/contexts/error-context.js
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
import { createContext, useContext, useState } from 'react';
|
||||||
|
|
||||||
|
|
||||||
|
export const AlertContext = createContext({ undefined });
|
||||||
|
|
||||||
|
export const AlertProvider = (props) => {
|
||||||
|
const { children } = props;
|
||||||
|
/*
|
||||||
|
{
|
||||||
|
severity: '', // options => error, warning, info, success
|
||||||
|
message: '',
|
||||||
|
title: '',
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
// const [alert, setAlert] = useState(null);
|
||||||
|
const [alert, setAlert] = useState();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AlertContext.Provider
|
||||||
|
value={{
|
||||||
|
alert,
|
||||||
|
setAlert,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</AlertContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const AlertConsumer = AlertContext.Consumer;
|
||||||
|
|
||||||
|
export const useAlertContext = () => useContext(AlertContext);
|
||||||
|
|
@ -1,14 +1,16 @@
|
||||||
import ChartBarIcon from '@heroicons/react/24/solid/ChartBarIcon';
|
import ChartBarIcon from '@heroicons/react/24/solid/ChartBarIcon';
|
||||||
import CogIcon from '@heroicons/react/24/solid/CogIcon';
|
import CogIcon from '@heroicons/react/24/solid/CogIcon';
|
||||||
import ChatBubbleLeftRightIcon from '@heroicons/react/24/solid/ChatBubbleLeftRightIcon'
|
import ChatBubbleLeftRightIcon from '@heroicons/react/24/solid/ChatBubbleLeftRightIcon'
|
||||||
import MapIcon from '@heroicons/react/24/solid/MapIcon'
|
|
||||||
import RectangleGroupIcon from '@heroicons/react/24/solid/RectangleGroupIcon'
|
import RectangleGroupIcon from '@heroicons/react/24/solid/RectangleGroupIcon'
|
||||||
import ArrowDownOnSquareStackIcon from '@heroicons/react/24/solid/ArrowDownOnSquareStackIcon'
|
import ArrowDownOnSquareStackIcon from '@heroicons/react/24/solid/ArrowDownOnSquareStackIcon'
|
||||||
import UserGroupIcon from '@heroicons/react/24/solid/UserGroupIcon'
|
import UserGroupIcon from '@heroicons/react/24/solid/UserGroupIcon'
|
||||||
import KeyIcon from '@heroicons/react/24/solid/KeyIcon'
|
import KeyIcon from '@heroicons/react/24/solid/KeyIcon'
|
||||||
import CpuChip from '@heroicons/react/24/solid/CpuChipIcon';
|
import CpuChip from '@heroicons/react/24/solid/CpuChipIcon';
|
||||||
import BriefCaseIcon from '@heroicons/react/24/outline/BriefcaseIcon';
|
|
||||||
import { SvgIcon } from '@mui/material';
|
import { SvgIcon } from '@mui/material';
|
||||||
|
import FolderIcon from '@heroicons/react/24/solid/FolderIcon';
|
||||||
|
import ShieldCheckIcon from '@heroicons/react/24/solid/ShieldCheckIcon';
|
||||||
|
import EnvelopeIcon from '@heroicons/react/24/solid/EnvelopeIcon';
|
||||||
|
import UserIcon from '@heroicons/react/24/solid/UserIcon';
|
||||||
|
|
||||||
export const items = [
|
export const items = [
|
||||||
{
|
{
|
||||||
|
|
@ -48,19 +50,19 @@ export const items = [
|
||||||
</SvgIcon>
|
</SvgIcon>
|
||||||
),
|
),
|
||||||
disabled: true
|
disabled: true
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
title: 'Message',
|
||||||
|
tooltip: 'Upgrade to Business Plan',
|
||||||
|
disabled: true,
|
||||||
|
icon: (
|
||||||
|
<SvgIcon fontSize="small">
|
||||||
|
<EnvelopeIcon color='gray'/>
|
||||||
|
</SvgIcon>
|
||||||
|
)
|
||||||
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: 'Map',
|
|
||||||
tooltip: 'Upgrade to Business Plan',
|
|
||||||
icon: (
|
|
||||||
<SvgIcon fontSize="small">
|
|
||||||
<MapIcon color='gray'/>
|
|
||||||
</SvgIcon>
|
|
||||||
),
|
|
||||||
disabled: true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: 'Credentials',
|
title: 'Credentials',
|
||||||
path: '/credentials',
|
path: '/credentials',
|
||||||
|
|
@ -71,11 +73,43 @@ export const items = [
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Users',
|
title: 'Access Control',
|
||||||
path: '/users',
|
disabled: true,
|
||||||
|
tooltip: 'Upgrade to Business Plan',
|
||||||
icon: (
|
icon: (
|
||||||
<SvgIcon fontSize="small">
|
<SvgIcon fontSize="small">
|
||||||
<UserGroupIcon />
|
<UserGroupIcon color='gray'/>
|
||||||
|
</SvgIcon>
|
||||||
|
),
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
title: 'Roles',
|
||||||
|
disabled: true,
|
||||||
|
tooltip: 'Upgrade to Business Plan',
|
||||||
|
icon: (
|
||||||
|
<SvgIcon fontSize="small">
|
||||||
|
<ShieldCheckIcon color='gray'/>
|
||||||
|
</SvgIcon>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Users',
|
||||||
|
path: '/access-control/users',
|
||||||
|
icon: (
|
||||||
|
<SvgIcon fontSize="small">
|
||||||
|
<UserIcon/>
|
||||||
|
</SvgIcon>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'File Server',
|
||||||
|
tooltip: 'Upgrade to Business Plan',
|
||||||
|
disabled: true,
|
||||||
|
icon: (
|
||||||
|
<SvgIcon fontSize="small">
|
||||||
|
<FolderIcon color='gray'/>
|
||||||
</SvgIcon>
|
</SvgIcon>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ import { styled } from '@mui/material/styles';
|
||||||
import { withAuthGuard } from 'src/hocs/with-auth-guard';
|
import { withAuthGuard } from 'src/hocs/with-auth-guard';
|
||||||
import { SideNav } from './side-nav';
|
import { SideNav } from './side-nav';
|
||||||
import { TopNav } from './top-nav';
|
import { TopNav } from './top-nav';
|
||||||
|
import { useAlertContext } from 'src/contexts/error-context';
|
||||||
|
import { Alert, AlertTitle, Snackbar } from '@mui/material';
|
||||||
|
|
||||||
const SIDE_NAV_WIDTH = 280;
|
const SIDE_NAV_WIDTH = 280;
|
||||||
|
|
||||||
|
|
@ -28,6 +30,8 @@ export const Layout = withAuthGuard((props) => {
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
const [openNav, setOpenNav] = useState(false);
|
const [openNav, setOpenNav] = useState(false);
|
||||||
|
|
||||||
|
const {alert, setAlert} = useAlertContext();
|
||||||
|
|
||||||
const handlePathnameChange = useCallback(
|
const handlePathnameChange = useCallback(
|
||||||
() => {
|
() => {
|
||||||
if (openNav) {
|
if (openNav) {
|
||||||
|
|
@ -57,6 +61,21 @@ export const Layout = withAuthGuard((props) => {
|
||||||
{children}
|
{children}
|
||||||
</LayoutContainer>
|
</LayoutContainer>
|
||||||
</LayoutRoot>
|
</LayoutRoot>
|
||||||
|
{alert && <Snackbar
|
||||||
|
open={true}
|
||||||
|
autoHideDuration={4000}
|
||||||
|
anchorOrigin={{vertical:'bottom', horizontal: 'right'}}
|
||||||
|
onClose={() => setAlert(null)}
|
||||||
|
>
|
||||||
|
<Alert
|
||||||
|
severity={alert?.severity}
|
||||||
|
variant={alert?.severity == 'success' ? 'standard' : 'filled'}
|
||||||
|
sx={{ width: '100%' }}
|
||||||
|
>
|
||||||
|
{alert?.title && <AlertTitle>{alert.title}</AlertTitle>}
|
||||||
|
{alert?.message}
|
||||||
|
</Alert>
|
||||||
|
</Snackbar>}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
@ -9,7 +9,7 @@ import { usePathname } from 'next/navigation';
|
||||||
export const SideNavItem = (props) => {
|
export const SideNavItem = (props) => {
|
||||||
const { active = false, disabled, external, icon, path, title, children, padleft, tooltip } = props;
|
const { active = false, disabled, external, icon, path, title, children, padleft, tooltip } = props;
|
||||||
|
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(true);
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
|
|
||||||
const isItemActive = (currentPath, itemPath) => {
|
const isItemActive = (currentPath, itemPath) => {
|
||||||
|
|
@ -64,10 +64,14 @@ export const SideNavItem = (props) => {
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
||||||
{icon && (
|
{icon && (
|
||||||
<Box
|
<Box
|
||||||
component="span"
|
component="span"
|
||||||
|
onClick={()=>{
|
||||||
|
if (!path){
|
||||||
|
setOpen(!open)
|
||||||
|
}
|
||||||
|
}}
|
||||||
sx={{
|
sx={{
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
color: 'neutral.400',
|
color: 'neutral.400',
|
||||||
|
|
@ -85,6 +89,11 @@ export const SideNavItem = (props) => {
|
||||||
)}
|
)}
|
||||||
<Box
|
<Box
|
||||||
component="span"
|
component="span"
|
||||||
|
onClick={()=>{
|
||||||
|
if (!path){
|
||||||
|
setOpen(!open)
|
||||||
|
}
|
||||||
|
}}
|
||||||
sx={{
|
sx={{
|
||||||
color: 'neutral.400',
|
color: 'neutral.400',
|
||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,10 @@ import { useNProgress } from 'src/hooks/use-nprogress';
|
||||||
import { createTheme } from 'src/theme';
|
import { createTheme } from 'src/theme';
|
||||||
import { createEmotionCache } from 'src/utils/create-emotion-cache';
|
import { createEmotionCache } from 'src/utils/create-emotion-cache';
|
||||||
import 'simplebar-react/dist/simplebar.min.css';
|
import 'simplebar-react/dist/simplebar.min.css';
|
||||||
import { WsProvider } from 'src/contexts/socketio-context';
|
|
||||||
import '../utils/map.css';
|
import '../utils/map.css';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
|
import { BackendProvider } from 'src/contexts/backend-context';
|
||||||
|
import { AlertProvider } from 'src/contexts/error-context';
|
||||||
|
|
||||||
const clientSideEmotionCache = createEmotionCache();
|
const clientSideEmotionCache = createEmotionCache();
|
||||||
|
|
||||||
|
|
@ -33,7 +34,7 @@ const App = (props) => {
|
||||||
<CacheProvider value={emotionCache}>
|
<CacheProvider value={emotionCache}>
|
||||||
<Head>
|
<Head>
|
||||||
<title>
|
<title>
|
||||||
Oktopus | TR-369 Controller
|
Oktopus | Controller
|
||||||
</title>
|
</title>
|
||||||
<meta
|
<meta
|
||||||
name="viewport"
|
name="viewport"
|
||||||
|
|
@ -42,16 +43,22 @@ const App = (props) => {
|
||||||
</Head>
|
</Head>
|
||||||
<LocalizationProvider dateAdapter={AdapterDateFns}>
|
<LocalizationProvider dateAdapter={AdapterDateFns}>
|
||||||
<AuthProvider>
|
<AuthProvider>
|
||||||
<ThemeProvider theme={theme}>
|
{/* <WsProvider> */}
|
||||||
<CssBaseline />
|
<AlertProvider>
|
||||||
<AuthConsumer>
|
<BackendProvider>
|
||||||
{
|
<ThemeProvider theme={theme}>
|
||||||
(auth) => auth.isLoading
|
<CssBaseline />
|
||||||
? <SplashScreen />
|
<AuthConsumer>
|
||||||
: getLayout(<Component {...pageProps} />)
|
{
|
||||||
}
|
(auth) => auth.isLoading
|
||||||
</AuthConsumer>
|
? <SplashScreen />
|
||||||
</ThemeProvider>
|
: getLayout(<Component {...pageProps} />)
|
||||||
|
}
|
||||||
|
</AuthConsumer>
|
||||||
|
</ThemeProvider>
|
||||||
|
</BackendProvider>
|
||||||
|
</AlertProvider>
|
||||||
|
{/* </WsProvider> */}
|
||||||
</AuthProvider>
|
</AuthProvider>
|
||||||
</LocalizationProvider>
|
</LocalizationProvider>
|
||||||
</CacheProvider>
|
</CacheProvider>
|
||||||
|
|
|
||||||
|
|
@ -204,15 +204,10 @@ const Page = () => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getColumns()
|
getColumns()
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
if (auth.user.token) {
|
|
||||||
console.log("auth.user.token =", auth.user.token)
|
|
||||||
} else {
|
|
||||||
auth.user.token = localStorage.getItem("token")
|
|
||||||
}
|
|
||||||
|
|
||||||
var myHeaders = new Headers();
|
var myHeaders = new Headers();
|
||||||
myHeaders.append("Content-Type", "application/json");
|
myHeaders.append("Content-Type", "application/json");
|
||||||
myHeaders.append("Authorization", auth.user.token);
|
myHeaders.append("Authorization", localStorage.getItem("token"));
|
||||||
|
|
||||||
var requestOptions = {
|
var requestOptions = {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
|
|
@ -293,8 +288,9 @@ const Page = () => {
|
||||||
console.log("set alias result:", content)
|
console.log("set alias result:", content)
|
||||||
setShowSetDeviceAlias(false)
|
setShowSetDeviceAlias(false)
|
||||||
setDeviceAlias(null)
|
setDeviceAlias(null)
|
||||||
orders[deviceToBeChanged].Alias = alias
|
devices[deviceToBeChanged].Alias = alias
|
||||||
setDeviceToBeChanged(null)
|
setDeviceToBeChanged(null)
|
||||||
|
setDevices([...devices])
|
||||||
}
|
}
|
||||||
// .then(response => {
|
// .then(response => {
|
||||||
// if (response.status === 401) {
|
// if (response.status === 401) {
|
||||||
|
|
@ -415,7 +411,7 @@ const Page = () => {
|
||||||
<>
|
<>
|
||||||
<Head>
|
<Head>
|
||||||
<title>
|
<title>
|
||||||
Oktopus | TR-369
|
Oktopus | Controller
|
||||||
</title>
|
</title>
|
||||||
</Head>
|
</Head>
|
||||||
|
|
||||||
|
|
@ -651,7 +647,7 @@ const Page = () => {
|
||||||
</SvgIcon>
|
</SvgIcon>
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>}
|
</Tooltip>}
|
||||||
{/* <Tooltip title="Edit the device alias">
|
<Tooltip title="Edit the device alias">
|
||||||
<Button
|
<Button
|
||||||
onClick={()=>{
|
onClick={()=>{
|
||||||
setDeviceToBeChanged(index)
|
setDeviceToBeChanged(index)
|
||||||
|
|
@ -667,7 +663,7 @@ const Page = () => {
|
||||||
</SvgIcon>
|
</SvgIcon>
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip title="Edit device labels">
|
{/* <Tooltip title="Edit device labels">
|
||||||
<Button
|
<Button
|
||||||
onClick={()=>{
|
onClick={()=>{
|
||||||
setDeviceToBeChanged(index)
|
setDeviceToBeChanged(index)
|
||||||
|
|
@ -724,7 +720,7 @@ const Page = () => {
|
||||||
<Input value={deviceAlias} onChange={(e) => { setDeviceAlias(e.target.value) }}
|
<Input value={deviceAlias} onChange={(e) => { setDeviceAlias(e.target.value) }}
|
||||||
onKeyUp={e => {
|
onKeyUp={e => {
|
||||||
if (e.key === 'Enter') {
|
if (e.key === 'Enter') {
|
||||||
setNewDeviceAlias(deviceAlias, orders[deviceToBeChanged].SN)
|
setNewDeviceAlias(deviceAlias, devices[deviceToBeChanged].SN)
|
||||||
}
|
}
|
||||||
}}>
|
}}>
|
||||||
</Input>
|
</Input>
|
||||||
|
|
@ -736,7 +732,7 @@ const Page = () => {
|
||||||
setDeviceToBeChanged(null)
|
setDeviceToBeChanged(null)
|
||||||
}}>Cancel</Button>
|
}}>Cancel</Button>
|
||||||
<Button onClick={() => {
|
<Button onClick={() => {
|
||||||
setNewDeviceAlias(deviceAlias, orders[deviceToBeChanged].SN)
|
setNewDeviceAlias(deviceAlias, devices[deviceToBeChanged].SN)
|
||||||
}}>Save</Button>
|
}}>Save</Button>
|
||||||
</DialogActions>
|
</DialogActions>
|
||||||
</Dialog>}
|
</Dialog>}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,9 @@ import DevicePhoneMobile from '@heroicons/react/24/solid/DevicePhoneMobileIcon';
|
||||||
import WrenchScrewDriverIcon from '@heroicons/react/24/outline/WrenchScrewdriverIcon';
|
import WrenchScrewDriverIcon from '@heroicons/react/24/outline/WrenchScrewdriverIcon';
|
||||||
import CommandLineIcon from '@heroicons/react/24/outline/CommandLineIcon';
|
import CommandLineIcon from '@heroicons/react/24/outline/CommandLineIcon';
|
||||||
import { DevicesWiFi } from 'src/sections/devices/cwmp/devices-wifi';
|
import { DevicesWiFi } from 'src/sections/devices/cwmp/devices-wifi';
|
||||||
|
import ArrowTrendingUpIcon from '@heroicons/react/24/outline/ArrowTrendingUpIcon';
|
||||||
|
import DocumentTextIcon from '@heroicons/react/24/outline/DocumentTextIcon';
|
||||||
|
import MapPinIcon from '@heroicons/react/24/outline/MapPinIcon';
|
||||||
|
|
||||||
|
|
||||||
const Page = () => {
|
const Page = () => {
|
||||||
|
|
@ -31,10 +34,10 @@ const Page = () => {
|
||||||
switch(section){
|
switch(section){
|
||||||
case "msg":
|
case "msg":
|
||||||
return <DevicesRPC/>
|
return <DevicesRPC/>
|
||||||
case "wifi":
|
/* case "wifi":
|
||||||
return <DevicesWiFi/>
|
return <DevicesWiFi/> */
|
||||||
default:
|
default:
|
||||||
router.push(`/devices/cwmp/${deviceID}/wifi`)
|
router.replace(`/devices/cwmp/${deviceID}/msg`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -42,7 +45,7 @@ const Page = () => {
|
||||||
<>
|
<>
|
||||||
<Head>
|
<Head>
|
||||||
<title>
|
<title>
|
||||||
Oktopus | TR-369
|
Oktopus | Controller
|
||||||
</title>
|
</title>
|
||||||
</Head>
|
</Head>
|
||||||
<Box
|
<Box
|
||||||
|
|
@ -52,9 +55,9 @@ const Page = () => {
|
||||||
py: 0,
|
py: 0,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Container maxWidth="lg" >
|
<Container maxWidth="xg">
|
||||||
<Stack spacing={3} >
|
<Stack spacing={3} mb={3}>
|
||||||
<Breadcrumbs separator="›" aria-label="breadcrumb" sx={{md: 40, mr: 20}}>
|
<Breadcrumbs separator="›" aria-label="breadcrumb" ml={10}>
|
||||||
{[<Link underline="hover" key="1" color="inherit" href="/devices">
|
{[<Link underline="hover" key="1" color="inherit" href="/devices">
|
||||||
Devices
|
Devices
|
||||||
</Link>,
|
</Link>,
|
||||||
|
|
@ -71,19 +74,19 @@ const Page = () => {
|
||||||
display:'flex',
|
display:'flex',
|
||||||
justifyContent:'center',
|
justifyContent:'center',
|
||||||
}}>
|
}}>
|
||||||
<Tabs value={router.query.id[1]} aria-label="icon label tabs example">
|
<Tabs value={router.query.id[1]} aria-label="icon label tabs example" variant='scrollable'>
|
||||||
|
<Tooltip title="Upgrade to Business Plan" placement="bottom">
|
||||||
<Tab
|
<Tab
|
||||||
icon={<SvgIcon><WifiIcon/></SvgIcon>}
|
icon={<SvgIcon><WifiIcon/></SvgIcon>}
|
||||||
iconPosition={"end"}
|
iconPosition={"end"}
|
||||||
label="Wi-Fi"
|
label="Wi-Fi"
|
||||||
onClick={()=>{router.push(`/devices/cwmp/${deviceID}/wifi`)}}
|
value={"wifi"}
|
||||||
value={"wifi"}/>
|
style={{opacity:"0.5", cursor:"default"}}/></Tooltip>
|
||||||
<Tooltip title="Upgrade to Business Plan" placement="bottom">
|
<Tooltip title="Upgrade to Business Plan" placement="bottom">
|
||||||
<Tab
|
<Tab
|
||||||
icon={<SvgIcon><SignalIcon/></SvgIcon>}
|
icon={<SvgIcon><SignalIcon/></SvgIcon>}
|
||||||
iconPosition={"end"}
|
iconPosition={"end"}
|
||||||
label="Site Survey"
|
label="Site Survey"
|
||||||
onClick={()=>{router.push(`/devices/cwmp/${deviceID}/site-survey`)}}
|
|
||||||
value={"site-survey"}
|
value={"site-survey"}
|
||||||
style={{opacity:"0.5", cursor:"default"}}/></Tooltip>
|
style={{opacity:"0.5", cursor:"default"}}/></Tooltip>
|
||||||
<Tooltip title="Upgrade to Business Plan" placement="bottom">
|
<Tooltip title="Upgrade to Business Plan" placement="bottom">
|
||||||
|
|
@ -92,7 +95,6 @@ const Page = () => {
|
||||||
iconPosition={"end"}
|
iconPosition={"end"}
|
||||||
label="Connected Devices"
|
label="Connected Devices"
|
||||||
style={{opacity:"0.5", cursor:"default"}}
|
style={{opacity:"0.5", cursor:"default"}}
|
||||||
onClick={()=>{router.push(`/devices/cwmp/${deviceID}/connected-devices`)}}
|
|
||||||
value={"connected-devices"}
|
value={"connected-devices"}
|
||||||
/></Tooltip>
|
/></Tooltip>
|
||||||
<Tooltip title="Upgrade to Business Plan" placement="bottom">
|
<Tooltip title="Upgrade to Business Plan" placement="bottom">
|
||||||
|
|
@ -100,7 +102,6 @@ const Page = () => {
|
||||||
icon={<SvgIcon><WrenchScrewDriverIcon/></SvgIcon>}
|
icon={<SvgIcon><WrenchScrewDriverIcon/></SvgIcon>}
|
||||||
iconPosition={"end"}
|
iconPosition={"end"}
|
||||||
label="Diagnostic"
|
label="Diagnostic"
|
||||||
onClick={()=>{router.push(`/devices/cwmp/${deviceID}/diagnostic`)}}
|
|
||||||
value={"diagnostic"}
|
value={"diagnostic"}
|
||||||
style={{opacity:"0.5", cursor:"default"}}/></Tooltip>
|
style={{opacity:"0.5", cursor:"default"}}/></Tooltip>
|
||||||
<Tooltip title="Upgrade to Business Plan" placement="bottom">
|
<Tooltip title="Upgrade to Business Plan" placement="bottom">
|
||||||
|
|
@ -108,25 +109,48 @@ const Page = () => {
|
||||||
icon={<SvgIcon><ServerStackIcon/></SvgIcon>}
|
icon={<SvgIcon><ServerStackIcon/></SvgIcon>}
|
||||||
iconPosition={"end"}
|
iconPosition={"end"}
|
||||||
label="Ports"
|
label="Ports"
|
||||||
onClick={()=>{router.push(`/devices/usp/${deviceID}/ports`)}}
|
|
||||||
style={{opacity:"0.5", cursor:"default"}}
|
style={{opacity:"0.5", cursor:"default"}}
|
||||||
value={"ports"} /></Tooltip>
|
value={"ports"} /></Tooltip>
|
||||||
<Tooltip title="Upgrade to Business Plan" placement="bottom">
|
<Tooltip title="Upgrade to Business Plan" placement="bottom">
|
||||||
<Tab
|
<Tab
|
||||||
|
icon={<SvgIcon><ArrowTrendingUpIcon/></SvgIcon>}
|
||||||
|
iconPosition={"end"}
|
||||||
|
label="Historic"
|
||||||
|
value={"historic"}
|
||||||
|
style={{opacity:"0.5", cursor:"default"}}/></Tooltip>
|
||||||
|
<Tooltip title="Upgrade to Business Plan" placement="bottom">
|
||||||
|
<Tab
|
||||||
icon={<SvgIcon><CommandLineIcon/></SvgIcon>}
|
icon={<SvgIcon><CommandLineIcon/></SvgIcon>}
|
||||||
iconPosition={"end"}
|
iconPosition={"end"}
|
||||||
label="Actions"
|
label="Actions"
|
||||||
onClick={()=>{router.push(`/devices/usp/${deviceID}/actions`)}}
|
|
||||||
style={{opacity:"0.5", cursor:"default"}}
|
style={{opacity:"0.5", cursor:"default"}}
|
||||||
value={"actions"} /></Tooltip>
|
value={"actions"} /></Tooltip>
|
||||||
|
<Tooltip title="Upgrade to Business Plan" placement="bottom">
|
||||||
|
<Tab
|
||||||
|
icon={<SvgIcon><DocumentTextIcon/></SvgIcon>}
|
||||||
|
iconPosition={"end"}
|
||||||
|
label="Logs"
|
||||||
|
style={{opacity:"0.5", cursor:"default"}}
|
||||||
|
value={"logs"} /></Tooltip>
|
||||||
|
<Tooltip title="Upgrade to Business Plan" placement="bottom">
|
||||||
|
<Tab
|
||||||
|
icon={<SvgIcon><MapPinIcon/></SvgIcon>}
|
||||||
|
iconPosition={"end"}
|
||||||
|
label="Location"
|
||||||
|
style={{opacity:"0.5", cursor:"default"}}
|
||||||
|
value={"location"} /></Tooltip>
|
||||||
<Tab
|
<Tab
|
||||||
value={"msg"}
|
value={"msg"}
|
||||||
onClick={()=>{router.push(`/devices/cwmp/${deviceID}/msg`)}}
|
onClick={()=>{router.push(`/devices/cwmp/${deviceID}/msg`)}}
|
||||||
icon={<SvgIcon><EnvelopeIcon/></SvgIcon>}
|
icon={<SvgIcon><EnvelopeIcon/></SvgIcon>}
|
||||||
iconPosition={"end"}
|
iconPosition={"end"}
|
||||||
label="Remote Messages" />
|
label="Messages" />
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</Box>
|
</Box>
|
||||||
|
</Stack>
|
||||||
|
</Container>
|
||||||
|
<Container maxWidth="lg">
|
||||||
|
<Stack spacing={3}>
|
||||||
{
|
{
|
||||||
sectionHandler()
|
sectionHandler()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,9 @@ import SignalIcon from '@heroicons/react/24/solid/SignalIcon';
|
||||||
import DevicePhoneMobile from '@heroicons/react/24/solid/DevicePhoneMobileIcon';
|
import DevicePhoneMobile from '@heroicons/react/24/solid/DevicePhoneMobileIcon';
|
||||||
import WrenchScrewDriverIcon from '@heroicons/react/24/outline/WrenchScrewdriverIcon';
|
import WrenchScrewDriverIcon from '@heroicons/react/24/outline/WrenchScrewdriverIcon';
|
||||||
import CommandLineIcon from '@heroicons/react/24/outline/CommandLineIcon';
|
import CommandLineIcon from '@heroicons/react/24/outline/CommandLineIcon';
|
||||||
|
import CubeTransparentIcon from '@heroicons/react/24/outline/CubeTransparentIcon';
|
||||||
|
import MapPin from '@heroicons/react/24/outline/MapPinIcon';
|
||||||
|
import ArrowTrendingUp from '@heroicons/react/24/outline/ArrowTrendingUpIcon';
|
||||||
|
|
||||||
const Page = () => {
|
const Page = () => {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
@ -36,7 +39,7 @@ const Page = () => {
|
||||||
case "discovery":
|
case "discovery":
|
||||||
return <DevicesDiscovery/>
|
return <DevicesDiscovery/>
|
||||||
default:
|
default:
|
||||||
router.push(`/devices/usp/${deviceID}/discovery`)
|
router.replace(`/devices/usp/${deviceID}/discovery`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -44,7 +47,7 @@ const Page = () => {
|
||||||
<>
|
<>
|
||||||
<Head>
|
<Head>
|
||||||
<title>
|
<title>
|
||||||
Oktopus | TR-369
|
Oktopus | Controller
|
||||||
</title>
|
</title>
|
||||||
</Head>
|
</Head>
|
||||||
<Box
|
<Box
|
||||||
|
|
@ -54,9 +57,9 @@ const Page = () => {
|
||||||
py: 0,
|
py: 0,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Container maxWidth="lg" >
|
<Container maxWidth="xg" >
|
||||||
<Stack spacing={3} >
|
<Stack spacing={3} mb={3}>
|
||||||
<Breadcrumbs separator="›" aria-label="breadcrumb" sx={{md: 40, mr: 20}}>
|
<Breadcrumbs separator="›" aria-label="breadcrumb"ml={10}>
|
||||||
{[<Link underline="hover" key="1" color="inherit" href="/devices">
|
{[<Link underline="hover" key="1" color="inherit" href="/devices">
|
||||||
Devices
|
Devices
|
||||||
</Link>,
|
</Link>,
|
||||||
|
|
@ -72,9 +75,8 @@ const Page = () => {
|
||||||
<Box sx={{
|
<Box sx={{
|
||||||
display:'flex',
|
display:'flex',
|
||||||
justifyContent:'center'
|
justifyContent:'center'
|
||||||
}}
|
}}>
|
||||||
mb={3}>
|
<Tabs value={router.query.id[1]} aria-label="icon label tabs example" variant='scrollable'>
|
||||||
<Tabs value={router.query.id[1]} aria-label="icon label tabs example">
|
|
||||||
<Tooltip title="Upgrade to Business Plan" placement="bottom">
|
<Tooltip title="Upgrade to Business Plan" placement="bottom">
|
||||||
<Tab
|
<Tab
|
||||||
icon={<SvgIcon><WifiIcon/></SvgIcon>}
|
icon={<SvgIcon><WifiIcon/></SvgIcon>}
|
||||||
|
|
@ -117,6 +119,27 @@ const Page = () => {
|
||||||
value={"ports"} /></Tooltip>
|
value={"ports"} /></Tooltip>
|
||||||
<Tooltip title="Upgrade to Business Plan" placement="bottom">
|
<Tooltip title="Upgrade to Business Plan" placement="bottom">
|
||||||
<Tab
|
<Tab
|
||||||
|
icon={<SvgIcon><ArrowTrendingUp/></SvgIcon>}
|
||||||
|
iconPosition={"end"}
|
||||||
|
label="Historic"
|
||||||
|
style={{cursor:"default", opacity: 0.5}}
|
||||||
|
value={"historic"} /></Tooltip>
|
||||||
|
<Tooltip title="Upgrade to Business Plan" placement="bottom">
|
||||||
|
<Tab
|
||||||
|
icon={<SvgIcon><CubeTransparentIcon/></SvgIcon>}
|
||||||
|
iconPosition={"end"}
|
||||||
|
label="LCM"
|
||||||
|
style={{cursor:"default", opacity: 0.5}}
|
||||||
|
value={"lcm"} /></Tooltip>
|
||||||
|
<Tooltip title="Upgrade to Business Plan" placement="bottom">
|
||||||
|
<Tab
|
||||||
|
icon={<SvgIcon><MapPin/></SvgIcon>}
|
||||||
|
iconPosition={"end"}
|
||||||
|
label="Location"
|
||||||
|
style={{cursor:"default", opacity: 0.5}}
|
||||||
|
value={"location"} /></Tooltip>
|
||||||
|
<Tooltip title="Upgrade to Business Plan" placement="bottom">
|
||||||
|
<Tab
|
||||||
icon={<SvgIcon><CommandLineIcon/></SvgIcon>}
|
icon={<SvgIcon><CommandLineIcon/></SvgIcon>}
|
||||||
iconPosition={"end"}
|
iconPosition={"end"}
|
||||||
label="Actions"
|
label="Actions"
|
||||||
|
|
@ -127,15 +150,19 @@ const Page = () => {
|
||||||
onClick={()=>{router.push(`/devices/usp/${deviceID}/discovery`)}}
|
onClick={()=>{router.push(`/devices/usp/${deviceID}/discovery`)}}
|
||||||
icon={<SvgIcon><MagnifyingGlassIcon/></SvgIcon>}
|
icon={<SvgIcon><MagnifyingGlassIcon/></SvgIcon>}
|
||||||
iconPosition={"end"}
|
iconPosition={"end"}
|
||||||
label="Discover Parameters" />
|
label="Parameters" />
|
||||||
<Tab
|
<Tab
|
||||||
value={"msg"}
|
value={"msg"}
|
||||||
onClick={()=>{router.push(`/devices/usp/${deviceID}/msg`)}}
|
onClick={()=>{router.push(`/devices/usp/${deviceID}/msg`)}}
|
||||||
icon={<SvgIcon><EnvelopeIcon/></SvgIcon>}
|
icon={<SvgIcon><EnvelopeIcon/></SvgIcon>}
|
||||||
iconPosition={"end"}
|
iconPosition={"end"}
|
||||||
label="Remote Messages" />
|
label="Messages" />
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</Box>
|
</Box>
|
||||||
|
</Stack>
|
||||||
|
</Container>
|
||||||
|
<Container maxWidth="lg">
|
||||||
|
<Stack spacing={3}>
|
||||||
{
|
{
|
||||||
sectionHandler()
|
sectionHandler()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -129,7 +129,7 @@ const Page = () => {
|
||||||
<>
|
<>
|
||||||
<Head>
|
<Head>
|
||||||
<title>
|
<title>
|
||||||
Oktopus | TR-369
|
Oktopus | Controller
|
||||||
</title>
|
</title>
|
||||||
</Head>
|
</Head>
|
||||||
<Box
|
<Box
|
||||||
|
|
|
||||||
|
|
@ -1,259 +0,0 @@
|
||||||
import Head from 'next/head';
|
|
||||||
import { GoogleMap, useLoadScript, Marker, OverlayView } from "@react-google-maps/api"
|
|
||||||
import { Layout as DashboardLayout } from 'src/layouts/dashboard/layout';
|
|
||||||
import { useEffect, useMemo, useState } from 'react';
|
|
||||||
import mapStyles from '../utils/mapStyles.json';
|
|
||||||
import { useRouter } from 'next/router';
|
|
||||||
|
|
||||||
const getPixelPositionOffset = pixelOffset => (width, height) => ({
|
|
||||||
x: -(width / 2) + pixelOffset.x,
|
|
||||||
y: -(height / 2) + pixelOffset.y
|
|
||||||
});
|
|
||||||
|
|
||||||
const Popup = props => {
|
|
||||||
return (
|
|
||||||
<OverlayView
|
|
||||||
position={props.anchorPosition}
|
|
||||||
mapPaneName={OverlayView.OVERLAY_MOUSE_TARGET}
|
|
||||||
getPixelPositionOffset={getPixelPositionOffset(props.markerPixelOffset)}
|
|
||||||
>
|
|
||||||
<div className="popup-tip-anchor">
|
|
||||||
<div className="popup-bubble-anchor">
|
|
||||||
<div className="popup-bubble-content">{props.content}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</OverlayView>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const Page = () => {
|
|
||||||
|
|
||||||
const libraries = useMemo(() => ['places'], []);
|
|
||||||
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
const [mapRef, setMapRef] = useState(null);
|
|
||||||
|
|
||||||
const [mapCenter, setMapCenter] = useState(null);
|
|
||||||
const [markers, setMarkers] = useState([]);
|
|
||||||
const [activeMarker, setActiveMarker] = useState(null);
|
|
||||||
const [activeMarkerdata, setActiveMarkerdata] = useState(null);
|
|
||||||
const [zoom, setZoom] = useState(null)
|
|
||||||
|
|
||||||
const handleDragEnd = () => {
|
|
||||||
if (mapRef) {
|
|
||||||
const newCenter = mapRef.getCenter();
|
|
||||||
console.log("newCenter:",newCenter.lat(), newCenter.lng());
|
|
||||||
localStorage.setItem("mapCenter", JSON.stringify({"lat":newCenter.lat(),"lng":newCenter.lng()}))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleZoomChange = () => {
|
|
||||||
if (mapRef) {
|
|
||||||
const newZoom = mapRef.getZoom();
|
|
||||||
console.log("new zoom", newZoom)
|
|
||||||
localStorage.setItem("zoom", newZoom)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleOnLoad = map => {
|
|
||||||
setMapRef(map);
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchMarkers = async () => {
|
|
||||||
|
|
||||||
var myHeaders = new Headers();
|
|
||||||
myHeaders.append("Content-Type", "application/json");
|
|
||||||
myHeaders.append("Authorization", localStorage.getItem("token"));
|
|
||||||
|
|
||||||
var requestOptions = {
|
|
||||||
method: 'GET',
|
|
||||||
headers: myHeaders,
|
|
||||||
redirect: 'follow'
|
|
||||||
};
|
|
||||||
|
|
||||||
let result = await fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/api/map`, requestOptions)
|
|
||||||
|
|
||||||
if (result.status == 200) {
|
|
||||||
const content = await result.json()
|
|
||||||
setMarkers(content)
|
|
||||||
}else if (result.status == 403) {
|
|
||||||
console.log("num tenx permissão, seu boca de sandália")
|
|
||||||
return router.push("/403")
|
|
||||||
}else if (result.status == 401){
|
|
||||||
console.log("taix nem autenticado, sai fora oh")
|
|
||||||
return router.push("/auth/login")
|
|
||||||
} else {
|
|
||||||
setMarkers([])
|
|
||||||
console.log("error to get map markers")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const fetchActiveMarkerData = async (id) => {
|
|
||||||
var myHeaders = new Headers();
|
|
||||||
myHeaders.append("Content-Type", "application/json");
|
|
||||||
myHeaders.append("Authorization", localStorage.getItem("token"));
|
|
||||||
|
|
||||||
var requestOptions = {
|
|
||||||
method: 'GET',
|
|
||||||
headers: myHeaders,
|
|
||||||
redirect: 'follow'
|
|
||||||
};
|
|
||||||
|
|
||||||
let result = await fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/api/device?id=`+id, requestOptions)
|
|
||||||
|
|
||||||
if (result.status == 200) {
|
|
||||||
const content = await result.json()
|
|
||||||
setActiveMarkerdata(content)
|
|
||||||
}else if (result.status == 403) {
|
|
||||||
return router.push("/403")
|
|
||||||
}else if (result.status == 401){
|
|
||||||
return router.push("/auth/login")
|
|
||||||
} else {
|
|
||||||
console.log("no device info found")
|
|
||||||
const content = await result.json()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(()=> {
|
|
||||||
fetchMarkers();
|
|
||||||
|
|
||||||
let zoomFromLocalStorage = localStorage.getItem("zoom")
|
|
||||||
if (zoomFromLocalStorage) {
|
|
||||||
setZoom(Number(zoomFromLocalStorage))
|
|
||||||
}else{
|
|
||||||
setZoom(25)
|
|
||||||
}
|
|
||||||
|
|
||||||
let mapCenterFromLocalStorage = localStorage.getItem("mapCenter")
|
|
||||||
if (mapCenterFromLocalStorage){
|
|
||||||
let fmtMapCenter = JSON.parse(localStorage.getItem("mapCenter"))
|
|
||||||
console.log("mapCenterFromLocalStorage:", fmtMapCenter)
|
|
||||||
setMapCenter({
|
|
||||||
lat: Number(fmtMapCenter.lat),
|
|
||||||
lng: Number(fmtMapCenter.lng),
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Check if geolocation is supported by the browser
|
|
||||||
if ("geolocation" in navigator) {
|
|
||||||
// Prompt user for permission to access their location
|
|
||||||
navigator.geolocation.getCurrentPosition(
|
|
||||||
// Get the user's latitude and longitude coordinates
|
|
||||||
// Success callback function
|
|
||||||
function(position) {
|
|
||||||
// Update the map with the user's new location
|
|
||||||
setMapCenter({
|
|
||||||
lat: position.coords.latitude,
|
|
||||||
lng: position.coords.longitude,
|
|
||||||
})
|
|
||||||
},
|
|
||||||
// Error callback function
|
|
||||||
function(error) {
|
|
||||||
// Handle errors, e.g. user denied location sharing permissions
|
|
||||||
console.log("Error getting user location:", error);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
// Geolocation is not supported by the browser
|
|
||||||
console.log("Geolocation is not supported by this browser, or the user denied access");
|
|
||||||
}
|
|
||||||
},[])
|
|
||||||
|
|
||||||
const mapOptions = useMemo(
|
|
||||||
() => ({
|
|
||||||
disableDefaultUI: false,
|
|
||||||
clickableIcons: true,
|
|
||||||
zoomControl: true,
|
|
||||||
controlSize: 23,
|
|
||||||
styles: mapStyles,
|
|
||||||
mapTypeControlOptions: {
|
|
||||||
mapTypeIds: ['roadmap', 'satellite'],
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
|
|
||||||
const { isLoaded } = useLoadScript({
|
|
||||||
googleMapsApiKey: process.env.NEXT_PUBLIC_GOOGLE_MAPS_KEY,
|
|
||||||
libraries: libraries,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!isLoaded) {
|
|
||||||
return <p>Loading...</p>;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ( markers && zoom &&
|
|
||||||
<>
|
|
||||||
<Head>
|
|
||||||
<title>
|
|
||||||
Maps | Oktopus
|
|
||||||
</title>
|
|
||||||
</Head>
|
|
||||||
<GoogleMap
|
|
||||||
options={mapOptions}
|
|
||||||
zoom={zoom}
|
|
||||||
center={mapCenter ? mapCenter : {
|
|
||||||
lat: 0.0,
|
|
||||||
lng: 0.0,
|
|
||||||
}}
|
|
||||||
mapContainerStyle={{ width: '100%', height: '100%' }}
|
|
||||||
onLoad={handleOnLoad}
|
|
||||||
clickableIcons={false}
|
|
||||||
onDragEnd={handleDragEnd}
|
|
||||||
onZoomChanged={handleZoomChange}
|
|
||||||
>
|
|
||||||
{
|
|
||||||
markers.map((marker, index) => (
|
|
||||||
<Marker
|
|
||||||
key={index}
|
|
||||||
position={{ lat: marker.coordinates.lat, lng: marker.coordinates.lng }}
|
|
||||||
icon={{
|
|
||||||
url: marker.img,
|
|
||||||
scaledSize: new window.google.maps.Size(50, 50),
|
|
||||||
anchor: new window.google.maps.Point(25, 25),
|
|
||||||
}}
|
|
||||||
draggable={false}
|
|
||||||
clickable={true}
|
|
||||||
onClick={() => {
|
|
||||||
setActiveMarkerdata(null);
|
|
||||||
if (activeMarker?.sn === marker.sn) {
|
|
||||||
setActiveMarker(null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
fetchActiveMarkerData(marker.sn);
|
|
||||||
setActiveMarker({
|
|
||||||
sn: marker.sn,
|
|
||||||
position: { lat: marker.coordinates.lat, lng: marker.coordinates.lng }
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
</Marker>
|
|
||||||
))
|
|
||||||
}
|
|
||||||
{activeMarker &&
|
|
||||||
<Popup
|
|
||||||
anchorPosition={activeMarker.position}
|
|
||||||
markerPixelOffset={{ x: 0, y: -32 }}
|
|
||||||
content={activeMarkerdata ?
|
|
||||||
<div>
|
|
||||||
<div>SN: {activeMarker.sn}</div>
|
|
||||||
<div>
|
|
||||||
<div>Model: {activeMarkerdata.Model?activeMarkerdata.Model:activeMarkerdata.ProductClass}</div>
|
|
||||||
<div>Alias: {activeMarkerdata.Alias}</div>
|
|
||||||
<div>Status: {activeMarkerdata.Status == 2 ? <span style={{color:"green"}}>online</span> : <span style={{color:"red"}}>offline</span>}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
: <p>no device info found</p>}
|
|
||||||
/>}
|
|
||||||
</GoogleMap>
|
|
||||||
</>
|
|
||||||
)};
|
|
||||||
|
|
||||||
Page.getLayout = (page) => (
|
|
||||||
<DashboardLayout>
|
|
||||||
{page}
|
|
||||||
</DashboardLayout>
|
|
||||||
);
|
|
||||||
|
|
||||||
export default Page;
|
|
||||||
|
|
@ -19,37 +19,26 @@ import {
|
||||||
DialogContentText,
|
DialogContentText,
|
||||||
DialogActions,
|
DialogActions,
|
||||||
Box,
|
Box,
|
||||||
IconButton
|
IconButton,
|
||||||
|
Grid
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import XMarkIcon from '@heroicons/react/24/outline/XMarkIcon';
|
import XMarkIcon from '@heroicons/react/24/outline/XMarkIcon';
|
||||||
import PaperAirplane from '@heroicons/react/24/solid/PaperAirplaneIcon';
|
import PaperAirplane from '@heroicons/react/24/solid/PaperAirplaneIcon';
|
||||||
import CircularProgress from '@mui/material/CircularProgress';
|
import CircularProgress from '@mui/material/CircularProgress';
|
||||||
import Backdrop from '@mui/material/Backdrop';
|
import Backdrop from '@mui/material/Backdrop';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
|
import { useBackendContext } from 'src/contexts/backend-context';
|
||||||
|
import DocumentArrowDown from '@heroicons/react/24/outline/DocumentArrowDownIcon';
|
||||||
|
import TrashIcon from '@heroicons/react/24/outline/TrashIcon';
|
||||||
|
import PlusCircleIcon from '@heroicons/react/24/outline/PlusCircleIcon';
|
||||||
|
import EnvelopeIcon from '@heroicons/react/24/outline/EnvelopeIcon';
|
||||||
|
import CheckIcon from '@heroicons/react/24/outline/CheckIcon';
|
||||||
|
|
||||||
|
|
||||||
export const DevicesRPC = () => {
|
export const DevicesRPC = () => {
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
let { httpRequest } = useBackendContext()
|
||||||
const [open, setOpen] = useState(false);
|
|
||||||
const [scroll, setScroll] = useState('paper');
|
|
||||||
const [answer, setAnswer] = useState(false)
|
|
||||||
const [content, setContent] = useState('')
|
|
||||||
const [age, setAge] = useState(2);
|
|
||||||
|
|
||||||
const [value, setValue] = useState(`<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<soap:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:cwmp="urn:dslforum-org:cwmp-1-0" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:schemaLocation="urn:dslforum-org:cwmp-1-0 ..\schemas\wt121.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
|
||||||
<soap:Header/>
|
|
||||||
<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
|
|
||||||
<cwmp:GetParameterValues>
|
|
||||||
<ParameterNames>
|
|
||||||
<string>InternetGatewayDevice.LANDevice.1.WLANConfiguration.1.</string>
|
|
||||||
<string>InternetGatewayDevice.LANDevice.1.WLANConfiguration.2.</string>
|
|
||||||
</ParameterNames>
|
|
||||||
</cwmp:GetParameterValues>
|
|
||||||
</soap:Body>
|
|
||||||
</soap:Envelope>`)
|
|
||||||
|
|
||||||
var prettifyXml = function(sourceXml)
|
var prettifyXml = function(sourceXml)
|
||||||
{
|
{
|
||||||
|
|
@ -75,129 +64,219 @@ var prettifyXml = function(sourceXml)
|
||||||
return resultXml;
|
return resultXml;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
const [scroll, setScroll] = useState('paper');
|
||||||
|
const [answer, setAnswer] = useState(false)
|
||||||
|
const [content, setContent] = useState('')
|
||||||
|
const [age, setAge] = useState(6);
|
||||||
|
const [newMessage, setNewMessage] = useState(false)
|
||||||
|
const [message, setMessage] = useState(null)
|
||||||
|
const [currentMsg, setCurrentMsg] = useState(0)
|
||||||
|
const [newMsgName, setNewMsgName] = useState("")
|
||||||
|
const [value, setValue] = useState()
|
||||||
|
const [saveChanges, setSaveChanges] = useState(false)
|
||||||
|
const [loadingSaveMsg, setLoadingSaveMsg] = useState(false)
|
||||||
|
const possibleMsgs = [
|
||||||
|
`<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<soap:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:cwmp="urn:dslforum-org:cwmp-1-0" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:schemaLocation="urn:dslforum-org:cwmp-1-0 ..\schemas\wt121.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
<soap:Header/>
|
||||||
|
<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
|
||||||
|
<cwmp:SetParameterValues>
|
||||||
|
<ParameterList soapenc:arrayType="cwmp:ParameterValueStruct[4]">
|
||||||
|
<ParameterValueStruct>
|
||||||
|
<Name>InternetGatewayDevice.TraceRouteDiagnostics.Host</Name>
|
||||||
|
<Value>192.168.60.4</Value>
|
||||||
|
</ParameterValueStruct>
|
||||||
|
</ParameterList>
|
||||||
|
<ParameterKey></ParameterKey>
|
||||||
|
</cwmp:SetParameterValues>
|
||||||
|
</soap:Body>
|
||||||
|
</soap:Envelope>`,
|
||||||
|
`<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<soap:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:cwmp="urn:dslforum-org:cwmp-1-0" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:schemaLocation="urn:dslforum-org:cwmp-1-0 ..\schemas\wt121.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
<soap:Header/>
|
||||||
|
<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
|
||||||
|
<cwmp:DeleteObject>
|
||||||
|
<ObjectName>InternetGatewayDevice.LANDevice.1.WLANConfiguration.2.</ObjectName>
|
||||||
|
<ParameterKey></ParameterKey>
|
||||||
|
</cwmp:DeleteObject>
|
||||||
|
</soap:Body>
|
||||||
|
</soap:Envelope>`,
|
||||||
|
`<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<soap:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:cwmp="urn:dslforum-org:cwmp-1-0" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:schemaLocation="urn:dslforum-org:cwmp-1-0 ..\schemas\wt121.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
<soap:Header/>
|
||||||
|
<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
|
||||||
|
<cwmp:AddObject>
|
||||||
|
<ObjectName>InternetGatewayDevice.LANDevice.1.WLANConfiguration.</ObjectName>
|
||||||
|
<ParameterKey></ParameterKey>
|
||||||
|
</cwmp:AddObject>
|
||||||
|
</soap:Body>
|
||||||
|
</soap:Envelope>`,
|
||||||
|
`<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<soap:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:cwmp="urn:dslforum-org:cwmp-1-0" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:schemaLocation="urn:dslforum-org:cwmp-1-0 ..\schemas\wt121.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
<soap:Header/>
|
||||||
|
<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
|
||||||
|
<cwmp:Reboot>
|
||||||
|
<CommandKey>
|
||||||
|
007
|
||||||
|
</CommandKey>
|
||||||
|
</cwmp:Reboot>
|
||||||
|
</soap:Body>
|
||||||
|
</soap:Envelope>`,
|
||||||
|
`<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<soap:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:cwmp="urn:dslforum-org:cwmp-1-0" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:schemaLocation="urn:dslforum-org:cwmp-1-0 ..schemaswt121.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
<soap:Header/>
|
||||||
|
<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
|
||||||
|
<cwmp:GetParameterValues>
|
||||||
|
<ParameterNames>
|
||||||
|
<string>InternetGatewayDevice.LANDevice.1.WLANConfiguration.1.</string>
|
||||||
|
</ParameterNames>
|
||||||
|
</cwmp:GetParameterValues>
|
||||||
|
</soap:Body>
|
||||||
|
</soap:Envelope>`,`<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<soap:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:cwmp="urn:dslforum-org:cwmp-1-0" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:schemaLocation="urn:dslforum-org:cwmp-1-0 ..\schemas\wt121.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
<soap:Header/>
|
||||||
|
<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
|
||||||
|
<cwmp:GetParameterNames>
|
||||||
|
<ParameterPath>InternetGatewayDevice.</ParameterPath>
|
||||||
|
<NextLevel>1</NextLevel>
|
||||||
|
</cwmp:GetParameterNames>
|
||||||
|
</soap:Body>
|
||||||
|
</soap:Envelope>`,
|
||||||
|
`<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<soap:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:cwmp="urn:dslforum-org:cwmp-1-0" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:schemaLocation="urn:dslforum-org:cwmp-1-0 ..\schemas\wt121.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
<soap:Header/>
|
||||||
|
<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
|
||||||
|
<cwmp:GetParameterAttributes>
|
||||||
|
<ParameterNames>
|
||||||
|
<string>InternetGatewayDevice.LANDevice.1.WLANConfiguration.</string>
|
||||||
|
</ParameterNames>
|
||||||
|
</cwmp:GetParameterAttributes>
|
||||||
|
</soap:Body>
|
||||||
|
</soap:Envelope>`]
|
||||||
|
const [newMsgValue, setNewMsgValue] = useState(possibleMsgs[age-1])
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
const handleNewMessageValue = (event) => {
|
||||||
|
setNewMsgValue(event.target.value)
|
||||||
|
}
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
};
|
};
|
||||||
const handleOpen = () => {
|
|
||||||
setOpen(true);
|
|
||||||
var myHeaders = new Headers();
|
|
||||||
myHeaders.append("Authorization", localStorage.getItem("token"));
|
|
||||||
|
|
||||||
var raw = value
|
const handleCancelNewMsgTemplate = () => {
|
||||||
|
setNewMessage(false)
|
||||||
|
setNewMsgName("")
|
||||||
|
setNewMsgValue(possibleMsgs[age-1])
|
||||||
|
// setValue(possibleMsgs[age-1])
|
||||||
|
}
|
||||||
|
|
||||||
var requestOptions = {
|
const saveMsg = async () => {
|
||||||
method: 'PUT',
|
let {status} = await httpRequest(
|
||||||
headers: myHeaders,
|
`/api/device/message?name=`+message[currentMsg].name,
|
||||||
body: raw,
|
"PUT",
|
||||||
redirect: 'follow'
|
value,
|
||||||
};
|
null,
|
||||||
|
)
|
||||||
var method;
|
if ( status === 204){
|
||||||
|
setSaveChanges(false)
|
||||||
switch(age) {
|
setMessage(message.map((msg, index) => {
|
||||||
case 1:
|
if (index === currentMsg) {
|
||||||
method="addObject"
|
return {...msg, value: value}
|
||||||
break;
|
}else{
|
||||||
case 2:
|
return msg
|
||||||
method="getParameterValues"
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
method="setParameterValues"
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
method="deleteObject"
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/api/device/cwmp/${router.query.id[0]}/${method}`, requestOptions)
|
|
||||||
.then(response => response.text())
|
|
||||||
.then(result => {
|
|
||||||
if (result.status === 401){
|
|
||||||
router.push("/auth/login")
|
|
||||||
}
|
}
|
||||||
setOpen(false)
|
}))
|
||||||
setAnswer(true)
|
}
|
||||||
let teste = prettifyXml(result)
|
}
|
||||||
console.log(teste)
|
|
||||||
setContent(teste)
|
const createNewMsg = async () => {
|
||||||
})
|
setLoading(true)
|
||||||
.catch(error => console.log('error', error));
|
let {status} = await httpRequest(
|
||||||
};
|
`/api/device/message/cwmp?name=`+newMsgName,
|
||||||
|
"POST",
|
||||||
|
newMsgValue,
|
||||||
|
null,
|
||||||
|
)
|
||||||
|
if ( status === 204){
|
||||||
|
setNewMessage(false)
|
||||||
|
setNewMsgName("")
|
||||||
|
let result = await fetchMessages()
|
||||||
|
if (result) {
|
||||||
|
setCurrentMsg(result.length-1)
|
||||||
|
}
|
||||||
|
setValue(newMsgValue)
|
||||||
|
setNewMsgValue(possibleMsgs[age-1])
|
||||||
|
}
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleChangeMessage = (event) => {
|
||||||
|
setSaveChanges(false)
|
||||||
|
setCurrentMsg(event.target.value)
|
||||||
|
setValue(message[event.target.value].value)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDeleteMessage = async () => {
|
||||||
|
let {status} = await httpRequest(
|
||||||
|
`/api/device/message?name=`+message[currentMsg].name.replace(" ", '+'),
|
||||||
|
"DELETE",
|
||||||
|
)
|
||||||
|
if ( status === 204){
|
||||||
|
fetchMessages()
|
||||||
|
setCurrentMsg(0)
|
||||||
|
setValue("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleOpen = async () => {
|
||||||
|
setOpen(true);
|
||||||
|
|
||||||
|
let {result, status} = await httpRequest(
|
||||||
|
`/api/device/cwmp/${router.query.id[0]}/generic`,
|
||||||
|
"PUT",
|
||||||
|
value,
|
||||||
|
null,
|
||||||
|
"text",
|
||||||
|
)
|
||||||
|
if (status === 200){
|
||||||
|
setAnswer(true)
|
||||||
|
console.log("result:",result)
|
||||||
|
let answer = prettifyXml(result)
|
||||||
|
if (answer == "null"){
|
||||||
|
answer = result
|
||||||
|
}
|
||||||
|
console.log(answer)
|
||||||
|
setContent(answer)
|
||||||
|
}
|
||||||
|
setOpen(false)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchMessages = async () => {
|
||||||
|
let {result, status} = await httpRequest(
|
||||||
|
`/api/device/message?type=cwmp`,
|
||||||
|
"GET",
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
)
|
||||||
|
if ( status === 200){
|
||||||
|
setMessage(result)
|
||||||
|
setValue(result ? result[0].value : "")
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const handleChangeRPC = (event) => {
|
const handleChangeRPC = (event) => {
|
||||||
setAge(event.target.value);
|
setAge(event.target.value);
|
||||||
switch(event.target.value) {
|
setNewMsgValue(possibleMsgs[event.target.value-1])
|
||||||
case 1:
|
|
||||||
setValue(`<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<soap:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:cwmp="urn:dslforum-org:cwmp-1-0" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:schemaLocation="urn:dslforum-org:cwmp-1-0 ..\schemas\wt121.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
|
||||||
<soap:Header/>
|
|
||||||
<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
|
|
||||||
<cwmp:AddObject>
|
|
||||||
<ObjectName>InternetGatewayDevice.LANDevice.</ObjectName>
|
|
||||||
<ParameterKey></ParameterKey>
|
|
||||||
</cwmp:AddObject>
|
|
||||||
</soap:Body>
|
|
||||||
</soap:Envelope>`)
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
setValue(`<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<soap:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:cwmp="urn:dslforum-org:cwmp-1-0" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:schemaLocation="urn:dslforum-org:cwmp-1-0 ..\schemas\wt121.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
|
||||||
<soap:Header/>
|
|
||||||
<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
|
|
||||||
<cwmp:GetParameterValues>
|
|
||||||
<ParameterNames>
|
|
||||||
<string>InternetGatewayDevice.LANDevice.1.WLANConfiguration.1.</string>
|
|
||||||
<string>InternetGatewayDevice.LANDevice.1.WLANConfiguration.2.</string>
|
|
||||||
<string>InternetGatewayDevice.LANDevice.2.WLANConfiguration.2.</string>
|
|
||||||
<string>InternetGatewayDevice.LANDevice.2.WLANConfiguration.1.</string>
|
|
||||||
</ParameterNames>
|
|
||||||
</cwmp:GetParameterValues>
|
|
||||||
</soap:Body>
|
|
||||||
</soap:Envelope>`)
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
setValue(`
|
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<soap:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:cwmp="urn:dslforum-org:cwmp-1-0" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:schemaLocation="urn:dslforum-org:cwmp-1-0 ..\schemas\wt121.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
|
||||||
<soap:Header/>
|
|
||||||
<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
|
|
||||||
<cwmp:SetParameterValues>
|
|
||||||
<ParameterList soapenc:arrayType="cwmp:ParameterValueStruct[3]">
|
|
||||||
<ParameterValueStruct>
|
|
||||||
<Name>InternetGatewayDevice.LANDevice.1.WLANConfiguration.1.Enable</Name>
|
|
||||||
<Value>0</Value>
|
|
||||||
</ParameterValueStruct>
|
|
||||||
<ParameterValueStruct>
|
|
||||||
<Name>InternetGatewayDevice.LANDevice.1.WLANConfiguration.2.SSID</Name>
|
|
||||||
<Value>HUAWEI_TEST-2</Value>
|
|
||||||
</ParameterValueStruct>
|
|
||||||
</ParameterList>
|
|
||||||
<ParameterKey>LC1309123</ParameterKey>
|
|
||||||
</cwmp:SetParameterValues>
|
|
||||||
</soap:Body>
|
|
||||||
</soap:Envelope>`)
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
setValue(`<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<soap:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:cwmp="urn:dslforum-org:cwmp-1-0" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:schemaLocation="urn:dslforum-org:cwmp-1-0 ..\schemas\wt121.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
|
||||||
<soap:Header/>
|
|
||||||
<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
|
|
||||||
<cwmp:DeleteObject>
|
|
||||||
<ObjectName>InternetGatewayDevice.LANDevice.3.</ObjectName>
|
|
||||||
<ParameterKey></ParameterKey>
|
|
||||||
</cwmp:DeleteObject>
|
|
||||||
</soap:Body>
|
|
||||||
</soap:Envelope>`)
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// code block
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleChange = (event) => {
|
const handleEditMessage = (event) => {
|
||||||
setValue(event.target.value);
|
setSaveChanges(true)
|
||||||
};
|
setValue(event.target.value)
|
||||||
|
}
|
||||||
|
|
||||||
const handleSubmit = useCallback(
|
const handleSubmit = useCallback(
|
||||||
(event) => {
|
(event) => {
|
||||||
|
|
@ -206,54 +285,91 @@ const handleOpen = () => {
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchMessages();
|
||||||
|
},[]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmit}>
|
<form onSubmit={handleSubmit}>
|
||||||
<Card>
|
<Card>
|
||||||
<CardActions sx={{ justifyContent: 'flex-end'}}>
|
<CardHeader sx={{ justifyContent: 'flex-end'}}
|
||||||
<FormControl sx={{width:'100px'}}>
|
avatar={<SvgIcon>< EnvelopeIcon/></SvgIcon>}
|
||||||
<Select
|
title="Custom Message"
|
||||||
labelId="demo-simple-select-standard-label"
|
action={
|
||||||
id="demo-simple-select-standard"
|
<Stack direction={"row"} spacing={1} width={"100%"} justifyContent={"flex-end"}>
|
||||||
value={age}
|
<Button sx={{ backgroundColor: "rgba(48, 109, 111, 0.04)" }}
|
||||||
label="Action"
|
endIcon={<SvgIcon><PlusCircleIcon /></SvgIcon>}
|
||||||
onChange={(event)=>{handleChangeRPC(event)}}
|
onClick={()=>{setNewMessage(true)}}
|
||||||
variant='standard'
|
>
|
||||||
>
|
<Stack direction={"row"} spacing={1}>
|
||||||
<MenuItem value={1}>Create</MenuItem>
|
New Message
|
||||||
<MenuItem value={2}>Read</MenuItem>
|
</Stack>
|
||||||
<MenuItem value={3}>Update</MenuItem>
|
</Button>
|
||||||
<MenuItem value={4}>Delete</MenuItem>
|
</Stack>}
|
||||||
</Select>
|
>
|
||||||
</FormControl>
|
</CardHeader>
|
||||||
</CardActions>
|
|
||||||
<Divider />
|
<Divider />
|
||||||
<CardContent>
|
<CardContent>
|
||||||
|
<Stack pb={4} spacing={5} direction={"row"}>
|
||||||
|
<FormControl sx={{display:"flex", width: "15%"}} variant="standard" >
|
||||||
|
<InputLabel>Message</InputLabel>
|
||||||
|
<Select
|
||||||
|
value={currentMsg}
|
||||||
|
onChange={(event)=>{handleChangeMessage(event)}}
|
||||||
|
>
|
||||||
|
{message && message.map((msg, index) => {
|
||||||
|
return <MenuItem value={index}>{msg.name}</MenuItem>
|
||||||
|
})}
|
||||||
|
</Select>
|
||||||
|
</FormControl>
|
||||||
|
</Stack>
|
||||||
<Stack
|
<Stack
|
||||||
spacing={3}
|
spacing={3}
|
||||||
alignItems={'stretch'}
|
alignItems={'stretch'}
|
||||||
>
|
>
|
||||||
<TextField
|
{!loadingSaveMsg ? <TextField
|
||||||
id="outlined-multiline-static"
|
id="outlined-multiline-static"
|
||||||
size="large"
|
size="large"
|
||||||
multiline="true"
|
multiline="true"
|
||||||
label="Mensagem"
|
// label="Payload"
|
||||||
name="password"
|
name="password"
|
||||||
onChange={handleChange}
|
onChange={handleEditMessage}
|
||||||
value={value}
|
value={value}
|
||||||
|
variant="filled"
|
||||||
fullWidth
|
fullWidth
|
||||||
rows="15"
|
rows="15"
|
||||||
/>
|
/>:<CircularProgress />}
|
||||||
</Stack>
|
</Stack>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
<Divider />
|
{/* <Divider /> */}
|
||||||
<CardActions sx={{ justifyContent: 'flex-end' }}>
|
<CardActions>
|
||||||
<Button
|
<Stack direction={"row"} spacing={1} width={"100%"} justifyContent={"flex-start"}>
|
||||||
variant="contained"
|
<Button
|
||||||
endIcon={<SvgIcon><PaperAirplane /></SvgIcon>}
|
variant="contained"
|
||||||
onClick={handleOpen}
|
endIcon={<SvgIcon><TrashIcon /></SvgIcon>}
|
||||||
>
|
onClick={handleDeleteMessage}
|
||||||
Send
|
disabled={!message}
|
||||||
</Button>
|
>
|
||||||
|
Delete
|
||||||
|
</Button>
|
||||||
|
{!loadingSaveMsg ? <Button
|
||||||
|
variant="contained"
|
||||||
|
endIcon={<SvgIcon><DocumentArrowDown /></SvgIcon>}
|
||||||
|
onClick={saveMsg}
|
||||||
|
disabled={!saveChanges}
|
||||||
|
>
|
||||||
|
Save
|
||||||
|
</Button>: <CircularProgress />}
|
||||||
|
</Stack>
|
||||||
|
<Stack direction={"row"} spacing={1} width={"100%"} justifyContent={"flex-end"}>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
endIcon={<SvgIcon><PaperAirplane /></SvgIcon>}
|
||||||
|
onClick={handleOpen}
|
||||||
|
>
|
||||||
|
Send
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
</CardActions>
|
</CardActions>
|
||||||
<Backdrop
|
<Backdrop
|
||||||
sx={{ color: '#fff', zIndex: (theme) => theme.zIndex.drawer + 1 }}
|
sx={{ color: '#fff', zIndex: (theme) => theme.zIndex.drawer + 1 }}
|
||||||
|
|
@ -307,6 +423,83 @@ const handleOpen = () => {
|
||||||
}}>Ok</Button>
|
}}>Ok</Button>
|
||||||
</DialogActions>
|
</DialogActions>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
<Dialog open={newMessage} maxWidth={"800px"}>
|
||||||
|
<DialogTitle>
|
||||||
|
<SvgIcon><EnvelopeIcon/></SvgIcon>
|
||||||
|
</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<Stack
|
||||||
|
direction={"row"}
|
||||||
|
container
|
||||||
|
pb={3}
|
||||||
|
// direction="column"
|
||||||
|
// alignItems="center"
|
||||||
|
// justifyContent="center"
|
||||||
|
pt={1}
|
||||||
|
spacing={3}
|
||||||
|
>
|
||||||
|
<TextField
|
||||||
|
variant='standard'
|
||||||
|
fullWidth
|
||||||
|
value={newMsgName}
|
||||||
|
onChange={(event)=>{setNewMsgName(event.target.value)}}
|
||||||
|
label="Name"
|
||||||
|
sx={{maxWidth: "30%", justifyContent:"center"}}
|
||||||
|
/>
|
||||||
|
<FormControl sx={{display:"flex", width: "30%"}} variant="standard" >
|
||||||
|
<InputLabel>Template</InputLabel>
|
||||||
|
<Select
|
||||||
|
value={age}
|
||||||
|
label="Action"
|
||||||
|
name='action'
|
||||||
|
onChange={(event)=>{handleChangeRPC(event)}}
|
||||||
|
>
|
||||||
|
<MenuItem value={1}>SetParameterValues</MenuItem>
|
||||||
|
<MenuItem value={2}>DeleteObject</MenuItem>
|
||||||
|
<MenuItem value={3}>AddObject</MenuItem>
|
||||||
|
<MenuItem value={4}>Reboot</MenuItem>
|
||||||
|
<MenuItem value={5}>GetParameterValues</MenuItem>
|
||||||
|
<MenuItem value={6}>GetParameterNames</MenuItem>
|
||||||
|
<MenuItem value={7}>GetParameterAttributes</MenuItem>
|
||||||
|
</Select>
|
||||||
|
</FormControl>
|
||||||
|
</Stack>
|
||||||
|
<Stack
|
||||||
|
spacing={3}
|
||||||
|
alignItems={'stretch'}
|
||||||
|
width={"600px"}
|
||||||
|
>
|
||||||
|
<TextField
|
||||||
|
id="outlined-multiline-static"
|
||||||
|
size="large"
|
||||||
|
multiline="true"
|
||||||
|
label="Payload"
|
||||||
|
name="password"
|
||||||
|
onChange={handleNewMessageValue}
|
||||||
|
value={newMsgValue}
|
||||||
|
// fullWidth
|
||||||
|
// rows="15"
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
</DialogContent>
|
||||||
|
{/* <Divider/> */}
|
||||||
|
<Stack direction={"row"} spacing={1} width={"100%"} justifyContent={"flex-end"} p={2}>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
onClick={handleCancelNewMsgTemplate}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
{!loading ?
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
endIcon={<SvgIcon><CheckIcon /></SvgIcon>}
|
||||||
|
onClick={createNewMsg}
|
||||||
|
>
|
||||||
|
Save
|
||||||
|
</Button>:<CircularProgress />}
|
||||||
|
</Stack>
|
||||||
|
</Dialog>
|
||||||
</Card>
|
</Card>
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -19,151 +19,296 @@ import {
|
||||||
DialogContentText,
|
DialogContentText,
|
||||||
DialogActions,
|
DialogActions,
|
||||||
Box,
|
Box,
|
||||||
IconButton
|
IconButton,
|
||||||
|
Grid
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import XMarkIcon from '@heroicons/react/24/outline/XMarkIcon';
|
import XMarkIcon from '@heroicons/react/24/outline/XMarkIcon';
|
||||||
import PaperAirplane from '@heroicons/react/24/solid/PaperAirplaneIcon';
|
import PaperAirplane from '@heroicons/react/24/solid/PaperAirplaneIcon';
|
||||||
import CircularProgress from '@mui/material/CircularProgress';
|
import CircularProgress from '@mui/material/CircularProgress';
|
||||||
import Backdrop from '@mui/material/Backdrop';
|
import Backdrop from '@mui/material/Backdrop';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
|
import { useBackendContext } from 'src/contexts/backend-context';
|
||||||
|
import DocumentArrowDown from '@heroicons/react/24/outline/DocumentArrowDownIcon';
|
||||||
|
import TrashIcon from '@heroicons/react/24/outline/TrashIcon';
|
||||||
|
import PlusCircleIcon from '@heroicons/react/24/outline/PlusCircleIcon';
|
||||||
|
import EnvelopeIcon from '@heroicons/react/24/outline/EnvelopeIcon';
|
||||||
|
import CheckIcon from '@heroicons/react/24/outline/CheckIcon';
|
||||||
|
|
||||||
|
|
||||||
export const DevicesRPC = () => {
|
export const DevicesRPC = () => {
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
let { httpRequest } = useBackendContext()
|
||||||
|
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const [scroll, setScroll] = useState('paper');
|
const [scroll, setScroll] = useState('paper');
|
||||||
const [answer, setAnswer] = useState(false)
|
const [answer, setAnswer] = useState(false)
|
||||||
const [content, setContent] = useState('')
|
const [content, setContent] = useState('')
|
||||||
const [age, setAge] = useState(2);
|
const [age, setAge] = useState(6);
|
||||||
|
const [newMessage, setNewMessage] = useState(false)
|
||||||
|
const [message, setMessage] = useState(null)
|
||||||
|
const [currentMsg, setCurrentMsg] = useState(0)
|
||||||
|
const [newMsgName, setNewMsgName] = useState("")
|
||||||
|
const [value, setValue] = useState()
|
||||||
|
const [saveChanges, setSaveChanges] = useState(false)
|
||||||
|
const [loadingSaveMsg, setLoadingSaveMsg] = useState(false)
|
||||||
|
const possibleMsgs = [
|
||||||
|
`{
|
||||||
|
"header": {
|
||||||
|
"msg_id": "b7dc38ea-aefb-4761-aa55-edaa97adb2f0",
|
||||||
|
"msg_type": 4
|
||||||
|
},
|
||||||
|
"body": {
|
||||||
|
"request": {
|
||||||
|
"set": {
|
||||||
|
"allow_partial":true,
|
||||||
|
"update_objs":[
|
||||||
|
{
|
||||||
|
"obj_path":"Device.IP.Interface.1.",
|
||||||
|
"param_settings":[
|
||||||
|
{
|
||||||
|
"param":"Alias",
|
||||||
|
"value":"test",
|
||||||
|
"required":true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
`{
|
||||||
|
"header": {
|
||||||
|
"msg_id": "b7dc38ea-aefb-4761-aa55-edaa97adb2f0",
|
||||||
|
"msg_type": 10
|
||||||
|
},
|
||||||
|
"body": {
|
||||||
|
"request": {
|
||||||
|
"delete": {
|
||||||
|
"allow_partial": true,
|
||||||
|
"obj_paths": [
|
||||||
|
"Device.IP.Interface.[Alias==test]."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
`
|
||||||
|
{
|
||||||
|
"header": {
|
||||||
|
"msg_id": "b7dc38ea-aefb-4761-aa55-edaa97adb2f0",
|
||||||
|
"msg_type": 8
|
||||||
|
},
|
||||||
|
"body": {
|
||||||
|
"request": {
|
||||||
|
"add": {
|
||||||
|
"allow_partial": true,
|
||||||
|
"create_objs": [
|
||||||
|
{
|
||||||
|
"obj_path": "Device.IP.Interface.",
|
||||||
|
"param_settings": [
|
||||||
|
{
|
||||||
|
"param": "Alias",
|
||||||
|
"value": "test",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
`{
|
||||||
|
"header": {
|
||||||
|
"msg_id": "b7dc38ea-aefb-4761-aa55-edaa97adb2f0",
|
||||||
|
"msg_type": 6
|
||||||
|
},
|
||||||
|
"body": {
|
||||||
|
"request": {
|
||||||
|
"operate": {
|
||||||
|
"command": "Device.Reboot()",
|
||||||
|
"send_resp": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
`{
|
||||||
|
"header": {
|
||||||
|
"msg_id": "b7dc38ea-aefb-4761-aa55-edaa97adb2f0",
|
||||||
|
"msg_type": 1
|
||||||
|
},
|
||||||
|
"body": {
|
||||||
|
"request": {
|
||||||
|
"get": {
|
||||||
|
"paramPaths": [
|
||||||
|
"Device.WiFi.SSID.[Name==wlan0].",
|
||||||
|
"Device.IP.Interface.*.Alias",
|
||||||
|
"Device.DeviceInfo.FirmwareImage.*.Alias",
|
||||||
|
"Device.IP.Interface.1.IPv4Address.1.IPAddress"
|
||||||
|
],
|
||||||
|
"maxDepth": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`,`{
|
||||||
|
"header": {
|
||||||
|
"msg_id": "b7dc38ea-aefb-4761-aa55-edaa97adb2f0",
|
||||||
|
"msg_type": 12
|
||||||
|
},
|
||||||
|
"body": {
|
||||||
|
"request": {
|
||||||
|
"get_supported_dm": {
|
||||||
|
"obj_paths" : [
|
||||||
|
"Device."
|
||||||
|
],
|
||||||
|
"first_level_only" : false,
|
||||||
|
"return_commands" : false,
|
||||||
|
"return_events" : false,
|
||||||
|
"return_params" : true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
`{
|
||||||
|
"header": {
|
||||||
|
"msg_id": "b7dc38ea-aefb-4761-aa55-edaa97adb2f0",
|
||||||
|
"msg_type": 14
|
||||||
|
},
|
||||||
|
"body": {
|
||||||
|
"request": {
|
||||||
|
"get_instances": {
|
||||||
|
"obj_paths" : ["Device.DeviceInfo."],
|
||||||
|
"first_level_only" : false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`]
|
||||||
|
const [newMsgValue, setNewMsgValue] = useState(possibleMsgs[age-1])
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
const [value, setValue] = useState(`{
|
const handleNewMessageValue = (event) => {
|
||||||
"param_paths": [
|
setNewMsgValue(event.target.value)
|
||||||
"Device.WiFi.SSID.[Name==wlan0].",
|
}
|
||||||
"Device.IP.Interface.*.Alias",
|
|
||||||
"Device.DeviceInfo.FirmwareImage.*.Alias",
|
|
||||||
"Device.IP.Interface.1.IPv4Address.1.IPAddress"
|
|
||||||
],
|
|
||||||
"max_depth": 2
|
|
||||||
}`)
|
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
};
|
};
|
||||||
const handleOpen = () => {
|
|
||||||
setOpen(true);
|
|
||||||
var myHeaders = new Headers();
|
|
||||||
myHeaders.append("Content-Type", "application/json");
|
|
||||||
myHeaders.append("Authorization", localStorage.getItem("token"));
|
|
||||||
|
|
||||||
var raw = value
|
const handleCancelNewMsgTemplate = () => {
|
||||||
|
setNewMessage(false)
|
||||||
|
setNewMsgName("")
|
||||||
|
setNewMsgValue(possibleMsgs[age-1])
|
||||||
|
// setValue(possibleMsgs[age-1])
|
||||||
|
}
|
||||||
|
|
||||||
var requestOptions = {
|
const saveMsg = async () => {
|
||||||
method: 'PUT',
|
let {status} = await httpRequest(
|
||||||
headers: myHeaders,
|
`/api/device/message?name=`+message[currentMsg].name,
|
||||||
body: raw,
|
"PUT",
|
||||||
redirect: 'follow'
|
value,
|
||||||
};
|
null,
|
||||||
|
)
|
||||||
var method;
|
if ( status === 204){
|
||||||
|
setSaveChanges(false)
|
||||||
switch(age) {
|
setMessage(message.map((msg, index) => {
|
||||||
case 1:
|
if (index === currentMsg) {
|
||||||
method="add"
|
return {...msg, value: value}
|
||||||
break;
|
}else{
|
||||||
case 2:
|
return msg
|
||||||
method="get"
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
method="set"
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
method="del"
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/api/device/${router.query.id[0]}/any/${method}`, requestOptions)
|
|
||||||
.then(response => response.text())
|
|
||||||
.then(result => {
|
|
||||||
if (result.status === 401){
|
|
||||||
router.push("/auth/login")
|
|
||||||
}
|
}
|
||||||
setOpen(false)
|
}))
|
||||||
setAnswer(true)
|
}
|
||||||
let teste = JSON.stringify(JSON.parse(result), null, 2)
|
}
|
||||||
console.log(teste)
|
|
||||||
setContent(teste)
|
const createNewMsg = async () => {
|
||||||
})
|
setLoading(true)
|
||||||
.catch(error => console.log('error', error));
|
let {status} = await httpRequest(
|
||||||
};
|
`/api/device/message/usp?name=`+newMsgName,
|
||||||
|
"POST",
|
||||||
|
newMsgValue,
|
||||||
|
null,
|
||||||
|
)
|
||||||
|
if ( status === 204){
|
||||||
|
setNewMessage(false)
|
||||||
|
setNewMsgName("")
|
||||||
|
let result = await fetchMessages()
|
||||||
|
if (result) {
|
||||||
|
setCurrentMsg(result.length-1)
|
||||||
|
}
|
||||||
|
setValue(newMsgValue)
|
||||||
|
setNewMsgValue(possibleMsgs[age-1])
|
||||||
|
}
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleChangeMessage = (event) => {
|
||||||
|
setSaveChanges(false)
|
||||||
|
setCurrentMsg(event.target.value)
|
||||||
|
setValue(message[event.target.value].value)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDeleteMessage = async () => {
|
||||||
|
let {status} = await httpRequest(
|
||||||
|
`/api/device/message?name=`+message[currentMsg].name.replace(" ", '+'),
|
||||||
|
"DELETE",
|
||||||
|
)
|
||||||
|
if ( status === 204){
|
||||||
|
fetchMessages()
|
||||||
|
setCurrentMsg(0)
|
||||||
|
setValue("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleOpen = async () => {
|
||||||
|
setOpen(true);
|
||||||
|
|
||||||
|
let {result, status} = await httpRequest(
|
||||||
|
`/api/device/${router.query.id[0]}/any/generic`,
|
||||||
|
"PUT",
|
||||||
|
value,
|
||||||
|
null,
|
||||||
|
)
|
||||||
|
if (status === 200){
|
||||||
|
setAnswer(true)
|
||||||
|
console.log("result:",result)
|
||||||
|
let answer = JSON.stringify(result, null, 2)
|
||||||
|
if (answer == "null"){
|
||||||
|
answer = result
|
||||||
|
}
|
||||||
|
console.log(answer)
|
||||||
|
setContent(answer)
|
||||||
|
}
|
||||||
|
setOpen(false)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchMessages = async () => {
|
||||||
|
let {result, status} = await httpRequest(
|
||||||
|
`/api/device/message?type=usp`,
|
||||||
|
"GET",
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
)
|
||||||
|
if ( status === 200){
|
||||||
|
setMessage(result)
|
||||||
|
setValue(result ? result[0].value : "")
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const handleChangeRPC = (event) => {
|
const handleChangeRPC = (event) => {
|
||||||
setAge(event.target.value);
|
setAge(event.target.value);
|
||||||
switch(event.target.value) {
|
setNewMsgValue(possibleMsgs[event.target.value-1])
|
||||||
case 1:
|
|
||||||
setValue(`{
|
|
||||||
"allow_partial": true,
|
|
||||||
"create_objs": [
|
|
||||||
{
|
|
||||||
"obj_path": "Device.IP.Interface.",
|
|
||||||
"param_settings": [
|
|
||||||
{
|
|
||||||
"param": "Alias",
|
|
||||||
"value": "test",
|
|
||||||
"required": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}`)
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
setValue(`{
|
|
||||||
"param_paths": [
|
|
||||||
"Device.WiFi.SSID.[Name==wlan0].",
|
|
||||||
"Device.IP.Interface.*.Alias",
|
|
||||||
"Device.DeviceInfo.FirmwareImage.*.Alias",
|
|
||||||
"Device.IP.Interface.1.IPv4Address.1.IPAddress"
|
|
||||||
],
|
|
||||||
"max_depth": 2
|
|
||||||
}`)
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
setValue(`
|
|
||||||
{
|
|
||||||
"allow_partial":true,
|
|
||||||
"update_objs":[
|
|
||||||
{
|
|
||||||
"obj_path":"Device.IP.Interface.[Alias==pamonha].",
|
|
||||||
"param_settings":[
|
|
||||||
{
|
|
||||||
"param":"Alias",
|
|
||||||
"value":"goiaba",
|
|
||||||
"required":true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}`)
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
setValue(`{
|
|
||||||
"allow_partial": true,
|
|
||||||
"obj_paths": [
|
|
||||||
"Device.IP.Interface.3."
|
|
||||||
]
|
|
||||||
}`)
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// code block
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleChange = (event) => {
|
const handleEditMessage = (event) => {
|
||||||
setValue(event.target.value);
|
if (message) {
|
||||||
};
|
setSaveChanges(true)
|
||||||
|
}
|
||||||
|
setValue(event.target.value)
|
||||||
|
}
|
||||||
|
|
||||||
const handleSubmit = useCallback(
|
const handleSubmit = useCallback(
|
||||||
(event) => {
|
(event) => {
|
||||||
|
|
@ -172,54 +317,91 @@ const handleOpen = () => {
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchMessages();
|
||||||
|
},[]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmit}>
|
<form onSubmit={handleSubmit}>
|
||||||
<Card>
|
<Card>
|
||||||
<CardActions sx={{ justifyContent: 'flex-end'}}>
|
<CardHeader sx={{ justifyContent: 'flex-end'}}
|
||||||
<FormControl sx={{width:'100px'}}>
|
avatar={<SvgIcon>< EnvelopeIcon/></SvgIcon>}
|
||||||
<Select
|
title="Custom Message"
|
||||||
labelId="demo-simple-select-standard-label"
|
action={
|
||||||
id="demo-simple-select-standard"
|
<Stack direction={"row"} spacing={1} width={"100%"} justifyContent={"flex-end"}>
|
||||||
value={age}
|
<Button sx={{ backgroundColor: "rgba(48, 109, 111, 0.04)" }}
|
||||||
label="Action"
|
endIcon={<SvgIcon><PlusCircleIcon /></SvgIcon>}
|
||||||
onChange={(event)=>{handleChangeRPC(event)}}
|
onClick={()=>{setNewMessage(true)}}
|
||||||
variant='standard'
|
>
|
||||||
>
|
<Stack direction={"row"} spacing={1}>
|
||||||
<MenuItem value={1}>Create</MenuItem>
|
New Message
|
||||||
<MenuItem value={2}>Read</MenuItem>
|
</Stack>
|
||||||
<MenuItem value={3}>Update</MenuItem>
|
</Button>
|
||||||
<MenuItem value={4}>Delete</MenuItem>
|
</Stack>}
|
||||||
</Select>
|
>
|
||||||
</FormControl>
|
</CardHeader>
|
||||||
</CardActions>
|
|
||||||
<Divider />
|
<Divider />
|
||||||
<CardContent>
|
<CardContent>
|
||||||
|
<Stack pb={4} spacing={5} direction={"row"}>
|
||||||
|
<FormControl sx={{display:"flex", width: "15%"}} variant="standard" >
|
||||||
|
<InputLabel>Message</InputLabel>
|
||||||
|
<Select
|
||||||
|
value={currentMsg}
|
||||||
|
onChange={(event)=>{handleChangeMessage(event)}}
|
||||||
|
>
|
||||||
|
{message && message.map((msg, index) => {
|
||||||
|
return <MenuItem value={index}>{msg.name}</MenuItem>
|
||||||
|
})}
|
||||||
|
</Select>
|
||||||
|
</FormControl>
|
||||||
|
</Stack>
|
||||||
<Stack
|
<Stack
|
||||||
spacing={3}
|
spacing={3}
|
||||||
alignItems={'stretch'}
|
alignItems={'stretch'}
|
||||||
>
|
>
|
||||||
<TextField
|
{!loadingSaveMsg ? <TextField
|
||||||
id="outlined-multiline-static"
|
id="outlined-multiline-static"
|
||||||
size="large"
|
size="large"
|
||||||
multiline="true"
|
multiline="true"
|
||||||
label="Mensagem"
|
// label="Payload"
|
||||||
name="password"
|
name="password"
|
||||||
onChange={handleChange}
|
onChange={handleEditMessage}
|
||||||
value={value}
|
value={value}
|
||||||
|
variant="filled"
|
||||||
fullWidth
|
fullWidth
|
||||||
rows="15"
|
rows="15"
|
||||||
/>
|
/>:<CircularProgress />}
|
||||||
</Stack>
|
</Stack>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
<Divider />
|
{/* <Divider /> */}
|
||||||
<CardActions sx={{ justifyContent: 'flex-end' }}>
|
<CardActions>
|
||||||
<Button
|
<Stack direction={"row"} spacing={1} width={"100%"} justifyContent={"flex-start"}>
|
||||||
variant="contained"
|
<Button
|
||||||
endIcon={<SvgIcon><PaperAirplane /></SvgIcon>}
|
variant="contained"
|
||||||
onClick={handleOpen}
|
endIcon={<SvgIcon><TrashIcon /></SvgIcon>}
|
||||||
>
|
onClick={handleDeleteMessage}
|
||||||
Send
|
disabled={!message}
|
||||||
</Button>
|
>
|
||||||
|
Delete
|
||||||
|
</Button>
|
||||||
|
{!loadingSaveMsg ? <Button
|
||||||
|
variant="contained"
|
||||||
|
endIcon={<SvgIcon><DocumentArrowDown /></SvgIcon>}
|
||||||
|
onClick={saveMsg}
|
||||||
|
disabled={!saveChanges}
|
||||||
|
>
|
||||||
|
Save
|
||||||
|
</Button>: <CircularProgress />}
|
||||||
|
</Stack>
|
||||||
|
<Stack direction={"row"} spacing={1} width={"100%"} justifyContent={"flex-end"}>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
endIcon={<SvgIcon><PaperAirplane /></SvgIcon>}
|
||||||
|
onClick={handleOpen}
|
||||||
|
>
|
||||||
|
Send
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
</CardActions>
|
</CardActions>
|
||||||
<Backdrop
|
<Backdrop
|
||||||
sx={{ color: '#fff', zIndex: (theme) => theme.zIndex.drawer + 1 }}
|
sx={{ color: '#fff', zIndex: (theme) => theme.zIndex.drawer + 1 }}
|
||||||
|
|
@ -273,6 +455,83 @@ const handleOpen = () => {
|
||||||
}}>Ok</Button>
|
}}>Ok</Button>
|
||||||
</DialogActions>
|
</DialogActions>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
<Dialog open={newMessage} maxWidth={"800px"}>
|
||||||
|
<DialogTitle>
|
||||||
|
<SvgIcon><EnvelopeIcon/></SvgIcon>
|
||||||
|
</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<Stack
|
||||||
|
direction={"row"}
|
||||||
|
container
|
||||||
|
pb={3}
|
||||||
|
// direction="column"
|
||||||
|
// alignItems="center"
|
||||||
|
// justifyContent="center"
|
||||||
|
pt={1}
|
||||||
|
spacing={3}
|
||||||
|
>
|
||||||
|
<TextField
|
||||||
|
variant='standard'
|
||||||
|
fullWidth
|
||||||
|
value={newMsgName}
|
||||||
|
onChange={(event)=>{setNewMsgName(event.target.value)}}
|
||||||
|
label="Name"
|
||||||
|
sx={{maxWidth: "30%", justifyContent:"center"}}
|
||||||
|
/>
|
||||||
|
<FormControl sx={{display:"flex", width: "30%"}} variant="standard" >
|
||||||
|
<InputLabel>Template</InputLabel>
|
||||||
|
<Select
|
||||||
|
value={age}
|
||||||
|
label="Action"
|
||||||
|
name='action'
|
||||||
|
onChange={(event)=>{handleChangeRPC(event)}}
|
||||||
|
>
|
||||||
|
<MenuItem value={1}>Set</MenuItem>
|
||||||
|
<MenuItem value={2}>Delete</MenuItem>
|
||||||
|
<MenuItem value={3}>Add</MenuItem>
|
||||||
|
<MenuItem value={4}>Operate</MenuItem>
|
||||||
|
<MenuItem value={5}>Get</MenuItem>
|
||||||
|
<MenuItem value={6}>Get Supported DM</MenuItem>
|
||||||
|
<MenuItem value={7}>Get Instances</MenuItem>
|
||||||
|
</Select>
|
||||||
|
</FormControl>
|
||||||
|
</Stack>
|
||||||
|
<Stack
|
||||||
|
spacing={3}
|
||||||
|
alignItems={'stretch'}
|
||||||
|
width={"600px"}
|
||||||
|
>
|
||||||
|
<TextField
|
||||||
|
id="outlined-multiline-static"
|
||||||
|
size="large"
|
||||||
|
multiline="true"
|
||||||
|
label="Payload"
|
||||||
|
name="password"
|
||||||
|
onChange={handleNewMessageValue}
|
||||||
|
value={newMsgValue}
|
||||||
|
// fullWidth
|
||||||
|
// rows="15"
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
</DialogContent>
|
||||||
|
{/* <Divider/> */}
|
||||||
|
<Stack direction={"row"} spacing={1} width={"100%"} justifyContent={"flex-end"} p={2}>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
onClick={handleCancelNewMsgTemplate}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
{!loading ?
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
endIcon={<SvgIcon><CheckIcon /></SvgIcon>}
|
||||||
|
onClick={createNewMsg}
|
||||||
|
>
|
||||||
|
Save
|
||||||
|
</Button>:<CircularProgress />}
|
||||||
|
</Stack>
|
||||||
|
</Dialog>
|
||||||
</Card>
|
</Card>
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,14 @@ import {
|
||||||
Stack,
|
Stack,
|
||||||
TextField
|
TextField
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
|
import { useBackendContext } from 'src/contexts/backend-context';
|
||||||
|
import { useAlertContext } from 'src/contexts/error-context';
|
||||||
|
|
||||||
export const SettingsPassword = () => {
|
export const SettingsPassword = () => {
|
||||||
|
|
||||||
|
let {httpRequest} = useBackendContext();
|
||||||
|
let {setAlert} = useAlertContext();
|
||||||
|
|
||||||
const [values, setValues] = useState({
|
const [values, setValues] = useState({
|
||||||
password: '',
|
password: '',
|
||||||
confirm: ''
|
confirm: ''
|
||||||
|
|
@ -26,15 +32,8 @@ export const SettingsPassword = () => {
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleSubmit = useCallback(
|
|
||||||
(event) => {
|
|
||||||
event.preventDefault();
|
|
||||||
},
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmit}>
|
<form>
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader
|
<CardHeader
|
||||||
subheader="Update password"
|
subheader="Update password"
|
||||||
|
|
@ -66,7 +65,26 @@ export const SettingsPassword = () => {
|
||||||
</CardContent>
|
</CardContent>
|
||||||
<Divider />
|
<Divider />
|
||||||
<CardActions sx={{ justifyContent: 'flex-end' }}>
|
<CardActions sx={{ justifyContent: 'flex-end' }}>
|
||||||
<Button variant="contained">
|
<Button variant="contained"
|
||||||
|
onClick={async ()=>{
|
||||||
|
if (values.password !== values.confirm) {
|
||||||
|
console.log("Passwords do not match")
|
||||||
|
setAlert({
|
||||||
|
severity: 'error',
|
||||||
|
message: 'Passwords do not match'
|
||||||
|
});
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let {status} = await httpRequest('/api/auth/password', 'PUT', JSON.stringify({"password": values.password}))
|
||||||
|
if (status === 204) {
|
||||||
|
console.log("Password updated")
|
||||||
|
setAlert({
|
||||||
|
severity: 'success',
|
||||||
|
message: 'Password updated'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
Update
|
Update
|
||||||
</Button>
|
</Button>
|
||||||
</CardActions>
|
</CardActions>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user