mirror of
https://git.rwth-aachen.de/acs/public/villas/web-backend-go/
synced 2025-03-30 00:00:12 +01:00
renaming visualization to dashboard
This commit is contained in:
parent
c565c04ba9
commit
c33438b395
20 changed files with 550 additions and 1947 deletions
|
@ -105,10 +105,10 @@ test:signal:
|
|||
variables:
|
||||
TEST_FOLDER: routes/signal
|
||||
|
||||
test:visualization:
|
||||
test:dashboard:
|
||||
extends: test:simulation
|
||||
variables:
|
||||
TEST_FOLDER: routes/visualization
|
||||
TEST_FOLDER: routes/dashboard
|
||||
|
||||
test:widget:
|
||||
extends: test:simulation
|
||||
|
|
|
@ -62,7 +62,7 @@ func DropTables(db *gorm.DB) {
|
|||
db.DropTableIfExists(&File{})
|
||||
db.DropTableIfExists(&Simulation{})
|
||||
db.DropTableIfExists(&User{})
|
||||
db.DropTableIfExists(&Visualization{})
|
||||
db.DropTableIfExists(&Dashboard{})
|
||||
db.DropTableIfExists(&Widget{})
|
||||
}
|
||||
|
||||
|
@ -74,7 +74,7 @@ func MigrateModels(db *gorm.DB) {
|
|||
db.AutoMigrate(&File{})
|
||||
db.AutoMigrate(&Simulation{})
|
||||
db.AutoMigrate(&User{})
|
||||
db.AutoMigrate(&Visualization{})
|
||||
db.AutoMigrate(&Dashboard{})
|
||||
db.AutoMigrate(&Widget{})
|
||||
}
|
||||
|
||||
|
@ -154,10 +154,10 @@ func DummyPopulateDB(test_db *gorm.DB) {
|
|||
checkErr(test_db.Create(&usr_A).Error)
|
||||
checkErr(test_db.Create(&usr_B).Error)
|
||||
|
||||
vis_A := Visualization{Name: "Visualization_A"}
|
||||
vis_B := Visualization{Name: "Visualization_B"}
|
||||
checkErr(test_db.Create(&vis_A).Error)
|
||||
checkErr(test_db.Create(&vis_B).Error)
|
||||
dab_A := Dashboard{Name: "Dashboard_A"}
|
||||
dab_B := Dashboard{Name: "Dashboard_B"}
|
||||
checkErr(test_db.Create(&dab_A).Error)
|
||||
checkErr(test_db.Create(&dab_B).Error)
|
||||
|
||||
widg_A := Widget{Name: "Widget_A"}
|
||||
widg_B := Widget{Name: "Widget_B"}
|
||||
|
@ -178,13 +178,13 @@ func DummyPopulateDB(test_db *gorm.DB) {
|
|||
checkErr(test_db.Model(&simn_A).Association("SimulationModels").Append(&mo_A).Error)
|
||||
checkErr(test_db.Model(&simn_A).Association("SimulationModels").Append(&mo_B).Error)
|
||||
|
||||
// Simulation HM Visualizations
|
||||
checkErr(test_db.Model(&simn_A).Association("Visualizations").Append(&vis_A).Error)
|
||||
checkErr(test_db.Model(&simn_A).Association("Visualizations").Append(&vis_B).Error)
|
||||
// Simulation HM Dashboards
|
||||
checkErr(test_db.Model(&simn_A).Association("Dashboards").Append(&dab_A).Error)
|
||||
checkErr(test_db.Model(&simn_A).Association("Dashboards").Append(&dab_B).Error)
|
||||
|
||||
// Visualization HM Widget
|
||||
checkErr(test_db.Model(&vis_A).Association("Widgets").Append(&widg_A).Error)
|
||||
checkErr(test_db.Model(&vis_A).Association("Widgets").Append(&widg_B).Error)
|
||||
// Dashboard HM Widget
|
||||
checkErr(test_db.Model(&dab_A).Association("Widgets").Append(&widg_A).Error)
|
||||
checkErr(test_db.Model(&dab_A).Association("Widgets").Append(&widg_B).Error)
|
||||
|
||||
// SimulationModel HM Signals
|
||||
checkErr(test_db.Model(&mo_A).Association("InputMapping").Append(&inSig_A).Error)
|
||||
|
|
|
@ -34,7 +34,7 @@ func TestDummyDBAssociations(t *testing.T) {
|
|||
var simn Simulation
|
||||
var usr User
|
||||
var usrs []User
|
||||
var vis Visualization
|
||||
var dab Dashboard
|
||||
var widg Widget
|
||||
|
||||
var sigs []Signal
|
||||
|
@ -42,7 +42,7 @@ func TestDummyDBAssociations(t *testing.T) {
|
|||
var files []File
|
||||
var files_sm []File
|
||||
var simns []Simulation
|
||||
var viss []Visualization
|
||||
var dabs []Dashboard
|
||||
var widgs []Widget
|
||||
|
||||
// User
|
||||
|
@ -77,10 +77,10 @@ func TestDummyDBAssociations(t *testing.T) {
|
|||
"Expected to have %v simulation models. Has %v.", 2, len(mos))
|
||||
}
|
||||
|
||||
a.NoError(db.Model(&simn).Related(&viss, "Visualizations").Error)
|
||||
if len(viss) != 2 {
|
||||
a.NoError(db.Model(&simn).Related(&dabs, "Dashboards").Error)
|
||||
if len(dabs) != 2 {
|
||||
a.Fail("Simulation Associations",
|
||||
"Expected to have %v Visualizations. Has %v.", 2, len(viss))
|
||||
"Expected to have %v Dashboards. Has %v.", 2, len(dabs))
|
||||
}
|
||||
|
||||
// Simulator
|
||||
|
@ -115,14 +115,14 @@ func TestDummyDBAssociations(t *testing.T) {
|
|||
|
||||
fmt.Println("SimulatorID: ", mo.SimulatorID)
|
||||
|
||||
// Visualization
|
||||
// Dashboard
|
||||
|
||||
a.NoError(db.Find(&vis, 1).Error, fM("Visualization"))
|
||||
a.EqualValues("Visualization_A", vis.Name)
|
||||
a.NoError(db.Find(&dab, 1).Error, fM("Dashboard"))
|
||||
a.EqualValues("Dashboard_A", dab.Name)
|
||||
|
||||
// Visualization Associations
|
||||
// Dashboard Associations
|
||||
|
||||
a.NoError(db.Model(&vis).Related(&widgs, "Widgets").Error)
|
||||
a.NoError(db.Model(&dab).Related(&widgs, "Widgets").Error)
|
||||
if len(widgs) != 2 {
|
||||
a.Fail("Widget Associations",
|
||||
"Expected to have %v Widget. Has %v.", 2, len(widgs))
|
||||
|
|
|
@ -30,8 +30,8 @@ type Simulation struct {
|
|||
Users []*User `gorm:"not null;many2many:user_simulations"`
|
||||
// SimulationModels that belong to the simulation
|
||||
SimulationModels []SimulationModel `gorm:"foreignkey:SimulationID"`
|
||||
// Visualizations that belong to the simulation
|
||||
Visualizations []Visualization `gorm:"foreignkey:SimulationID"`
|
||||
// Dashboards that belong to the simulation
|
||||
Dashboards []Dashboard `gorm:"foreignkey:SimulationID"`
|
||||
}
|
||||
|
||||
// SimulationModel data model
|
||||
|
@ -98,18 +98,18 @@ type Simulator struct {
|
|||
SimulationModels []SimulationModel `gorm:"foreignkey:SimulatorID"`
|
||||
}
|
||||
|
||||
// Visualization data model
|
||||
type Visualization struct {
|
||||
// ID of visualization
|
||||
// Dashboard data model
|
||||
type Dashboard struct {
|
||||
// ID of dashboard
|
||||
ID uint `gorm:"primary_key;auto_increment"`
|
||||
// Name of visualization
|
||||
// Name of dashboard
|
||||
Name string `gorm:"not null"`
|
||||
// Grid of visualization
|
||||
// Grid of dashboard
|
||||
Grid int `gorm:"default:15"`
|
||||
// ID of simulation to which visualization belongs
|
||||
// ID of simulation to which dashboard belongs
|
||||
SimulationID uint
|
||||
// Widgets that belong to visualization
|
||||
Widgets []Widget `gorm:"foreignkey:VisualizationID"`
|
||||
// Widgets that belong to dashboard
|
||||
Widgets []Widget `gorm:"foreignkey:DashboardID"`
|
||||
}
|
||||
|
||||
// Widget data model
|
||||
|
@ -138,8 +138,8 @@ type Widget struct {
|
|||
IsLocked bool `gorm:"default:false"`
|
||||
// Custom properties of widget as JSON string
|
||||
CustomProperties string
|
||||
// ID of visualization to which widget belongs
|
||||
VisualizationID uint
|
||||
// ID of dashboard to which widget belongs
|
||||
DashboardID uint
|
||||
// Files that belong to widget (for example images)
|
||||
Files []File `gorm:"foreignkey:WidgetID"`
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ type SimulatorResponse struct {
|
|||
RawProperties string `json:"RawProperties"`
|
||||
}
|
||||
|
||||
type VisualizationResponse struct {
|
||||
type DashboardResponse struct {
|
||||
ID uint `json:"ID"`
|
||||
Name string `json:"Name"`
|
||||
Grid int `json:"Grid"`
|
||||
|
@ -54,7 +54,7 @@ type WidgetResponse struct {
|
|||
X int `json:"X"`
|
||||
Y int `json:"Y"`
|
||||
Z int `json:"Z"`
|
||||
VisualizationID uint `json:"VisualizationID"`
|
||||
DashboardID uint `json:"DashboardID"`
|
||||
IsLocked bool `json:"IsLocked"`
|
||||
CustomProperties string `json:"CustomProperties"`
|
||||
}
|
||||
|
@ -117,12 +117,12 @@ type ResponseMsgSignal struct {
|
|||
Signal SignalResponse `json:"signal"`
|
||||
}
|
||||
|
||||
type ResponseMsgVisualizations struct {
|
||||
Visualizations []VisualizationResponse `json:"visualizations"`
|
||||
type ResponseMsgDashboards struct {
|
||||
Dashboards []DashboardResponse `json:"dashboards"`
|
||||
}
|
||||
|
||||
type ResponseMsgVisualization struct {
|
||||
Visualization VisualizationResponse `json:"visualization"`
|
||||
type ResponseMsgDashboard struct {
|
||||
Dashboard DashboardResponse `json:"dashboard"`
|
||||
}
|
||||
|
||||
type ResponseMsgWidgets struct {
|
||||
|
|
|
@ -18,7 +18,7 @@ const ModelUser = ModelName("user")
|
|||
const ModelSimulation = ModelName("simulation")
|
||||
const ModelSimulator = ModelName("simulator")
|
||||
const ModelSimulatorAction = ModelName("simulatoraction")
|
||||
const ModelVisualization = ModelName("visualization")
|
||||
const ModelDashboard = ModelName("dashboard")
|
||||
const ModelWidget = ModelName("widget")
|
||||
const ModelSimulationModel = ModelName("simulationmodel")
|
||||
const ModelSignal = ModelName("signal")
|
||||
|
@ -56,7 +56,7 @@ var Roles = RoleActions{
|
|||
ModelSimulator: crud,
|
||||
ModelSimulatorAction: crud,
|
||||
ModelWidget: crud,
|
||||
ModelVisualization: crud,
|
||||
ModelDashboard: crud,
|
||||
ModelSignal: crud,
|
||||
ModelFile: crud,
|
||||
},
|
||||
|
@ -67,14 +67,14 @@ var Roles = RoleActions{
|
|||
ModelSimulator: _r__,
|
||||
ModelSimulatorAction: _ru_,
|
||||
ModelWidget: crud,
|
||||
ModelVisualization: crud,
|
||||
ModelDashboard: crud,
|
||||
ModelSignal: crud,
|
||||
ModelFile: crud,
|
||||
},
|
||||
"Guest": {
|
||||
ModelSimulation: _r__,
|
||||
ModelSimulationModel: _r__,
|
||||
ModelVisualization: _r__,
|
||||
ModelDashboard: _r__,
|
||||
ModelWidget: _r__,
|
||||
ModelSimulator: _r__,
|
||||
ModelSimulatorAction: _r__,
|
||||
|
|
|
@ -151,30 +151,30 @@ func (self *SimulatorSerializer) Response() SimulatorResponse {
|
|||
return response
|
||||
}
|
||||
|
||||
// Visualization/s Serializers
|
||||
// Dashboard/s Serializers
|
||||
|
||||
type VisualizationsSerializer struct {
|
||||
Ctx *gin.Context
|
||||
Visualizations []Visualization
|
||||
type DashboardsSerializer struct {
|
||||
Ctx *gin.Context
|
||||
Dashboards []Dashboard
|
||||
}
|
||||
|
||||
func (self *VisualizationsSerializer) Response() []VisualizationResponse {
|
||||
response := []VisualizationResponse{}
|
||||
for _, visualization := range self.Visualizations {
|
||||
serializer := VisualizationSerializer{self.Ctx, visualization}
|
||||
func (self *DashboardsSerializer) Response() []DashboardResponse {
|
||||
response := []DashboardResponse{}
|
||||
for _, dashboard := range self.Dashboards {
|
||||
serializer := DashboardSerializer{self.Ctx, dashboard}
|
||||
response = append(response, serializer.Response())
|
||||
}
|
||||
return response
|
||||
}
|
||||
|
||||
type VisualizationSerializer struct {
|
||||
type DashboardSerializer struct {
|
||||
Ctx *gin.Context
|
||||
Visualization
|
||||
Dashboard
|
||||
}
|
||||
|
||||
func (self *VisualizationSerializer) Response() VisualizationResponse {
|
||||
func (self *DashboardSerializer) Response() DashboardResponse {
|
||||
|
||||
response := VisualizationResponse{
|
||||
response := DashboardResponse{
|
||||
Name: self.Name,
|
||||
Grid: self.Grid,
|
||||
SimulationID: self.SimulationID,
|
||||
|
@ -207,18 +207,18 @@ type WidgetSerializer struct {
|
|||
func (self *WidgetSerializer) Response() WidgetResponse {
|
||||
|
||||
response := WidgetResponse{
|
||||
ID: self.ID,
|
||||
Name: self.Name,
|
||||
Type: self.Type,
|
||||
Width: self.Width,
|
||||
Height: self.Height,
|
||||
MinWidth: self.MinWidth,
|
||||
MinHeight: self.MinHeight,
|
||||
X: self.X,
|
||||
Y: self.Y,
|
||||
Z: self.Z,
|
||||
VisualizationID: self.VisualizationID,
|
||||
IsLocked: self.IsLocked,
|
||||
ID: self.ID,
|
||||
Name: self.Name,
|
||||
Type: self.Type,
|
||||
Width: self.Width,
|
||||
Height: self.Height,
|
||||
MinWidth: self.MinWidth,
|
||||
MinHeight: self.MinHeight,
|
||||
X: self.X,
|
||||
Y: self.Y,
|
||||
Z: self.Z,
|
||||
DashboardID: self.DashboardID,
|
||||
IsLocked: self.IsLocked,
|
||||
//CustomProperties
|
||||
}
|
||||
return response
|
||||
|
|
1397
doc/api/api.yaml
1397
doc/api/api.yaml
File diff suppressed because it is too large
Load diff
183
routes/dashboard/dashboardEndpoints.go
Normal file
183
routes/dashboard/dashboardEndpoints.go
Normal file
|
@ -0,0 +1,183 @@
|
|||
package dashboard
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
|
||||
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/simulation"
|
||||
)
|
||||
|
||||
func RegisterDashboardEndpoints(r *gin.RouterGroup) {
|
||||
|
||||
r.GET("", getDashboards)
|
||||
r.POST("", addDashboard)
|
||||
r.PUT("/:dashboardID", updateDashboard)
|
||||
r.GET("/:dashboardID", getDashboard)
|
||||
r.DELETE("/:dashboardID", deleteDashboard)
|
||||
}
|
||||
|
||||
// getDashboards godoc
|
||||
// @Summary Get all dashboards of simulation
|
||||
// @ID getDashboards
|
||||
// @Produce json
|
||||
// @Tags dashboards
|
||||
// @Success 200 {array} common.DashboardResponse "Array of dashboards to which belong to simulation"
|
||||
// @Failure 401 "Unauthorized Access"
|
||||
// @Failure 403 "Access forbidden."
|
||||
// @Failure 404 "Not found"
|
||||
// @Failure 500 "Internal server error"
|
||||
// @Param simulationID query int true "Simulation ID"
|
||||
// @Router /dashboards [get]
|
||||
func getDashboards(c *gin.Context) {
|
||||
|
||||
ok, sim := simulation.CheckPermissions(c, common.Read, "query", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
db := common.GetDB()
|
||||
var dab []common.Dashboard
|
||||
err := db.Order("ID asc").Model(sim).Related(&dab, "Dashboards").Error
|
||||
if common.ProvideErrorResponse(c, err) {
|
||||
return
|
||||
}
|
||||
|
||||
serializer := common.DashboardsSerializer{c, dab}
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"dashboards": serializer.Response(),
|
||||
})
|
||||
}
|
||||
|
||||
// addDashboard godoc
|
||||
// @Summary Add a dashboard to a simulation
|
||||
// @ID addDashboard
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Tags dashboards
|
||||
// @Param inputDab body common.DashboardResponse true "Dashboard to be added incl. ID of simulation"
|
||||
// @Success 200 "OK."
|
||||
// @Failure 401 "Unauthorized Access"
|
||||
// @Failure 403 "Access forbidden."
|
||||
// @Failure 404 "Not found"
|
||||
// @Failure 500 "Internal server error"
|
||||
// @Router /dashboards [post]
|
||||
func addDashboard(c *gin.Context) {
|
||||
|
||||
var newDab Dashboard
|
||||
err := c.BindJSON(&newDab)
|
||||
if err != nil {
|
||||
errormsg := "Bad request. Error binding form data to JSON: " + err.Error()
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": errormsg,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
ok, _ := simulation.CheckPermissions(c, common.Create, "body", int(newDab.SimulationID))
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
// add dashboard to DB and add association to simulation
|
||||
err = newDab.addToSimulation()
|
||||
if common.ProvideErrorResponse(c, err) == false {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "OK.",
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// updateDashboard godoc
|
||||
// @Summary Update a dashboard
|
||||
// @ID updateDashboard
|
||||
// @Tags dashboards
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param inputDab body common.DashboardResponse true "Dashboard to be updated"
|
||||
// @Success 200 "OK."
|
||||
// @Failure 401 "Unauthorized Access"
|
||||
// @Failure 403 "Access forbidden."
|
||||
// @Failure 404 "Not found"
|
||||
// @Failure 500 "Internal server error"
|
||||
// @Param dashboardID path int true "Dashboard ID"
|
||||
// @Router /dashboards/{dashboardID} [put]
|
||||
func updateDashboard(c *gin.Context) {
|
||||
|
||||
ok, d := CheckPermissions(c, common.Update, "path", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
var modifiedDab Dashboard
|
||||
err := c.BindJSON(&modifiedDab)
|
||||
if err != nil {
|
||||
errormsg := "Bad request. Error binding form data to JSON: " + err.Error()
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": errormsg,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
err = d.update(modifiedDab)
|
||||
if common.ProvideErrorResponse(c, err) == false {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "OK.",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// getDashboard godoc
|
||||
// @Summary Get a dashboard
|
||||
// @ID getDashboard
|
||||
// @Tags dashboards
|
||||
// @Produce json
|
||||
// @Success 200 {object} common.DashboardResponse "Requested dashboard."
|
||||
// @Failure 401 "Unauthorized Access"
|
||||
// @Failure 403 "Access forbidden."
|
||||
// @Failure 404 "Not found"
|
||||
// @Failure 500 "Internal server error"
|
||||
// @Param dashboardID path int true "Dashboard ID"
|
||||
// @Router /dashboards/{dashboardID} [get]
|
||||
func getDashboard(c *gin.Context) {
|
||||
|
||||
ok, dab := CheckPermissions(c, common.Read, "path", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
serializer := common.DashboardSerializer{c, dab.Dashboard}
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"dashboard": serializer.Response(),
|
||||
})
|
||||
}
|
||||
|
||||
// deleteDashboard godoc
|
||||
// @Summary Delete a dashboard
|
||||
// @ID deleteDashboard
|
||||
// @Tags dashboards
|
||||
// @Produce json
|
||||
// @Success 200 "OK."
|
||||
// @Failure 401 "Unauthorized Access"
|
||||
// @Failure 403 "Access forbidden."
|
||||
// @Failure 404 "Not found"
|
||||
// @Failure 500 "Internal server error"
|
||||
// @Param dashboardID path int true "Dashboard ID"
|
||||
// @Router /dashboards/{dashboardID} [delete]
|
||||
func deleteDashboard(c *gin.Context) {
|
||||
ok, dab := CheckPermissions(c, common.Delete, "path", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
err := dab.delete()
|
||||
if common.ProvideErrorResponse(c, err) {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "OK.",
|
||||
})
|
||||
}
|
75
routes/dashboard/dashboardMethods.go
Normal file
75
routes/dashboard/dashboardMethods.go
Normal file
|
@ -0,0 +1,75 @@
|
|||
package dashboard
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
|
||||
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/simulation"
|
||||
)
|
||||
|
||||
type Dashboard struct {
|
||||
common.Dashboard
|
||||
}
|
||||
|
||||
func (v *Dashboard) save() error {
|
||||
db := common.GetDB()
|
||||
err := db.Create(v).Error
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *Dashboard) ByID(id uint) error {
|
||||
db := common.GetDB()
|
||||
err := db.Find(d, id).Error
|
||||
if err != nil {
|
||||
return fmt.Errorf("Dashboard with id=%v does not exist", id)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Dashboard) addToSimulation() error {
|
||||
db := common.GetDB()
|
||||
var sim simulation.Simulation
|
||||
err := sim.ByID(d.SimulationID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// save dashboard to DB
|
||||
err = d.save()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// associate dashboard with simulation
|
||||
err = db.Model(&sim).Association("Dashboards").Append(d).Error
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *Dashboard) update(modifiedDab Dashboard) error {
|
||||
|
||||
db := common.GetDB()
|
||||
|
||||
err := db.Model(d).Updates(map[string]interface{}{
|
||||
"Name": modifiedDab.Name,
|
||||
"Grid": modifiedDab.Grid,
|
||||
}).Error
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *Dashboard) delete() error {
|
||||
|
||||
db := common.GetDB()
|
||||
var sim simulation.Simulation
|
||||
err := sim.ByID(d.SimulationID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// remove association between Dashboard and Simulation
|
||||
// Dashboard itself is not deleted from DB, it remains as "dangling"
|
||||
err = db.Model(&sim).Association("Dashboards").Delete(d).Error
|
||||
|
||||
return err
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package visualization
|
||||
package dashboard
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
@ -11,48 +11,48 @@ import (
|
|||
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/simulation"
|
||||
)
|
||||
|
||||
func CheckPermissions(c *gin.Context, operation common.CRUD, visIDSource string, visIDBody int) (bool, Visualization) {
|
||||
func CheckPermissions(c *gin.Context, operation common.CRUD, dabIDSource string, dabIDBody int) (bool, Dashboard) {
|
||||
|
||||
var vis Visualization
|
||||
var dab Dashboard
|
||||
|
||||
err := common.ValidateRole(c, common.ModelVisualization, operation)
|
||||
err := common.ValidateRole(c, common.ModelDashboard, operation)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnprocessableEntity, "Access denied (role validation failed).")
|
||||
return false, vis
|
||||
return false, dab
|
||||
}
|
||||
|
||||
var visID int
|
||||
if visIDSource == "path" {
|
||||
visID, err = strconv.Atoi(c.Param("visualizationID"))
|
||||
var dabID int
|
||||
if dabIDSource == "path" {
|
||||
dabID, err = strconv.Atoi(c.Param("dashboardID"))
|
||||
if err != nil {
|
||||
errormsg := fmt.Sprintf("Bad request. No or incorrect format of simulationID path parameter")
|
||||
errormsg := fmt.Sprintf("Bad request. No or incorrect format of dashboardID path parameter")
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": errormsg,
|
||||
})
|
||||
return false, vis
|
||||
return false, dab
|
||||
}
|
||||
} else if visIDSource == "query" {
|
||||
visID, err = strconv.Atoi(c.Request.URL.Query().Get("visualizationID"))
|
||||
} else if dabIDSource == "query" {
|
||||
dabID, err = strconv.Atoi(c.Request.URL.Query().Get("dashboardID"))
|
||||
if err != nil {
|
||||
errormsg := fmt.Sprintf("Bad request. No or incorrect format of visualizationID query parameter")
|
||||
errormsg := fmt.Sprintf("Bad request. No or incorrect format of dashboardID query parameter")
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": errormsg,
|
||||
})
|
||||
return false, vis
|
||||
return false, dab
|
||||
}
|
||||
} else if visIDSource == "body" {
|
||||
visID = visIDBody
|
||||
} else if dabIDSource == "body" {
|
||||
dabID = dabIDBody
|
||||
}
|
||||
|
||||
err = vis.ByID(uint(visID))
|
||||
err = dab.ByID(uint(dabID))
|
||||
if common.ProvideErrorResponse(c, err) {
|
||||
return false, vis
|
||||
return false, dab
|
||||
}
|
||||
|
||||
ok, _ := simulation.CheckPermissions(c, operation, "body", int(vis.SimulationID))
|
||||
ok, _ := simulation.CheckPermissions(c, operation, "body", int(dab.SimulationID))
|
||||
if !ok {
|
||||
return false, vis
|
||||
return false, dab
|
||||
}
|
||||
|
||||
return true, vis
|
||||
return true, dab
|
||||
}
|
162
routes/dashboard/dashboard_test.go
Normal file
162
routes/dashboard/dashboard_test.go
Normal file
|
@ -0,0 +1,162 @@
|
|||
package dashboard
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
|
||||
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/user"
|
||||
)
|
||||
|
||||
var token string
|
||||
|
||||
type credentials struct {
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
var cred = credentials{
|
||||
Username: "User_A",
|
||||
Password: "abc123",
|
||||
}
|
||||
|
||||
var msgOK = common.ResponseMsg{
|
||||
Message: "OK.",
|
||||
}
|
||||
|
||||
var dabA = common.DashboardResponse{
|
||||
ID: 1,
|
||||
Name: "Dashboard_A",
|
||||
Grid: 15,
|
||||
SimulationID: 1,
|
||||
}
|
||||
|
||||
var dabB = common.DashboardResponse{
|
||||
ID: 2,
|
||||
Name: "Dashboard_B",
|
||||
Grid: 15,
|
||||
SimulationID: 1,
|
||||
}
|
||||
|
||||
var dabC = common.Dashboard{
|
||||
ID: 3,
|
||||
Name: "Dashboard_C",
|
||||
Grid: 99,
|
||||
SimulationID: 1,
|
||||
}
|
||||
|
||||
var dabCupdated = common.Dashboard{
|
||||
ID: dabC.ID,
|
||||
Name: "Dashboard_CUpdated",
|
||||
SimulationID: dabC.SimulationID,
|
||||
Grid: dabC.Grid,
|
||||
}
|
||||
|
||||
var dabC_response = common.DashboardResponse{
|
||||
ID: dabC.ID,
|
||||
Name: dabC.Name,
|
||||
Grid: dabC.Grid,
|
||||
SimulationID: dabC.SimulationID,
|
||||
}
|
||||
|
||||
var dabC_responseUpdated = common.DashboardResponse{
|
||||
ID: dabCupdated.ID,
|
||||
Name: dabCupdated.Name,
|
||||
Grid: dabCupdated.Grid,
|
||||
SimulationID: dabCupdated.SimulationID,
|
||||
}
|
||||
|
||||
var myDashboards = []common.DashboardResponse{
|
||||
dabA,
|
||||
dabB,
|
||||
}
|
||||
|
||||
var msgDashboards = common.ResponseMsgDashboards{
|
||||
Dashboards: myDashboards,
|
||||
}
|
||||
|
||||
var msgDab = common.ResponseMsgDashboard{
|
||||
Dashboard: dabC_response,
|
||||
}
|
||||
|
||||
var msgDabupdated = common.ResponseMsgDashboard{
|
||||
Dashboard: dabC_responseUpdated,
|
||||
}
|
||||
|
||||
// Test /dashboards endpoints
|
||||
func TestEndpoints(t *testing.T) {
|
||||
|
||||
db := common.DummyInitDB()
|
||||
defer db.Close()
|
||||
common.DummyPopulateDB(db)
|
||||
|
||||
router := gin.Default()
|
||||
api := router.Group("/api")
|
||||
|
||||
// All endpoints require authentication except when someone wants to
|
||||
// login (POST /authenticate)
|
||||
user.VisitorAuthenticate(api.Group("/authenticate"))
|
||||
|
||||
api.Use(user.Authentication(true))
|
||||
|
||||
RegisterDashboardEndpoints(api.Group("/dashboards"))
|
||||
|
||||
credjson, err := json.Marshal(cred)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
msgOKjson, err := json.Marshal(msgOK)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
msgDashboardsjson, err := json.Marshal(msgDashboards)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
msgDabjson, err := json.Marshal(msgDab)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
msgDabupdatedjson, err := json.Marshal(msgDabupdated)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
dabCjson, err := json.Marshal(dabC)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
dabCupdatedjson, err := json.Marshal(dabCupdated)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
token = common.AuthenticateForTest(t, router, "/api/authenticate", "POST", credjson, 200)
|
||||
|
||||
// test GET models
|
||||
common.TestEndpoint(t, router, token, "/api/dashboards?simulationID=1", "GET", nil, 200, string(msgDashboardsjson))
|
||||
|
||||
// test POST models
|
||||
common.TestEndpoint(t, router, token, "/api/dashboards", "POST", dabCjson, 200, string(msgOKjson))
|
||||
|
||||
// test GET models/:ModelID to check if previous POST worked correctly
|
||||
common.TestEndpoint(t, router, token, "/api/dashboards/3", "GET", nil, 200, string(msgDabjson))
|
||||
|
||||
// test PUT models/:ModelID
|
||||
common.TestEndpoint(t, router, token, "/api/dashboards/3", "PUT", dabCupdatedjson, 200, string(msgOKjson))
|
||||
common.TestEndpoint(t, router, token, "/api/dashboards/3", "GET", nil, 200, string(msgDabupdatedjson))
|
||||
|
||||
// test DELETE models/:ModelID
|
||||
common.TestEndpoint(t, router, token, "/api/dashboards/3", "DELETE", nil, 200, string(msgOKjson))
|
||||
common.TestEndpoint(t, router, token, "/api/dashboards?simulationID=1", "GET", nil, 200, string(msgDashboardsjson))
|
||||
|
||||
// TODO add testing for other return codes
|
||||
|
||||
}
|
|
@ -1,183 +0,0 @@
|
|||
package visualization
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
|
||||
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/simulation"
|
||||
)
|
||||
|
||||
func RegisterVisualizationEndpoints(r *gin.RouterGroup) {
|
||||
|
||||
r.GET("", getVisualizations)
|
||||
r.POST("", addVisualization)
|
||||
r.PUT("/:visualizationID", updateVisualization)
|
||||
r.GET("/:visualizationID", getVisualization)
|
||||
r.DELETE("/:visualizationID", deleteVisualization)
|
||||
}
|
||||
|
||||
// getVisualizations godoc
|
||||
// @Summary Get all visualizations of simulation
|
||||
// @ID getVisualizations
|
||||
// @Produce json
|
||||
// @Tags visualizations
|
||||
// @Success 200 {array} common.VisualizationResponse "Array of visualizations to which belong to simulation"
|
||||
// @Failure 401 "Unauthorized Access"
|
||||
// @Failure 403 "Access forbidden."
|
||||
// @Failure 404 "Not found"
|
||||
// @Failure 500 "Internal server error"
|
||||
// @Param simulationID query int true "Simulation ID"
|
||||
// @Router /visualizations [get]
|
||||
func getVisualizations(c *gin.Context) {
|
||||
|
||||
ok, sim := simulation.CheckPermissions(c, common.Read, "query", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
db := common.GetDB()
|
||||
var vis []common.Visualization
|
||||
err := db.Order("ID asc").Model(sim).Related(&vis, "Visualizations").Error
|
||||
if common.ProvideErrorResponse(c, err) {
|
||||
return
|
||||
}
|
||||
|
||||
serializer := common.VisualizationsSerializer{c, vis}
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"visualizations": serializer.Response(),
|
||||
})
|
||||
}
|
||||
|
||||
// addVisualization godoc
|
||||
// @Summary Add a visualization to a simulation
|
||||
// @ID addVisualization
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Tags visualizations
|
||||
// @Param inputVis body common.VisualizationResponse true "Visualization to be added incl. ID of simulation"
|
||||
// @Success 200 "OK."
|
||||
// @Failure 401 "Unauthorized Access"
|
||||
// @Failure 403 "Access forbidden."
|
||||
// @Failure 404 "Not found"
|
||||
// @Failure 500 "Internal server error"
|
||||
// @Router /visualizations [post]
|
||||
func addVisualization(c *gin.Context) {
|
||||
|
||||
var newVis Visualization
|
||||
err := c.BindJSON(&newVis)
|
||||
if err != nil {
|
||||
errormsg := "Bad request. Error binding form data to JSON: " + err.Error()
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": errormsg,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
ok, _ := simulation.CheckPermissions(c, common.Create, "body", int(newVis.SimulationID))
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
// add visualization to DB and add association to simulation
|
||||
err = newVis.addToSimulation()
|
||||
if common.ProvideErrorResponse(c, err) == false {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "OK.",
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// updateVisualization godoc
|
||||
// @Summary Update a visualization
|
||||
// @ID updateVisualization
|
||||
// @Tags visualizations
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param inputVis body common.VisualizationResponse true "Visualization to be updated"
|
||||
// @Success 200 "OK."
|
||||
// @Failure 401 "Unauthorized Access"
|
||||
// @Failure 403 "Access forbidden."
|
||||
// @Failure 404 "Not found"
|
||||
// @Failure 500 "Internal server error"
|
||||
// @Param visualizationID path int true "Visualization ID"
|
||||
// @Router /visualizations/{visualizationID} [put]
|
||||
func updateVisualization(c *gin.Context) {
|
||||
|
||||
ok, v := CheckPermissions(c, common.Update, "path", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
var modifiedVis Visualization
|
||||
err := c.BindJSON(&modifiedVis)
|
||||
if err != nil {
|
||||
errormsg := "Bad request. Error binding form data to JSON: " + err.Error()
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": errormsg,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
err = v.update(modifiedVis)
|
||||
if common.ProvideErrorResponse(c, err) == false {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "OK.",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// getVisualization godoc
|
||||
// @Summary Get a visualization
|
||||
// @ID getVisualization
|
||||
// @Tags visualizations
|
||||
// @Produce json
|
||||
// @Success 200 {object} common.VisualizationResponse "Requested visualization."
|
||||
// @Failure 401 "Unauthorized Access"
|
||||
// @Failure 403 "Access forbidden."
|
||||
// @Failure 404 "Not found"
|
||||
// @Failure 500 "Internal server error"
|
||||
// @Param visualizationID path int true "Visualization ID"
|
||||
// @Router /visualizations/{visualizationID} [get]
|
||||
func getVisualization(c *gin.Context) {
|
||||
|
||||
ok, vis := CheckPermissions(c, common.Read, "path", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
serializer := common.VisualizationSerializer{c, vis.Visualization}
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"visualization": serializer.Response(),
|
||||
})
|
||||
}
|
||||
|
||||
// deleteVisualization godoc
|
||||
// @Summary Delete a visualization
|
||||
// @ID deleteVisualization
|
||||
// @Tags visualizations
|
||||
// @Produce json
|
||||
// @Success 200 "OK."
|
||||
// @Failure 401 "Unauthorized Access"
|
||||
// @Failure 403 "Access forbidden."
|
||||
// @Failure 404 "Not found"
|
||||
// @Failure 500 "Internal server error"
|
||||
// @Param visualizationID path int true "Visualization ID"
|
||||
// @Router /visualizations/{visualizationID} [delete]
|
||||
func deleteVisualization(c *gin.Context) {
|
||||
ok, vis := CheckPermissions(c, common.Delete, "path", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
err := vis.delete()
|
||||
if common.ProvideErrorResponse(c, err) {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "OK.",
|
||||
})
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
package visualization
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
|
||||
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/simulation"
|
||||
)
|
||||
|
||||
type Visualization struct {
|
||||
common.Visualization
|
||||
}
|
||||
|
||||
func (v *Visualization) save() error {
|
||||
db := common.GetDB()
|
||||
err := db.Create(v).Error
|
||||
return err
|
||||
}
|
||||
|
||||
func (v *Visualization) ByID(id uint) error {
|
||||
db := common.GetDB()
|
||||
err := db.Find(v, id).Error
|
||||
if err != nil {
|
||||
return fmt.Errorf("Visualization with id=%v does not exist", id)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *Visualization) addToSimulation() error {
|
||||
db := common.GetDB()
|
||||
var sim simulation.Simulation
|
||||
err := sim.ByID(v.SimulationID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// save visualization to DB
|
||||
err = v.save()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// associate visualization with simulation
|
||||
err = db.Model(&sim).Association("Visualizations").Append(v).Error
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (v *Visualization) update(modifiedVis Visualization) error {
|
||||
|
||||
db := common.GetDB()
|
||||
|
||||
err := db.Model(v).Updates(map[string]interface{}{
|
||||
"Name": modifiedVis.Name,
|
||||
"Grid": modifiedVis.Grid,
|
||||
}).Error
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (v *Visualization) delete() error {
|
||||
|
||||
db := common.GetDB()
|
||||
var sim simulation.Simulation
|
||||
err := sim.ByID(v.SimulationID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// remove association between Visualization and Simulation
|
||||
// Visualization itself is not deleted from DB, it remains as "dangling"
|
||||
err = db.Model(&sim).Association("Visualizations").Delete(v).Error
|
||||
|
||||
return err
|
||||
}
|
|
@ -1,162 +0,0 @@
|
|||
package visualization
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
|
||||
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/user"
|
||||
)
|
||||
|
||||
var token string
|
||||
|
||||
type credentials struct {
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
var cred = credentials{
|
||||
Username: "User_A",
|
||||
Password: "abc123",
|
||||
}
|
||||
|
||||
var msgOK = common.ResponseMsg{
|
||||
Message: "OK.",
|
||||
}
|
||||
|
||||
var visA = common.VisualizationResponse{
|
||||
ID: 1,
|
||||
Name: "Visualization_A",
|
||||
Grid: 15,
|
||||
SimulationID: 1,
|
||||
}
|
||||
|
||||
var visB = common.VisualizationResponse{
|
||||
ID: 2,
|
||||
Name: "Visualization_B",
|
||||
Grid: 15,
|
||||
SimulationID: 1,
|
||||
}
|
||||
|
||||
var visC = common.Visualization{
|
||||
ID: 3,
|
||||
Name: "Visualization_C",
|
||||
Grid: 99,
|
||||
SimulationID: 1,
|
||||
}
|
||||
|
||||
var visCupdated = common.Visualization{
|
||||
ID: visC.ID,
|
||||
Name: "Visualization_CUpdated",
|
||||
SimulationID: visC.SimulationID,
|
||||
Grid: visC.Grid,
|
||||
}
|
||||
|
||||
var visC_response = common.VisualizationResponse{
|
||||
ID: visC.ID,
|
||||
Name: visC.Name,
|
||||
Grid: visC.Grid,
|
||||
SimulationID: visC.SimulationID,
|
||||
}
|
||||
|
||||
var visC_responseUpdated = common.VisualizationResponse{
|
||||
ID: visCupdated.ID,
|
||||
Name: visCupdated.Name,
|
||||
Grid: visCupdated.Grid,
|
||||
SimulationID: visCupdated.SimulationID,
|
||||
}
|
||||
|
||||
var myVisualizations = []common.VisualizationResponse{
|
||||
visA,
|
||||
visB,
|
||||
}
|
||||
|
||||
var msgVisualizations = common.ResponseMsgVisualizations{
|
||||
Visualizations: myVisualizations,
|
||||
}
|
||||
|
||||
var msgVis = common.ResponseMsgVisualization{
|
||||
Visualization: visC_response,
|
||||
}
|
||||
|
||||
var msgVisupdated = common.ResponseMsgVisualization{
|
||||
Visualization: visC_responseUpdated,
|
||||
}
|
||||
|
||||
// Test /models endpoints
|
||||
func TestVisualizationEndpoints(t *testing.T) {
|
||||
|
||||
db := common.DummyInitDB()
|
||||
defer db.Close()
|
||||
common.DummyPopulateDB(db)
|
||||
|
||||
router := gin.Default()
|
||||
api := router.Group("/api")
|
||||
|
||||
// All endpoints require authentication except when someone wants to
|
||||
// login (POST /authenticate)
|
||||
user.VisitorAuthenticate(api.Group("/authenticate"))
|
||||
|
||||
api.Use(user.Authentication(true))
|
||||
|
||||
RegisterVisualizationEndpoints(api.Group("/visualizations"))
|
||||
|
||||
credjson, err := json.Marshal(cred)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
msgOKjson, err := json.Marshal(msgOK)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
msgVisualizationsjson, err := json.Marshal(msgVisualizations)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
msgVisjson, err := json.Marshal(msgVis)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
msgVisupdatedjson, err := json.Marshal(msgVisupdated)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
visCjson, err := json.Marshal(visC)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
visCupdatedjson, err := json.Marshal(visCupdated)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
token = common.AuthenticateForTest(t, router, "/api/authenticate", "POST", credjson, 200)
|
||||
|
||||
// test GET models
|
||||
common.TestEndpoint(t, router, token, "/api/visualizations?simulationID=1", "GET", nil, 200, string(msgVisualizationsjson))
|
||||
|
||||
// test POST models
|
||||
common.TestEndpoint(t, router, token, "/api/visualizations", "POST", visCjson, 200, string(msgOKjson))
|
||||
|
||||
// test GET models/:ModelID to check if previous POST worked correctly
|
||||
common.TestEndpoint(t, router, token, "/api/visualizations/3", "GET", nil, 200, string(msgVisjson))
|
||||
|
||||
// test PUT models/:ModelID
|
||||
common.TestEndpoint(t, router, token, "/api/visualizations/3", "PUT", visCupdatedjson, 200, string(msgOKjson))
|
||||
common.TestEndpoint(t, router, token, "/api/visualizations/3", "GET", nil, 200, string(msgVisupdatedjson))
|
||||
|
||||
// test DELETE models/:ModelID
|
||||
common.TestEndpoint(t, router, token, "/api/visualizations/3", "DELETE", nil, 200, string(msgOKjson))
|
||||
common.TestEndpoint(t, router, token, "/api/visualizations?simulationID=1", "GET", nil, 200, string(msgVisualizationsjson))
|
||||
|
||||
// TODO add testing for other return codes
|
||||
|
||||
}
|
|
@ -6,7 +6,7 @@ import (
|
|||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
|
||||
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/visualization"
|
||||
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/dashboard"
|
||||
)
|
||||
|
||||
func RegisterWidgetEndpoints(r *gin.RouterGroup) {
|
||||
|
@ -18,27 +18,27 @@ func RegisterWidgetEndpoints(r *gin.RouterGroup) {
|
|||
}
|
||||
|
||||
// getWidgets godoc
|
||||
// @Summary Get all widgets of visualization
|
||||
// @Summary Get all widgets of dashboard
|
||||
// @ID getWidgets
|
||||
// @Produce json
|
||||
// @Tags widgets
|
||||
// @Success 200 {array} common.WidgetResponse "Array of widgets to which belong to visualization"
|
||||
// @Success 200 {array} common.WidgetResponse "Array of widgets to which belong to dashboard"
|
||||
// @Failure 401 "Unauthorized Access"
|
||||
// @Failure 403 "Access forbidden."
|
||||
// @Failure 404 "Not found"
|
||||
// @Failure 500 "Internal server error"
|
||||
// @Param visualizationID query int true "Visualization ID"
|
||||
// @Param dashboardID query int true "Dashboard ID"
|
||||
// @Router /widgets [get]
|
||||
func getWidgets(c *gin.Context) {
|
||||
|
||||
ok, vis := visualization.CheckPermissions(c, common.Read, "query", -1)
|
||||
ok, dab := dashboard.CheckPermissions(c, common.Read, "query", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
db := common.GetDB()
|
||||
var widgets []common.Widget
|
||||
err := db.Order("ID asc").Model(vis).Related(&widgets, "Widgets").Error
|
||||
err := db.Order("ID asc").Model(dab).Related(&widgets, "Widgets").Error
|
||||
if common.ProvideErrorResponse(c, err) {
|
||||
return
|
||||
}
|
||||
|
@ -50,12 +50,12 @@ func getWidgets(c *gin.Context) {
|
|||
}
|
||||
|
||||
// addWidget godoc
|
||||
// @Summary Add a widget to a visualization
|
||||
// @Summary Add a widget to a dashboard
|
||||
// @ID addWidget
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Tags widgets
|
||||
// @Param inputWidget body common.WidgetResponse true "Widget to be added incl. ID of visualization"
|
||||
// @Param inputWidget body common.WidgetResponse true "Widget to be added incl. ID of dashboard"
|
||||
// @Success 200 "OK."
|
||||
// @Failure 401 "Unauthorized Access"
|
||||
// @Failure 403 "Access forbidden."
|
||||
|
@ -74,12 +74,12 @@ func addWidget(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
ok, _ := visualization.CheckPermissions(c, common.Create, "body", int(newWidget.VisualizationID))
|
||||
ok, _ := dashboard.CheckPermissions(c, common.Create, "body", int(newWidget.DashboardID))
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
err = newWidget.addToVisualization()
|
||||
err = newWidget.addToDashboard()
|
||||
|
||||
if common.ProvideErrorResponse(c, err) == false {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"fmt"
|
||||
|
||||
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
|
||||
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/visualization"
|
||||
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/dashboard"
|
||||
)
|
||||
|
||||
type Widget struct {
|
||||
|
@ -26,22 +26,22 @@ func (w *Widget) ByID(id uint) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (w *Widget) addToVisualization() error {
|
||||
func (w *Widget) addToDashboard() error {
|
||||
db := common.GetDB()
|
||||
var vis visualization.Visualization
|
||||
err := vis.ByID(uint(w.VisualizationID))
|
||||
var dab dashboard.Dashboard
|
||||
err := dab.ByID(uint(w.DashboardID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// save visualization to DB
|
||||
// save widget to DB
|
||||
err = w.save()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// associate visualization with simulation
|
||||
err = db.Model(&vis).Association("Widgets").Append(w).Error
|
||||
// associate dashboard with simulation
|
||||
err = db.Model(&dab).Association("Widgets").Append(w).Error
|
||||
|
||||
return err
|
||||
}
|
||||
|
@ -69,15 +69,15 @@ func (w *Widget) update(modifiedWidget Widget) error {
|
|||
func (w *Widget) delete() error {
|
||||
|
||||
db := common.GetDB()
|
||||
var vis visualization.Visualization
|
||||
err := vis.ByID(w.VisualizationID)
|
||||
var dab dashboard.Dashboard
|
||||
err := dab.ByID(w.DashboardID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// remove association between Visualization and Widget
|
||||
// remove association between Dashboard and Widget
|
||||
// Widget itself is not deleted from DB, it remains as "dangling"
|
||||
err = db.Model(&vis).Association("Widgets").Delete(w).Error
|
||||
err = db.Model(&dab).Association("Widgets").Delete(w).Error
|
||||
|
||||
// TODO: What about files that belong to a widget? Keep them or remove them here?
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
|
||||
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/visualization"
|
||||
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/dashboard"
|
||||
)
|
||||
|
||||
func CheckPermissions(c *gin.Context, operation common.CRUD, widgetIDBody int) (bool, Widget) {
|
||||
|
@ -40,7 +40,7 @@ func CheckPermissions(c *gin.Context, operation common.CRUD, widgetIDBody int) (
|
|||
return false, w
|
||||
}
|
||||
|
||||
ok, _ := visualization.CheckPermissions(c, operation, "body", int(w.VisualizationID))
|
||||
ok, _ := dashboard.CheckPermissions(c, operation, "body", int(w.DashboardID))
|
||||
if !ok {
|
||||
return false, w
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ var wdgA = common.WidgetResponse{
|
|||
Z: 0,
|
||||
IsLocked: false,
|
||||
CustomProperties: "",
|
||||
VisualizationID: 1,
|
||||
DashboardID: 1,
|
||||
}
|
||||
|
||||
var wdgB = common.WidgetResponse{
|
||||
|
@ -55,7 +55,7 @@ var wdgB = common.WidgetResponse{
|
|||
Z: 0,
|
||||
IsLocked: false,
|
||||
CustomProperties: "",
|
||||
VisualizationID: 1,
|
||||
DashboardID: 1,
|
||||
}
|
||||
|
||||
var wdgC = common.Widget{
|
||||
|
@ -71,7 +71,7 @@ var wdgC = common.Widget{
|
|||
Z: 13,
|
||||
IsLocked: false,
|
||||
CustomProperties: "",
|
||||
VisualizationID: 1,
|
||||
DashboardID: 1,
|
||||
}
|
||||
|
||||
var wdgCupdated = common.Widget{
|
||||
|
@ -87,7 +87,7 @@ var wdgCupdated = common.Widget{
|
|||
Z: wdgC.Z,
|
||||
IsLocked: wdgC.IsLocked,
|
||||
CustomProperties: wdgC.CustomProperties,
|
||||
VisualizationID: wdgC.VisualizationID,
|
||||
DashboardID: wdgC.DashboardID,
|
||||
}
|
||||
|
||||
var wdgC_response = common.WidgetResponse{
|
||||
|
@ -103,7 +103,7 @@ var wdgC_response = common.WidgetResponse{
|
|||
Z: wdgC.Z,
|
||||
IsLocked: wdgC.IsLocked,
|
||||
CustomProperties: wdgC.CustomProperties,
|
||||
VisualizationID: wdgC.VisualizationID,
|
||||
DashboardID: wdgC.DashboardID,
|
||||
}
|
||||
|
||||
var wdgC_responseUpdated = common.WidgetResponse{
|
||||
|
@ -119,7 +119,7 @@ var wdgC_responseUpdated = common.WidgetResponse{
|
|||
Z: wdgC.Z,
|
||||
IsLocked: wdgC.IsLocked,
|
||||
CustomProperties: wdgC.CustomProperties,
|
||||
VisualizationID: wdgC.VisualizationID,
|
||||
DashboardID: wdgC.DashboardID,
|
||||
}
|
||||
|
||||
var myWidgets = []common.WidgetResponse{
|
||||
|
@ -139,7 +139,7 @@ var msgWdgupdated = common.ResponseMsgWidget{
|
|||
Widget: wdgC_responseUpdated,
|
||||
}
|
||||
|
||||
// Test /models endpoints
|
||||
// Test /widgets endpoints
|
||||
func TestWidgetEndpoints(t *testing.T) {
|
||||
|
||||
db := common.DummyInitDB()
|
||||
|
@ -194,22 +194,22 @@ func TestWidgetEndpoints(t *testing.T) {
|
|||
|
||||
token = common.AuthenticateForTest(t, router, "/api/authenticate", "POST", credjson, 200)
|
||||
|
||||
// test GET models
|
||||
common.TestEndpoint(t, router, token, "/api/widgets?visualizationID=1", "GET", nil, 200, string(msgWidgetsjson))
|
||||
// test GET widgets
|
||||
common.TestEndpoint(t, router, token, "/api/widgets?dashboardID=1", "GET", nil, 200, string(msgWidgetsjson))
|
||||
|
||||
// test POST models
|
||||
// test POST widgets
|
||||
common.TestEndpoint(t, router, token, "/api/widgets", "POST", wdgCjson, 200, string(msgOKjson))
|
||||
|
||||
// test GET models/:ModelID to check if previous POST worked correctly
|
||||
// test GET widgets/:widgetID to check if previous POST worked correctly
|
||||
common.TestEndpoint(t, router, token, "/api/widgets/3", "GET", nil, 200, string(msgWdgjson))
|
||||
|
||||
// test PUT models/:ModelID
|
||||
// test PUT widgets/:widgetID
|
||||
common.TestEndpoint(t, router, token, "/api/widgets/3", "PUT", wdgCupdatedjson, 200, string(msgOKjson))
|
||||
common.TestEndpoint(t, router, token, "/api/widgets/3", "GET", nil, 200, string(msgWdgupdatedjson))
|
||||
|
||||
// test DELETE models/:ModelID
|
||||
// test DELETE widgets/:widgetID
|
||||
common.TestEndpoint(t, router, token, "/api/widgets/3", "DELETE", nil, 200, string(msgOKjson))
|
||||
common.TestEndpoint(t, router, token, "/api/widgets?visualizationID=1", "GET", nil, 200, string(msgWidgetsjson))
|
||||
common.TestEndpoint(t, router, token, "/api/widgets?dashboardID=1", "GET", nil, 200, string(msgWidgetsjson))
|
||||
|
||||
// TODO add testing for other return codes
|
||||
|
||||
|
|
4
start.go
4
start.go
|
@ -12,11 +12,11 @@ import (
|
|||
|
||||
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
|
||||
_ "git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/doc/api" // doc/api folder is used by Swag CLI, you have to import it
|
||||
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/dashboard"
|
||||
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/simulation"
|
||||
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/simulationmodel"
|
||||
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/simulator"
|
||||
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/user"
|
||||
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/visualization"
|
||||
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/widget"
|
||||
)
|
||||
|
||||
|
@ -57,7 +57,7 @@ func main() {
|
|||
simulation.RegisterSimulationEndpoints(api.Group("/simulations"))
|
||||
simulationmodel.RegisterSimulationModelEndpoints(api.Group("/models"))
|
||||
signal.RegisterSignalEndpoints(api.Group("/signals"))
|
||||
visualization.RegisterVisualizationEndpoints(api.Group("/visualizations"))
|
||||
dashboard.RegisterDashboardEndpoints(api.Group("/dashboards"))
|
||||
widget.RegisterWidgetEndpoints(api.Group("/widgets"))
|
||||
file.RegisterFileEndpoints(api.Group("/files"))
|
||||
user.RegisterUserEndpoints(api.Group("/users"))
|
||||
|
|
Loading…
Add table
Reference in a new issue