mirror of
https://git.rwth-aachen.de/acs/public/villas/web-backend-go/
synced 2025-03-30 00:00:12 +01:00
WIP: initial version of result data model, endpoints, methods, validators, middleware #38
This commit is contained in:
parent
adbef6abda
commit
89311af146
15 changed files with 2311 additions and 4 deletions
|
@ -93,6 +93,7 @@ func DropTables() {
|
|||
DBpool.DropTableIfExists(&User{})
|
||||
DBpool.DropTableIfExists(&Dashboard{})
|
||||
DBpool.DropTableIfExists(&Widget{})
|
||||
DBpool.DropTableIfExists(&Result{})
|
||||
// The following statement deletes the many to many relationship between users and scenarios
|
||||
DBpool.DropTableIfExists("user_scenarios")
|
||||
}
|
||||
|
@ -107,4 +108,5 @@ func MigrateModels() {
|
|||
DBpool.AutoMigrate(&User{})
|
||||
DBpool.AutoMigrate(&Dashboard{})
|
||||
DBpool.AutoMigrate(&Widget{})
|
||||
DBpool.AutoMigrate(&Result{})
|
||||
}
|
||||
|
|
|
@ -144,6 +144,8 @@ func TestScenarioAssociations(t *testing.T) {
|
|||
dashboardB := Dashboard{}
|
||||
fileA := File{}
|
||||
fileB := File{}
|
||||
resultA := Result{}
|
||||
resultB := Result{}
|
||||
|
||||
// add scenarios to DB
|
||||
assert.NoError(t, DBpool.Create(&scenarioA).Error)
|
||||
|
@ -165,6 +167,10 @@ func TestScenarioAssociations(t *testing.T) {
|
|||
assert.NoError(t, DBpool.Create(&fileA).Error)
|
||||
assert.NoError(t, DBpool.Create(&fileB).Error)
|
||||
|
||||
// add results to DB
|
||||
assert.NoError(t, DBpool.Create(&resultA).Error)
|
||||
assert.NoError(t, DBpool.Create(&resultB).Error)
|
||||
|
||||
// add many-to-many associations between users and scenarios
|
||||
// User HM Scenarios, Scenario HM Users (Many-to-Many)
|
||||
assert.NoError(t, DBpool.Model(&scenarioA).Association("Users").Append(&userA).Error)
|
||||
|
@ -184,6 +190,10 @@ func TestScenarioAssociations(t *testing.T) {
|
|||
assert.NoError(t, DBpool.Model(&scenarioA).Association("Dashboards").Append(&dashboardA).Error)
|
||||
assert.NoError(t, DBpool.Model(&scenarioA).Association("Dashboards").Append(&dashboardB).Error)
|
||||
|
||||
// Scenario HM Results
|
||||
assert.NoError(t, DBpool.Model(&scenarioA).Association("Results").Append(&resultA).Error)
|
||||
assert.NoError(t, DBpool.Model(&scenarioA).Association("Results").Append(&resultB).Error)
|
||||
|
||||
var scenario1 Scenario
|
||||
assert.NoError(t, DBpool.Find(&scenario1, 1).Error, fmt.Sprintf("Find Scenario with ID=1"))
|
||||
|
||||
|
@ -218,6 +228,14 @@ func TestScenarioAssociations(t *testing.T) {
|
|||
assert.Fail(t, "Scenario Associations",
|
||||
"Expected to have %v Files. Has %v.", 2, len(files))
|
||||
}
|
||||
|
||||
// Get results of scenario1
|
||||
var results []File
|
||||
assert.NoError(t, DBpool.Model(&scenario1).Related(&results, "Results").Error)
|
||||
if len(files) != 2 {
|
||||
assert.Fail(t, "Scenario Associations",
|
||||
"Expected to have %v Results. Has %v.", 2, len(results))
|
||||
}
|
||||
}
|
||||
|
||||
func TestICAssociations(t *testing.T) {
|
||||
|
|
|
@ -32,8 +32,8 @@ import (
|
|||
// except the json tags that are needed for serializing the models
|
||||
type Model struct {
|
||||
ID uint `json:"id,omitempty" gorm:"primary_key:true"`
|
||||
CreatedAt time.Time `json:"-"`
|
||||
UpdatedAt time.Time `json:"-"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
DeletedAt *time.Time `json:"-" sql:"index"`
|
||||
}
|
||||
|
||||
|
@ -71,6 +71,8 @@ type Scenario struct {
|
|||
Dashboards []Dashboard `json:"-" gorm:"foreignkey:ScenarioID" `
|
||||
// Files that belong to the Scenario (for example images, models, etc.)
|
||||
Files []File `json:"-" gorm:"foreignkey:ScenarioID"`
|
||||
// Results that belong to the Scenario
|
||||
Results []Result `json:"-" gorm:"foreignkey:ScenarioID"`
|
||||
}
|
||||
|
||||
// ComponentConfiguration data model
|
||||
|
@ -212,3 +214,16 @@ type File struct {
|
|||
// Width of an image file in pixels (optional)
|
||||
ImageWidth int `json:"imageWidth" gorm:"default:0"`
|
||||
}
|
||||
|
||||
// Result data model
|
||||
type Result struct {
|
||||
Model
|
||||
// JSON snapshots of component configurations used to generate results
|
||||
ConfigSnapshots []postgres.Jsonb `json:"configSnapshots"`
|
||||
// Description of results
|
||||
Description string `json:"description"`
|
||||
// ID of Scenario to which result belongs
|
||||
ScenarioID uint `json:"scenarioID"`
|
||||
// File IDs associated with result
|
||||
ResultFileIDs pq.Int64Array `json:"resultFileIDs" gorm:"type:integer[]"`
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ const ModelWidget = ModelName("widget")
|
|||
const ModelComponentConfiguration = ModelName("component-configuration")
|
||||
const ModelSignal = ModelName("signal")
|
||||
const ModelFile = ModelName("file")
|
||||
const ModelResult = ModelName("result")
|
||||
|
||||
type CRUD string
|
||||
|
||||
|
@ -83,6 +84,7 @@ var Roles = RoleActions{
|
|||
ModelDashboard: crud,
|
||||
ModelSignal: crud,
|
||||
ModelFile: crud,
|
||||
ModelResult: crud,
|
||||
},
|
||||
"User": {
|
||||
ModelUser: _ru_,
|
||||
|
@ -95,6 +97,7 @@ var Roles = RoleActions{
|
|||
ModelDashboard: crud,
|
||||
ModelSignal: crud,
|
||||
ModelFile: crud,
|
||||
ModelResult: crud,
|
||||
},
|
||||
"Guest": {
|
||||
ModelScenario: _r__,
|
||||
|
@ -107,6 +110,7 @@ var Roles = RoleActions{
|
|||
ModelUsers: none,
|
||||
ModelSignal: _r__,
|
||||
ModelFile: _r__,
|
||||
ModelResult: none,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
678
doc/api/docs.go
678
doc/api/docs.go
|
@ -1,6 +1,6 @@
|
|||
// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
||||
// This file was generated by swaggo/swag at
|
||||
// 2020-11-11 16:32:47.799676915 +0100 CET m=+0.126448240
|
||||
// 2020-11-19 17:20:42.626650342 +0100 CET m=+0.093632886
|
||||
|
||||
package docs
|
||||
|
||||
|
@ -1439,6 +1439,517 @@ var doc = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/results": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"Bearer": []
|
||||
}
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"results"
|
||||
],
|
||||
"summary": "Get all results of scenario",
|
||||
"operationId": "getResults",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Scenario ID",
|
||||
"name": "scenarioID",
|
||||
"in": "query",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Results which belong to scenario",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseResults"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Not found",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Unprocessable entity",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal server error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"Bearer": []
|
||||
}
|
||||
],
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"results"
|
||||
],
|
||||
"summary": "Add a result to a scenario",
|
||||
"operationId": "addResult",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Result to be added incl. ID of Scenario",
|
||||
"name": "inputResult",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/result.addResultRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Result that was added",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseResult"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Not found",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Unprocessable entity",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal server error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/results/{resultID}": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"Bearer": []
|
||||
}
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"results"
|
||||
],
|
||||
"summary": "Get a Result",
|
||||
"operationId": "getResult",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Result ID",
|
||||
"name": "resultID",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Result that was requested",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseResult"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Not found",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Unprocessable entity",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal server error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"put": {
|
||||
"security": [
|
||||
{
|
||||
"Bearer": []
|
||||
}
|
||||
],
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"results"
|
||||
],
|
||||
"summary": "Update a result",
|
||||
"operationId": "updateResult",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Result to be updated",
|
||||
"name": "inputResult",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/result.updateResultRequest"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Result ID",
|
||||
"name": "resultID",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Result that was updated",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseResult"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Not found",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Unprocessable entity",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal server error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"security": [
|
||||
{
|
||||
"Bearer": []
|
||||
}
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"results"
|
||||
],
|
||||
"summary": "Delete a Result",
|
||||
"operationId": "deleteResult",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Result ID",
|
||||
"name": "resultID",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Result that was deleted",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseResult"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Not found",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Unprocessable entity",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal server error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/results/{resultID}/file": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"Bearer": []
|
||||
}
|
||||
],
|
||||
"consumes": [
|
||||
"text/plain",
|
||||
"text/csv",
|
||||
"application/gzip",
|
||||
"application/x-gtar",
|
||||
"application/x-tar",
|
||||
"application/x-ustar",
|
||||
"application/zip",
|
||||
"application/msexcel",
|
||||
"application/xml",
|
||||
"application/x-bag"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"results"
|
||||
],
|
||||
"summary": "Upload a result file to the DB and associate it with scenario and result",
|
||||
"operationId": "addResultFile",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "file",
|
||||
"description": "File to be uploaded",
|
||||
"name": "inputFile",
|
||||
"in": "formData",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Result ID",
|
||||
"name": "resultID",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Result that was updated",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseResult"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Not found",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Unprocessable entity",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal server error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/results/{resultID}/file/{fileID}": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"Bearer": []
|
||||
}
|
||||
],
|
||||
"produces": [
|
||||
"text/plain",
|
||||
"text/csv",
|
||||
"application/gzip",
|
||||
"application/x-gtar",
|
||||
"application/x-tar",
|
||||
"application/x-ustar",
|
||||
"application/zip",
|
||||
"application/msexcel",
|
||||
"application/xml",
|
||||
"application/x-bag"
|
||||
],
|
||||
"tags": [
|
||||
"results"
|
||||
],
|
||||
"summary": "Download a result file",
|
||||
"operationId": "getResultFile",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Result ID",
|
||||
"name": "resultID",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "ID of the file to download",
|
||||
"name": "fileID",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "File that was requested",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseFile"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Not found",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Unprocessable entity",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal server error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"security": [
|
||||
{
|
||||
"Bearer": []
|
||||
}
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"results"
|
||||
],
|
||||
"summary": "Delete a result file",
|
||||
"operationId": "deleteResultFile",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Result ID",
|
||||
"name": "resultID",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "ID of the file to delete",
|
||||
"name": "fileID",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Result for which file was deleted",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseResult"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Not found",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Unprocessable entity",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal server error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/scenarios": {
|
||||
"get": {
|
||||
"security": [
|
||||
|
@ -2889,6 +3400,9 @@ var doc = `{
|
|||
"database.ComponentConfiguration": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"createdAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"fileIDs": {
|
||||
"description": "Array of file IDs used by the component configuration",
|
||||
"type": "string"
|
||||
|
@ -2919,12 +3433,18 @@ var doc = `{
|
|||
"startParameters": {
|
||||
"description": "Start parameters of Component Configuration as JSON",
|
||||
"type": "string"
|
||||
},
|
||||
"updatedAt": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"database.Dashboard": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"createdAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"grid": {
|
||||
"description": "Grid of dashboard",
|
||||
"type": "integer"
|
||||
|
@ -2943,12 +3463,18 @@ var doc = `{
|
|||
"scenarioID": {
|
||||
"description": "ID of scenario to which dashboard belongs",
|
||||
"type": "integer"
|
||||
},
|
||||
"updatedAt": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"database.File": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"createdAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"date": {
|
||||
"description": "Last modification time of file",
|
||||
"type": "string"
|
||||
|
@ -2956,6 +3482,14 @@ var doc = `{
|
|||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"imageHeight": {
|
||||
"description": "Height of an image file in pixels (optional)",
|
||||
"type": "integer"
|
||||
},
|
||||
"imageWidth": {
|
||||
"description": "Width of an image file in pixels (optional)",
|
||||
"type": "integer"
|
||||
},
|
||||
"name": {
|
||||
"description": "Name of file",
|
||||
"type": "string"
|
||||
|
@ -2971,6 +3505,9 @@ var doc = `{
|
|||
"type": {
|
||||
"description": "Type of file (MIME type)",
|
||||
"type": "string"
|
||||
},
|
||||
"updatedAt": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -2985,6 +3522,9 @@ var doc = `{
|
|||
"description": "Category of IC (simulator, gateway, database, etc.)",
|
||||
"type": "string"
|
||||
},
|
||||
"createdAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"description": "Description of the IC",
|
||||
"type": "string"
|
||||
|
@ -3020,6 +3560,9 @@ var doc = `{
|
|||
"description": "Type of IC (RTDS, VILLASnode, RTDS, etc.)",
|
||||
"type": "string"
|
||||
},
|
||||
"updatedAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"uptime": {
|
||||
"description": "Uptime of the IC",
|
||||
"type": "number"
|
||||
|
@ -3034,9 +3577,42 @@ var doc = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"database.Result": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"configSnapshots": {
|
||||
"description": "JSON snapshots of component configurations used to generate results",
|
||||
"type": "string"
|
||||
},
|
||||
"createdAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"description": "Description of results",
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"resultFileIDs": {
|
||||
"description": "File IDs associated with result",
|
||||
"type": "string"
|
||||
},
|
||||
"scenarioID": {
|
||||
"description": "ID of Scenario to which result belongs",
|
||||
"type": "integer"
|
||||
},
|
||||
"updatedAt": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"database.Scenario": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"createdAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
|
@ -3051,6 +3627,9 @@ var doc = `{
|
|||
"startParameters": {
|
||||
"description": "Start parameters of scenario as JSON",
|
||||
"type": "string"
|
||||
},
|
||||
"updatedAt": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -3061,6 +3640,9 @@ var doc = `{
|
|||
"description": "ID of Component Configuration",
|
||||
"type": "integer"
|
||||
},
|
||||
"createdAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"direction": {
|
||||
"description": "Direction of the signal (in or out)",
|
||||
"type": "string"
|
||||
|
@ -3083,6 +3665,9 @@ var doc = `{
|
|||
"unit": {
|
||||
"description": "Unit of Signal",
|
||||
"type": "string"
|
||||
},
|
||||
"updatedAt": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -3093,6 +3678,9 @@ var doc = `{
|
|||
"description": "Indicating status of user (false means user is inactive and should not be able to login)",
|
||||
"type": "boolean"
|
||||
},
|
||||
"createdAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
|
@ -3104,6 +3692,9 @@ var doc = `{
|
|||
"description": "Role of user",
|
||||
"type": "string"
|
||||
},
|
||||
"updatedAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"username": {
|
||||
"description": "Username of user",
|
||||
"type": "string"
|
||||
|
@ -3113,6 +3704,9 @@ var doc = `{
|
|||
"database.Widget": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"createdAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"customProperties": {
|
||||
"description": "Custom properties of widget as JSON string",
|
||||
"type": "string"
|
||||
|
@ -3152,6 +3746,9 @@ var doc = `{
|
|||
"description": "Type of widget",
|
||||
"type": "string"
|
||||
},
|
||||
"updatedAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"width": {
|
||||
"description": "Width of widget",
|
||||
"type": "integer"
|
||||
|
@ -3279,6 +3876,26 @@ var doc = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"docs.ResponseResult": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"result": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/database.Result"
|
||||
}
|
||||
}
|
||||
},
|
||||
"docs.ResponseResults": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"results": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/database.Result"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"docs.ResponseScenario": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
@ -3462,6 +4079,65 @@ var doc = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"result.addResultRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"result": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/result.validNewResult"
|
||||
}
|
||||
}
|
||||
},
|
||||
"result.updateResultRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"result": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/result.validUpdatedResult"
|
||||
}
|
||||
}
|
||||
},
|
||||
"result.validNewResult": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"ConfigSnapshots",
|
||||
"ScenarioID"
|
||||
],
|
||||
"properties": {
|
||||
"ConfigSnapshots": {
|
||||
"type": "string"
|
||||
},
|
||||
"Description": {
|
||||
"type": "string"
|
||||
},
|
||||
"ResultFileIDs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"ScenarioID": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"result.validUpdatedResult": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"configSnapshots": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"resultFileIDs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"scenario.addScenarioRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
|
@ -101,3 +101,11 @@ type ResponseFiles struct {
|
|||
type ResponseFile struct {
|
||||
file database.File
|
||||
}
|
||||
|
||||
type ResponseResults struct {
|
||||
results []database.Result
|
||||
}
|
||||
|
||||
type ResponseResult struct {
|
||||
result database.Result
|
||||
}
|
||||
|
|
|
@ -1422,6 +1422,517 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"/results": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"Bearer": []
|
||||
}
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"results"
|
||||
],
|
||||
"summary": "Get all results of scenario",
|
||||
"operationId": "getResults",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Scenario ID",
|
||||
"name": "scenarioID",
|
||||
"in": "query",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Results which belong to scenario",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseResults"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Not found",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Unprocessable entity",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal server error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"Bearer": []
|
||||
}
|
||||
],
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"results"
|
||||
],
|
||||
"summary": "Add a result to a scenario",
|
||||
"operationId": "addResult",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Result to be added incl. ID of Scenario",
|
||||
"name": "inputResult",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/result.addResultRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Result that was added",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseResult"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Not found",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Unprocessable entity",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal server error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/results/{resultID}": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"Bearer": []
|
||||
}
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"results"
|
||||
],
|
||||
"summary": "Get a Result",
|
||||
"operationId": "getResult",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Result ID",
|
||||
"name": "resultID",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Result that was requested",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseResult"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Not found",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Unprocessable entity",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal server error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"put": {
|
||||
"security": [
|
||||
{
|
||||
"Bearer": []
|
||||
}
|
||||
],
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"results"
|
||||
],
|
||||
"summary": "Update a result",
|
||||
"operationId": "updateResult",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Result to be updated",
|
||||
"name": "inputResult",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/result.updateResultRequest"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Result ID",
|
||||
"name": "resultID",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Result that was updated",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseResult"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Not found",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Unprocessable entity",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal server error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"security": [
|
||||
{
|
||||
"Bearer": []
|
||||
}
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"results"
|
||||
],
|
||||
"summary": "Delete a Result",
|
||||
"operationId": "deleteResult",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Result ID",
|
||||
"name": "resultID",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Result that was deleted",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseResult"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Not found",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Unprocessable entity",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal server error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/results/{resultID}/file": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"Bearer": []
|
||||
}
|
||||
],
|
||||
"consumes": [
|
||||
"text/plain",
|
||||
"text/csv",
|
||||
"application/gzip",
|
||||
"application/x-gtar",
|
||||
"application/x-tar",
|
||||
"application/x-ustar",
|
||||
"application/zip",
|
||||
"application/msexcel",
|
||||
"application/xml",
|
||||
"application/x-bag"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"results"
|
||||
],
|
||||
"summary": "Upload a result file to the DB and associate it with scenario and result",
|
||||
"operationId": "addResultFile",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "file",
|
||||
"description": "File to be uploaded",
|
||||
"name": "inputFile",
|
||||
"in": "formData",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Result ID",
|
||||
"name": "resultID",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Result that was updated",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseResult"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Not found",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Unprocessable entity",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal server error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/results/{resultID}/file/{fileID}": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"Bearer": []
|
||||
}
|
||||
],
|
||||
"produces": [
|
||||
"text/plain",
|
||||
"text/csv",
|
||||
"application/gzip",
|
||||
"application/x-gtar",
|
||||
"application/x-tar",
|
||||
"application/x-ustar",
|
||||
"application/zip",
|
||||
"application/msexcel",
|
||||
"application/xml",
|
||||
"application/x-bag"
|
||||
],
|
||||
"tags": [
|
||||
"results"
|
||||
],
|
||||
"summary": "Download a result file",
|
||||
"operationId": "getResultFile",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Result ID",
|
||||
"name": "resultID",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "ID of the file to download",
|
||||
"name": "fileID",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "File that was requested",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseFile"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Not found",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Unprocessable entity",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal server error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"security": [
|
||||
{
|
||||
"Bearer": []
|
||||
}
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"results"
|
||||
],
|
||||
"summary": "Delete a result file",
|
||||
"operationId": "deleteResultFile",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Result ID",
|
||||
"name": "resultID",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "ID of the file to delete",
|
||||
"name": "fileID",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Result for which file was deleted",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseResult"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Not found",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Unprocessable entity",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal server error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/docs.ResponseError"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/scenarios": {
|
||||
"get": {
|
||||
"security": [
|
||||
|
@ -2872,6 +3383,9 @@
|
|||
"database.ComponentConfiguration": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"createdAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"fileIDs": {
|
||||
"description": "Array of file IDs used by the component configuration",
|
||||
"type": "string"
|
||||
|
@ -2902,12 +3416,18 @@
|
|||
"startParameters": {
|
||||
"description": "Start parameters of Component Configuration as JSON",
|
||||
"type": "string"
|
||||
},
|
||||
"updatedAt": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"database.Dashboard": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"createdAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"grid": {
|
||||
"description": "Grid of dashboard",
|
||||
"type": "integer"
|
||||
|
@ -2926,12 +3446,18 @@
|
|||
"scenarioID": {
|
||||
"description": "ID of scenario to which dashboard belongs",
|
||||
"type": "integer"
|
||||
},
|
||||
"updatedAt": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"database.File": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"createdAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"date": {
|
||||
"description": "Last modification time of file",
|
||||
"type": "string"
|
||||
|
@ -2939,6 +3465,14 @@
|
|||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"imageHeight": {
|
||||
"description": "Height of an image file in pixels (optional)",
|
||||
"type": "integer"
|
||||
},
|
||||
"imageWidth": {
|
||||
"description": "Width of an image file in pixels (optional)",
|
||||
"type": "integer"
|
||||
},
|
||||
"name": {
|
||||
"description": "Name of file",
|
||||
"type": "string"
|
||||
|
@ -2954,6 +3488,9 @@
|
|||
"type": {
|
||||
"description": "Type of file (MIME type)",
|
||||
"type": "string"
|
||||
},
|
||||
"updatedAt": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -2968,6 +3505,9 @@
|
|||
"description": "Category of IC (simulator, gateway, database, etc.)",
|
||||
"type": "string"
|
||||
},
|
||||
"createdAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"description": "Description of the IC",
|
||||
"type": "string"
|
||||
|
@ -3003,6 +3543,9 @@
|
|||
"description": "Type of IC (RTDS, VILLASnode, RTDS, etc.)",
|
||||
"type": "string"
|
||||
},
|
||||
"updatedAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"uptime": {
|
||||
"description": "Uptime of the IC",
|
||||
"type": "number"
|
||||
|
@ -3017,9 +3560,42 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"database.Result": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"configSnapshots": {
|
||||
"description": "JSON snapshots of component configurations used to generate results",
|
||||
"type": "string"
|
||||
},
|
||||
"createdAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"description": "Description of results",
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"resultFileIDs": {
|
||||
"description": "File IDs associated with result",
|
||||
"type": "string"
|
||||
},
|
||||
"scenarioID": {
|
||||
"description": "ID of Scenario to which result belongs",
|
||||
"type": "integer"
|
||||
},
|
||||
"updatedAt": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"database.Scenario": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"createdAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
|
@ -3034,6 +3610,9 @@
|
|||
"startParameters": {
|
||||
"description": "Start parameters of scenario as JSON",
|
||||
"type": "string"
|
||||
},
|
||||
"updatedAt": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -3044,6 +3623,9 @@
|
|||
"description": "ID of Component Configuration",
|
||||
"type": "integer"
|
||||
},
|
||||
"createdAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"direction": {
|
||||
"description": "Direction of the signal (in or out)",
|
||||
"type": "string"
|
||||
|
@ -3066,6 +3648,9 @@
|
|||
"unit": {
|
||||
"description": "Unit of Signal",
|
||||
"type": "string"
|
||||
},
|
||||
"updatedAt": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -3076,6 +3661,9 @@
|
|||
"description": "Indicating status of user (false means user is inactive and should not be able to login)",
|
||||
"type": "boolean"
|
||||
},
|
||||
"createdAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
|
@ -3087,6 +3675,9 @@
|
|||
"description": "Role of user",
|
||||
"type": "string"
|
||||
},
|
||||
"updatedAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"username": {
|
||||
"description": "Username of user",
|
||||
"type": "string"
|
||||
|
@ -3096,6 +3687,9 @@
|
|||
"database.Widget": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"createdAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"customProperties": {
|
||||
"description": "Custom properties of widget as JSON string",
|
||||
"type": "string"
|
||||
|
@ -3135,6 +3729,9 @@
|
|||
"description": "Type of widget",
|
||||
"type": "string"
|
||||
},
|
||||
"updatedAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"width": {
|
||||
"description": "Width of widget",
|
||||
"type": "integer"
|
||||
|
@ -3262,6 +3859,26 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"docs.ResponseResult": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"result": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/database.Result"
|
||||
}
|
||||
}
|
||||
},
|
||||
"docs.ResponseResults": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"results": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/database.Result"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"docs.ResponseScenario": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
@ -3445,6 +4062,65 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"result.addResultRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"result": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/result.validNewResult"
|
||||
}
|
||||
}
|
||||
},
|
||||
"result.updateResultRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"result": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/result.validUpdatedResult"
|
||||
}
|
||||
}
|
||||
},
|
||||
"result.validNewResult": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"ConfigSnapshots",
|
||||
"ScenarioID"
|
||||
],
|
||||
"properties": {
|
||||
"ConfigSnapshots": {
|
||||
"type": "string"
|
||||
},
|
||||
"Description": {
|
||||
"type": "string"
|
||||
},
|
||||
"ResultFileIDs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"ScenarioID": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"result.validUpdatedResult": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"configSnapshots": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"resultFileIDs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"scenario.addScenarioRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
|
@ -83,6 +83,8 @@ definitions:
|
|||
type: object
|
||||
database.ComponentConfiguration:
|
||||
properties:
|
||||
createdAt:
|
||||
type: string
|
||||
fileIDs:
|
||||
description: Array of file IDs used by the component configuration
|
||||
type: string
|
||||
|
@ -106,9 +108,13 @@ definitions:
|
|||
startParameters:
|
||||
description: Start parameters of Component Configuration as JSON
|
||||
type: string
|
||||
updatedAt:
|
||||
type: string
|
||||
type: object
|
||||
database.Dashboard:
|
||||
properties:
|
||||
createdAt:
|
||||
type: string
|
||||
grid:
|
||||
description: Grid of dashboard
|
||||
type: integer
|
||||
|
@ -123,14 +129,24 @@ definitions:
|
|||
scenarioID:
|
||||
description: ID of scenario to which dashboard belongs
|
||||
type: integer
|
||||
updatedAt:
|
||||
type: string
|
||||
type: object
|
||||
database.File:
|
||||
properties:
|
||||
createdAt:
|
||||
type: string
|
||||
date:
|
||||
description: Last modification time of file
|
||||
type: string
|
||||
id:
|
||||
type: integer
|
||||
imageHeight:
|
||||
description: Height of an image file in pixels (optional)
|
||||
type: integer
|
||||
imageWidth:
|
||||
description: Width of an image file in pixels (optional)
|
||||
type: integer
|
||||
name:
|
||||
description: Name of file
|
||||
type: string
|
||||
|
@ -143,6 +159,8 @@ definitions:
|
|||
type:
|
||||
description: Type of file (MIME type)
|
||||
type: string
|
||||
updatedAt:
|
||||
type: string
|
||||
type: object
|
||||
database.InfrastructureComponent:
|
||||
properties:
|
||||
|
@ -152,6 +170,8 @@ definitions:
|
|||
category:
|
||||
description: Category of IC (simulator, gateway, database, etc.)
|
||||
type: string
|
||||
createdAt:
|
||||
type: string
|
||||
description:
|
||||
description: Description of the IC
|
||||
type: string
|
||||
|
@ -178,6 +198,8 @@ definitions:
|
|||
type:
|
||||
description: Type of IC (RTDS, VILLASnode, RTDS, etc.)
|
||||
type: string
|
||||
updatedAt:
|
||||
type: string
|
||||
uptime:
|
||||
description: Uptime of the IC
|
||||
type: number
|
||||
|
@ -188,8 +210,31 @@ definitions:
|
|||
description: WebsocketURL if the IC
|
||||
type: string
|
||||
type: object
|
||||
database.Result:
|
||||
properties:
|
||||
configSnapshots:
|
||||
description: JSON snapshots of component configurations used to generate results
|
||||
type: string
|
||||
createdAt:
|
||||
type: string
|
||||
description:
|
||||
description: Description of results
|
||||
type: string
|
||||
id:
|
||||
type: integer
|
||||
resultFileIDs:
|
||||
description: File IDs associated with result
|
||||
type: string
|
||||
scenarioID:
|
||||
description: ID of Scenario to which result belongs
|
||||
type: integer
|
||||
updatedAt:
|
||||
type: string
|
||||
type: object
|
||||
database.Scenario:
|
||||
properties:
|
||||
createdAt:
|
||||
type: string
|
||||
id:
|
||||
type: integer
|
||||
name:
|
||||
|
@ -201,12 +246,16 @@ definitions:
|
|||
startParameters:
|
||||
description: Start parameters of scenario as JSON
|
||||
type: string
|
||||
updatedAt:
|
||||
type: string
|
||||
type: object
|
||||
database.Signal:
|
||||
properties:
|
||||
configID:
|
||||
description: ID of Component Configuration
|
||||
type: integer
|
||||
createdAt:
|
||||
type: string
|
||||
direction:
|
||||
description: Direction of the signal (in or out)
|
||||
type: string
|
||||
|
@ -224,6 +273,8 @@ definitions:
|
|||
unit:
|
||||
description: Unit of Signal
|
||||
type: string
|
||||
updatedAt:
|
||||
type: string
|
||||
type: object
|
||||
database.User:
|
||||
properties:
|
||||
|
@ -231,6 +282,8 @@ definitions:
|
|||
description: Indicating status of user (false means user is inactive and should
|
||||
not be able to login)
|
||||
type: boolean
|
||||
createdAt:
|
||||
type: string
|
||||
id:
|
||||
type: integer
|
||||
mail:
|
||||
|
@ -239,12 +292,16 @@ definitions:
|
|||
role:
|
||||
description: Role of user
|
||||
type: string
|
||||
updatedAt:
|
||||
type: string
|
||||
username:
|
||||
description: Username of user
|
||||
type: string
|
||||
type: object
|
||||
database.Widget:
|
||||
properties:
|
||||
createdAt:
|
||||
type: string
|
||||
customProperties:
|
||||
description: Custom properties of widget as JSON string
|
||||
type: string
|
||||
|
@ -274,6 +331,8 @@ definitions:
|
|||
type:
|
||||
description: Type of widget
|
||||
type: string
|
||||
updatedAt:
|
||||
type: string
|
||||
width:
|
||||
description: Width of widget
|
||||
type: integer
|
||||
|
@ -358,6 +417,19 @@ definitions:
|
|||
$ref: '#/definitions/database.InfrastructureComponent'
|
||||
type: array
|
||||
type: object
|
||||
docs.ResponseResult:
|
||||
properties:
|
||||
result:
|
||||
$ref: '#/definitions/database.Result'
|
||||
type: object
|
||||
type: object
|
||||
docs.ResponseResults:
|
||||
properties:
|
||||
results:
|
||||
items:
|
||||
$ref: '#/definitions/database.Result'
|
||||
type: array
|
||||
type: object
|
||||
docs.ResponseScenario:
|
||||
properties:
|
||||
scenario:
|
||||
|
@ -479,6 +551,45 @@ definitions:
|
|||
WebsocketURL:
|
||||
type: string
|
||||
type: object
|
||||
result.addResultRequest:
|
||||
properties:
|
||||
result:
|
||||
$ref: '#/definitions/result.validNewResult'
|
||||
type: object
|
||||
type: object
|
||||
result.updateResultRequest:
|
||||
properties:
|
||||
result:
|
||||
$ref: '#/definitions/result.validUpdatedResult'
|
||||
type: object
|
||||
type: object
|
||||
result.validNewResult:
|
||||
properties:
|
||||
ConfigSnapshots:
|
||||
type: string
|
||||
Description:
|
||||
type: string
|
||||
ResultFileIDs:
|
||||
items:
|
||||
type: integer
|
||||
type: array
|
||||
ScenarioID:
|
||||
type: integer
|
||||
required:
|
||||
- ConfigSnapshots
|
||||
- ScenarioID
|
||||
type: object
|
||||
result.validUpdatedResult:
|
||||
properties:
|
||||
configSnapshots:
|
||||
type: string
|
||||
description:
|
||||
type: string
|
||||
resultFileIDs:
|
||||
items:
|
||||
type: integer
|
||||
type: array
|
||||
type: object
|
||||
scenario.addScenarioRequest:
|
||||
properties:
|
||||
scenario:
|
||||
|
@ -1616,6 +1727,342 @@ paths:
|
|||
summary: Prometheus metrics endpoint
|
||||
tags:
|
||||
- metrics
|
||||
/results:
|
||||
get:
|
||||
operationId: getResults
|
||||
parameters:
|
||||
- description: Scenario ID
|
||||
in: query
|
||||
name: scenarioID
|
||||
required: true
|
||||
type: integer
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: Results which belong to scenario
|
||||
schema:
|
||||
$ref: '#/definitions/docs.ResponseResults'
|
||||
"404":
|
||||
description: Not found
|
||||
schema:
|
||||
$ref: '#/definitions/docs.ResponseError'
|
||||
"422":
|
||||
description: Unprocessable entity
|
||||
schema:
|
||||
$ref: '#/definitions/docs.ResponseError'
|
||||
"500":
|
||||
description: Internal server error
|
||||
schema:
|
||||
$ref: '#/definitions/docs.ResponseError'
|
||||
security:
|
||||
- Bearer: []
|
||||
summary: Get all results of scenario
|
||||
tags:
|
||||
- results
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
operationId: addResult
|
||||
parameters:
|
||||
- description: Result to be added incl. ID of Scenario
|
||||
in: body
|
||||
name: inputResult
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/result.addResultRequest'
|
||||
type: object
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: Result that was added
|
||||
schema:
|
||||
$ref: '#/definitions/docs.ResponseResult'
|
||||
"400":
|
||||
description: Bad request
|
||||
schema:
|
||||
$ref: '#/definitions/docs.ResponseError'
|
||||
"404":
|
||||
description: Not found
|
||||
schema:
|
||||
$ref: '#/definitions/docs.ResponseError'
|
||||
"422":
|
||||
description: Unprocessable entity
|
||||
schema:
|
||||
$ref: '#/definitions/docs.ResponseError'
|
||||
"500":
|
||||
description: Internal server error
|
||||
schema:
|
||||
$ref: '#/definitions/docs.ResponseError'
|
||||
security:
|
||||
- Bearer: []
|
||||
summary: Add a result to a scenario
|
||||
tags:
|
||||
- results
|
||||
/results/{resultID}:
|
||||
delete:
|
||||
operationId: deleteResult
|
||||
parameters:
|
||||
- description: Result ID
|
||||
in: path
|
||||
name: resultID
|
||||
required: true
|
||||
type: integer
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: Result that was deleted
|
||||
schema:
|
||||
$ref: '#/definitions/docs.ResponseResult'
|
||||
"400":
|
||||
description: Bad request
|
||||
schema:
|
||||
$ref: '#/definitions/docs.ResponseError'
|
||||
"404":
|
||||
description: Not found
|
||||
schema:
|
||||
$ref: '#/definitions/docs.ResponseError'
|
||||
"422":
|
||||
description: Unprocessable entity
|
||||
schema:
|
||||
$ref: '#/definitions/docs.ResponseError'
|
||||
"500":
|
||||
description: Internal server error
|
||||
schema:
|
||||
$ref: '#/definitions/docs.ResponseError'
|
||||
security:
|
||||
- Bearer: []
|
||||
summary: Delete a Result
|
||||
tags:
|
||||
- results
|
||||
get:
|
||||
operationId: getResult
|
||||
parameters:
|
||||
- description: Result ID
|
||||
in: path
|
||||
name: resultID
|
||||
required: true
|
||||
type: integer
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: Result that was requested
|
||||
schema:
|
||||
$ref: '#/definitions/docs.ResponseResult'
|
||||
"400":
|
||||
description: Bad request
|
||||
schema:
|
||||
$ref: '#/definitions/docs.ResponseError'
|
||||
"404":
|
||||
description: Not found
|
||||
schema:
|
||||
$ref: '#/definitions/docs.ResponseError'
|
||||
"422":
|
||||
description: Unprocessable entity
|
||||
schema:
|
||||
$ref: '#/definitions/docs.ResponseError'
|
||||
"500":
|
||||
description: Internal server error
|
||||
schema:
|
||||
$ref: '#/definitions/docs.ResponseError'
|
||||
security:
|
||||
- Bearer: []
|
||||
summary: Get a Result
|
||||
tags:
|
||||
- results
|
||||
put:
|
||||
consumes:
|
||||
- application/json
|
||||
operationId: updateResult
|
||||
parameters:
|
||||
- description: Result to be updated
|
||||
in: body
|
||||
name: inputResult
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/result.updateResultRequest'
|
||||
type: object
|
||||
- description: Result ID
|
||||
in: path
|
||||
name: resultID
|
||||
required: true
|
||||
type: integer
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: Result that was updated
|
||||
schema:
|
||||
$ref: '#/definitions/docs.ResponseResult'
|
||||
"400":
|
||||
description: Bad request
|
||||
schema:
|
||||
$ref: '#/definitions/docs.ResponseError'
|
||||
"404":
|
||||
description: Not found
|
||||
schema:
|
||||
$ref: '#/definitions/docs.ResponseError'
|
||||
"422":
|
||||
description: Unprocessable entity
|
||||
schema:
|
||||
$ref: '#/definitions/docs.ResponseError'
|
||||
"500":
|
||||
description: Internal server error
|
||||
schema:
|
||||
$ref: '#/definitions/docs.ResponseError'
|
||||
security:
|
||||
- Bearer: []
|
||||
summary: Update a result
|
||||
tags:
|
||||
- results
|
||||
/results/{resultID}/file:
|
||||
post:
|
||||
consumes:
|
||||
- text/plain
|
||||
- text/csv
|
||||
- application/gzip
|
||||
- application/x-gtar
|
||||
- application/x-tar
|
||||
- application/x-ustar
|
||||
- application/zip
|
||||
- application/msexcel
|
||||
- application/xml
|
||||
- application/x-bag
|
||||
operationId: addResultFile
|
||||
parameters:
|
||||
- description: File to be uploaded
|
||||
in: formData
|
||||
name: inputFile
|
||||
required: true
|
||||
type: file
|
||||
- description: Result ID
|
||||
in: path
|
||||
name: resultID
|
||||
required: true
|
||||
type: integer
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: Result that was updated
|
||||
schema:
|
||||
$ref: '#/definitions/docs.ResponseResult'
|
||||
"400":
|
||||
description: Bad request
|
||||
schema:
|
||||
$ref: '#/definitions/docs.ResponseError'
|
||||
"404":
|
||||
description: Not found
|
||||
schema:
|
||||
$ref: '#/definitions/docs.ResponseError'
|
||||
"422":
|
||||
description: Unprocessable entity
|
||||
schema:
|
||||
$ref: '#/definitions/docs.ResponseError'
|
||||
"500":
|
||||
description: Internal server error
|
||||
schema:
|
||||
$ref: '#/definitions/docs.ResponseError'
|
||||
security:
|
||||
- Bearer: []
|
||||
summary: Upload a result file to the DB and associate it with scenario and result
|
||||
tags:
|
||||
- results
|
||||
/results/{resultID}/file/{fileID}:
|
||||
delete:
|
||||
operationId: deleteResultFile
|
||||
parameters:
|
||||
- description: Result ID
|
||||
in: path
|
||||
name: resultID
|
||||
required: true
|
||||
type: integer
|
||||
- description: ID of the file to delete
|
||||
in: path
|
||||
name: fileID
|
||||
required: true
|
||||
type: integer
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: Result for which file was deleted
|
||||
schema:
|
||||
$ref: '#/definitions/docs.ResponseResult'
|
||||
"400":
|
||||
description: Bad request
|
||||
schema:
|
||||
$ref: '#/definitions/docs.ResponseError'
|
||||
"404":
|
||||
description: Not found
|
||||
schema:
|
||||
$ref: '#/definitions/docs.ResponseError'
|
||||
"422":
|
||||
description: Unprocessable entity
|
||||
schema:
|
||||
$ref: '#/definitions/docs.ResponseError'
|
||||
"500":
|
||||
description: Internal server error
|
||||
schema:
|
||||
$ref: '#/definitions/docs.ResponseError'
|
||||
security:
|
||||
- Bearer: []
|
||||
summary: Delete a result file
|
||||
tags:
|
||||
- results
|
||||
get:
|
||||
operationId: getResultFile
|
||||
parameters:
|
||||
- description: Result ID
|
||||
in: path
|
||||
name: resultID
|
||||
required: true
|
||||
type: integer
|
||||
- description: ID of the file to download
|
||||
in: path
|
||||
name: fileID
|
||||
required: true
|
||||
type: integer
|
||||
produces:
|
||||
- text/plain
|
||||
- text/csv
|
||||
- application/gzip
|
||||
- application/x-gtar
|
||||
- application/x-tar
|
||||
- application/x-ustar
|
||||
- application/zip
|
||||
- application/msexcel
|
||||
- application/xml
|
||||
- application/x-bag
|
||||
responses:
|
||||
"200":
|
||||
description: File that was requested
|
||||
schema:
|
||||
$ref: '#/definitions/docs.ResponseFile'
|
||||
"400":
|
||||
description: Bad request
|
||||
schema:
|
||||
$ref: '#/definitions/docs.ResponseError'
|
||||
"404":
|
||||
description: Not found
|
||||
schema:
|
||||
$ref: '#/definitions/docs.ResponseError'
|
||||
"422":
|
||||
description: Unprocessable entity
|
||||
schema:
|
||||
$ref: '#/definitions/docs.ResponseError'
|
||||
"500":
|
||||
description: Internal server error
|
||||
schema:
|
||||
$ref: '#/definitions/docs.ResponseError'
|
||||
security:
|
||||
- Bearer: []
|
||||
summary: Download a result file
|
||||
tags:
|
||||
- results
|
||||
/scenarios:
|
||||
get:
|
||||
operationId: getScenarios
|
||||
|
|
|
@ -88,8 +88,10 @@ func (d *Dashboard) delete() error {
|
|||
}
|
||||
|
||||
// remove association between Dashboard and Scenario
|
||||
// Dashboard itself is not deleted from DB, it remains as "dangling"
|
||||
err = db.Model(&sim).Association("Dashboards").Delete(d).Error
|
||||
|
||||
// Dashboard itself is not deleted from DB, it remains as "dangling"
|
||||
// TODO: delete dashboard and associated widgets
|
||||
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ import (
|
|||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/healthz"
|
||||
infrastructure_component "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/infrastructure-component"
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/metrics"
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/result"
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/scenario"
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/signal"
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/user"
|
||||
|
@ -68,6 +69,7 @@ func RegisterEndpoints(router *gin.Engine, api *gin.RouterGroup) {
|
|||
file.RegisterFileEndpoints(api.Group("/files"))
|
||||
user.RegisterUserEndpoints(api.Group("/users"))
|
||||
infrastructure_component.RegisterICEndpoints(api.Group("/ic"))
|
||||
result.RegisterResultEndpoints(api.Group("/results"))
|
||||
|
||||
router.GET("swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
|
||||
|
||||
|
|
281
routes/result/result_endpoints.go
Normal file
281
routes/result/result_endpoints.go
Normal file
|
@ -0,0 +1,281 @@
|
|||
package result
|
||||
|
||||
import (
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/database"
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/helper"
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/scenario"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func RegisterResultEndpoints(r *gin.RouterGroup) {
|
||||
r.GET("", getResults)
|
||||
r.POST("", addResult)
|
||||
r.PUT("/:resultID", updateResult)
|
||||
r.GET("/:resultID", getResult)
|
||||
r.DELETE("/:scenarioID", deleteResult)
|
||||
r.POST("/:resultID/file", addResultFile)
|
||||
r.GET("/:resultID/file/:fileID", getResultFile)
|
||||
r.DELETE("/:resultID/file/:fileID", deleteResultFile)
|
||||
}
|
||||
|
||||
// getResults godoc
|
||||
// @Summary Get all results of scenario
|
||||
// @ID getResults
|
||||
// @Produce json
|
||||
// @Tags results
|
||||
// @Success 200 {object} docs.ResponseResults "Results which belong to scenario"
|
||||
// @Failure 404 {object} docs.ResponseError "Not found"
|
||||
// @Failure 422 {object} docs.ResponseError "Unprocessable entity"
|
||||
// @Failure 500 {object} docs.ResponseError "Internal server error"
|
||||
// @Param scenarioID query int true "Scenario ID"
|
||||
// @Router /results [get]
|
||||
// @Security Bearer
|
||||
func getResults(c *gin.Context) {
|
||||
|
||||
ok, scenario := scenario.CheckPermissions(c, database.Read, "query", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
db := database.GetDB()
|
||||
var result []database.Result
|
||||
err := db.Order("ID asc").Model(scenario).Related(&result, "Results").Error
|
||||
if !helper.DBError(c, err) {
|
||||
c.JSON(http.StatusOK, gin.H{"result": result})
|
||||
}
|
||||
}
|
||||
|
||||
// addResult godoc
|
||||
// @Summary Add a result to a scenario
|
||||
// @ID addResult
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Tags results
|
||||
// @Success 200 {object} docs.ResponseResult "Result that was added"
|
||||
// @Failure 400 {object} docs.ResponseError "Bad request"
|
||||
// @Failure 404 {object} docs.ResponseError "Not found"
|
||||
// @Failure 422 {object} docs.ResponseError "Unprocessable entity"
|
||||
// @Failure 500 {object} docs.ResponseError "Internal server error"
|
||||
// @Param inputResult body result.addResultRequest true "Result to be added incl. ID of Scenario"
|
||||
// @Router /results [post]
|
||||
// @Security Bearer
|
||||
func addResult(c *gin.Context) {
|
||||
|
||||
// bind request to JSON
|
||||
var req addResultRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
helper.BadRequestError(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Validate the request
|
||||
if err := req.validate(); err != nil {
|
||||
helper.UnprocessableEntityError(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Create the new result from the request
|
||||
newResult := req.createResult()
|
||||
|
||||
// Check if user is allowed to modify scenario specified in request
|
||||
ok, _ := scenario.CheckPermissions(c, database.Update, "body", int(newResult.ScenarioID))
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
// add result to DB and add association to scenario
|
||||
err := newResult.addToScenario()
|
||||
if !helper.DBError(c, err) {
|
||||
c.JSON(http.StatusOK, gin.H{"result": newResult.Result})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// updateResult godoc
|
||||
// @Summary Update a result
|
||||
// @ID updateResult
|
||||
// @Tags results
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} docs.ResponseResult "Result that was updated"
|
||||
// @Failure 400 {object} docs.ResponseError "Bad request"
|
||||
// @Failure 404 {object} docs.ResponseError "Not found"
|
||||
// @Failure 422 {object} docs.ResponseError "Unprocessable entity"
|
||||
// @Failure 500 {object} docs.ResponseError "Internal server error"
|
||||
// @Param inputResult body result.updateResultRequest true "Result to be updated"
|
||||
// @Param resultID path int true "Result ID"
|
||||
// @Router /results/{resultID} [put]
|
||||
// @Security Bearer
|
||||
func updateResult(c *gin.Context) {
|
||||
|
||||
ok, oldResult := CheckPermissions(c, database.Update, "path", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
var req updateResultRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
helper.BadRequestError(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Validate the request
|
||||
if err := req.Result.validate(); err != nil {
|
||||
helper.BadRequestError(c, err.Error())
|
||||
return
|
||||
}
|
||||
// Create the updatedResult from oldResult
|
||||
updatedResult := req.updatedResult(oldResult)
|
||||
|
||||
// update the Result in the DB
|
||||
err := oldResult.update(updatedResult)
|
||||
if !helper.DBError(c, err) {
|
||||
c.JSON(http.StatusOK, gin.H{"result": updatedResult.Result})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// getResult godoc
|
||||
// @Summary Get a Result
|
||||
// @ID getResult
|
||||
// @Tags results
|
||||
// @Produce json
|
||||
// @Success 200 {object} docs.ResponseResult "Result that was requested"
|
||||
// @Failure 400 {object} docs.ResponseError "Bad request"
|
||||
// @Failure 404 {object} docs.ResponseError "Not found"
|
||||
// @Failure 422 {object} docs.ResponseError "Unprocessable entity"
|
||||
// @Failure 500 {object} docs.ResponseError "Internal server error"
|
||||
// @Param resultID path int true "Result ID"
|
||||
// @Router /results/{resultID} [get]
|
||||
// @Security Bearer
|
||||
func getResult(c *gin.Context) {
|
||||
|
||||
ok, result := CheckPermissions(c, database.Read, "path", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"result": result.Result})
|
||||
}
|
||||
|
||||
// deleteResult godoc
|
||||
// @Summary Delete a Result
|
||||
// @ID deleteResult
|
||||
// @Tags results
|
||||
// @Produce json
|
||||
// @Success 200 {object} docs.ResponseResult "Result that was deleted"
|
||||
// @Failure 400 {object} docs.ResponseError "Bad request"
|
||||
// @Failure 404 {object} docs.ResponseError "Not found"
|
||||
// @Failure 422 {object} docs.ResponseError "Unprocessable entity"
|
||||
// @Failure 500 {object} docs.ResponseError "Internal server error"
|
||||
// @Param resultID path int true "Result ID"
|
||||
// @Router /results/{resultID} [delete]
|
||||
// @Security Bearer
|
||||
func deleteResult(c *gin.Context) {
|
||||
ok, result := CheckPermissions(c, database.Delete, "path", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
err := result.delete()
|
||||
if !helper.DBError(c, err) {
|
||||
c.JSON(http.StatusOK, gin.H{"result": result.Result})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// addResultFile godoc
|
||||
// @Summary Upload a result file to the DB and associate it with scenario and result
|
||||
// @ID addResultFile
|
||||
// @Tags results
|
||||
// @Accept text/plain
|
||||
// @Accept text/csv
|
||||
// @Accept application/gzip
|
||||
// @Accept application/x-gtar
|
||||
// @Accept application/x-tar
|
||||
// @Accept application/x-ustar
|
||||
// @Accept application/zip
|
||||
// @Accept application/msexcel
|
||||
// @Accept application/xml
|
||||
// @Accept application/x-bag
|
||||
// @Produce json
|
||||
// @Success 200 {object} docs.ResponseResult "Result that was updated"
|
||||
// @Failure 400 {object} docs.ResponseError "Bad request"
|
||||
// @Failure 404 {object} docs.ResponseError "Not found"
|
||||
// @Failure 422 {object} docs.ResponseError "Unprocessable entity"
|
||||
// @Failure 500 {object} docs.ResponseError "Internal server error"
|
||||
// @Param inputFile formData file true "File to be uploaded"
|
||||
// @Param resultID path int true "Result ID"
|
||||
// @Router /results/{resultID}/file [post]
|
||||
// @Security Bearer
|
||||
func addResultFile(c *gin.Context) {
|
||||
ok, _ := CheckPermissions(c, database.Update, "path", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
// TODO check permissions of scenario first (file will be added to scenario)
|
||||
|
||||
// TODO add file to DB, associate with scenario and add file ID to result
|
||||
|
||||
}
|
||||
|
||||
// getResultFile godoc
|
||||
// @Summary Download a result file
|
||||
// @ID getResultFile
|
||||
// @Tags results
|
||||
// @Produce text/plain
|
||||
// @Produce text/csv
|
||||
// @Produce application/gzip
|
||||
// @Produce application/x-gtar
|
||||
// @Produce application/x-tar
|
||||
// @Produce application/x-ustar
|
||||
// @Produce application/zip
|
||||
// @Produce application/msexcel
|
||||
// @Produce application/xml
|
||||
// @Produce application/x-bag
|
||||
// @Success 200 {object} docs.ResponseFile "File that was requested"
|
||||
// @Failure 400 {object} docs.ResponseError "Bad request"
|
||||
// @Failure 404 {object} docs.ResponseError "Not found"
|
||||
// @Failure 422 {object} docs.ResponseError "Unprocessable entity"
|
||||
// @Failure 500 {object} docs.ResponseError "Internal server error"
|
||||
// @Param resultID path int true "Result ID"
|
||||
// @Param fileID path int true "ID of the file to download"
|
||||
// @Router /results/{resultID}/file/{fileID} [get]
|
||||
// @Security Bearer
|
||||
func getResultFile(c *gin.Context) {
|
||||
|
||||
// check access
|
||||
ok, _ := CheckPermissions(c, database.Read, "path", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
// TODO download result file
|
||||
}
|
||||
|
||||
// deleteResultFile godoc
|
||||
// @Summary Delete a result file
|
||||
// @ID deleteResultFile
|
||||
// @Tags results
|
||||
// @Produce json
|
||||
// @Success 200 {object} docs.ResponseResult "Result for which file was deleted"
|
||||
// @Failure 400 {object} docs.ResponseError "Bad request"
|
||||
// @Failure 404 {object} docs.ResponseError "Not found"
|
||||
// @Failure 422 {object} docs.ResponseError "Unprocessable entity"
|
||||
// @Failure 500 {object} docs.ResponseError "Internal server error"
|
||||
// @Param resultID path int true "Result ID"
|
||||
// @Param fileID path int true "ID of the file to delete"
|
||||
// @Router /results/{resultID}/file/{fileID} [delete]
|
||||
// @Security Bearer
|
||||
func deleteResultFile(c *gin.Context) {
|
||||
// TODO check access to scenario (file deletion) first
|
||||
|
||||
// check access
|
||||
ok, _ := CheckPermissions(c, database.Update, "path", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
}
|
75
routes/result/result_methods.go
Normal file
75
routes/result/result_methods.go
Normal file
|
@ -0,0 +1,75 @@
|
|||
package result
|
||||
|
||||
import (
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/database"
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/scenario"
|
||||
)
|
||||
|
||||
type Result struct {
|
||||
database.Result
|
||||
}
|
||||
|
||||
func (r *Result) save() error {
|
||||
db := database.GetDB()
|
||||
err := db.Create(r).Error
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *Result) ByID(id uint) error {
|
||||
db := database.GetDB()
|
||||
err := db.Find(r, id).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Result) addToScenario() error {
|
||||
db := database.GetDB()
|
||||
var sco scenario.Scenario
|
||||
err := sco.ByID(r.ScenarioID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// save result to DB
|
||||
err = r.save()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// associate result with scenario
|
||||
err = db.Model(&sco).Association("Results").Append(r).Error
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *Result) update(modifiedResult Result) error {
|
||||
|
||||
db := database.GetDB()
|
||||
|
||||
err := db.Model(r).Updates(map[string]interface{}{
|
||||
"Description": modifiedResult.Description,
|
||||
"ConfigSnapshots": modifiedResult.ConfigSnapshots,
|
||||
"ResultFileIDs": modifiedResult.ResultFileIDs,
|
||||
}).Error
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *Result) delete() error {
|
||||
|
||||
db := database.GetDB()
|
||||
var sco scenario.Scenario
|
||||
err := sco.ByID(r.ScenarioID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// remove association between Result and Scenario
|
||||
err = db.Model(&sco).Association("Results").Delete(r).Error
|
||||
|
||||
// TODO delete Result + files (if any)
|
||||
|
||||
return err
|
||||
}
|
37
routes/result/result_middleware.go
Normal file
37
routes/result/result_middleware.go
Normal file
|
@ -0,0 +1,37 @@
|
|||
package result
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/database"
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/helper"
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/scenario"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func CheckPermissions(c *gin.Context, operation database.CRUD, resultIDSource string, resultIDBody int) (bool, Result) {
|
||||
|
||||
var result Result
|
||||
|
||||
err := database.ValidateRole(c, database.ModelResult, operation)
|
||||
if err != nil {
|
||||
helper.UnprocessableEntityError(c, fmt.Sprintf("Access denied (role validation failed): %v", err.Error()))
|
||||
return false, result
|
||||
}
|
||||
|
||||
resultID, err := helper.GetIDOfElement(c, "resultID", resultIDSource, resultIDBody)
|
||||
if err != nil {
|
||||
return false, result
|
||||
}
|
||||
|
||||
err = result.ByID(uint(resultID))
|
||||
if helper.DBError(c, err) {
|
||||
return false, result
|
||||
}
|
||||
|
||||
ok, _ := scenario.CheckPermissions(c, operation, "body", int(result.ScenarioID))
|
||||
if !ok {
|
||||
return false, result
|
||||
}
|
||||
|
||||
return true, result
|
||||
}
|
1
routes/result/result_test.go
Normal file
1
routes/result/result_test.go
Normal file
|
@ -0,0 +1 @@
|
|||
package result
|
63
routes/result/result_validators.go
Normal file
63
routes/result/result_validators.go
Normal file
|
@ -0,0 +1,63 @@
|
|||
package result
|
||||
|
||||
import (
|
||||
"github.com/jinzhu/gorm/dialects/postgres"
|
||||
"gopkg.in/go-playground/validator.v9"
|
||||
)
|
||||
|
||||
var validate *validator.Validate
|
||||
|
||||
type validNewResult struct {
|
||||
Description string `form:"Description" validate:"omitempty"`
|
||||
ResultFileIDs []int64 `form:"ResultFileIDs" validate:"omitempty"`
|
||||
ConfigSnapshots []postgres.Jsonb `form:"ConfigSnapshots" validate:"required"`
|
||||
ScenarioID uint `form:"ScenarioID" validate:"required"`
|
||||
}
|
||||
|
||||
type validUpdatedResult struct {
|
||||
Description string `form:"Description" validate:"omitempty" json:"description"`
|
||||
ResultFileIDs []int64 `form:"ResultFileIDs" validate:"omitempty" json:"resultFileIDs"`
|
||||
ConfigSnapshots []postgres.Jsonb `form:"ConfigSnapshots" validate:"omitempty" json:"configSnapshots"`
|
||||
}
|
||||
|
||||
type addResultRequest struct {
|
||||
Result validNewResult `json:"result"`
|
||||
}
|
||||
|
||||
type updateResultRequest struct {
|
||||
Result validUpdatedResult `json:"result"`
|
||||
}
|
||||
|
||||
func (r *addResultRequest) validate() error {
|
||||
validate = validator.New()
|
||||
errs := validate.Struct(r)
|
||||
return errs
|
||||
}
|
||||
|
||||
func (r *validUpdatedResult) validate() error {
|
||||
validate = validator.New()
|
||||
errs := validate.Struct(r)
|
||||
return errs
|
||||
}
|
||||
|
||||
func (r *addResultRequest) createResult() Result {
|
||||
var s Result
|
||||
|
||||
s.Description = r.Result.Description
|
||||
s.ConfigSnapshots = r.Result.ConfigSnapshots
|
||||
s.ResultFileIDs = r.Result.ResultFileIDs
|
||||
s.ScenarioID = r.Result.ScenarioID
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func (r *updateResultRequest) updatedResult(oldResult Result) Result {
|
||||
// Use the old Result as a basis for the updated Result `s`
|
||||
s := oldResult
|
||||
|
||||
s.Result.Description = r.Result.Description
|
||||
s.ConfigSnapshots = r.Result.ConfigSnapshots
|
||||
s.ResultFileIDs = r.Result.ResultFileIDs
|
||||
|
||||
return s
|
||||
}
|
Loading…
Add table
Reference in a new issue