diff --git a/SAS/TMSS/frontend/tmss_webapp/src/App.css b/SAS/TMSS/frontend/tmss_webapp/src/App.css index 8f8060fe51b3fa34406ae0a9d7f7ef95f388201e..1d772a2691add1286729b5b2053889bf8a5aa4e2 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/App.css +++ b/SAS/TMSS/frontend/tmss_webapp/src/App.css @@ -90,7 +90,7 @@ p { margin-bottom: 5px; } -.p-grid span { +.main-content .p-grid span { margin-bottom: 10px; } diff --git a/SAS/TMSS/frontend/tmss_webapp/src/__mocks__/project.service.data.js b/SAS/TMSS/frontend/tmss_webapp/src/__mocks__/project.service.data.js index 42680f340c62c61e5ef8432cc223493880842a2b..ab49f92eec7585581a21305ed884ead2f8c929a9 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/__mocks__/project.service.data.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/__mocks__/project.service.data.js @@ -219,7 +219,115 @@ const ProjectServiceMock= { "resource_type_id": "Support hours", "value": 32400 } - ] + ], + projectList: [ + { + "name": "OSR-01", + "url": "http://192.168.99.100:8008/api/project/OSR-01", + "can_trigger": false, + "created_at": "2020-08-25T14:29:04.881620", + "cycles": [ + "http://192.168.99.100:8008/api/cycle/Cycle%2014" + ], + "cycles_ids": [ + "Cycle 14" + ], + "description": "OSR-01", + "expert": false, + "filler": false, + "period_category": "http://192.168.99.100:8008/api/period_category/single_cycle", + "period_category_value": "single_cycle", + "priority_rank": 1, + "private_data": true, + "project_category": "http://192.168.99.100:8008/api/project_category/regular", + "project_category_value": "regular", + "quota": [ + "http://192.168.99.100:8008/api/project_quota/1", + "http://192.168.99.100:8008/api/project_quota/2", + "http://192.168.99.100:8008/api/project_quota/3", + "http://192.168.99.100:8008/api/project_quota/4", + "http://192.168.99.100:8008/api/project_quota/5", + "http://192.168.99.100:8008/api/project_quota/6", + "http://192.168.99.100:8008/api/project_quota/7" + ], + "quota_ids": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7 + ], + "tags": [], + "trigger_priority": 1000, + "updated_at": "2020-08-25T14:29:04.881640" + }, + { + "name": "OSR-02", + "url": "http://192.168.99.100:8008/api/project/OSR-02", + "can_trigger": false, + "created_at": "2020-08-28T07:52:07.411136", + "cycles": [], + "cycles_ids": [], + "description": "OSR-02", + "expert": false, + "filler": false, + "period_category": null, + "period_category_value": null, + "priority_rank": 1, + "private_data": true, + "project_category": null, + "project_category_value": null, + "quota": [ + "http://192.168.99.100:8008/api/project_quota/8", + "http://192.168.99.100:8008/api/project_quota/9", + "http://192.168.99.100:8008/api/project_quota/10", + "http://192.168.99.100:8008/api/project_quota/11", + "http://192.168.99.100:8008/api/project_quota/12", + "http://192.168.99.100:8008/api/project_quota/13", + "http://192.168.99.100:8008/api/project_quota/14" + ], + "quota_ids": [ + 8, + 9, + 10, + 11, + 12, + 13, + 14 + ], + "tags": [], + "trigger_priority": 1000, + "updated_at": "2020-08-28T07:52:07.411167" + }, + { + "name": "TMSS-Commissioning", + "url": "http://192.168.99.100:8008/api/project/TMSS-Commissioning", + "can_trigger": false, + "created_at": "2020-08-25T13:28:34.760707", + "cycles": [ + "http://192.168.99.100:8008/api/cycle/Cycle%2014" + ], + "cycles_ids": [ + "Cycle 14" + ], + "description": "Project for all TMSS tests and commissioning", + "expert": true, + "filler": false, + "period_category": null, + "period_category_value": null, + "priority_rank": 1, + "private_data": true, + "project_category": null, + "project_category_value": null, + "quota": [], + "quota_ids": [], + "tags": [], + "trigger_priority": 1000, + "updated_at": "2020-08-25T13:28:34.760729" + } + ] } export default ProjectServiceMock; \ No newline at end of file diff --git a/SAS/TMSS/frontend/tmss_webapp/src/__mocks__/scheduleunit.service.data.js b/SAS/TMSS/frontend/tmss_webapp/src/__mocks__/scheduleunit.service.data.js new file mode 100644 index 0000000000000000000000000000000000000000..3dc1484cf61fa7e7f68250f0e986cbc794defd8f --- /dev/null +++ b/SAS/TMSS/frontend/tmss_webapp/src/__mocks__/scheduleunit.service.data.js @@ -0,0 +1,753 @@ +const SUServiceMock= { + scheduleSetList: [ + { + "id": 1, + "url": "http://192.168.99.100:8008/api/scheduling_set/1", + "created_at": "2020-08-25T13:28:42.045214", + "description": "", + "generator_doc": {}, + "generator_source": null, + "generator_source_id": null, + "generator_template": "http://192.168.99.100:8008/api/generator_template/1", + "generator_template_id": 1, + "name": "Test Scheduling Set UC1 example 0", + "project": "http://192.168.99.100:8008/api/project/TMSS-Commissioning", + "project_id": "TMSS-Commissioning", + "scheduling_unit_drafts": [ + "http://192.168.99.100:8008/api/scheduling_unit_draft/2", + "http://192.168.99.100:8008/api/scheduling_unit_draft/1" + ], + "scheduling_unit_drafts_ids": [ + 2, + 1 + ], + "tags": [ + "TEST", + "UC1" + ], + "updated_at": "2020-08-25T13:28:42.047512" + }, + { + "id": 2, + "url": "http://192.168.99.100:8008/api/scheduling_set/2", + "created_at": "2020-08-25T13:28:49.545042", + "description": "", + "generator_doc": {}, + "generator_source": null, + "generator_source_id": null, + "generator_template": "http://192.168.99.100:8008/api/generator_template/2", + "generator_template_id": 2, + "name": "Test Scheduling Set UC1 example 1", + "project": "http://192.168.99.100:8008/api/project/TMSS-Commissioning", + "project_id": "TMSS-Commissioning", + "scheduling_unit_drafts": [ + "http://192.168.99.100:8008/api/scheduling_unit_draft/4", + "http://192.168.99.100:8008/api/scheduling_unit_draft/3" + ], + "scheduling_unit_drafts_ids": [ + 4, + 3 + ], + "tags": [ + "TEST", + "UC1" + ], + "updated_at": "2020-08-25T13:28:49.546151" + }, + { + "id": 3, + "url": "http://192.168.99.100:8008/api/scheduling_set/3", + "created_at": "2020-08-25T13:28:57.025339", + "description": "", + "generator_doc": {}, + "generator_source": null, + "generator_source_id": null, + "generator_template": "http://192.168.99.100:8008/api/generator_template/3", + "generator_template_id": 3, + "name": "Test Scheduling Set UC1 example 2", + "project": "http://192.168.99.100:8008/api/project/TMSS-Commissioning", + "project_id": "TMSS-Commissioning", + "scheduling_unit_drafts": [ + "http://192.168.99.100:8008/api/scheduling_unit_draft/6", + "http://192.168.99.100:8008/api/scheduling_unit_draft/5" + ], + "scheduling_unit_drafts_ids": [ + 6, + 5 + ], + "tags": [ + "TEST", + "UC1" + ], + "updated_at": "2020-08-25T13:28:57.026492" + } + ], + observStrategies: [ + { + "id": 1, + "url": "http://192.168.99.100:8008/api/scheduling_unit_observing_strategy_template/1", + "created_at": "2020-08-25T13:28:33.974187", + "description": "UC1 observation strategy template", + "name": "UC1 observation strategy template", + "scheduling_unit_template": "http://192.168.99.100:8008/api/scheduling_unit_template/1", + "scheduling_unit_template_id": 1, + "tags": [ + "UC1" + ], + "template": { + "tasks": { + "Pipeline 1": { + "tags": [], + "description": "Preprocessing Pipeline for Calibrator Observation 1", + "specifications_doc": { + "flag": { + "rfi_strategy": "auto", + "outerchannels": true, + "autocorrelations": true + }, + "demix": { + "sources": {}, + "time_steps": 10, + "ignore_target": false, + "frequency_steps": 64 + }, + "average": { + "time_steps": 1, + "frequency_steps": 4 + }, + "storagemanager": "dysco" + }, + "specifications_template": "preprocessing schema" + }, + "Pipeline 2": { + "tags": [], + "description": "Preprocessing Pipeline for Calibrator Observation 2", + "specifications_doc": { + "flag": { + "rfi_strategy": "auto", + "outerchannels": true, + "autocorrelations": true + }, + "demix": { + "sources": {}, + "time_steps": 10, + "ignore_target": false, + "frequency_steps": 64 + }, + "average": { + "time_steps": 1, + "frequency_steps": 4 + }, + "storagemanager": "dysco" + }, + "specifications_template": "preprocessing schema" + }, + "Pipeline SAP0": { + "tags": [], + "description": "Preprocessing Pipeline for Target Observation SAP0", + "specifications_doc": { + "flag": { + "rfi_strategy": "auto", + "outerchannels": true, + "autocorrelations": true + }, + "demix": { + "sources": {}, + "time_steps": 10, + "ignore_target": false, + "frequency_steps": 64 + }, + "average": { + "time_steps": 1, + "frequency_steps": 4 + }, + "storagemanager": "dysco" + }, + "specifications_template": "preprocessing schema" + }, + "Pipeline SAP1": { + "tags": [], + "description": "Preprocessing Pipeline for Target Observation SAP1", + "specifications_doc": { + "flag": { + "rfi_strategy": "auto", + "outerchannels": true, + "autocorrelations": true + }, + "demix": { + "sources": {}, + "time_steps": 10, + "ignore_target": false, + "frequency_steps": 64 + }, + "average": { + "time_steps": 1, + "frequency_steps": 4 + }, + "storagemanager": "dysco" + }, + "specifications_template": "preprocessing schema" + }, + "Target Observation": { + "tags": [], + "description": "Target Observation for UC1 HBA scheduling unit", + "specifications_doc": { + "QA": { + "plots": { + "enabled": true, + "autocorrelation": true, + "crosscorrelation": true + }, + "file_conversion": { + "enabled": true, + "nr_of_subbands": -1, + "nr_of_timestamps": 256 + } + }, + "SAPs": [ + { + "name": "target0", + "subbands": [ + 349, + 372 + ], + "digital_pointing": { + "angle1": 3.9935314947195253, + "angle2": 0.5324708659626034, + "angle3": 24, + "direction_type": "J2000" + } + }, + { + "name": "target1", + "subbands": [ + 349, + 372 + ], + "digital_pointing": { + "angle1": 3.9935314947195253, + "angle2": 0.5324708659626034, + "angle3": 24, + "direction_type": "J2000" + } + } + ], + "filter": "HBA_110_190", + "duration": 28800, + "stations": [ + { + "group": "ALL", + "min_stations": 1 + } + ], + "tile_beam": { + "angle1": 5.324708659626033, + "angle2": 0.7099611546168045, + "angle3": 42, + "direction_type": "J2000" + }, + "correlator": { + "storage_cluster": "CEP4", + "integration_time": 1, + "channels_per_subband": 64 + }, + "antenna_set": "HBA_DUAL_INNER" + }, + "specifications_template": "observation schema" + }, + "Calibrator Observation 1": { + "tags": [], + "description": "Calibrator Observation for UC1 HBA scheduling unit", + "specifications_doc": { + "duration": 600, + "pointing": { + "angle1": 0, + "angle2": 0, + "angle3": 0, + "direction_type": "J2000" + }, + "autoselect": false + }, + "specifications_template": "calibrator schema" + }, + "Calibrator Observation 2": { + "tags": [], + "description": "Calibrator Observation for UC1 HBA scheduling unit", + "specifications_doc": { + "duration": 600, + "pointing": { + "angle1": 0, + "angle2": 0, + "angle3": 0, + "direction_type": "J2000" + }, + "autoselect": false + }, + "specifications_template": "calibrator schema" + } + }, + "parameters": [ + { + "name": "Target Pointing 0", + "refs": [ + "#/tasks/Target Observation/specifications_doc/SAPs/0/digital_pointing" + ] + }, + { + "name": "Target Pointing 1", + "refs": [ + "#/tasks/Target Observation/specifications_doc/SAPs/1/digital_pointing" + ] + }, + { + "name": "Tile Beam", + "refs": [ + "#/tasks/Target Observation/specifications_doc/tile_beam" + ] + } + ], + "task_relations": [ + { + "tags": [], + "input": { + "role": "input", + "datatype": "visibilities" + }, + "output": { + "role": "correlator", + "datatype": "visibilities" + }, + "consumer": "Pipeline 1", + "producer": "Calibrator Observation 1", + "dataformat": "MeasurementSet", + "selection_doc": {}, + "selection_template": "All" + }, + { + "tags": [], + "input": { + "role": "input", + "datatype": "visibilities" + }, + "output": { + "role": "correlator", + "datatype": "visibilities" + }, + "consumer": "Pipeline 2", + "producer": "Calibrator Observation 2", + "dataformat": "MeasurementSet", + "selection_doc": {}, + "selection_template": "All" + }, + { + "tags": [], + "input": { + "role": "input", + "datatype": "visibilities" + }, + "output": { + "role": "correlator", + "datatype": "visibilities" + }, + "consumer": "Pipeline SAP0", + "producer": "Target Observation", + "dataformat": "MeasurementSet", + "selection_doc": { + "sap": [ + 0 + ] + }, + "selection_template": "SAP" + }, + { + "tags": [], + "input": { + "role": "input", + "datatype": "visibilities" + }, + "output": { + "role": "correlator", + "datatype": "visibilities" + }, + "consumer": "Pipeline SAP1", + "producer": "Target Observation", + "dataformat": "MeasurementSet", + "selection_doc": { + "sap": [ + 1 + ] + }, + "selection_template": "SAP" + } + ], + "task_scheduling_relations": [ + { + "first": "Calibrator Observation 1", + "second": "Target Observation", + "placement": "before", + "time_offset": 60 + }, + { + "first": "Calibrator Observation 2", + "second": "Target Observation", + "placement": "after", + "time_offset": 60 + } + ] + }, + "updated_at": "2020-08-25T13:28:33.974209", + "version": "0.1" + } + ], + schedulingUnitFromObservStrategy: { + "id": 1, + "url": "http://192.168.99.100:8008/api/scheduling_unit_draft/1", + "copies": null, + "copies_id": null, + "copy_reason": null, + "copy_reason_value": null, + "created_at": "2020-08-25T13:28:42.092602", + "description": "", + "duration": 30120, + "generator_instance_doc": null, + "name": "UC1 test scheduling unit 1.1", + "observation_strategy_template": "http://192.168.99.100:8008/api/scheduling_unit_observing_strategy_template/1", + "observation_strategy_template_id": 1, + "requirements_doc": { + "tasks": { + "Pipeline 1": { + "tags": [], + "description": "Preprocessing Pipeline for Calibrator Observation 1", + "specifications_doc": { + "flag": { + "rfi_strategy": "auto", + "outerchannels": true, + "autocorrelations": true + }, + "demix": { + "sources": {}, + "time_steps": 10, + "ignore_target": false, + "frequency_steps": 64 + }, + "average": { + "time_steps": 1, + "frequency_steps": 4 + }, + "storagemanager": "dysco" + }, + "specifications_template": "preprocessing schema" + }, + "Pipeline 2": { + "tags": [], + "description": "Preprocessing Pipeline for Calibrator Observation 2", + "specifications_doc": { + "flag": { + "rfi_strategy": "auto", + "outerchannels": true, + "autocorrelations": true + }, + "demix": { + "sources": {}, + "time_steps": 10, + "ignore_target": false, + "frequency_steps": 64 + }, + "average": { + "time_steps": 1, + "frequency_steps": 4 + }, + "storagemanager": "dysco" + }, + "specifications_template": "preprocessing schema" + }, + "Pipeline SAP0": { + "tags": [], + "description": "Preprocessing Pipeline for Target Observation SAP0", + "specifications_doc": { + "flag": { + "rfi_strategy": "auto", + "outerchannels": true, + "autocorrelations": true + }, + "demix": { + "sources": {}, + "time_steps": 10, + "ignore_target": false, + "frequency_steps": 64 + }, + "average": { + "time_steps": 1, + "frequency_steps": 4 + }, + "storagemanager": "dysco" + }, + "specifications_template": "preprocessing schema" + }, + "Pipeline SAP1": { + "tags": [], + "description": "Preprocessing Pipeline for Target Observation SAP1", + "specifications_doc": { + "flag": { + "rfi_strategy": "auto", + "outerchannels": true, + "autocorrelations": true + }, + "demix": { + "sources": {}, + "time_steps": 10, + "ignore_target": false, + "frequency_steps": 64 + }, + "average": { + "time_steps": 1, + "frequency_steps": 4 + }, + "storagemanager": "dysco" + }, + "specifications_template": "preprocessing schema" + }, + "Target Observation": { + "tags": [], + "description": "Target Observation for UC1 HBA scheduling unit", + "specifications_doc": { + "QA": { + "plots": { + "enabled": true, + "autocorrelation": true, + "crosscorrelation": true + }, + "file_conversion": { + "enabled": true, + "nr_of_subbands": -1, + "nr_of_timestamps": 256 + } + }, + "SAPs": [ + { + "name": "target0", + "subbands": [ + 349, + 372 + ], + "digital_pointing": { + "angle1": 3.9935314947195253, + "angle2": 0.5324708659626034, + "angle3": 24, + "direction_type": "J2000" + } + }, + { + "name": "target1", + "subbands": [ + 349, + 372 + ], + "digital_pointing": { + "angle1": 3.9935314947195253, + "angle2": 0.5324708659626034, + "angle3": 24, + "direction_type": "J2000" + } + } + ], + "filter": "HBA_110_190", + "duration": 28800, + "stations": [ + { + "group": "ALL", + "min_stations": 1 + } + ], + "tile_beam": { + "angle1": 5.324708659626033, + "angle2": 0.7099611546168045, + "angle3": 42, + "direction_type": "J2000" + }, + "correlator": { + "storage_cluster": "CEP4", + "integration_time": 1, + "channels_per_subband": 64 + }, + "antenna_set": "HBA_DUAL_INNER" + }, + "specifications_template": "observation schema" + }, + "Calibrator Observation 1": { + "tags": [], + "description": "Calibrator Observation for UC1 HBA scheduling unit", + "specifications_doc": { + "duration": 600, + "pointing": { + "angle1": 0, + "angle2": 0, + "angle3": 0, + "direction_type": "J2000" + }, + "autoselect": false + }, + "specifications_template": "calibrator schema" + }, + "Calibrator Observation 2": { + "tags": [], + "description": "Calibrator Observation for UC1 HBA scheduling unit", + "specifications_doc": { + "duration": 600, + "pointing": { + "angle1": 0, + "angle2": 0, + "angle3": 0, + "direction_type": "J2000" + }, + "autoselect": false + }, + "specifications_template": "calibrator schema" + } + }, + "parameters": [ + { + "name": "Target Pointing 0", + "refs": [ + "#/tasks/Target Observation/specifications_doc/SAPs/0/digital_pointing" + ] + }, + { + "name": "Target Pointing 1", + "refs": [ + "#/tasks/Target Observation/specifications_doc/SAPs/1/digital_pointing" + ] + }, + { + "name": "Tile Beam", + "refs": [ + "#/tasks/Target Observation/specifications_doc/tile_beam" + ] + } + ], + "task_relations": [ + { + "tags": [], + "input": { + "role": "input", + "datatype": "visibilities" + }, + "output": { + "role": "correlator", + "datatype": "visibilities" + }, + "consumer": "Pipeline 1", + "producer": "Calibrator Observation 1", + "dataformat": "MeasurementSet", + "selection_doc": {}, + "selection_template": "All" + }, + { + "tags": [], + "input": { + "role": "input", + "datatype": "visibilities" + }, + "output": { + "role": "correlator", + "datatype": "visibilities" + }, + "consumer": "Pipeline 2", + "producer": "Calibrator Observation 2", + "dataformat": "MeasurementSet", + "selection_doc": {}, + "selection_template": "All" + }, + { + "tags": [], + "input": { + "role": "input", + "datatype": "visibilities" + }, + "output": { + "role": "correlator", + "datatype": "visibilities" + }, + "consumer": "Pipeline SAP0", + "producer": "Target Observation", + "dataformat": "MeasurementSet", + "selection_doc": { + "sap": [ + 0 + ] + }, + "selection_template": "SAP" + }, + { + "tags": [], + "input": { + "role": "input", + "datatype": "visibilities" + }, + "output": { + "role": "correlator", + "datatype": "visibilities" + }, + "consumer": "Pipeline SAP1", + "producer": "Target Observation", + "dataformat": "MeasurementSet", + "selection_doc": { + "sap": [ + 1 + ] + }, + "selection_template": "SAP" + } + ], + "task_scheduling_relations": [ + { + "first": "Calibrator Observation 1", + "second": "Target Observation", + "placement": "before", + "time_offset": 60 + }, + { + "first": "Calibrator Observation 2", + "second": "Target Observation", + "placement": "after", + "time_offset": 60 + } + ] + }, + "requirements_template": "http://192.168.99.100:8008/api/scheduling_unit_template/1", + "requirements_template_id": 1, + "scheduling_set": "http://192.168.99.100:8008/api/scheduling_set/1", + "scheduling_set_id": 1, + "scheduling_unit_blueprints": [ + "http://192.168.99.100:8008/api/scheduling_unit_blueprint/1" + ], + "scheduling_unit_blueprints_ids": [ + 1 + ], + "tags": [ + "TEST", + "UC1" + ], + "task_drafts": [ + "http://192.168.99.100:8008/api/task_draft/5", + "http://192.168.99.100:8008/api/task_draft/7", + "http://192.168.99.100:8008/api/task_draft/6", + "http://192.168.99.100:8008/api/task_draft/4", + "http://192.168.99.100:8008/api/task_draft/3", + "http://192.168.99.100:8008/api/task_draft/2", + "http://192.168.99.100:8008/api/task_draft/1" + ], + "task_drafts_ids": [ + 5, + 7, + 6, + 4, + 3, + 2, + 1 + ], + "updated_at": "2020-08-25T13:28:42.119417" + } +}; + +export default SUServiceMock; \ No newline at end of file diff --git a/SAS/TMSS/frontend/tmss_webapp/src/__mocks__/task.service.data.js b/SAS/TMSS/frontend/tmss_webapp/src/__mocks__/task.service.data.js new file mode 100644 index 0000000000000000000000000000000000000000..6b7abd1e336416472b6360461fdbd23345871d7e --- /dev/null +++ b/SAS/TMSS/frontend/tmss_webapp/src/__mocks__/task.service.data.js @@ -0,0 +1,676 @@ +const TaskServiceMock= { + taskTemplates: [ + { + "id": 1, + "url": "http://192.168.99.100:8008/api/task_template/1", + "created_at": "2020-08-25T13:28:33.979487", + "description": "preprocessing settings", + "name": "preprocessing schema", + "schema": { + "$id": "http://example.com/example.json", + "type": "object", + "$schema": "http://json-schema.org/draft-06/schema#", + "required": [ + "storagemanager" + ], + "properties": { + "flag": { + "type": "object", + "title": "Flagging", + "default": {}, + "required": [ + "outerchannels", + "autocorrelations", + "rfi_strategy" + ], + "properties": { + "rfi_strategy": { + "enum": [ + "none", + "auto", + "HBAdefault", + "LBAdefault" + ], + "type": "string", + "title": "RFI flagging strategy", + "default": "auto" + }, + "outerchannels": { + "type": "boolean", + "title": "Flag outer channels", + "default": true + }, + "autocorrelations": { + "type": "boolean", + "title": "Flag auto correlations", + "default": true + } + }, + "additionalProperties": false + }, + "demix": { + "type": "object", + "title": "Demixing", + "default": {}, + "options": { + "dependencies": { + "demix": true + } + }, + "required": [ + "frequency_steps", + "time_steps", + "ignore_target", + "sources" + ], + "properties": { + "sources": { + "type": "object", + "title": "Sources", + "default": {}, + "properties": { + "CasA": { + "$ref": "#/definitions/demix_strategy", + "title": "CasA" + }, + "CygA": { + "$ref": "#/definitions/demix_strategy", + "title": "CygA" + }, + "HerA": { + "$ref": "#/definitions/demix_strategy", + "title": "HerA" + }, + "TauA": { + "$ref": "#/definitions/demix_strategy", + "title": "TauA" + }, + "VirA": { + "$ref": "#/definitions/demix_strategy", + "title": "VirA" + }, + "HydraA": { + "$ref": "#/definitions/demix_strategy", + "title": "HyrdraA" + } + }, + "additionalProperties": false + }, + "time_steps": { + "type": "integer", + "title": "Time steps", + "default": 10, + "minimum": 1, + "description": "Must be a multiple of the averaging time steps" + }, + "ignore_target": { + "type": "boolean", + "title": "Ignore target", + "default": false + }, + "frequency_steps": { + "type": "integer", + "title": "Frequency steps", + "default": 64, + "minimum": 1, + "description": "Must be a multiple of the averaging frequency steps" + } + }, + "additionalProperties": false + }, + "average": { + "type": "object", + "title": "Averaging", + "default": {}, + "required": [ + "frequency_steps", + "time_steps" + ], + "properties": { + "time_steps": { + "type": "integer", + "title": "Time steps", + "default": 1, + "minimum": 1 + }, + "frequency_steps": { + "type": "integer", + "title": "Frequency steps", + "default": 4, + "minimum": 1 + } + }, + "additionalProperties": false + }, + "storagemanager": { + "enum": [ + "basic", + "dysco" + ], + "type": "string", + "title": "Storage Manager", + "default": "dysco" + } + }, + "definitions": { + "demix_strategy": { + "enum": [ + "auto", + "yes", + "no" + ], + "type": "string", + "default": "auto" + } + }, + "additionalProperties": false + }, + "tags": [], + "type": "http://192.168.99.100:8008/api/task_type/pipeline", + "type_value": "pipeline", + "updated_at": "2020-08-25T13:28:33.979514", + "validation_code_js": "", + "version": "0.1" + }, + { + "id": 2, + "url": "http://192.168.99.100:8008/api/task_template/2", + "created_at": "2020-08-25T13:28:33.983945", + "description": "schema for observations", + "name": "observation schema", + "schema": { + "$id": "http://example.com/example.json", + "type": "object", + "$schema": "http://json-schema.org/draft-06/schema#", + "required": [ + "stations", + "antenna_set", + "filter", + "SAPs", + "duration", + "correlator" + ], + "properties": { + "QA": { + "type": "object", + "title": "Quality Assurance", + "default": {}, + "properties": { + "plots": { + "type": "object", + "title": "Plots", + "default": {}, + "properties": { + "enabled": { + "type": "boolean", + "title": "enabled", + "default": true, + "description": "Do/Don't create plots from the QA file from the observation" + }, + "autocorrelation": { + "type": "boolean", + "title": "autocorrelation", + "default": true, + "description": "Create autocorrelation plots for all stations" + }, + "crosscorrelation": { + "type": "boolean", + "title": "crosscorrelation", + "default": true, + "description": "Create crosscorrelation plots for all baselines" + } + }, + "description": "Create dynamic spectrum plots", + "additionalProperties": false + }, + "file_conversion": { + "type": "object", + "title": "File Conversion", + "default": {}, + "properties": { + "enabled": { + "type": "boolean", + "title": "enabled", + "default": true, + "description": "Do/Don't create a QA file for the observation" + }, + "nr_of_subbands": { + "type": "integer", + "title": "#subbands", + "default": -1, + "description": "Keep this number of subbands from the observation in the QA file, or all if -1" + }, + "nr_of_timestamps": { + "type": "integer", + "title": "#timestamps", + "default": 256, + "minimum": 1, + "description": "Extract this number of timestamps from the observation in the QA file (equidistantanly sampled, no averaging/interpolation)" + } + }, + "description": "Create a QA file for the observation", + "additionalProperties": false + } + }, + "description": "Specify Quality Assurance steps for this observation", + "additionalProperties": false + }, + "SAPs": { + "type": "array", + "items": { + "type": "object", + "title": "SAP", + "default": {}, + "required": [ + "digital_pointing", + "subbands" + ], + "properties": { + "name": { + "type": "string", + "title": "Name/target", + "default": "", + "description": "Identifier for this beam" + }, + "subbands": { + "type": "array", + "items": { + "type": "integer", + "title": "Subband", + "maximum": 511, + "minimum": 0 + }, + "title": "Subband list", + "default": [], + "additionalItems": false + }, + "digital_pointing": { + "$ref": "#/definitions/pointing", + "title": "Digital pointing", + "default": {} + } + }, + "headerTemplate": "{{ i0 }} - {{ self.name }}", + "additionalProperties": false + }, + "title": "SAPs", + "default": [ + {} + ], + "description": "Station beams", + "additionalItems": false + }, + "filter": { + "enum": [ + "LBA_10_70", + "LBA_30_70", + "LBA_10_90", + "LBA_30_90", + "HBA_110_190", + "HBA_210_250" + ], + "type": "string", + "title": "Band-pass filter", + "default": "HBA_110_190", + "description": "Must match antenna type" + }, + "duration": { + "type": "number", + "title": "Duration (seconds)", + "default": 300, + "minimum": 1, + "description": "Duration of this observation" + }, + "stations": { + "oneOf": [ + { + "type": "array", + "items": { + "enum": [ + "CS001", + "CS002", + "CS003", + "CS004", + "CS005", + "CS006", + "CS007", + "CS011", + "CS013", + "CS017", + "CS021", + "CS024", + "CS026", + "CS028", + "CS030", + "CS031", + "CS032", + "CS101", + "CS103", + "CS201", + "CS301", + "CS302", + "CS401", + "CS501", + "RS104", + "RS106", + "RS205", + "RS208", + "RS210", + "RS305", + "RS306", + "RS307", + "RS310", + "RS406", + "RS407", + "RS409", + "RS410", + "RS503", + "RS508", + "RS509", + "DE601", + "DE602", + "DE603", + "DE604", + "DE605", + "FR606", + "SE607", + "UK608", + "DE609", + "PL610", + "PL611", + "PL612", + "IE613", + "LV614" + ], + "type": "string", + "title": "Station", + "description": "" + }, + "title": "Fixed list", + "default": [ + "CS001" + ], + "minItems": 1, + "uniqueItems": true, + "additionalItems": false, + "additionalProperties": false + }, + { + "type": "array", + "items": { + "type": "object", + "title": "Station set", + "required": [ + "group", + "min_stations" + ], + "properties": { + "group": { + "enum": [ + "ALL", + "SUPERTERP", + "CORE", + "REMOTE", + "DUTCH", + "INTERNATIONAL" + ], + "type": "string", + "title": "Group/station", + "default": "ALL", + "description": "Which (group of) station(s) to select from" + }, + "min_stations": { + "type": "integer", + "title": "Minimum nr of stations", + "default": 1, + "minimum": 0, + "description": "Number of stations to use within group/station" + } + }, + "headerTemplate": "{{ self.group }}", + "additionalProperties": false + }, + "title": "Dynamic list", + "default": [ + {} + ], + "additionalItems": false + } + ], + "title": "Station list", + "default": [ + "CS001" + ] + }, + "tile_beam": { + "$ref": "#/definitions/pointing", + "title": "Tile beam", + "description": "HBA only" + }, + "correlator": { + "type": "object", + "title": "Correlator Settings", + "default": {}, + "required": [ + "channels_per_subband", + "integration_time", + "storage_cluster" + ], + "properties": { + "storage_cluster": { + "enum": [ + "CEP4", + "DragNet" + ], + "type": "string", + "title": "Storage cluster", + "default": "CEP4", + "description": "Cluster to write output to" + }, + "integration_time": { + "type": "number", + "title": "Integration time (seconds)", + "default": 1, + "minimum": 0.1, + "description": "Desired integration period" + }, + "channels_per_subband": { + "enum": [ + 8, + 16, + 32, + 64, + 128, + 256, + 512, + 1024 + ], + "type": "integer", + "title": "Channels/subband", + "default": 64, + "minimum": 8, + "description": "Number of frequency bands per subband" + } + }, + "additionalProperties": false + }, + "antenna_set": { + "enum": [ + "HBA_DUAL", + "HBA_DUAL_INNER", + "HBA_ONE", + "HBA_ONE_INNER", + "HBA_ZERO", + "HBA_ZERO_INNER", + "LBA_INNER", + "LBA_OUTER", + "LBA_SPARSE_EVEN", + "LBA_SPARSE_ODD", + "LBA_ALL" + ], + "type": "string", + "title": "Antenna set", + "default": "HBA_DUAL", + "description": "Fields & antennas to use" + } + }, + "definitions": { + "pointing": { + "type": "object", + "required": [ + "angle1", + "angle2" + ], + "properties": { + "angle1": { + "type": "number", + "title": "Angle 1", + "default": 0, + "description": "First angle (e.g. RA)" + }, + "angle2": { + "type": "number", + "title": "Angle 2", + "default": 0, + "description": "Second angle (e.g. DEC)" + }, + "angle3": { + "type": "number", + "title": "Angle 3", + "default": 0, + "description": "Third angle (e.g. N in LMN)" + }, + "direction_type": { + "enum": [ + "J2000", + "AZELGEO", + "LMN", + "SUN", + "MOON", + "MERCURY", + "VENUS", + "MARS", + "JUPITER", + "SATURN", + "URANUS", + "NEPTUNE", + "PLUTO" + ], + "type": "string", + "title": "Reference frame", + "default": "J2000", + "description": "" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + "tags": [], + "type": "http://192.168.99.100:8008/api/task_type/observation", + "type_value": "observation", + "updated_at": "2020-08-25T13:28:33.983964", + "validation_code_js": "", + "version": "0.1" + }, + { + "id": 3, + "url": "http://192.168.99.100:8008/api/task_template/3", + "created_at": "2020-08-25T13:28:33.988294", + "description": "addon schema for calibrator observations", + "name": "calibrator schema", + "schema": { + "$id": "http://example.com/example.json", + "type": "object", + "$schema": "http://json-schema.org/draft-06/schema#", + "required": [ + "autoselect", + "duration", + "pointing" + ], + "properties": { + "duration": { + "type": "number", + "title": "Duration (seconds)", + "default": 600, + "minimum": 1, + "description": "Duration of this observation" + }, + "pointing": { + "$ref": "#/definitions/pointing", + "title": "Digital pointing", + "default": {}, + "description": "Manually selected calibrator" + }, + "autoselect": { + "type": "boolean", + "title": "Auto-select", + "default": true, + "description": "Auto-select calibrator based on elevation" + } + }, + "definitions": { + "pointing": { + "type": "object", + "required": [ + "angle1", + "angle2" + ], + "properties": { + "angle1": { + "type": "number", + "title": "Angle 1", + "default": 0, + "description": "First angle [rad] (e.g. RA)" + }, + "angle2": { + "type": "number", + "title": "Angle 2", + "default": 0, + "description": "Second angle [rad] (e.g. DEC)" + }, + "angle3": { + "type": "number", + "title": "Angle 3", + "default": 0, + "description": "Third angle [rad] (e.g. N in LMN)" + }, + "direction_type": { + "enum": [ + "J2000", + "AZELGEO", + "LMN", + "SUN", + "MOON", + "MERCURY", + "VENUS", + "MARS", + "JUPITER", + "SATURN", + "URANUS", + "NEPTUNE", + "PLUTO" + ], + "type": "string", + "title": "Reference frame", + "default": "J2000", + "description": "" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + "tags": [], + "type": "http://192.168.99.100:8008/api/task_type/observation", + "type_value": "observation", + "updated_at": "2020-08-25T13:28:33.988312", + "validation_code_js": "", + "version": "0.1" + } + ] +}; + +export default TaskServiceMock; \ No newline at end of file diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/create.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/create.js index 420a66b4a6611b2e923f680da594e6e0cea1a37b..003677336ab1e9f6782ae80c34c0724b0beb8f5e 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/create.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/create.js @@ -31,9 +31,9 @@ export class SchedulingUnitCreate extends Component { errors: [], schedulingSets: [], schedulingUnit: { - project: props.match.params.project || null, + project: (props.match?props.match.params.project:null) || null, }, - projectDisabled: (props.match.params.project? true:false), + projectDisabled: (props.match?(props.match.params.project? true:false):false), observStrategy: {}, paramsSchema: null, validEditor: false, @@ -44,6 +44,7 @@ export class SchedulingUnitCreate extends Component { this.observStrategies = []; this.taskTemplates = []; this.tooltipOptions = UIConstants.tooltipOptions; + this.nameInput = React.createRef(); this.formRules = { name: {required: true, message: "Name can not be empty"}, description: {required: true, message: "Description can not be empty"}, @@ -56,6 +57,7 @@ export class SchedulingUnitCreate extends Component { this.changeStrategy = this.changeStrategy.bind(this); this.setSchedUnitParams = this.setSchedUnitParams.bind(this); this.validateForm = this.validateForm.bind(this); + this.validateEditor = this.validateEditor.bind(this); this.setEditorFunction = this.setEditorFunction.bind(this); this.saveSchedulingUnit = this.saveSchedulingUnit.bind(this); this.cancelCreate = this.cancelCreate.bind(this); @@ -132,6 +134,9 @@ export class SchedulingUnitCreate extends Component { }); } this.setState({observStrategy: observStrategy, paramsSchema: schema, paramsOutput: paramsOutput}); + if (this.state.editorFunction) { + this.state.editorFunction(); + } } /** @@ -141,15 +146,25 @@ export class SchedulingUnitCreate extends Component { * @param {Array} errors */ setEditorOutput(jsonOutput, errors) { + this.paramsOutput = jsonOutput; + this.validEditor = errors.length === 0; this.setState({ paramsOutput: jsonOutput, validEditor: errors.length === 0, validForm: this.validateForm()}); } + + /** + * This function is mainly added for Unit Tests. If this function is removed Unit Tests will fail. + */ + validateEditor() { + return this.validEditor?true:false; + } setSchedUnitParams(key, value) { let schedulingUnit = this.state.schedulingUnit; schedulingUnit[key] = value; - this.setState({schedulingUnit: schedulingUnit, validForm: this.validateForm(key)}); + this.setState({schedulingUnit: schedulingUnit, validForm: this.validateForm(key), validEditor: this.validateEditor()}); + this.validateEditor(); } /** @@ -216,7 +231,7 @@ export class SchedulingUnitCreate extends Component { if (schedulingUnit) { // this.growl.show({severity: 'success', summary: 'Success', detail: 'Scheduling Unit and tasks created successfully!'}); const dialog = {header: 'Success', detail: 'Scheduling Unit and Tasks are created successfully. Do you want to create another Scheduling Unit?'}; - this.setState({dialogVisible: true, dialog: dialog}) + this.setState({schedulingUnit: schedulingUnit, dialogVisible: true, dialog: dialog}) } else { this.growl.show({severity: 'error', summary: 'Error Occured', detail: 'Unable to save Scheduling Unit/Tasks'}); } @@ -228,6 +243,7 @@ export class SchedulingUnitCreate extends Component { reset() { const schedulingSets = this.state.schedulingSets; + this.nameInput.element.focus(); this.setState({ dialogVisible: false, dialog: { header: '', detail: ''}, @@ -263,7 +279,6 @@ export class SchedulingUnitCreate extends Component { parentFunction: this.setEditorFunction }); } - return ( <React.Fragment> <div className="p-grid"> @@ -287,6 +302,7 @@ export class SchedulingUnitCreate extends Component { <div className="col-lg-3 col-md-3 col-sm-12"> <InputText className={this.state.errors.name ?'input-error':''} id="schedUnitName" data-testid="name" tooltip="Enter name of the Scheduling Unit" tooltipOptions={this.tooltipOptions} maxLength="128" + ref={input => {this.nameInput = input;}} value={this.state.schedulingUnit.name} autoFocus onChange={(e) => this.setSchedUnitParams('name', e.target.value)} onBlur={(e) => this.setSchedUnitParams('name', e.target.value)}/> @@ -358,7 +374,8 @@ export class SchedulingUnitCreate extends Component { <div className="p-grid p-justify-start"> <div className="p-col-1"> - <Button label="Save" className="p-button-primary" icon="pi pi-check" onClick={this.saveSchedulingUnit} disabled={!this.state.validEditor || !this.state.validForm} /> + <Button label="Save" className="p-button-primary" icon="pi pi-check" onClick={this.saveSchedulingUnit} + disabled={!this.state.validEditor || !this.state.validForm} data-testid="save-btn" /> </div> <div className="p-col-1"> <Button label="Cancel" className="p-button-danger" icon="pi pi-times" onClick={this.cancelCreate} /> @@ -374,12 +391,12 @@ export class SchedulingUnitCreate extends Component { <Dialog header={this.state.dialog.header} visible={this.state.dialogVisible} style={{width: '25vw'}} inputId="confirm_dialog" modal={true} onHide={() => {this.setState({dialogVisible: false})}} footer={<div> - <Button key="back" onClick={() => {this.setState({dialogVisible: false, redirect: '/schedulingunit/draft/1/view'});}} label="No" /> + <Button key="back" onClick={() => {this.setState({dialogVisible: false, redirect: `/schedulingunit/view/draft/${this.state.schedulingUnit.id}`});}} label="No" /> <Button key="submit" type="primary" onClick={this.reset} label="Yes" /> </div> } > <div className="p-grid"> - <div className="col-lg-2 col-md-2 col-sm-2"> + <div className="col-lg-2 col-md-2 col-sm-2" style={{margin: 'auto'}}> <i className="pi pi-check-circle pi-large pi-success"></i> </div> <div className="col-lg-10 col-md-10 col-sm-10"> diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/create.test.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/create.test.js new file mode 100644 index 0000000000000000000000000000000000000000..42dca78f9223ea112e1a46e0514baad784a2e203 --- /dev/null +++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/create.test.js @@ -0,0 +1,140 @@ +import React from 'react'; +import { BrowserRouter as Router } from 'react-router-dom'; +import { act } from "react-dom/test-utils"; +import { render, cleanup, fireEvent } from '@testing-library/react'; +import '@testing-library/jest-dom/extend-expect'; + +import {SchedulingUnitCreate} from './create'; + +import ScheduleService from '../../services/schedule.service'; +import ProjectService from '../../services/project.service'; +import TaskService from '../../services/task.service'; + +import SUServiceMock from '../../__mocks__/scheduleunit.service.data'; +import ProjectServiceMock from '../../__mocks__/project.service.data'; +import TaskServiceMock from '../../__mocks__/task.service.data'; + + + +let projectListSpy, scheduleSetListSpy, observStrategiesSpy, taskTemplatesSpy, saveSUFromStrategySpy, updateSUSpy, createSUTasksSpy; + +beforeEach(() => { + setMockSpy(); +}); + +afterEach(() => { + // cleanup on exiting + clearMockSpy(); + cleanup(); +}); + +const setMockSpy = () => { + projectListSpy = jest.spyOn(ProjectService, 'getProjectList'); + projectListSpy.mockImplementation(() => { return Promise.resolve(ProjectServiceMock.projectList)}); + scheduleSetListSpy = jest.spyOn(ScheduleService, 'getSchedulingSets'); + scheduleSetListSpy.mockImplementation(() => { return Promise.resolve(SUServiceMock.scheduleSetList)}); + observStrategiesSpy = jest.spyOn(ScheduleService, 'getObservationStrategies'); + observStrategiesSpy.mockImplementation(() => { return Promise.resolve(SUServiceMock.observStrategies)}); + taskTemplatesSpy = jest.spyOn(TaskService, 'getTaskTemplates'); + taskTemplatesSpy.mockImplementation(() => { return Promise.resolve(TaskServiceMock.taskTemplates)}); + saveSUFromStrategySpy = jest.spyOn(ScheduleService, 'saveSUDraftFromObservStrategy'); + saveSUFromStrategySpy.mockImplementation((observStrategy, schedulingUnit) => { + return Promise.resolve(SUServiceMock.schedulingUnitFromObservStrategy); + }); + updateSUSpy = jest.spyOn(ScheduleService, 'updateSchedulingUnitDraft'); + updateSUSpy.mockImplementation((schedulingUnit) => { + return Promise.resolve(SUServiceMock.schedulingUnitFromObservStrategy); + }); + createSUTasksSpy = jest.spyOn(ScheduleService, 'createSUTaskDrafts'); + createSUTasksSpy.mockImplementation((schedulingUnit) => { + return Promise.resolve(SUServiceMock.schedulingUnitFromObservStrategy); + }); + +} + +const clearMockSpy = () => { + projectListSpy.mockRestore(); + scheduleSetListSpy.mockRestore(); + observStrategiesSpy.mockRestore(); + taskTemplatesSpy.mockRestore(); + saveSUFromStrategySpy.mockRestore(); + updateSUSpy.mockRestore(); + createSUTasksSpy.mockRestore(); +} + +it("renders create page with all fields and default values", async() => { + console.log("renders create page with all fields and default values ------------------------"); + + let content; + await act(async () => { + content = render(<Router><SchedulingUnitCreate /></Router>); + }); + + expect(content.queryByText('Scheduling Unit - Add')).not.toBe(null); // Page loaded successfully + expect(projectListSpy).toHaveBeenCalled(); // Mock Spy called successfully + expect(observStrategiesSpy).toHaveBeenCalled(); // Mock Spy called successfully + expect(scheduleSetListSpy).toHaveBeenCalled(); // Mock Spy called successfully + expect(taskTemplatesSpy).toHaveBeenCalled(); // Mock Spy called successfully + expect(content.queryByText('TMSS-Commissioning')).toBeInTheDocument(); // Project Dropdown loaded successfully + expect(content.queryByText('UC1 observation strategy template')).toBeInTheDocument(); // Observation Strategy Dropdown loaded successfully + expect(content.queryByText('Task Parameters')).not.toBeInTheDocument(); // JSON Editor not rendered + expect(content.queryByTestId('save-btn')).toHaveAttribute("disabled"); +}); + +it("creates new Scheduling Unit with default values", async() => { + console.log("creates new Scheduling Unit with default values ------------------------"); + + let content; + await act(async () => { + content = render(<Router><SchedulingUnitCreate /></Router>); + }); + + const nameInput = content.queryByTestId('name'); + const descInput = content.queryByTestId('description'); + const projInput = content.getAllByRole("listbox")[0].children[2] ; + const observStrategyInput = content.getAllByRole("listbox")[2].children[0] ; + + // Set values for all mandatory input and test if save button is enabled + fireEvent.change(nameInput, { target: { value: 'UC1 test scheduling unit 1.1' } }); + expect(nameInput.value).toBe("UC1 test scheduling unit 1.1"); + fireEvent.change(descInput, { target: { value: 'UC1 test scheduling unit 1.1' } }); + expect(descInput.value).toBe("UC1 test scheduling unit 1.1"); + + // After selecting values for all dropdowns + await act(async () => { + fireEvent.click(projInput); + }); + const schedulingSetInput = content.getAllByRole("listbox")[1].children[0] ; + expect(content.queryAllByText('Select Project').length).toBe(1); + expect(content.queryAllByText('TMSS-Commissioning').length).toBe(3); + + await act(async () => { + fireEvent.click(schedulingSetInput); + }); + expect(content.queryAllByText('Select Scheduling Set').length).toBe(1); + expect(content.queryAllByText('Test Scheduling Set UC1 example 0').length).toBe(3); + + await act( async() => { + fireEvent.click(observStrategyInput); + }); + expect(content.queryAllByText('Select Strategy').length).toBe(1); + expect(content.queryAllByText('UC1 observation strategy template').length).toBe(3); + expect(content.queryByText('Task Parameters')).toBeInTheDocument(); + expect(content.queryByText('Target Pointing 0')).toBeInTheDocument(); + // expect(content.queryByText('Not a valid input. Mimimum: 00:00:00, Maximum:23:59:59.')).not.toBeInTheDocument(); + // expect(content.queryByText('Not a valid input. Mimimum: 00:00:00, Maximum:90:00:00.')).not.toBeInTheDocument(); + + /* This is set again to call the validateEditor function in the component. + If this is removed, the editor validation will not occur in the test but works in browser.*/ + await act( async() => { + fireEvent.change(nameInput, { target: { value: 'UC1 test scheduling unit 1.1' } }); + }); + + expect(content.queryByTestId('save-btn').hasAttribute("disabled")).toBeFalsy(); + + await act(async () => { + fireEvent.click(content.queryByTestId('save-btn')); + }); + expect(saveSUFromStrategySpy).toHaveBeenCalled(); + +}); \ No newline at end of file diff --git a/SAS/TMSS/frontend/tmss_webapp/src/services/schedule.service.js b/SAS/TMSS/frontend/tmss_webapp/src/services/schedule.service.js index 519837afe2e8513dc6802b106aa77fe73181f93b..e2497e87c5ae0eb8841744bfef59c4c28ad1ae5e 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/services/schedule.service.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/services/schedule.service.js @@ -192,13 +192,11 @@ const ScheduleService = { if (schedulingUnit && schedulingUnit.id) { schedulingUnit.requirements_doc = observStrategy.template; delete schedulingUnit['duration']; - const suUpdateResponse = await axios.put(`/api/scheduling_unit_draft/${schedulingUnit.id}/`, schedulingUnit); - schedulingUnit = suUpdateResponse.data; + schedulingUnit = await this.updateSchedulingUnitDraft(schedulingUnit); if (!schedulingUnit || !schedulingUnit.id) { return null; } - const suCreateTaskResponse = await axios.get(`/api/scheduling_unit_draft/${schedulingUnit.id}/create_task_drafts/`); - schedulingUnit = suCreateTaskResponse.data; + schedulingUnit = await this.createSUTaskDrafts(schedulingUnit); if (schedulingUnit && schedulingUnit.task_drafts.length > 0) { return schedulingUnit; } @@ -208,6 +206,24 @@ const ScheduleService = { console.error(error); return null; }; + }, + updateSchedulingUnitDraft: async function(schedulingUnit) { + try { + const suUpdateResponse = await axios.put(`/api/scheduling_unit_draft/${schedulingUnit.id}/`, schedulingUnit); + return suUpdateResponse.data; + } catch(error) { + console.error(error); + return null + } + }, + createSUTaskDrafts: async (schedulingUnit) => { + try { + const suCreateTaskResponse = await axios.get(`/api/scheduling_unit_draft/${schedulingUnit.id}/create_task_drafts/`); + return suCreateTaskResponse.data; + } catch(error) { + console.error(error); + return null; + } } }