Commit afb311a8 authored by Sonja Happ's avatar Sonja Happ
Browse files

Merge branch 'file-scenario-association' into 'master'

Change of data model: associate files with scenario instead of widgets and component configs

See merge request !15
parents 0e54b7ba 8b60430d
......@@ -142,6 +142,8 @@ func TestScenarioAssociations(t *testing.T) {
configB := ComponentConfiguration{}
dashboardA := Dashboard{}
dashboardB := Dashboard{}
fileA := File{}
fileB := File{}
// add scenarios to DB
assert.NoError(t, DBpool.Create(&scenarioA).Error)
......@@ -159,6 +161,10 @@ func TestScenarioAssociations(t *testing.T) {
assert.NoError(t, DBpool.Create(&dashboardA).Error)
assert.NoError(t, DBpool.Create(&dashboardB).Error)
// add files to DB
assert.NoError(t, DBpool.Create(&fileA).Error)
assert.NoError(t, DBpool.Create(&fileB).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)
......@@ -166,6 +172,10 @@ func TestScenarioAssociations(t *testing.T) {
assert.NoError(t, DBpool.Model(&scenarioB).Association("Users").Append(&userA).Error)
assert.NoError(t, DBpool.Model(&scenarioB).Association("Users").Append(&userB).Error)
// add Component Configuration has many files associations
assert.NoError(t, DBpool.Model(&scenarioA).Association("Files").Append(&fileA).Error)
assert.NoError(t, DBpool.Model(&scenarioA).Association("Files").Append(&fileB).Error)
// add scenario has many component configurations associations
assert.NoError(t, DBpool.Model(&scenarioA).Association("ComponentConfigurations").Append(&configA).Error)
assert.NoError(t, DBpool.Model(&scenarioA).Association("ComponentConfigurations").Append(&configB).Error)
......@@ -200,6 +210,14 @@ func TestScenarioAssociations(t *testing.T) {
assert.Fail(t, "Scenario Associations",
"Expected to have %v Dashboards. Has %v.", 2, len(dashboards))
}
// Get files of scenario1
var files []File
assert.NoError(t, DBpool.Model(&scenario1).Related(&files, "Files").Error)
if len(files) != 2 {
assert.Fail(t, "Scenario Associations",
"Expected to have %v Files. Has %v.", 2, len(files))
}
}
func TestICAssociations(t *testing.T) {
......@@ -249,10 +267,6 @@ func TestComponentConfigurationAssociations(t *testing.T) {
outSignalB := Signal{Direction: "out"}
inSignalA := Signal{Direction: "in"}
inSignalB := Signal{Direction: "in"}
fileA := File{}
fileB := File{}
fileC := File{}
fileD := File{}
icA := InfrastructureComponent{}
icB := InfrastructureComponent{}
......@@ -266,12 +280,6 @@ func TestComponentConfigurationAssociations(t *testing.T) {
assert.NoError(t, DBpool.Create(&inSignalA).Error)
assert.NoError(t, DBpool.Create(&inSignalB).Error)
// add files to DB
assert.NoError(t, DBpool.Create(&fileA).Error)
assert.NoError(t, DBpool.Create(&fileB).Error)
assert.NoError(t, DBpool.Create(&fileC).Error)
assert.NoError(t, DBpool.Create(&fileD).Error)
// add ICs to DB
assert.NoError(t, DBpool.Create(&icA).Error)
assert.NoError(t, DBpool.Create(&icB).Error)
......@@ -282,10 +290,6 @@ func TestComponentConfigurationAssociations(t *testing.T) {
assert.NoError(t, DBpool.Model(&configA).Association("OutputMapping").Append(&outSignalA).Error)
assert.NoError(t, DBpool.Model(&configA).Association("OutputMapping").Append(&outSignalB).Error)
// add Component Configuration has many files associations
assert.NoError(t, DBpool.Model(&configA).Association("Files").Append(&fileC).Error)
assert.NoError(t, DBpool.Model(&configA).Association("Files").Append(&fileD).Error)
// associate Component Configurations with IC
assert.NoError(t, DBpool.Model(&icA).Association("ComponentConfigurations").Append(&configA).Error)
assert.NoError(t, DBpool.Model(&icA).Association("ComponentConfigurations").Append(&configB).Error)
......@@ -306,13 +310,6 @@ func TestComponentConfigurationAssociations(t *testing.T) {
"Expected to have %v Output Signals. Has %v.", 2, len(signals))
}
// Get files of config1
var files []File
assert.NoError(t, DBpool.Model(&config1).Related(&files, "Files").Error)
if len(files) != 2 {
assert.Fail(t, "ComponentConfiguration Associations",
"Expected to have %v Files. Has %v.", 2, len(files))
}
}
func TestDashboardAssociations(t *testing.T) {
......@@ -358,35 +355,13 @@ func TestWidgetAssociations(t *testing.T) {
// create copies of global test data
widgetA := Widget{}
widgetB := Widget{}
fileA := File{}
fileB := File{}
fileC := File{}
fileD := File{}
// add widgets to DB
assert.NoError(t, DBpool.Create(&widgetA).Error)
assert.NoError(t, DBpool.Create(&widgetB).Error)
// add files to DB
assert.NoError(t, DBpool.Create(&fileA).Error)
assert.NoError(t, DBpool.Create(&fileB).Error)
assert.NoError(t, DBpool.Create(&fileC).Error)
assert.NoError(t, DBpool.Create(&fileD).Error)
// add widget has many files associations to DB
assert.NoError(t, DBpool.Model(&widgetA).Association("Files").Append(&fileA).Error)
assert.NoError(t, DBpool.Model(&widgetA).Association("Files").Append(&fileB).Error)
var widget1 Widget
assert.NoError(t, DBpool.Find(&widget1, 1).Error, fmt.Sprintf("Find Widget with ID=1"))
// Get files of widget
var files []File
assert.NoError(t, DBpool.Model(&widget1).Related(&files, "Files").Error)
if len(files) != 2 {
assert.Fail(t, "Widget Associations",
"Expected to have %v Files. Has %v.", 2, len(files))
}
}
func TestFileAssociations(t *testing.T) {
......
......@@ -69,6 +69,8 @@ type Scenario struct {
ComponentConfigurations []ComponentConfiguration `json:"-" gorm:"foreignkey:ScenarioID" `
// Dashboards that belong to the Scenario
Dashboards []Dashboard `json:"-" gorm:"foreignkey:ScenarioID" `
// Files that belong to the Scenario (for example images, models, etc.)
Files []File `json:"-" gorm:"foreignkey:ScenarioID"`
}
// ComponentConfiguration data model
......@@ -90,8 +92,6 @@ type ComponentConfiguration struct {
OutputMapping []Signal `json:"-" gorm:"foreignkey:ConfigID"`
// Mapping of input signals of the Component Configuration, order of signals is important
InputMapping []Signal `json:"-" gorm:"foreignkey:ConfigID"`
// Files of Component Configuration (can be CIM and other ComponentConfiguration file formats)
Files []File `json:"-" gorm:"foreignkey:ConfigID"`
// Currently selected FileID
SelectedFileID uint `json:"selectedFileID" gorm:"default:0"`
}
......@@ -178,8 +178,6 @@ type Widget struct {
CustomProperties postgres.Jsonb `json:"customProperties"`
// ID of dashboard to which widget belongs
DashboardID uint `json:"dashboardID"`
// Files that belong to widget (for example images)
Files []File `json:"-" gorm:"foreignkey:WidgetID"`
// IDs of signals that widget uses
SignalIDs pq.Int64Array `json:"signalIDs" gorm:"type:integer[]"`
}
......@@ -195,10 +193,8 @@ type File struct {
Size uint `json:"size"`
// Last modification time of file
Date string `json:"date"`
// ID of Component Configuration to which file belongs
ConfigID uint `json:"configID"`
// ID of widget to which file belongs
WidgetID uint `json:"widgetID"`
// ID of Scenario to which file belongs
ScenarioID uint `json:"scenarioID"`
// File itself
FileData []byte `json:"-" gorm:"column:FileData"`
}
// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
// This file was generated by swaggo/swag at
// 2020-03-13 17:14:16.841484501 +0100 CET m=+0.100488476
// 2020-05-26 11:22:58.121837163 +0200 CEST m=+0.130733859
package docs
......@@ -751,7 +751,7 @@ var doc = `{
"tags": [
"files"
],
"summary": "Get all files of a specific component configuration or widget",
"summary": "Get all files of a specific scenario",
"operationId": "getFiles",
"parameters": [
{
......@@ -761,24 +761,17 @@ var doc = `{
"in": "header",
"required": true
},
{
"type": "string",
"description": "Set to config for files of component configuration, set to widget for files of widget",
"name": "objectType",
"in": "query",
"required": true
},
{
"type": "integer",
"description": "ID of either config or widget of which files are requested",
"name": "objectID",
"description": "Scenario ID",
"name": "scenarioID",
"in": "query",
"required": true
}
],
"responses": {
"200": {
"description": "Files which belong to config or widget",
"description": "Files which belong to scenario",
"schema": {
"type": "object",
"$ref": "#/definitions/docs.ResponseFiles"
......@@ -822,7 +815,7 @@ var doc = `{
"tags": [
"files"
],
"summary": "Add a file to a specific component config or widget",
"summary": "Add a file to a specific scenario",
"operationId": "addFile",
"parameters": [
{
......@@ -839,17 +832,10 @@ var doc = `{
"in": "formData",
"required": true
},
{
"type": "string",
"description": "Set to config for files of component config, set to widget for files of widget",
"name": "objectType",
"in": "query",
"required": true
},
{
"type": "integer",
"description": "ID of either config or widget of which files are requested",
"name": "objectID",
"description": "ID of scenario to which file shall be added",
"name": "scenarioID",
"in": "query",
"required": true
}
......@@ -3248,10 +3234,6 @@ var doc = `{
"database.File": {
"type": "object",
"properties": {
"configID": {
"description": "ID of Component Configuration to which file belongs",
"type": "integer"
},
"date": {
"description": "Last modification time of file",
"type": "string"
......@@ -3263,6 +3245,10 @@ var doc = `{
"description": "Name of file",
"type": "string"
},
"scenarioID": {
"description": "ID of Scenario to which file belongs",
"type": "integer"
},
"size": {
"description": "Size of file (in byte)",
"type": "integer"
......@@ -3270,16 +3256,16 @@ var doc = `{
"type": {
"description": "Type of file (MIME type)",
"type": "string"
},
"widgetID": {
"description": "ID of widget to which file belongs",
"type": "integer"
}
}
},
"database.InfrastructureComponent": {
"type": "object",
"properties": {
"category": {
"description": "Category of IC (simulator, gateway, database, etc.)",
"type": "string"
},
"host": {
"description": "Host if the IC",
"type": "string"
......@@ -3287,8 +3273,8 @@ var doc = `{
"id": {
"type": "integer"
},
"modelType": {
"description": "Model type supported by the IC",
"name": {
"description": "Name of the IC",
"type": "string"
},
"properties": {
......@@ -3307,6 +3293,10 @@ var doc = `{
"description": "Time of last state update",
"type": "string"
},
"type": {
"description": "Type of IC (RTDS, VILLASnode, RTDS, etc.)",
"type": "string"
},
"uptime": {
"description": "Uptime of the IC",
"type": "integer"
......@@ -3659,16 +3649,20 @@ var doc = `{
"infrastructure_component.validNewIC": {
"type": "object",
"required": [
"Category",
"Host",
"Name",
"Type",
"Properties",
"UUID"
],
"properties": {
"Category": {
"type": "string"
},
"Host": {
"type": "string"
},
"Type": {
"Name": {
"type": "string"
},
"Properties": {
......@@ -3677,6 +3671,9 @@ var doc = `{
"State": {
"type": "string"
},
"Type": {
"type": "string"
},
"UUID": {
"type": "string"
}
......@@ -3685,10 +3682,13 @@ var doc = `{
"infrastructure_component.validUpdatedIC": {
"type": "object",
"properties": {
"Category": {
"type": "string"
},
"Host": {
"type": "string"
},
"Type": {
"Name": {
"type": "string"
},
"Properties": {
......@@ -3697,6 +3697,9 @@ var doc = `{
"State": {
"type": "string"
},
"Type": {
"type": "string"
},
"UUID": {
"type": "string"
}
......
......@@ -736,7 +736,7 @@
"tags": [
"files"
],
"summary": "Get all files of a specific component configuration or widget",
"summary": "Get all files of a specific scenario",
"operationId": "getFiles",
"parameters": [
{
......@@ -746,24 +746,17 @@
"in": "header",
"required": true
},
{
"type": "string",
"description": "Set to config for files of component configuration, set to widget for files of widget",
"name": "objectType",
"in": "query",
"required": true
},
{
"type": "integer",
"description": "ID of either config or widget of which files are requested",
"name": "objectID",
"description": "Scenario ID",
"name": "scenarioID",
"in": "query",
"required": true
}
],
"responses": {
"200": {
"description": "Files which belong to config or widget",
"description": "Files which belong to scenario",
"schema": {
"type": "object",
"$ref": "#/definitions/docs.ResponseFiles"
......@@ -807,7 +800,7 @@
"tags": [
"files"
],
"summary": "Add a file to a specific component config or widget",
"summary": "Add a file to a specific scenario",
"operationId": "addFile",
"parameters": [
{
......@@ -824,17 +817,10 @@
"in": "formData",
"required": true
},
{
"type": "string",
"description": "Set to config for files of component config, set to widget for files of widget",
"name": "objectType",
"in": "query",
"required": true
},
{
"type": "integer",
"description": "ID of either config or widget of which files are requested",
"name": "objectID",
"description": "ID of scenario to which file shall be added",
"name": "scenarioID",
"in": "query",
"required": true
}
......@@ -3233,10 +3219,6 @@
"database.File": {
"type": "object",
"properties": {
"configID": {
"description": "ID of Component Configuration to which file belongs",
"type": "integer"
},
"date": {
"description": "Last modification time of file",
"type": "string"
......@@ -3248,6 +3230,10 @@
"description": "Name of file",
"type": "string"
},
"scenarioID": {
"description": "ID of Scenario to which file belongs",
"type": "integer"
},
"size": {
"description": "Size of file (in byte)",
"type": "integer"
......@@ -3255,16 +3241,16 @@
"type": {
"description": "Type of file (MIME type)",
"type": "string"
},
"widgetID": {
"description": "ID of widget to which file belongs",
"type": "integer"
}
}
},
"database.InfrastructureComponent": {
"type": "object",
"properties": {
"category": {
"description": "Category of IC (simulator, gateway, database, etc.)",
"type": "string"
},
"host": {
"description": "Host if the IC",
"type": "string"
......@@ -3272,8 +3258,8 @@
"id": {
"type": "integer"
},
"modelType": {
"description": "Model type supported by the IC",
"name": {
"description": "Name of the IC",
"type": "string"
},
"properties": {
......@@ -3292,6 +3278,10 @@
"description": "Time of last state update",
"type": "string"
},
"type": {
"description": "Type of IC (RTDS, VILLASnode, RTDS, etc.)",
"type": "string"
},
"uptime": {
"description": "Uptime of the IC",
"type": "integer"
......@@ -3644,16 +3634,20 @@
"infrastructure_component.validNewIC": {
"type": "object",
"required": [
"Category",
"Host",
"Modeltype",
"Properties",
"Name",
"Type",
"UUID"
],
"properties": {
"Category": {
"type": "string"
},
"Host": {
"type": "string"
},
"Modeltype": {
"Name": {
"type": "string"
},
"Properties": {
......@@ -3662,6 +3656,9 @@
"State": {
"type": "string"
},
"Type": {
"type": "string"
},
"UUID": {
"type": "string"
}
......@@ -3670,10 +3667,13 @@
"infrastructure_component.validUpdatedIC": {
"type": "object",
"properties": {
"Category": {
"type": "string"
},
"Host": {
"type": "string"
},
"Modeltype": {
"Name": {
"type": "string"
},
"Properties": {
......@@ -3682,6 +3682,9 @@
"State": {
"type": "string"
},
"Type": {
"type": "string"
},
"UUID": {
"type": "string"
}
......
......@@ -115,9 +115,6 @@ definitions:
type: object
database.File:
properties:
configID:
description: ID of Component Configuration to which file belongs
type: integer
date:
description: Last modification time of file
type: string
......@@ -126,25 +123,28 @@ definitions:
name:
description: Name of file
type: string
scenarioID:
description: ID of Scenario to which file belongs
type: integer
size:
description: Size of file (in byte)
type: integer
type:
description: Type of file (MIME type)
type: string
widgetID:
description: ID of widget to which file belongs
type: integer
type: object
database.InfrastructureComponent:
properties:
category:
description: Category of IC (simulator, gateway, database, etc.)
type: string
host:
description: Host if the IC
type: string
id:
type: integer
modelType:
description: Model type supported by the IC
name:
description: Name of the IC
type: string
properties:
description: Properties of IC as JSON string
......@@ -158,6 +158,9 @@ definitions:
stateUpdateAt:
description: Time of last state update
type: string
type:
description: Type of IC (RTDS, VILLASnode, RTDS, etc.)
type: string
uptime:
description: Uptime of the IC
type: integer
......@@ -398,32 +401,41 @@ definitions:
type: object
infrastructure_component.validNewIC:
properties:
Category:
type: string
Host:
type: string
Modeltype:
Name:
type: string
Properties:
type: string
State:
type: string
Type:
type: string
UUID:
type: string
required:
- Category
- Host
- Modeltype
- Properties
- Name
- Type
- UUID
type: object
infrastructure_component.validUpdatedIC:
properties:
Category:
type: string
Host:
type: string
Modeltype:
Name: