diff --git a/README.md b/README.md index a1c36b5..dc6e229 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ user@user-laptop:~$ cd oktopus/deploy/compose user@user-laptop:~/oktopus/deploy/compose$ COMPOSE_PROFILES=nats,controller,cwmp,mqtt,stomp,ws,adapter,frontend,portainer docker compose up -d Oktopus deployment in Kubernetes still is in beta phase: Instructions for Kubernetes deployment

- UI will open at port 3000: + UI will open at port 80:

Agent

diff --git a/backend/services/acs/internal/config/config.go b/backend/services/acs/internal/config/config.go index 53a3431..e6e6325 100644 --- a/backend/services/acs/internal/config/config.go +++ b/backend/services/acs/internal/config/config.go @@ -73,6 +73,8 @@ func NewConfig() *Config { ctx := context.TODO() + log.Printf("Connection Request User: %q and Password: %q", *connReqUser, *connReqPasswd) + return &Config{ Nats: Nats{ Url: *natsUrl, diff --git a/backend/services/acs/internal/server/handler/cwmp.go b/backend/services/acs/internal/server/handler/cwmp.go index 423b2fc..3f3bc65 100644 --- a/backend/services/acs/internal/server/handler/cwmp.go +++ b/backend/services/acs/internal/server/handler/cwmp.go @@ -116,7 +116,7 @@ func (h *Handler) CwmpHandler(w http.ResponseWriter, r *http.Request) { } else if e.KindOf() == "SetParameterValuesResponse" { log.Println("Receive SetParameterValuesResponse from CPE:", cpe.SerialNumber) msgAnswer(cpe.Waiting.Callback, cpe.Waiting.Time, h.acsConfig.DeviceAnswerTimeout, tmp) - }else if e.KindOf() == "Fault" { + } else if e.KindOf() == "Fault" { log.Println("Receive FaultResponse from CPE:", cpe.SerialNumber) msgAnswer(cpe.Waiting.Callback, cpe.Waiting.Time, h.acsConfig.DeviceAnswerTimeout, tmp) log.Println(body) @@ -156,9 +156,11 @@ func (h *Handler) ConnectionRequest(cpe CPE) error { ok, err := auth.Auth(h.acsConfig.ConnReqUsername, h.acsConfig.ConnReqPassword, cpe.ConnectionRequestURL) if !ok { cpe.Queue.Dequeue() - log.Println("Error while authenticating to CPE: ", err) + log.Println("Error while authenticating to CPE, err:", err) + } else { + log.Println("<-- Successfully authenticated to CPE", cpe.SerialNumber) } - log.Println("<-- Successfully authenticated to CPE", cpe.SerialNumber) + return err } diff --git a/backend/services/controller/internal/api/api.go b/backend/services/controller/internal/api/api.go index 12f2626..4046436 100644 --- a/backend/services/controller/internal/api/api.go +++ b/backend/services/controller/internal/api/api.go @@ -24,16 +24,11 @@ type Api struct { db db.Database kv jetstream.KeyValue ctx context.Context - enterpise bool + enterpise config.Enterprise } const REQUEST_TIMEOUT = time.Second * 30 -const ( - NormalUser = iota - AdminUser -) - func NewApi(c *config.Config, js jetstream.JetStream, nc *nats.Conn, bridge bridge.Bridge, d db.Database, kv jetstream.KeyValue) Api { return Api{ port: c.RestApi.Port, @@ -48,6 +43,11 @@ func NewApi(c *config.Config, js jetstream.JetStream, nc *nats.Conn, bridge brid } func (a *Api) StartApi() { + + if a.enterpise.SupportPassword != "" && a.enterpise.SupportEmail != "" { + go registerEnterpriseSupport(a.enterpise.SupportEmail, a.enterpise.SupportPassword, a.db) + } + r := mux.NewRouter() authentication := r.PathPrefix("/api/auth").Subrouter() authentication.HandleFunc("/login", a.generateToken).Methods("PUT") @@ -77,7 +77,7 @@ func (a *Api) StartApi() { iot.HandleFunc("/{sn}/{mtp}/instances", a.deviceGetParameterInstances).Methods("PUT") iot.HandleFunc("/{sn}/{mtp}/operate", a.deviceOperateMsg).Methods("PUT") iot.HandleFunc("/{sn}/{mtp}/fw_update", a.deviceFwUpdate).Methods("PUT") //TODO: put it to work and generalize for usp and cwmp - if a.enterpise { + if a.enterpise.Enable { iot.HandleFunc("/{sn}/sitesurvey", a.deviceSiteSurvey).Methods("GET") iot.HandleFunc("/{sn}/connecteddevices", a.deviceConnectedDevices).Methods("GET") iot.HandleFunc("/{sn}/traceroute", a.deviceTraceRoute).Methods("GET", "PUT") @@ -124,3 +124,32 @@ func (a *Api) StartApi() { }() log.Println("Running REST API at port", a.port) } + +func registerEnterpriseSupport(email, password string, d db.Database) { + + user := db.User{ + Email: email, + Password: password, + Name: "Enterprise Support", + Level: db.AdminUser, + } + + for { + if err := user.HashPassword(password); err != nil { + return + } + + err := d.RegisterUser(user) + if err != nil { + if err == db.ErrorUserExists { + log.Println("Enterprise support user already registered.") + return + } + log.Println("Error to register enterprise support user:", err) + time.Sleep(time.Second * 5) + continue + } + log.Println("Enterprise support user registered successfully.") + return + } +} diff --git a/backend/services/controller/internal/api/device.go b/backend/services/controller/internal/api/device.go index bcb68ea..527886c 100644 --- a/backend/services/controller/internal/api/device.go +++ b/backend/services/controller/internal/api/device.go @@ -8,6 +8,7 @@ import ( "strconv" "github.com/leandrofars/oktopus/internal/bridge" + "github.com/leandrofars/oktopus/internal/db" local "github.com/leandrofars/oktopus/internal/nats" "github.com/leandrofars/oktopus/internal/utils" "github.com/nats-io/nats.go/jetstream" @@ -134,7 +135,7 @@ func (a *Api) deviceAuth(w http.ResponseWriter, r *http.Request) { utils.MarshallEncoder(err, w) return } - if user.Level != AdminUser { + if user.Level != db.AdminUser { w.WriteHeader(http.StatusForbidden) return } diff --git a/backend/services/controller/internal/api/user.go b/backend/services/controller/internal/api/user.go index b3893ad..5484a06 100644 --- a/backend/services/controller/internal/api/user.go +++ b/backend/services/controller/internal/api/user.go @@ -51,7 +51,7 @@ func (a *Api) registerUser(w http.ResponseWriter, r *http.Request) { //Check if user which is requesting creation has the necessary privileges rUser, err := a.db.FindUser(email) - if rUser.Level != AdminUser { + if rUser.Level != db.AdminUser { w.WriteHeader(http.StatusForbidden) return } @@ -63,7 +63,7 @@ func (a *Api) registerUser(w http.ResponseWriter, r *http.Request) { return } - user.Level = NormalUser + user.Level = db.NormalUser if err := user.HashPassword(user.Password); err != nil { w.WriteHeader(http.StatusInternalServerError) @@ -112,7 +112,7 @@ func (a *Api) deleteUser(w http.ResponseWriter, r *http.Request) { userEmail := mux.Vars(r)["user"] - if rUser.Email == userEmail || (rUser.Level == AdminUser && rUser.Email != userEmail) { //Admin can delete any account, but admin account can never be deleted + if rUser.Email == userEmail || (rUser.Level == db.AdminUser) { //Admin can delete any account if err := a.db.DeleteUser(userEmail); err != nil { w.WriteHeader(http.StatusInternalServerError) json.NewEncoder(w).Encode(err) @@ -138,7 +138,7 @@ func (a *Api) changePassword(w http.ResponseWriter, r *http.Request) { userToChangePasswd := mux.Vars(r)["user"] if userToChangePasswd != "" && userToChangePasswd != email { rUser, _ := a.db.FindUser(email) - if rUser.Level != AdminUser { + if rUser.Level != db.AdminUser { w.WriteHeader(http.StatusForbidden) return } @@ -168,28 +168,61 @@ func (a *Api) changePassword(w http.ResponseWriter, r *http.Request) { func (a *Api) registerAdminUser(w http.ResponseWriter, r *http.Request) { + tokenString := r.Header.Get("Authorization") + if tokenString == "" { + users, err := a.db.FindAllUsers() + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + utils.MarshallEncoder(err, w) + } + + if !adminUserExists(users, a.enterpise.SupportEmail) { + var user db.User + err = json.NewDecoder(r.Body).Decode(&user) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + return + } + + user.Level = db.AdminUser + + if err := user.HashPassword(user.Password); err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + + if err := a.db.RegisterUser(user); err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + } else { + w.WriteHeader(http.StatusForbidden) + } + + return + } + + email, err := auth.ValidateToken(tokenString) + if err != nil { + w.WriteHeader(http.StatusUnauthorized) + return + } + + //Check if user which is requesting creation has the necessary privileges + rUser, err := a.db.FindUser(email) + if rUser.Level != db.AdminUser { + w.WriteHeader(http.StatusForbidden) + return + } + var user db.User - err := json.NewDecoder(r.Body).Decode(&user) + err = json.NewDecoder(r.Body).Decode(&user) if err != nil { w.WriteHeader(http.StatusBadRequest) return } - users, err := a.db.FindAllUsers() - if err != nil { - log.Println(err) - w.WriteHeader(http.StatusInternalServerError) - return - } - adminExists := adminUserExists(users) - if adminExists { - log.Println("There might exist only one admin") - w.WriteHeader(http.StatusBadRequest) - json.NewEncoder(w).Encode("There might exist only one admin") - return - } - - user.Level = AdminUser + user.Level = db.AdminUser if err := user.HashPassword(user.Password); err != nil { w.WriteHeader(http.StatusInternalServerError) @@ -202,9 +235,14 @@ func (a *Api) registerAdminUser(w http.ResponseWriter, r *http.Request) { } } -func adminUserExists(users []map[string]interface{}) bool { +func adminUserExists(users []map[string]interface{}, supportEmail string) bool { + + if len(users) == 0 { + return false + } + for _, x := range users { - if x["level"].(int32) == AdminUser { + if db.UserLevels(x["level"].(int32)) == db.AdminUser && x["email"].(string) != supportEmail { log.Println("Admin exists") return true } @@ -220,7 +258,7 @@ func (a *Api) adminUserExists(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusInternalServerError) return } - adminExits := adminUserExists(users) + adminExits := adminUserExists(users, a.enterpise.SupportEmail) json.NewEncoder(w).Encode(adminExits) return } diff --git a/backend/services/controller/internal/api/wifi.go b/backend/services/controller/internal/api/wifi.go index b6353f7..e6b2213 100644 --- a/backend/services/controller/internal/api/wifi.go +++ b/backend/services/controller/internal/api/wifi.go @@ -213,7 +213,7 @@ func (a *Api) deviceWifi(w http.ResponseWriter, r *http.Request) { if device.Cwmp == entity.Online { - if a.enterpise { + if a.enterpise.Enable { a.getEnterpriseResource("wifi", "get", device, sn, w, []byte{}, "cwmp", "098") return } @@ -347,7 +347,7 @@ func (a *Api) deviceWifi(w http.ResponseWriter, r *http.Request) { if device.Cwmp == entity.Online { - if a.enterpise { + if a.enterpise.Enable { payload, err := io.ReadAll(r.Body) if err != nil { w.WriteHeader(http.StatusInternalServerError) diff --git a/backend/services/controller/internal/config/config.go b/backend/services/controller/internal/config/config.go index 0e6c228..ff97dd6 100644 --- a/backend/services/controller/internal/config/config.go +++ b/backend/services/controller/internal/config/config.go @@ -29,11 +29,17 @@ type RestApi struct { Ctx context.Context } +type Enterprise struct { + Enable bool + SupportPassword string + SupportEmail string +} + type Config struct { RestApi RestApi Nats Nats Mongo Mongo - Enterprise bool + Enterprise Enterprise } func NewConfig() *Config { @@ -47,6 +53,8 @@ func NewConfig() *Config { flApiPort := flag.String("api_port", lookupEnvOrString("REST_API_PORT", "8000"), "Rest api port") mongoUri := flag.String("mongo_uri", lookupEnvOrString("MONGO_URI", "mongodb://localhost:27017"), "uri for mongodb server") enterpise := flag.Bool("enterprise", lookupEnvOrBool("ENTERPRISE", false), "enterprise version enable") + enterprise_support_password := flag.String("enterprise_support_password", lookupEnvOrString("ENTERPRISE_SUPPORT_PASSWORD", ""), "enterprise support password") + enterpise_support_email := flag.String("enterprise_support_email", lookupEnvOrString("ENTERPRISE_SUPPORT_EMAIL", ""), "enterprise support email") flHelp := flag.Bool("help", false, "Help") /* @@ -80,7 +88,11 @@ func NewConfig() *Config { Uri: *mongoUri, Ctx: ctx, }, - Enterprise: *enterpise, + Enterprise: Enterprise{ + Enable: *enterpise, + SupportPassword: *enterprise_support_password, + SupportEmail: *enterpise_support_email, + }, } } diff --git a/backend/services/controller/internal/db/user.go b/backend/services/controller/internal/db/user.go index e7e2cfc..2cc8162 100644 --- a/backend/services/controller/internal/db/user.go +++ b/backend/services/controller/internal/db/user.go @@ -9,12 +9,19 @@ import ( "golang.org/x/crypto/bcrypt" ) +type UserLevels int32 + +const ( + NormalUser UserLevels = iota + AdminUser +) + type User struct { - Email string `json:"email"` - Name string `json:"name"` - Password string `json:"password,omitempty"` - Level int `json:"level"` - Phone string `json:"phone"` + Email string `json:"email"` + Name string `json:"name"` + Password string `json:"password,omitempty"` + Level UserLevels `json:"level"` + Phone string `json:"phone"` } var ErrorUserExists = errors.New("User already exists") diff --git a/deploy/compose/.env.frontend b/deploy/compose/.env.frontend deleted file mode 100644 index 365e938..0000000 --- a/deploy/compose/.env.frontend +++ /dev/null @@ -1,17 +0,0 @@ -# ----------------------------- Local Environment ---------------------------- # - -NEXT_PUBLIC_REST_ENDPOINT="http://localhost:8000/api" -NEXT_PUBLIC_WS_ENDPOINT="http://localhost:5000/" -# ---------------------------------------------------------------------------- # - -# -------------------------- Production Environment -------------------------- # - -#NEXT_PUBLIC_REST_ENPOINT="https://demo.oktopus.app.br/api" -#NEXT_PUBLIC_WS_ENPOINT="https://demo.oktopus.app.br/" -# ---------------------------------------------------------------------------- # - -# ---------------------------- Mocked Environment ---------------------------- # - -#NEXT_PUBLIC_REST_ENPOINT="https://d9962fd9-2464-4a30-9a86-a15a04b57ad0.mock.pstmn.io" - -# ---------------------------------------------------------------------------- # diff --git a/deploy/compose/docker-compose.yaml b/deploy/compose/docker-compose.yaml index ed8c17a..5fdbddd 100644 --- a/deploy/compose/docker-compose.yaml +++ b/deploy/compose/docker-compose.yaml @@ -151,10 +151,8 @@ services: #/* -------------------------------- Frontend -------------------------------- */ frontend: - image: 'oktopusp/frontend' + image: 'oktopusp/frontend-ce' container_name: frontend - env_file: - - .env.frontend ports: - 3000:3000 networks: @@ -187,6 +185,21 @@ services: usp_network: ipv4_address: 172.16.235.16 profiles: [cwmp] + + nginx: + image: nginx:latest + container_name: nginx + ports: + - 80:80 + depends_on: + - frontend + - controller + - socketio + volumes: + - ./nginx.conf:/etc/nginx/conf.d/default.conf + networks: + usp_network: + ipv4_address: 172.16.235.17 networks: usp_network: diff --git a/deploy/compose/nginx.conf b/deploy/compose/nginx.conf new file mode 100644 index 0000000..1bba7d8 --- /dev/null +++ b/deploy/compose/nginx.conf @@ -0,0 +1,41 @@ +server { + listen 80; + listen [::]:80; + server_name _; + root /usr/share/nginx/html; + + include /etc/nginx/default.d/*.conf; + + error_page 404 /404.html; + location = /404.html { + } + + location / { + proxy_pass http://frontend:3000; + proxy_read_timeout 60; + proxy_connect_timeout 60; + proxy_redirect off; + } + location /api { + proxy_pass http://controller:8000; + proxy_read_timeout 60; + proxy_connect_timeout 60; + proxy_redirect off; + } + location /socket.io { + proxy_pass http://socketio:5000; + proxy_read_timeout 60; + proxy_connect_timeout 60; + proxy_redirect off; + + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_cache_bypass $http_upgrade; + } + + error_page 500 502 503 504 /50x.html; + location = /50x.html { + } +} \ No newline at end of file diff --git a/deploy/compose/run.sh b/deploy/compose/run.sh new file mode 100644 index 0000000..a4d5a44 --- /dev/null +++ b/deploy/compose/run.sh @@ -0,0 +1 @@ +COMPOSE_PROFILES=nats,controller,cwmp,mqtt,stomp,ws,adapter,frontend,portainer docker compose up -d diff --git a/deploy/compose/stop.sh b/deploy/compose/stop.sh new file mode 100644 index 0000000..24d95ab --- /dev/null +++ b/deploy/compose/stop.sh @@ -0,0 +1 @@ +COMPOSE_PROFILES=nats,controller,cwmp,mqtt,stomp,ws,adapter,frontend,portainer docker compose down diff --git a/frontend/.env b/frontend/.env index 32dec17..2116eeb 100644 --- a/frontend/.env +++ b/frontend/.env @@ -1,8 +1,9 @@ # ----------------------------- Local Environment ---------------------------- # -NEXT_PUBLIC_REST_ENDPOINT="http://localhost:8000/api" +NEXT_PUBLIC_REST_ENDPOINT="http://localhost:8000" NEXT_PUBLIC_WS_ENDPOINT="http://localhost:5000/" NEXT_PUBLIC_ENTERPRISE_VERSION="false" +NEXT_PUBLIC_GOOGLE_MAPS_KEY="" # ---------------------------------------------------------------------------- # # -------------------------- Production Environment -------------------------- # diff --git a/frontend/build/.dockerignore b/frontend/build/.dockerignore index aced64b..0e0ab04 100644 --- a/frontend/build/.dockerignore +++ b/frontend/build/.dockerignore @@ -1 +1,4 @@ -.next/ \ No newline at end of file +../.next/ +../node_modules/ +../.env +../.env.local \ No newline at end of file diff --git a/frontend/build/Dockerfile b/frontend/build/Dockerfile deleted file mode 100644 index fede4c2..0000000 --- a/frontend/build/Dockerfile +++ /dev/null @@ -1,29 +0,0 @@ -FROM node:18.17.0-alpine as builder - -WORKDIR /app - -COPY ../ ./ - -RUN npm install - -RUN NEXT_PUBLIC_REST_ENDPOINT=REST_API_URL NEXT_PUBLIC_WS_ENDPOINT=WS_URL NEXT_PUBLIC_ENTERPRISE_VERSION=ENTERPRISE_VERSION npm run build - -RUN ls -la && echo "Listing directory contents done" - -FROM node:18.17.0-alpine as runner - -WORKDIR /app - -COPY --from=builder /app/.next ./.next -COPY --from=builder /app/package.json ./package.json -COPY --from=builder /app/build/entrypoint.sh ./entrypoint.sh -COPY --from=builder /app/public ./public - - -RUN npm install - -RUN chmod 755 entrypoint.sh - -ENTRYPOINT ["/app/entrypoint.sh"] - -CMD [ "npm", "run", "start" ] diff --git a/frontend/build/Dockerfile.ce b/frontend/build/Dockerfile.ce new file mode 100644 index 0000000..47d6f17 --- /dev/null +++ b/frontend/build/Dockerfile.ce @@ -0,0 +1,22 @@ +FROM node:18.18.0-alpine as builder + +WORKDIR /app + +COPY ../ ./ +RUN rm .env && rm .env.local || true + +RUN npm install + +RUN NEXT_PUBLIC_ENTERPRISE_VERSION="false" npm run build + +FROM node:18.18.0-alpine as runner + +WORKDIR /app + +COPY --from=builder /app/.next ./.next +COPY --from=builder /app/package.json ./package.json +COPY --from=builder /app/public ./public + +RUN npm install + +CMD [ "npm", "run", "start" ] diff --git a/frontend/build/Dockerfile.ee b/frontend/build/Dockerfile.ee new file mode 100644 index 0000000..1c22a13 --- /dev/null +++ b/frontend/build/Dockerfile.ee @@ -0,0 +1,22 @@ +FROM node:18.18.0-alpine as builder + +WORKDIR /app + +COPY ../ ./ +RUN rm .env && rm .env.local || true + +RUN npm install + +RUN NEXT_PUBLIC_ENTERPRISE_VERSION="true" npm run build + +FROM node:18.18.0-alpine as runner + +WORKDIR /app + +COPY --from=builder /app/.next ./.next +COPY --from=builder /app/package.json ./package.json +COPY --from=builder /app/public ./public + +RUN npm install + +CMD [ "npm", "run", "start" ] \ No newline at end of file diff --git a/frontend/build/Makefile b/frontend/build/Makefile index 204a78b..b8ea587 100644 --- a/frontend/build/Makefile +++ b/frontend/build/Makefile @@ -18,48 +18,16 @@ help: @echo "Makefile commands:" @echo "" @echo "build - docker image build" - @echo "push - push docker image to registry" - @echo "run - create and start docker container with the image" - @echo "start - start existent docker container with the image" - @echo "stop - stop docker container running the image" - @echo "remove - remove docker container running the image" - @echo "delete - delete docker image" - @echo "logs - show logs of docker container" - @echo "bash - access container shell" @echo "release - tag image as latest and push to registry" - @echo "tag - tag image as latest" build: - @docker build -t ${DOCKER_USER}/${DOCKER_APP}:${DOCKER_TAG} -f Dockerfile ../ - -run: - @docker run -d --name ${DOCKER_USER}-${DOCKER_APP} ${DOCKER_USER}/${DOCKER_APP}:${DOCKER_TAG} - -stop: - @docker stop ${DOCKER_USER}-${DOCKER_APP} - -remove: stop - @docker rm ${DOCKER_USER}-${DOCKER_APP} - -delete: - @docker rmi ${DOCKER_USER}/${DOCKER_APP}:${DOCKER_TAG} - -start: - @docker start ${DOCKER_USER}-${DOCKER_APP} - -push: - @docker push ${DOCKER_USER}/${DOCKER_APP}:${DOCKER_TAG} - -logs: - @docker logs -f ${DOCKER_USER}-${DOCKER_APP} - -bash: - @docker exec -it ${DOCKER_USER}-${DOCKER_APP} ${CONTAINER_SHELL} + @docker build -t ${DOCKER_USER}/${DOCKER_APP}-ce:${DOCKER_TAG} -f Dockerfile.ce ../ + @docker build -t ${DOCKER_USER}/${DOCKER_APP}-ee:${DOCKER_TAG} -f Dockerfile.ee ../ release: build - @docker push ${DOCKER_USER}/${DOCKER_APP}:${DOCKER_TAG} - @docker tag ${DOCKER_USER}/${DOCKER_APP}:${DOCKER_TAG} ${DOCKER_USER}/${DOCKER_APP}:latest - @docker push ${DOCKER_USER}/${DOCKER_APP}:latest - -tag: - docker tag ${DOCKER_USER}/${DOCKER_APP}:${DOCKER_TAG} ${DOCKER_USER}/${DOCKER_APP}:latest \ No newline at end of file + @docker push ${DOCKER_USER}/${DOCKER_APP}-ce:${DOCKER_TAG} + @docker push ${DOCKER_USER}/${DOCKER_APP}-ee:${DOCKER_TAG} + @docker tag ${DOCKER_USER}/${DOCKER_APP}-ce:${DOCKER_TAG} ${DOCKER_USER}/${DOCKER_APP}-ce:latest + @docker tag ${DOCKER_USER}/${DOCKER_APP}-ee:${DOCKER_TAG} ${DOCKER_USER}/${DOCKER_APP}-ee:latest + @docker push ${DOCKER_USER}/${DOCKER_APP}-ce:latest + @docker push ${DOCKER_USER}/${DOCKER_APP}-ee:latest \ No newline at end of file diff --git a/frontend/build/entrypoint.sh b/frontend/build/entrypoint.sh deleted file mode 100644 index 5eb5329..0000000 --- a/frontend/build/entrypoint.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env sh -set -Ex - -function apply_path { - - echo "Check that we have NEXT_PUBLIC_REST_ENDPOINT vars" - test -n "$NEXT_PUBLIC_REST_ENDPOINT" - - echo "Check that we have NEXT_PUBLIC_WS_ENDPOINT vars" - test -n "$NEXT_PUBLIC_WS_ENDPOINT" - - echo "Check that we have NEXT_PUBLIC_ENTERPRISE_VERSION vars" - test -n "$NEXT_PUBLIC_ENTERPRISE_VERSION" - - find /app/.next \( -type d -name .git -prune \) -o -type f -print0 | xargs -0 sed -i "s#REST_API_URL#$NEXT_PUBLIC_REST_ENDPOINT#g" - find /app/.next \( -type d -name .git -prune \) -o -type f -print0 | xargs -0 sed -i "s#WS_URL#$NEXT_PUBLIC_WS_ENDPOINT#g" - find /app/.next \( -type d -name .git -prune \) -o -type f -print0 | xargs -0 sed -i "s#ENTERPRISE_VERSION#$NEXT_PUBLIC_ENTERPRISE_VERSION#g" -} - -apply_path -echo "Starting Nextjs" -exec "$@" diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 15a1dda..cf2561d 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -17,6 +17,7 @@ "@mui/material": "5.11.10", "@mui/system": "5.11.9", "@mui/x-date-pickers": "5.0.19", + "@react-google-maps/api": "^2.19.3", "apexcharts": "3.37.0", "date-fns": "2.29.3", "formik": "2.2.9", @@ -499,6 +500,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@googlemaps/js-api-loader": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/@googlemaps/js-api-loader/-/js-api-loader-1.16.2.tgz", + "integrity": "sha512-psGw5u0QM6humao48Hn4lrChOM2/rA43ZCm3tKK9qQsEj1/VzqkCqnvGfEOshDbBQflydfaRovbKwZMF4AyqbA==", + "dependencies": { + "fast-deep-equal": "^3.1.3" + } + }, + "node_modules/@googlemaps/markerclusterer": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/@googlemaps/markerclusterer/-/markerclusterer-2.5.3.tgz", + "integrity": "sha512-x7lX0R5yYOoiNectr10wLgCBasNcXFHiADIBdmn7jQllF2B5ENQw5XtZK+hIw4xnV0Df0xhN4LN98XqA5jaiOw==", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "supercluster": "^8.0.1" + } + }, "node_modules/@heroicons/react": { "version": "2.0.16", "resolved": "https://registry.npmjs.org/@heroicons/react/-/react-2.0.16.tgz", @@ -1215,6 +1233,33 @@ "url": "https://opencollective.com/popperjs" } }, + "node_modules/@react-google-maps/api": { + "version": "2.19.3", + "resolved": "https://registry.npmjs.org/@react-google-maps/api/-/api-2.19.3.tgz", + "integrity": "sha512-jiLqvuOt5lOowkLeq7d077AByTyJp+s6hZVlLhlq7SBacBD37aUNpXBz2OsazfeR6Aw4a+9RRhAEjEFvrR1f5A==", + "dependencies": { + "@googlemaps/js-api-loader": "1.16.2", + "@googlemaps/markerclusterer": "2.5.3", + "@react-google-maps/infobox": "2.19.2", + "@react-google-maps/marker-clusterer": "2.19.2", + "@types/google.maps": "3.55.2", + "invariant": "2.2.4" + }, + "peerDependencies": { + "react": "^16.8 || ^17 || ^18", + "react-dom": "^16.8 || ^17 || ^18" + } + }, + "node_modules/@react-google-maps/infobox": { + "version": "2.19.2", + "resolved": "https://registry.npmjs.org/@react-google-maps/infobox/-/infobox-2.19.2.tgz", + "integrity": "sha512-6wvBqeJsQ/eFSvoxg+9VoncQvNoVCdmxzxRpLvmjPD+nNC6mHM0vJH1xSqaKijkMrfLJT0nfkTGpovrF896jwg==" + }, + "node_modules/@react-google-maps/marker-clusterer": { + "version": "2.19.2", + "resolved": "https://registry.npmjs.org/@react-google-maps/marker-clusterer/-/marker-clusterer-2.19.2.tgz", + "integrity": "sha512-x9ibmsP0ZVqzyCo1Pitbw+4b6iEXRw/r1TCy3vOUR3eKrzWLnHYZMR325BkZW2r8fnuWE/V3Fp4QZOP9qYORCw==" + }, "node_modules/@rushstack/eslint-patch": { "version": "1.10.3", "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.3.tgz", @@ -1245,6 +1290,11 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, + "node_modules/@types/google.maps": { + "version": "3.55.2", + "resolved": "https://registry.npmjs.org/@types/google.maps/-/google.maps-3.55.2.tgz", + "integrity": "sha512-JcTwzkxskR8DN/nnX96Pie3gGN3WHiPpuxzuQ9z3516o1bB243d8w8DHUJ8BohuzoT1o3HUFta2ns/mkZC8KRw==" + }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -2981,8 +3031,7 @@ "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "node_modules/fast-glob": { "version": "3.3.2", @@ -3529,6 +3578,14 @@ "node": ">= 0.4" } }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, "node_modules/is-array-buffer": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", @@ -4018,6 +4075,11 @@ "node": ">=4.0" } }, + "node_modules/kdbush": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/kdbush/-/kdbush-4.0.2.tgz", + "integrity": "sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA==" + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -5445,6 +5507,14 @@ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.1.3.tgz", "integrity": "sha512-GP6WDNWf+o403jrEp9c5jibKavrtLW+/qYGhFxFrG8maXhwTBI7gLLhiBb0o7uFccWN+EOS9aMO6cGHWAO07OA==" }, + "node_modules/supercluster": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/supercluster/-/supercluster-8.0.1.tgz", + "integrity": "sha512-IiOea5kJ9iqzD2t7QJq/cREyLHTtSmUT6gQsweojg9WH2sYJqZK9SswTu6jrscO6D1G5v5vYZ9ru/eq85lXeZQ==", + "dependencies": { + "kdbush": "^4.0.2" + } + }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -6440,6 +6510,23 @@ } } }, + "@googlemaps/js-api-loader": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/@googlemaps/js-api-loader/-/js-api-loader-1.16.2.tgz", + "integrity": "sha512-psGw5u0QM6humao48Hn4lrChOM2/rA43ZCm3tKK9qQsEj1/VzqkCqnvGfEOshDbBQflydfaRovbKwZMF4AyqbA==", + "requires": { + "fast-deep-equal": "^3.1.3" + } + }, + "@googlemaps/markerclusterer": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/@googlemaps/markerclusterer/-/markerclusterer-2.5.3.tgz", + "integrity": "sha512-x7lX0R5yYOoiNectr10wLgCBasNcXFHiADIBdmn7jQllF2B5ENQw5XtZK+hIw4xnV0Df0xhN4LN98XqA5jaiOw==", + "requires": { + "fast-deep-equal": "^3.1.3", + "supercluster": "^8.0.1" + } + }, "@heroicons/react": { "version": "2.0.16", "resolved": "https://registry.npmjs.org/@heroicons/react/-/react-2.0.16.tgz", @@ -6818,6 +6905,29 @@ "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==" }, + "@react-google-maps/api": { + "version": "2.19.3", + "resolved": "https://registry.npmjs.org/@react-google-maps/api/-/api-2.19.3.tgz", + "integrity": "sha512-jiLqvuOt5lOowkLeq7d077AByTyJp+s6hZVlLhlq7SBacBD37aUNpXBz2OsazfeR6Aw4a+9RRhAEjEFvrR1f5A==", + "requires": { + "@googlemaps/js-api-loader": "1.16.2", + "@googlemaps/markerclusterer": "2.5.3", + "@react-google-maps/infobox": "2.19.2", + "@react-google-maps/marker-clusterer": "2.19.2", + "@types/google.maps": "3.55.2", + "invariant": "2.2.4" + } + }, + "@react-google-maps/infobox": { + "version": "2.19.2", + "resolved": "https://registry.npmjs.org/@react-google-maps/infobox/-/infobox-2.19.2.tgz", + "integrity": "sha512-6wvBqeJsQ/eFSvoxg+9VoncQvNoVCdmxzxRpLvmjPD+nNC6mHM0vJH1xSqaKijkMrfLJT0nfkTGpovrF896jwg==" + }, + "@react-google-maps/marker-clusterer": { + "version": "2.19.2", + "resolved": "https://registry.npmjs.org/@react-google-maps/marker-clusterer/-/marker-clusterer-2.19.2.tgz", + "integrity": "sha512-x9ibmsP0ZVqzyCo1Pitbw+4b6iEXRw/r1TCy3vOUR3eKrzWLnHYZMR325BkZW2r8fnuWE/V3Fp4QZOP9qYORCw==" + }, "@rushstack/eslint-patch": { "version": "1.10.3", "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.3.tgz", @@ -6850,6 +6960,11 @@ } } }, + "@types/google.maps": { + "version": "3.55.2", + "resolved": "https://registry.npmjs.org/@types/google.maps/-/google.maps-3.55.2.tgz", + "integrity": "sha512-JcTwzkxskR8DN/nnX96Pie3gGN3WHiPpuxzuQ9z3516o1bB243d8w8DHUJ8BohuzoT1o3HUFta2ns/mkZC8KRw==" + }, "@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -8149,8 +8264,7 @@ "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "fast-glob": { "version": "3.3.2", @@ -8547,6 +8661,14 @@ "side-channel": "^1.0.4" } }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "requires": { + "loose-envify": "^1.0.0" + } + }, "is-array-buffer": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", @@ -8874,6 +8996,11 @@ "object.values": "^1.1.6" } }, + "kdbush": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/kdbush/-/kdbush-4.0.2.tgz", + "integrity": "sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA==" + }, "keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -9849,6 +9976,14 @@ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.1.3.tgz", "integrity": "sha512-GP6WDNWf+o403jrEp9c5jibKavrtLW+/qYGhFxFrG8maXhwTBI7gLLhiBb0o7uFccWN+EOS9aMO6cGHWAO07OA==" }, + "supercluster": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/supercluster/-/supercluster-8.0.1.tgz", + "integrity": "sha512-IiOea5kJ9iqzD2t7QJq/cREyLHTtSmUT6gQsweojg9WH2sYJqZK9SswTu6jrscO6D1G5v5vYZ9ru/eq85lXeZQ==", + "requires": { + "kdbush": "^4.0.2" + } + }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index 1003220..7347046 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -23,6 +23,7 @@ "@mui/material": "5.11.10", "@mui/system": "5.11.9", "@mui/x-date-pickers": "5.0.19", + "@react-google-maps/api": "^2.19.3", "apexcharts": "3.37.0", "date-fns": "2.29.3", "formik": "2.2.9", diff --git a/frontend/src/contexts/auth-context.js b/frontend/src/contexts/auth-context.js index 0b72543..83345d2 100644 --- a/frontend/src/contexts/auth-context.js +++ b/frontend/src/contexts/auth-context.js @@ -150,7 +150,7 @@ export const AuthProvider = (props) => { redirect: 'follow' }; - let result = await fetch(process.env.NEXT_PUBLIC_REST_ENDPOINT+"/auth/login", requestOptions) + let result = await fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/api/auth/login`, requestOptions) if (result.status != 200) { throw new Error('Please check your email and password'); @@ -199,7 +199,7 @@ export const AuthProvider = (props) => { redirect: 'follow' }; - let result = await fetch(process.env.NEXT_PUBLIC_REST_ENDPOINT+"/auth/admin/register", requestOptions) + let result = await fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/api/auth/admin/register`, requestOptions) if (result.status == 200) { router.push("/auth/login") diff --git a/frontend/src/layouts/dashboard/config.js b/frontend/src/layouts/dashboard/config.js index 1bd4cb2..171482a 100644 --- a/frontend/src/layouts/dashboard/config.js +++ b/frontend/src/layouts/dashboard/config.js @@ -42,7 +42,7 @@ export const items = [ // // // - // ) + // ), // }, { title: 'Credentials', diff --git a/frontend/src/layouts/dashboard/layout.js b/frontend/src/layouts/dashboard/layout.js index c3d0db7..2753fa6 100644 --- a/frontend/src/layouts/dashboard/layout.js +++ b/frontend/src/layouts/dashboard/layout.js @@ -49,12 +49,11 @@ export const Layout = withAuthGuard((props) => { return ( <> - setOpenNav(true)} /> + {pathname != "/map" && setOpenNav(true)} />} setOpenNav(false)} open={openNav} /> - {children} diff --git a/frontend/src/pages/auth/login.js b/frontend/src/pages/auth/login.js index d57d49a..41eb255 100644 --- a/frontend/src/pages/auth/login.js +++ b/frontend/src/pages/auth/login.js @@ -83,7 +83,7 @@ const Page = () => { redirect: 'follow', }; - let result = await (await fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT}/auth/admin/exists`, requestOptions)) + let result = await (await fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/api/auth/admin/exists`, requestOptions)) let content = await result.json() console.log("content: ", content) if (result.status != 200) { @@ -131,12 +131,12 @@ const Page = () => { Login - - This project is open source, reach out at Github or Slack - + This project is open source, reach out at Github or Slack + } {/* { redirect: 'follow' }; - fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT}/users`,requestOptions) + fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/api/users`,requestOptions) .then(response => response.json()) .then(result => { // let teste = JSON.stringify(JSON.parse(result), null, 2) diff --git a/frontend/src/pages/credentials.js b/frontend/src/pages/credentials.js index 31448b5..c065c64 100644 --- a/frontend/src/pages/credentials.js +++ b/frontend/src/pages/credentials.js @@ -49,7 +49,7 @@ const Page = () => { redirect: 'follow' } - return fetch(process.env.NEXT_PUBLIC_REST_ENDPOINT + '/device/auth?id='+id, requestOptions) + return fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/api/device/auth?id=${id}`, requestOptions) .then(response => { if (response.status === 401) { router.push("/auth/login") @@ -81,7 +81,7 @@ const Page = () => { redirect: 'follow' }; - let result = await fetch(process.env.NEXT_PUBLIC_REST_ENDPOINT+"/device/auth", requestOptions) + let result = await fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/api/device/auth`, requestOptions) if (result.status == 200) { console.log("user created: deu boa raça !!") @@ -134,7 +134,7 @@ const Page = () => { redirect: 'follow' } - let url = process.env.NEXT_PUBLIC_REST_ENDPOINT + '/device/auth' + let url = `${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/api/device/auth` if (id !== undefined && id !== "") { url += "?id="+id } @@ -224,7 +224,7 @@ const Page = () => { { if (e.key === 'Enter') { console.log("Fetch credentials per username: ", e.target.value) diff --git a/frontend/src/pages/devices.js b/frontend/src/pages/devices.js index a55f33e..45f2732 100644 --- a/frontend/src/pages/devices.js +++ b/frontend/src/pages/devices.js @@ -46,7 +46,7 @@ const Page = () => { redirect: 'follow' } - fetch(process.env.NEXT_PUBLIC_REST_ENDPOINT+'/device', requestOptions) + fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/api/device`, requestOptions) .then(response => { if (response.status === 401) router.push("/auth/login") @@ -86,7 +86,7 @@ const Page = () => { p = p - 1 p = p.toString() - fetch(process.env.NEXT_PUBLIC_REST_ENDPOINT+'/device?page_number='+p, requestOptions) + fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/api/device?page_number=+${p}`, requestOptions) .then(response => { if (response.status === 401) router.push("/auth/login") @@ -116,7 +116,7 @@ const Page = () => { } if (id == ""){ - return fetch(process.env.NEXT_PUBLIC_REST_ENDPOINT+'/device', requestOptions) + return fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/api/device`, requestOptions) .then(response => { if (response.status === 401) router.push("/auth/login") @@ -134,7 +134,7 @@ const Page = () => { }); } - let response = await fetch(process.env.NEXT_PUBLIC_REST_ENDPOINT+'/device?id='+id, requestOptions) + let response = await fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/api/device?id=${id}`, requestOptions) if (response.status === 401) router.push("/auth/login") let json = await response.json() diff --git a/frontend/src/pages/index.js b/frontend/src/pages/index.js index 1b79eb6..260fbfc 100644 --- a/frontend/src/pages/index.js +++ b/frontend/src/pages/index.js @@ -38,7 +38,7 @@ const Page = () => { redirect: 'follow', }; - let result = await (await fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT}/info/general`, requestOptions)) + let result = await (await fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/api/info/general`, requestOptions)) if (result.status === 401){ router.push("/auth/login") }else if (result.status != 200){ diff --git a/frontend/src/pages/map.js b/frontend/src/pages/map.js new file mode 100644 index 0000000..24a111c --- /dev/null +++ b/frontend/src/pages/map.js @@ -0,0 +1,86 @@ +import Head from 'next/head'; +import { GoogleMap, useLoadScript } 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'; + +const Page = () => { + + const libraries = useMemo(() => ['places'], []); + + const [mapCenter, setMapCenter] = useState(null); + + useEffect(()=> { + // 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.error("Error getting user location:", error); + } + ); + } else { + // Geolocation is not supported by the browser + console.error("Geolocation is not supported by this browser."); + } + },[]) + + 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

Loading...

; + } + + return ( mapCenter && + <> + + + Maps | Oktopus + + + console.log('Map Component Loaded...')} + clickableIcons={false} + /> + + )}; + + Page.getLayout = (page) => ( + + {page} + + ); + + export default Page; \ No newline at end of file diff --git a/frontend/src/pages/settings.js b/frontend/src/pages/settings.js index 7dab58a..2e3f360 100644 --- a/frontend/src/pages/settings.js +++ b/frontend/src/pages/settings.js @@ -8,7 +8,7 @@ const Page = () => ( <> - Settings | Devias Kit + Settings | Oktopus { redirect: 'follow' } - return fetch(process.env.NEXT_PUBLIC_REST_ENDPOINT + '/auth/delete/' + id, requestOptions) + return fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/auth/delete/${id}`, requestOptions) .then(response => { if (response.status === 401) { router.push("/auth/login") @@ -82,7 +82,7 @@ const Page = () => { redirect: 'follow' } - return fetch(process.env.NEXT_PUBLIC_REST_ENDPOINT + '/users', requestOptions) + return fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/api/users`, requestOptions) .then(response => { if (response.status === 401) { router.push("/auth/login") @@ -142,7 +142,7 @@ const Page = () => { redirect: 'follow' }; - let result = await fetch(process.env.NEXT_PUBLIC_REST_ENDPOINT+"/auth/register", requestOptions) + let result = await fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/api/auth/register`, requestOptions) if (result.status == 200) { console.log("user created: deu boa raça !!") diff --git a/frontend/src/sections/devices/cwmp/connecteddevices.js b/frontend/src/sections/devices/cwmp/connecteddevices.js index 6a24792..50e86a2 100644 --- a/frontend/src/sections/devices/cwmp/connecteddevices.js +++ b/frontend/src/sections/devices/cwmp/connecteddevices.js @@ -28,7 +28,7 @@ export const ConnectedDevices = () => { redirect: 'follow' }; - fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT}/device/${router.query.id[0]}/connecteddevices`, requestOptions) + fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/api/device/${router.query.id[0]}/connecteddevices`, requestOptions) .then(response => { if (response.status === 401) { router.push("/auth/login") diff --git a/frontend/src/sections/devices/cwmp/devices-diagnostic.js b/frontend/src/sections/devices/cwmp/devices-diagnostic.js index 41bbb8c..b796e9d 100644 --- a/frontend/src/sections/devices/cwmp/devices-diagnostic.js +++ b/frontend/src/sections/devices/cwmp/devices-diagnostic.js @@ -65,7 +65,7 @@ export const DevicesDiagnostic = () => { redirect: 'follow' }; - fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT}/device/${router.query.id[0]}/ping`, requestOptions) + fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/api/device/${router.query.id[0]}/ping`, requestOptions) .then(response => { if (response.status === 401) { router.push("/auth/login") @@ -95,7 +95,7 @@ export const DevicesDiagnostic = () => { body: JSON.stringify(content) }; - fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT}/device/${router.query.id[0]}/ping`, requestOptions) + fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/api/device/${router.query.id[0]}/ping`, requestOptions) .then(response => { if (response.status === 401) { router.push("/auth/login") diff --git a/frontend/src/sections/devices/cwmp/devices-rpc.js b/frontend/src/sections/devices/cwmp/devices-rpc.js index 5406d32..62c97b0 100644 --- a/frontend/src/sections/devices/cwmp/devices-rpc.js +++ b/frontend/src/sections/devices/cwmp/devices-rpc.js @@ -110,7 +110,7 @@ const handleOpen = () => { } - fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT}/device/cwmp/${router.query.id[0]}/${method}`, requestOptions) + 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){ diff --git a/frontend/src/sections/devices/cwmp/devices-wifi.js b/frontend/src/sections/devices/cwmp/devices-wifi.js index bd10cec..e9047f2 100644 --- a/frontend/src/sections/devices/cwmp/devices-wifi.js +++ b/frontend/src/sections/devices/cwmp/devices-wifi.js @@ -59,7 +59,7 @@ export const DevicesWiFi = () => { redirect: 'follow' }; - fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT}/device/${router.query.id[0]}/wifi`, requestOptions) + fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/api/device/${router.query.id[0]}/wifi`, requestOptions) .then(response => { if (response.status === 401) { router.push("/auth/login") @@ -197,7 +197,7 @@ export const DevicesWiFi = () => { body: data, redirect: 'follow' }; - fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT}/device/${router.query.id[0]}/wifi`, requestOptions) + fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/api/device/${router.query.id[0]}/wifi`, requestOptions) .then(response => { if (response.status === 401) { router.push("/auth/login") diff --git a/frontend/src/sections/devices/cwmp/site-survey.js b/frontend/src/sections/devices/cwmp/site-survey.js index 6e49349..1a97cfe 100644 --- a/frontend/src/sections/devices/cwmp/site-survey.js +++ b/frontend/src/sections/devices/cwmp/site-survey.js @@ -153,7 +153,7 @@ export const SiteSurvey = (props) => { redirect: 'follow' }; - fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT}/device/${router.query.id[0]}/sitesurvey`, requestOptions) + fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/api/device/${router.query.id[0]}/sitesurvey`, requestOptions) .then(response => { if (response.status === 401) { router.push("/auth/login") diff --git a/frontend/src/sections/devices/usp/devices-discovery.js b/frontend/src/sections/devices/usp/devices-discovery.js index 92aaa3a..ed003d4 100644 --- a/frontend/src/sections/devices/usp/devices-discovery.js +++ b/frontend/src/sections/devices/usp/devices-discovery.js @@ -96,7 +96,7 @@ const addDeviceObj = async(obj, setShowLoading, router, updateDeviceParameters) body: raw }; setShowLoading(true) - let result = await (await fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT}/device/${router.query.id[0]}/any/add`, requestOptions)) + let result = await (await fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/api/device/${router.query.id[0]}/any/add`, requestOptions)) if (result.status != 200) { if (result.status === 401){ router.push("/auth/login") @@ -131,7 +131,7 @@ const deleteDeviceObj = async(obj, setShowLoading, router, updateDeviceParameter body: raw }; setShowLoading(true) - let result = await (await fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT}/device/${router.query.id[0]}/any/del`, requestOptions)) + let result = await (await fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/api/device/${router.query.id[0]}/any/del`, requestOptions)) if (result.status != 200) { if (result.status === 401){ router.push("/auth/login") @@ -481,7 +481,7 @@ const getDeviceParameters = async (raw) =>{ body: raw }; - let result = await (await fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT}/device/${router.query.id[0]}/any/parameters`, requestOptions)) + let result = await (await fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/api/device/${router.query.id[0]}/any/parameters`, requestOptions)) if (result.status != 200) { if (result.status === 401){ router.push("/auth/login") @@ -505,7 +505,7 @@ const getDeviceParameterInstances = async (raw) =>{ body: raw }; - let result = await (await fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT}/device/${router.query.id[0]}/any/instances`, requestOptions)) + let result = await (await fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/api/device/${router.query.id[0]}/any/instances`, requestOptions)) if (result.status != 200) { throw new Error('Please check your email and password'); }else if (result.status === 401){ @@ -779,7 +779,7 @@ const getDeviceParameterInstances = async (raw) =>{ body: raw }; - let result = await (await fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT}/device/${router.query.id[0]}/any/get`, requestOptions)) + let result = await (await fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/api/device/${router.query.id[0]}/any/get`, requestOptions)) if (result.status != 200) { if (result.status === 401){ router.push("/auth/login") @@ -1029,7 +1029,7 @@ const getDeviceParameterInstances = async (raw) =>{ setOpen(false) setShowLoading(true) - let result = await (await fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT}/device/${router.query.id[0]}/any/set`, requestOptions)) + let result = await (await fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/api/device/${router.query.id[0]}/any/set`, requestOptions)) if (result.status != 200) { if (result.status === 401){ router.push("/auth/login") @@ -1172,7 +1172,7 @@ const getDeviceParameterInstances = async (raw) =>{ body: raw }; setShowLoading(true) - let result = await fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT}/device/${router.query.id[0]}/any/operate`, requestOptions) + let result = await fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/api/device/${router.query.id[0]}/any/operate`, requestOptions) let content = await result.json() if (result.status != 200) { setShowLoading(false) diff --git a/frontend/src/sections/devices/usp/devices-rpc.js b/frontend/src/sections/devices/usp/devices-rpc.js index 8406877..521bd9e 100644 --- a/frontend/src/sections/devices/usp/devices-rpc.js +++ b/frontend/src/sections/devices/usp/devices-rpc.js @@ -84,7 +84,7 @@ const handleOpen = () => { } - fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT}/device/${router.query.id[0]}/any/${method}`, requestOptions) + 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){ diff --git a/frontend/src/sections/overview/overview-latest-orders.js b/frontend/src/sections/overview/overview-latest-orders.js index ba3e2ae..1cc0ead 100644 --- a/frontend/src/sections/overview/overview-latest-orders.js +++ b/frontend/src/sections/overview/overview-latest-orders.js @@ -76,7 +76,7 @@ export const OverviewLatestOrders = (props) => { redirect: 'follow' }; - let result = await fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT}/device/alias?id=${sn}`, requestOptions) + let result = await fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/api/device/alias?id=${sn}`, requestOptions) console.log("result:", result) if (result.status === 401){ router.push("/auth/login") @@ -199,13 +199,6 @@ export const OverviewLatestOrders = (props) => { setDeviceAlias(order.Alias) setShowSetDeviceAlias(true) }} - onKeyDown={e => { - if (e.key === 'Enter') { - setDeviceToBeChanged(index) - setDeviceAlias(order.Alias) - setShowSetDeviceAlias(true) - } - }} > { */} + {showSetDeviceAlias&& Device Alias - {setDeviceAlias(e.target.value)}}> + {setDeviceAlias(e.target.value)}} + onKeyUp={e => { + if (e.key === 'Enter') { + setNewDeviceAlias(deviceAlias, orders[deviceToBeChanged].SN) + } + }}> @@ -255,7 +254,7 @@ export const OverviewLatestOrders = (props) => { setNewDeviceAlias(deviceAlias, orders[deviceToBeChanged].SN) }}>Save - + } ); }; diff --git a/frontend/src/utils/mapStyles.json b/frontend/src/utils/mapStyles.json new file mode 100644 index 0000000..b454593 --- /dev/null +++ b/frontend/src/utils/mapStyles.json @@ -0,0 +1,20 @@ +[ + { + "featureType": "all", + "elementType": "labels.text", + "stylers": [ + { + "visibility": "on" + } + ] + }, + { + "featureType": "poi", + "elementType": "labels.icon", + "stylers": [ + { + "visibility": "off" + } + ] + } + ] \ No newline at end of file