diff --git a/SAS/TMSS/frontend/tmss_webapp/src/App.css b/SAS/TMSS/frontend/tmss_webapp/src/App.css index 766fff47baad6747a35c03a164125f8d181f5956..8f8060fe51b3fa34406ae0a9d7f7ef95f388201e 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/App.css +++ b/SAS/TMSS/frontend/tmss_webapp/src/App.css @@ -90,6 +90,14 @@ p { margin-bottom: 5px; } +.p-grid span { + margin-bottom: 10px; +} + +.p-chips-token,.p-inputnumber span { + margin-bottom: 0px; +} + .p-field { margin-bottom: 0.5rem; } 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 066fd339758c56e64cc51a2ae81142eb978a583d..42680f340c62c61e5ef8432cc223493880842a2b 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 @@ -7,180 +7,90 @@ const ProjectServiceMock= { "url": "http://localhost:3000/api/resource_type/LOFAR%20Observing%20Time/", "created_at": "2020-07-29T07:31:21.708296", "description": "LOFAR Observing Time", - "resource_unit": "http://localhost:3000/api/resource_unit/second/", - "resource_unit_id": "second", "tags": [ ], "updated_at": "2020-07-29T07:31:21.708316", - "resourceUnit": { - "name": "second", - "url": "http://localhost:3000/api/resource_unit/second/", - "created_at": "2020-07-29T07:31:21.070088", - "description": "Unit of time or duration", - "tags": [ - ], - "updated_at": "2020-07-29T07:31:21.070114" - } + "quantity_value": "time" }, { "name": "LOFAR Observing Time prio A", "url": "http://localhost:3000/api/resource_type/LOFAR%20Observing%20Time%20prio%20A/", "created_at": "2020-07-29T07:31:21.827537", "description": "LOFAR Observing Time prio A", - "resource_unit": "http://localhost:3000/api/resource_unit/second/", - "resource_unit_id": "second", "tags": [ ], "updated_at": "2020-07-29T07:31:21.827675", - "resourceUnit": { - "name": "second", - "url": "http://localhost:3000/api/resource_unit/second/", - "created_at": "2020-07-29T07:31:21.070088", - "description": "Unit of time or duration", - "tags": [ - ], - "updated_at": "2020-07-29T07:31:21.070114" - } + "quantity_value": "time" }, { "name": "LOFAR Observing Time prio B", "url": "http://localhost:3000/api/resource_type/LOFAR%20Observing%20Time%20prio%20B/", "created_at": "2020-07-29T07:31:21.950948", "description": "LOFAR Observing Time prio B", - "resource_unit": "http://localhost:3000/api/resource_unit/second/", - "resource_unit_id": "second", "tags": [ ], "updated_at": "2020-07-29T07:31:21.950968", - "resourceUnit": { - "name": "second", - "url": "http://localhost:3000/api/resource_unit/second/", - "created_at": "2020-07-29T07:31:21.070088", - "description": "Unit of time or duration", - "tags": [ - ], - "updated_at": "2020-07-29T07:31:21.070114" - } + "quantity_value": "time" }, { "name": "CEP Processing Time", "url": "http://localhost:3000/api/resource_type/CEP%20Processing%20Time/", "created_at": "2020-07-29T07:31:22.097916", "description": "CEP Processing Time", - "resource_unit": "http://localhost:3000/api/resource_unit/second/", - "resource_unit_id": "second", "tags": [ ], "updated_at": "2020-07-29T07:31:22.097941", - "resourceUnit": { - "name": "second", - "url": "http://localhost:3000/api/resource_unit/second/", - "created_at": "2020-07-29T07:31:21.070088", - "description": "Unit of time or duration", - "tags": [ - ], - "updated_at": "2020-07-29T07:31:21.070114" - } + "quantity_value": "time" }, { "name": "LTA Storage", "url": "http://localhost:3000/api/resource_type/LTA%20Storage/", "created_at": "2020-07-29T07:31:22.210071", "description": "LTA Storage", - "resource_unit": "http://localhost:3000/api/resource_unit/byte/", - "resource_unit_id": "byte", "tags": [ ], "updated_at": "2020-07-29T07:31:22.210091", - "resourceUnit": { - "name": "byte", - "url": "http://localhost:3000/api/resource_unit/byte/", - "created_at": "2020-07-29T07:31:21.500997", - "description": "Unit of data storage", - "tags": [ - ], - "updated_at": "2020-07-29T07:31:21.501028" - } + "quantity_value": "bytes" }, { "name": "Number of triggers", "url": "http://localhost:3000/api/resource_type/Number%20of%20triggers/", "created_at": "2020-07-29T07:31:22.317313", "description": "Number of triggers", - "resource_unit": "http://localhost:3000/api/resource_unit/number/", - "resource_unit_id": "number", "tags": [ ], "updated_at": "2020-07-29T07:31:22.317341", - "resourceUnit": { - "name": "number", - "url": "http://localhost:3000/api/resource_unit/number/", - "created_at": "2020-07-29T07:31:21.596364", - "description": "Unit of count", - "tags": [ - ], - "updated_at": "2020-07-29T07:31:21.596385" - } + "quantity_value": "number" }, { "name": "LOFAR Support Time", "url": "http://localhost:3000/api/resource_type/LOFAR%20Support%20Time/", "created_at": "2020-07-29T07:31:22.437945", "description": "LOFAR Support Time", - "resource_unit": "http://localhost:3000/api/resource_unit/second/", - "resource_unit_id": "second", "tags": [ ], "updated_at": "2020-07-29T07:31:22.437964", - "resourceUnit": { - "name": "second", - "url": "http://localhost:3000/api/resource_unit/second/", - "created_at": "2020-07-29T07:31:21.070088", - "description": "Unit of time or duration", - "tags": [ - ], - "updated_at": "2020-07-29T07:31:21.070114" - } + "quantity_value": "time" }, { "name": "LOFAR Support hours", "url": "http://localhost:3000/api/resource_type/LOFAR%20Support%20hours/", "created_at": "2020-07-29T07:31:22.571850", "description": "LOFAR Support hours", - "resource_unit": "http://localhost:3000/api/resource_unit/second/", - "resource_unit_id": "second", "tags": [ ], "updated_at": "2020-07-29T07:31:22.571869", - "resourceUnit": { - "name": "second", - "url": "http://localhost:3000/api/resource_unit/second/", - "created_at": "2020-07-29T07:31:21.070088", - "description": "Unit of time or duration", - "tags": [ - ], - "updated_at": "2020-07-29T07:31:21.070114" - } + "quantity_value": "time" }, { "name": "Support hours", "url": "http://localhost:3000/api/resource_type/Support%20hours/", "created_at": "2020-07-29T07:31:22.694438", "description": "Support hours", - "resource_unit": "http://localhost:3000/api/resource_unit/second/", - "resource_unit_id": "second", "tags": [ ], "updated_at": "2020-07-29T07:31:22.694514", - "resourceUnit": { - "name": "second", - "url": "http://localhost:3000/api/resource_unit/second/", - "created_at": "2020-07-29T07:31:21.070088", - "description": "Unit of time or duration", - "tags": [ - ], - "updated_at": "2020-07-29T07:31:21.070114" - } + "quantity_value": "time" } ], projectResourceDefaults: { @@ -212,7 +122,7 @@ const ProjectServiceMock= { "private_data": true, "project_category": "Regular", "project_category_value": "Regular", - "project_quota": [ + "quota": [ "http://192.168.99.100:8008/api/project_quota/70/", "http://192.168.99.100:8008/api/project_quota/71/", "http://192.168.99.100:8008/api/project_quota/72/", @@ -222,7 +132,7 @@ const ProjectServiceMock= { "http://192.168.99.100:8008/api/project_quota/76/", "http://192.168.99.100:8008/api/project_quota/77/" ], - "project_quota_ids": [ + "quota_ids": [ 70, 71, 72, @@ -307,7 +217,7 @@ const ProjectServiceMock= { "project_id": "OSR-11", "resource_type": "http://192.168.99.100:8008/api/resource_type/Support%20hours/", "resource_type_id": "Support hours", - "value": 8 + "value": 32400 } ] } diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/ResourceInputList.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/ResourceInputList.js index c1d9019421ff16c5570e3371e8ff338342b404f7..d074a38c1eec2c23f9434dbe30475822cca302e9 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/ResourceInputList.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/ResourceInputList.js @@ -41,6 +41,7 @@ export class ResourceInputList extends Component { <InputNumber key={'item1-'+ index} id={'item1-'+ index} name={'item1-'+ index} suffix={` ${this.props.unitMap[item.quantity_value]?this.props.unitMap[item.quantity_value].display:''}`} placeholder={` ${this.props.unitMap[item.quantity_value]?this.props.unitMap[item.quantity_value].display:item.name}`} min={0} useGrouping={false} + inputId={`${item.name}`} min={0} useGrouping={false} value={this.state.projectQuota[item.name]} onChange={(e) => this.onInputChange(item.name, e)} onBlur={(e) => this.onInputChange(item.name, e)} diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/create.test.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/create.test.js index 84c2b338449d107059e43fa4396dead622a042fe..7eccc6d8e8814da4fb5788fbb43c47527697d628 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/create.test.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/create.test.js @@ -3,6 +3,7 @@ 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 _ from 'lodash'; import {ProjectCreate} from './create'; import ProjectService from '../../services/project.service'; @@ -65,6 +66,7 @@ it("renders without crashing with all back-end data loaded", async () => { await act(async () => { content = render(<Router><ProjectCreate /></Router>); }); + const spinButtons = content.queryAllByRole("spinbutton"); expect(content.queryByText('Project - Add')).not.toBe(null); // Page loaded successfully expect(projectCategoriesSpy).toHaveBeenCalled(); // Mock Spy called successfully @@ -73,8 +75,8 @@ it("renders without crashing with all back-end data loaded", async () => { expect(content.queryByText('Cycle-0')).toBeInTheDocument(); // Cycle multi-select loaded successfully expect(content.queryAllByText('Add Resources').length).toBe(2); // Resource Dropdown loaded successfully expect(content.queryByText('Support hours')).toBeInTheDocument(); // Resources other than Default Resources listed in dropdown - expect(content.queryByPlaceholderText('Support Hours')).toBe(null); // No resources other than Default Resources listed to get input - expect(content.queryByPlaceholderText('LOFAR Observing Time').value).toBe('1 Hours'); // Default Resource Listed with default value + expect(_.filter(spinButtons, {"id": "Support hours"}).length).toBe(0); // No resources other than Default Resources listed to get input + expect(_.filter(spinButtons, {"id": "LOFAR Observing Time"})[0].value).toBe('1 Hours'); // Default Resource Listed with default value }); it("Save button disabled initially when no data entered", async () => { @@ -222,31 +224,31 @@ it("save project with default resources", async () => { expect(content.queryByTestId('projectId').value).toBe(""); expect(content.queryByText("Success")).toBe(null); - const lofarObsTimeInput = content.queryByPlaceholderText('LOFAR Observing Time'); + const lofarObsTimeInput = _.filter(spinButtons, {"id": "LOFAR Observing Time"})[0]; fireEvent.change(lofarObsTimeInput, { target: { value: 10 } }); expect(lofarObsTimeInput.value).toBe('10'); - const lofarObsTimeAInput = content.queryByPlaceholderText('LOFAR Observing Time prio A'); + const lofarObsTimeAInput = _.filter(spinButtons, {"id": "LOFAR Observing Time prio A"})[0]; fireEvent.change(lofarObsTimeAInput, { target: { value: 15 } }); expect(lofarObsTimeAInput.value).toBe('15'); - const lofarObsTimeBInput = content.queryByPlaceholderText('LOFAR Observing Time prio B'); + const lofarObsTimeBInput = _.filter(spinButtons, {"id": "LOFAR Observing Time prio B"})[0]; fireEvent.change(lofarObsTimeBInput, { target: { value: 20 } }); expect(lofarObsTimeBInput.value).toBe('20'); - const cepProcTimeInput = content.queryByPlaceholderText('CEP Processing Time'); + const cepProcTimeInput = _.filter(spinButtons, {"id": "CEP Processing Time"})[0]; fireEvent.change(cepProcTimeInput, { target: { value: 5 } }); expect(cepProcTimeInput.value).toBe('5'); - const ltaStorageInput = content.queryByPlaceholderText('LTA Storage'); + const ltaStorageInput = _.filter(spinButtons, {"id": "LTA Storage"})[0]; fireEvent.change(ltaStorageInput, { target: { value: 2 } }); expect(ltaStorageInput.value).toBe('2'); - const noOfTriggerInput = content.queryByPlaceholderText('Number of triggers'); + const noOfTriggerInput = _.filter(spinButtons, {"id": "Number of triggers"})[0]; fireEvent.change(noOfTriggerInput, { target: { value: 3 } }); expect(noOfTriggerInput.value).toBe('3'); - const lofarSupTimeInput = content.queryByPlaceholderText('LOFAR Support Time'); + const lofarSupTimeInput = _.filter(spinButtons, {"id": "LOFAR Support Time"})[0]; fireEvent.change(lofarSupTimeInput, { target: { value: 25 } }); expect(lofarSupTimeInput.value).toBe('25'); @@ -268,7 +270,7 @@ it("save project with added resources", async () => { const nameInput = content.queryByTestId('name'); const descInput = content.queryByTestId('description'); - const spinButtons = content.queryAllByRole("spinbutton"); + let spinButtons = content.queryAllByRole("spinbutton"); const rankInput = spinButtons.filter(function(element) { return element.id==="proj-rank"})[0]; fireEvent.change(nameInput, { target: { value: 'OSR' } }); @@ -281,31 +283,31 @@ it("save project with added resources", async () => { expect(content.queryByTestId('projectId').value).toBe(""); expect(content.queryByText("Success")).toBe(null); - const lofarObsTimeInput = content.queryByPlaceholderText('LOFAR Observing Time'); + const lofarObsTimeInput = _.filter(spinButtons, {"id": "LOFAR Observing Time"})[0]; fireEvent.change(lofarObsTimeInput, { target: { value: 10 } }); expect(lofarObsTimeInput.value).toBe('10'); - const lofarObsTimeAInput = content.queryByPlaceholderText('LOFAR Observing Time prio A'); + const lofarObsTimeAInput = _.filter(spinButtons, {"id": "LOFAR Observing Time prio A"})[0]; fireEvent.change(lofarObsTimeAInput, { target: { value: 15 } }); expect(lofarObsTimeAInput.value).toBe('15'); - const lofarObsTimeBInput = content.queryByPlaceholderText('LOFAR Observing Time prio B'); + const lofarObsTimeBInput = _.filter(spinButtons, {"id": "LOFAR Observing Time prio B"})[0]; fireEvent.change(lofarObsTimeBInput, { target: { value: 20 } }); expect(lofarObsTimeBInput.value).toBe('20'); - const cepProcTimeInput = content.queryByPlaceholderText('CEP Processing Time'); + const cepProcTimeInput = _.filter(spinButtons, {"id": "CEP Processing Time"})[0]; fireEvent.change(cepProcTimeInput, { target: { value: 5 } }); expect(cepProcTimeInput.value).toBe('5'); - const ltaStorageInput = content.queryByPlaceholderText('LTA Storage'); + const ltaStorageInput = _.filter(spinButtons, {"id": "LTA Storage"})[0]; fireEvent.change(ltaStorageInput, { target: { value: 2 } }); expect(ltaStorageInput.value).toBe('2'); - const noOfTriggerInput = content.queryByPlaceholderText('Number of triggers'); + const noOfTriggerInput = _.filter(spinButtons, {"id": "Number of triggers"})[0]; fireEvent.change(noOfTriggerInput, { target: { value: 3 } }); expect(noOfTriggerInput.value).toBe('3'); - const lofarSupTimeInput = content.queryByPlaceholderText('LOFAR Support Time'); + const lofarSupTimeInput = _.filter(spinButtons, {"id": "LOFAR Support Time"})[0]; fireEvent.change(lofarSupTimeInput, { target: { value: 25 } }); expect(lofarSupTimeInput.value).toBe('25'); @@ -313,7 +315,7 @@ it("save project with added resources", async () => { expect(content.queryAllByText('Add Resources').length).toBe(2); expect(content.queryAllByText('Support hours').length).toBe(1); expect(content.getAllByRole("listbox")[3].children.length).toBe(2); - expect(content.queryByPlaceholderText('Support hours')).toBe(null); + expect(_.filter(spinButtons, {"id": "Support hours"}).length).toBe(0); const addResourceInput = content.getAllByRole("listbox")[3].children[1] ; fireEvent.click(addResourceInput); // After selecting New Resource @@ -323,9 +325,10 @@ it("save project with added resources", async () => { const addResourceBtn = content.queryByTestId('add_res_btn'); fireEvent.click(addResourceBtn); expect(content.queryAllByText('Add Resources').length).toBe(2); - expect(content.queryByPlaceholderText('Support hours')).not.toBe(null); + spinButtons = content.queryAllByRole("spinbutton"); - const newResourceInput = content.queryByPlaceholderText('Support hours'); + const newResourceInput = _.filter(spinButtons, {"id": "Support hours"})[0]; + expect(newResourceInput).not.toBe(null); fireEvent.change(newResourceInput, { target: { value: 30 } }); expect(newResourceInput.value).toBe('30'); @@ -360,15 +363,18 @@ it("remove default resource and added resource", async () => { const addResourceBtn = content.queryByTestId('add_res_btn'); fireEvent.click(addResourceBtn); expect(content.queryAllByText('Add Resources').length).toBe(2); - expect(content.queryByPlaceholderText('Support hours')).not.toBe(null); - expect(content.queryByPlaceholderText('CEP Processing Time')).not.toBe(null); + const spinButtons = content.queryAllByRole("spinbutton"); + + expect(_.filter(spinButtons, {"id": "Support hours"})[0]).not.toBe(null); + + expect(_.filter(spinButtons, {"id": "CEP Processing Time"})[0]).not.toBe(null); expect(content.queryByTestId('CEP Processing Time-btn')).not.toBe(null); const removeDefResBtn = content.queryByTestId('CEP Processing Time-btn'); await act(async () => { fireEvent.click(content.queryByTestId('CEP Processing Time-btn')); }); - expect(content.queryByPlaceholderText('CEP Processing Time')).toBe(null); + expect(_.filter(spinButtons, {"id": "CEP Processing Time"}).length).toBe(0); expect(content.queryByTestId('CEP Processing Time-btn')).toBe(null); const removeResourceBtn = content.queryByTestId('Support hours-btn'); diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/edit.test.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/edit.test.js index dd13177fac9e2e1321d5b873783a691d4b96e769..eae81b7db6746b68d5239aa7232026fed08aa4a5 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/edit.test.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/edit.test.js @@ -112,10 +112,10 @@ it("renders input fields with Project details if found", async () => { expect(content.queryByTestId("name").value).toBe('OSR-11'); const spinButtons = content.queryAllByRole("spinbutton"); - const trigPrioInput = spinButtons.filter(function(element) { return element.id==="trig_prio"})[0]; + const trigPrioInput = _.filter(spinButtons, {"id": "trig_prio"})[0]; expect(trigPrioInput.value).toBe("990"); - const rankInput = spinButtons.filter(function(element) { return element.id==="proj-rank"})[0]; + const rankInput = _.filter(spinButtons, {"id": "proj-rank"})[0]; expect(rankInput.value).toBe("5"); const trigger = content.getAllByLabelText(/trigger/i).filter((element) => { return element.id==="trigger"})[0]; @@ -132,15 +132,15 @@ it("renders input fields with Project details if found", async () => { const cycleInput = content.getAllByRole("listbox")[2] ; expect(content.queryAllByText('Cycle 0').length).toBe(2); - expect(content.queryByPlaceholderText("CEP Processing Time").value).toBe("10 Hours"); - expect(content.queryByPlaceholderText("LOFAR Observing Time").value).toBe("20 Hours"); - expect(content.queryByPlaceholderText("LOFAR Observing Time prio A").value).toBe("30 Hours"); - expect(content.queryByPlaceholderText("LOFAR Observing Time prio B").value).toBe("40 Hours"); - expect(content.queryByPlaceholderText("LOFAR Support Time").value).toBe("50 Hours"); - expect(content.queryByPlaceholderText("LTA Storage").value).toBe("6 TB"); - expect(content.queryByPlaceholderText("Number of triggers").value).toBe("7 Numbers"); - expect(content.queryByPlaceholderText("Support hours").value).toBe("8 "); - + expect(_.filter(spinButtons, {"id": "CEP Processing Time"})[0].value).toBe("10 Hours"); + expect(_.filter(spinButtons, {"id": "LOFAR Observing Time"})[0].value).toBe("20 Hours"); + expect(_.filter(spinButtons, {"id": "LOFAR Observing Time prio A"})[0].value).toBe("30 Hours"); + expect(_.filter(spinButtons, {"id": "LOFAR Observing Time prio B"})[0].value).toBe("40 Hours"); + expect(_.filter(spinButtons, {"id": "LOFAR Support Time"})[0].value).toBe("50 Hours"); + expect(_.filter(spinButtons, {"id": "LTA Storage"})[0].value).toBe("6 TB"); + expect(_.filter(spinButtons, {"id": "Number of triggers"})[0].value).toBe("7 Numbers"); + expect(_.filter(spinButtons, {"id": "Support hours"})[0].value).toBe("9 Hours"); + expect(content.queryByTestId('save-btn').hasAttribute("disabled")).toBeFalsy(); }); @@ -157,11 +157,11 @@ it("save Project after editing fields", async () => { expect(content.queryByTestId("name").value).toBe('OSR-11'); const spinButtons = content.queryAllByRole("spinbutton"); - const trigPrioInput = spinButtons.filter(function(element) { return element.id==="trig_prio"})[0]; + const trigPrioInput = _.filter(spinButtons, {"id": "trig_prio"})[0]; fireEvent.blur(trigPrioInput, { target: { value: 900 } }); expect(trigPrioInput.value).toBe("900"); - const rankInput = spinButtons.filter(function(element) { return element.id==="proj-rank"})[0]; + const rankInput = _.filter(spinButtons, {"id": "proj-rank"})[0]; fireEvent.blur(rankInput, { target: { value: 2 } }); expect(rankInput.value).toBe("2"); @@ -190,19 +190,19 @@ it("save Project after editing fields", async () => { expect(content.queryAllByText('Cycle-0').length).toBe(2); expect(content.queryAllByText('Cycle 0').length).toBe(1); - const lofarObsTimeInput = content.queryByPlaceholderText('LOFAR Observing Time'); + const lofarObsTimeInput = _.filter(spinButtons, {"id": "LOFAR Observing Time"})[0]; fireEvent.blur(lofarObsTimeInput, { target: { value: 10 } }); expect(lofarObsTimeInput.value).toBe('10 Hours'); - const cepProcTimeInput = content.queryByPlaceholderText('CEP Processing Time'); + const cepProcTimeInput = _.filter(spinButtons, {"id": "CEP Processing Time"})[0]; fireEvent.blur(cepProcTimeInput, { target: { value: 5 } }); expect(cepProcTimeInput.value).toBe('5 Hours'); - const ltaStorageInput = content.queryByPlaceholderText('LTA Storage'); + const ltaStorageInput = _.filter(spinButtons, {"id": "LTA Storage"})[0]; fireEvent.blur(ltaStorageInput, { target: { value: 2 } }); expect(ltaStorageInput.value).toBe('2 TB'); - const noOfTriggerInput = content.queryByPlaceholderText('Number of triggers'); + const noOfTriggerInput = _.filter(spinButtons, {"id": "Number of triggers"})[0]; fireEvent.blur(noOfTriggerInput, { target: { value: 3 } }); expect(noOfTriggerInput.value).toBe('3 Numbers'); @@ -238,13 +238,15 @@ it("save Project after adding, modifying and deleting resources", async () => { const addResourceBtn = content.queryByTestId('add_res_btn'); fireEvent.click(addResourceBtn); expect(content.queryAllByText('Add Resources').length).toBe(2); - expect(content.queryByPlaceholderText('LOFAR Support hours')).not.toBe(null); - const lofarSupHrsInput = content.queryByPlaceholderText('LOFAR Support hours'); + + const spinButtons = content.queryAllByRole("spinbutton"); + const lofarSupHrsInput = _.filter(spinButtons, {"id": "LOFAR Support hours"})[0]; + expect(lofarSupHrsInput).not.toBe(null); fireEvent.blur(lofarSupHrsInput, { target: { value: 100 } }); - expect(lofarSupHrsInput.value).toBe('100 '); + expect(lofarSupHrsInput.value).toBe('100 Hours'); // Editing existing resource - const lofarObsTimeInput = content.queryByPlaceholderText('LOFAR Observing Time'); + const lofarObsTimeInput = _.filter(spinButtons, {"id": "LOFAR Observing Time"})[0]; fireEvent.blur(lofarObsTimeInput, { target: { value: 10 } }); expect(lofarObsTimeInput.value).toBe('10 Hours'); diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/view.test.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/view.test.js index aaf9327d0308d4076806ba99897dc7a345df0e23..3847248a84ccbf4d50b6d39a0498b19a7d267d84 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/view.test.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/view.test.js @@ -66,7 +66,7 @@ it("renders Project details if found", async () => { expect(content.queryByText("50 Hours")).not.toBe(null); expect(content.queryByText("6 TB")).not.toBe(null); expect(content.queryByText("7 Numbers")).not.toBe(null); - expect(content.queryByText("8")).not.toBe(null); + expect(content.queryByText("9 Hours")).not.toBe(null); }); diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/SchedulingUnitList.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/SchedulingUnitList.js index 14923ef9cd77a73146c6c7375316805821f81249..94684738c10cb3f98a51e90306d7bc27c3cfd3f1 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/SchedulingUnitList.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/SchedulingUnitList.js @@ -39,8 +39,6 @@ class SchedulingUnitList extends Component{ defaultSortColumn: [{id: "Name", desc: false},{id: "Created Date", desc: false}], } } - - async getSchedulingUnitList () { const bluePrint = await ScheduleService.getSchedulingUnitBlueprint(); @@ -52,17 +50,17 @@ class SchedulingUnitList extends Component{ blueprintdata.map(blueP => { blueP.duration = moment.utc(blueP.duration*1000).format('HH:mm:ss'); blueP.type="Blueprint"; - blueP['actionpath'] = '/task/view/type/id'; + blueP['actionpath'] = '/schedulingunit/view/blueprint/'+blueP.id; return blueP; }); output.push(...blueprintdata); - scheduleunit['actionpath']='/schedulingunit/view'; + scheduleunit['actionpath']='/schedulingunit/view/draft/'+scheduleunit.id; scheduleunit['type'] = 'Draft'; scheduleunit['duration'] = moment.utc(scheduleunit.duration*1000).format('HH:mm:ss'); output.push(scheduleunit); } this.setState({ - scheduleunit: output, isLoading:false + scheduleunit: output, isLoading: false }); }) } diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/ViewSchedulingUnit.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/ViewSchedulingUnit.js index 46dd2fa42de19b50cacf93cbe8ae46bef4265be1..85fe51d31a33c8bc1ece62bb0c882394be43f44c 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/ViewSchedulingUnit.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/ViewSchedulingUnit.js @@ -49,34 +49,59 @@ class ViewSchedulingUnit extends Component{ "BluePrint / Task Draft link": "filter-input-100", "Relative Start Time (HH:mm:ss)": "filter-input-75", "Relative End Time (HH:mm:ss)": "filter-input-75", - }], - defaultSortColumn: [{id: "Name", desc: false}], + }] + } + if (this.props.match.params.id) { + this.state.scheduleunitId = this.props.match.params.id; + } + if (this.props.match.params.type) { + this.state.scheduleunitType = this.props.match.params.type; } } componentDidMount(){ - let schedule_id = this.props.location.state.id - if (schedule_id) { - ScheduleService.getSchedulingUnitDraftById(schedule_id) - .then(scheduleunit =>{ - ScheduleService.getScheduleTasksBySchedulingUnitId(scheduleunit.data.id) - .then(tasks =>{ - tasks.map(task => { - task.duration = moment.utc(task.duration*1000).format('HH:mm:ss'); - task.relative_start_time = moment.utc(task.relative_start_time*1000).format('HH:mm:ss'); - task.relative_stop_time = moment.utc(task.relative_stop_time*1000).format('HH:mm:ss'); - return task; + let schedule_id = this.state.scheduleunitId; + let schedule_type = this.state.scheduleunitType; + if (schedule_type && schedule_id) { + this.getScheduleUnit(schedule_type, schedule_id) + .then(schedulingUnit =>{ + if (schedulingUnit) { + this.getScheduleUnitTasks(schedule_type, schedulingUnit) + .then(tasks =>{ + /* tasks.map(task => { + task.duration = moment.utc(task.duration*1000).format('HH:mm:ss'); + task.relative_start_time = moment.utc(task.relative_start_time*1000).format('HH:mm:ss'); + task.relative_stop_time = moment.utc(task.relative_stop_time*1000).format('HH:mm:ss'); + return task; + });*/ + this.setState({ + scheduleunit : schedulingUnit, + schedule_unit_task : tasks, + isLoading: false, + }); }); + } else { this.setState({ - scheduleunit : scheduleunit.data, - schedule_unit_task : tasks, - isLoading: false + isLoading: false, }); - }); - }) + } + }); } } - + + getScheduleUnitTasks(type, scheduleunit){ + if(type === 'draft') + return ScheduleService.getTasksBySchedulingUnit(scheduleunit.id); + else + return ScheduleService.getTaskBlueprintsBySchedulingUnit(scheduleunit); + } + getScheduleUnit(type, id){ + if(type === 'draft') + return ScheduleService.getSchedulingUnitDraftById(id) + else + return ScheduleService.getSchedulingUnitBlueprintById(id) + } + render(){ return( <> @@ -97,7 +122,8 @@ class ViewSchedulingUnit extends Component{ </div> { this.state.isLoading ? <AppLoader/> :this.state.scheduleunit && <> - <div className="p-grid"> + <div className="main-content"> + <div className="p-grid"> <label className="col-lg-2 col-md-2 col-sm-12">Name</label> <span className="p-col-lg-4 col-md-4 col-sm-12">{this.state.scheduleunit.name}</span> <label className="col-lg-2 col-md-2 col-sm-12">Description</label> @@ -119,7 +145,7 @@ class ViewSchedulingUnit extends Component{ <label className="col-lg-2 col-md-2 col-sm-12">Template ID</label> <span className="col-lg-4 col-md-4 col-sm-12">{this.state.scheduleunit.requirements_template_id}</span> <label className="col-lg-2 col-md-2 col-sm-12">Scheduling set</label> - <span className="col-lg-4 col-md-4 col-sm-12">{this.state.scheduleunit.scheduling_set_id}</span> + <span className="col-lg-4 col-md-4 col-sm-12">{this.state.scheduleunit.scheduling_set_object.name}</span> </div> <div className="p-grid"> <label className="col-lg-2 col-md-2 col-sm-12">Duration (HH:mm:ss)</label> @@ -127,6 +153,7 @@ class ViewSchedulingUnit extends Component{ <label className="col-lg-2 col-md-2 col-sm-12">Tags</label> <Chips className="p-col-4 chips-readonly" disabled value={this.state.scheduleunit.tags}></Chips> </div> + </div> </> } diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/view.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/view.js index a8d612e25fed0eb865b57cd798a5ad8134e0d3a3..920698a47e5783b9dbf2504896800f60100d98b1 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/view.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/view.js @@ -1,7 +1,7 @@ import React, {Component} from 'react'; import {Link, Redirect} from 'react-router-dom' import moment from 'moment'; - +import _ from 'lodash'; import Jeditor from '../../components/JSONEditor/JEditor'; import TaskService from '../../services/task.service'; @@ -80,8 +80,9 @@ export class TaskView extends Component { .then((task) => { if (task) { TaskService.getSchedulingUnit(taskType, (taskType==='draft'?task.scheduling_unit_draft_id:task.scheduling_unit_blueprint_id)) - .then((schedulingUnit) => { - this.setState({schedulingUnit: schedulingUnit}); + .then((schedulingUnit) => {console.log('schedulingUnit' ,schedulingUnit) + let path = _.join(['/schedulingunit','view',((this.state.taskType === "draft")?'draft':'blueprint'),schedulingUnit.id], '/'); + this.setState({schedulingUnit: schedulingUnit, supath:path}); }); TaskService.getTaskTemplate(task.specifications_template_id) .then((taskTemplate) => { @@ -181,7 +182,7 @@ export class TaskView extends Component { {this.state.schedulingUnit && <> <label className="col-lg-2 col-md-2 col-sm-12">Scheduling Unit</label> - <Link className="col-lg-4 col-md-4 col-sm-12" to={ { pathname:'/schedulingunit/view', state: {id: this.state.schedulingUnit.id}}}>{this.state.schedulingUnit?this.state.schedulingUnit.name:''}</Link> + <Link className="col-lg-4 col-md-4 col-sm-12" to={ { pathname:this.state.supath, state: {id: this.state.schedulingUnit.id}}}>{this.state.schedulingUnit?this.state.schedulingUnit.name:''}</Link> </>} </div> <div className="p-grid"> @@ -204,7 +205,7 @@ export class TaskView extends Component { } {this.state.taskType === 'blueprint' && // <Link className="col-lg-4 col-md-4 col-sm-12" to={ { pathname:'/task/view', state: {id: this.state.task.draft_id, type: 'draft'}}}>{this.state.task.draftObject.name}</Link> - <Link className="col-lg-4 col-md-4 col-sm-12" to={ { pathname:`/task/view/draft/${this.state.task.draft_id}`}}>{this.state.task.draftObject.name}</Link> + <Link to={ { pathname:`/task/view/draft/${this.state.task.draft_id}`}}>{this.state.task.draftObject.name}</Link> } </div> </div> diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/index.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/index.js index 4aac9725ecf90e9a85e5e9f4dd07de422b6aa35e..fa0158f11db7c71fc60f61228047f8d5b2882fcd 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/routes/index.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/index.js @@ -50,6 +50,10 @@ export const routes = [ path: "/schedulingunit/view", component: ViewSchedulingUnit, name: 'Scheduling View' + },{ + path: "/schedulingunit/view/:type/:id", + component: ViewSchedulingUnit, + name: 'Scheduling View' },{ path: "/project", component: ProjectList, 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 684ca64d1a045269dc30c874019c40864af87834..519837afe2e8513dc6802b106aa77fe73181f93b 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/services/schedule.service.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/services/schedule.service.js @@ -1,5 +1,7 @@ import axios from 'axios' -import _ from 'lodash'; +import moment from 'moment'; + +import TaskService from './task.service'; axios.defaults.headers.common['Authorization'] = 'Basic dGVzdDp0ZXN0'; @@ -24,26 +26,68 @@ const ScheduleService = { }); return res; }, + getSchedulingUnitBlueprintById: async function (id){ + try { + const response = await axios.get('/api/scheduling_unit_blueprint/'+id); + let schedulingUnit = response.data; + if (schedulingUnit) { + const schedulingUnitDraft = await this.getSchedulingUnitDraftById(schedulingUnit.draft_id); + schedulingUnit.scheduling_set_id = schedulingUnitDraft.scheduling_set_id; + schedulingUnit.scheduling_set = schedulingUnitDraft.scheduling_set; + schedulingUnit.scheduling_set_object = schedulingUnitDraft.scheduling_set_object; + } + return schedulingUnit; + } catch(error) { + console.error(error); + return null; + } + }, getSchedulingUnitDraftById: async function (id){ + try { + const schedulingUnit = (await axios.get('/api/scheduling_unit_draft/'+id)).data; + const schedulingSet = (await axios.get(`/api/scheduling_set/${schedulingUnit.scheduling_set_id}`)).data; + schedulingUnit.scheduling_set_object = schedulingSet; + return schedulingUnit; + } catch(error){ + console.error('[schedule.services.getSchedulingUnitDraftById]',error); + return null; + } + }, + getTaskBlueprintById: async function(id){ let res = []; - await axios.get('/api/scheduling_unit_draft/'+id) + await axios.get('/api/task_blueprint/'+id) .then(response => { res= response; }).catch(function(error) { - console.error('[schedule.services.getSchedulingUnitDraftById]',error); + console.error('[schedule.services.getTaskBlueprintById]',error); }); return res; }, - getScheduleTasksBySchedulingUnitId: async function(id){ + getTaskBlueprintsBySchedulingUnit: async function(scheduleunit){ + // there no single api to fetch associated task_blueprint, so iteare the task_blueprint id to fetch associated task_blueprint + let taskblueprintsList = []; + if(scheduleunit.task_blueprints_ids){ + for(const id of scheduleunit.task_blueprints_ids){ + await this.getTaskBlueprintById(id).then(response =>{ + let taskblueprint = response.data; + taskblueprint['tasktype'] = 'Blueprint'; + taskblueprint['actionpath'] = '/task/view/blueprint/'+taskblueprint['id']; + taskblueprint['blueprint_draft'] = taskblueprint['draft']; + taskblueprint['relative_start_time'] = 0; + taskblueprint['relative_stop_time'] = 0; + taskblueprint.duration = moment.utc(taskblueprint.duration*1000).format('HH:mm:ss'); + taskblueprintsList.push(taskblueprint); + }) + } + } + return taskblueprintsList; + }, + getTasksBySchedulingUnit: async function(id){ let scheduletasklist=[]; - let taskblueprints = []; // Common keys for Task and Blueprint let commonkeys = ['id','created_at','description','name','tags','updated_at','url','do_cancel','relative_start_time','relative_stop_time','start_time','stop_time','duration']; - await this.getTaskBlueprints().then( blueprints =>{ - taskblueprints = blueprints.data.results; - }) await this.getTasksDraftBySchedulingUnitId(id) - .then(response =>{ + .then(async(response) =>{ for(const task of response.data.results){ let scheduletask = []; scheduletask['tasktype'] = 'Draft'; @@ -54,13 +98,12 @@ const ScheduleService = { for(const key of commonkeys){ scheduletask[key] = task[key]; } - + scheduletask.duration = moment.utc(scheduletask.duration*1000).format('HH:mm:ss'); + scheduletask.relative_start_time = moment.utc(scheduletask.relative_start_time*1000).format('HH:mm:ss'); + scheduletask.relative_stop_time = moment.utc(scheduletask.relative_stop_time*1000).format('HH:mm:ss'); //Fetch blueprint details for Task Draft - let filteredblueprints = _.filter(taskblueprints, function(o) { - if (o.draft_id === task['id']) return o; - }); - - for(const blueprint of filteredblueprints){ + const draftBlueprints = await TaskService.getDraftsTaskBlueprints(task.id); + for(const blueprint of draftBlueprints){ let taskblueprint = []; taskblueprint['tasktype'] = 'Blueprint'; taskblueprint['actionpath'] = '/task/view/blueprint/'+blueprint['id']; @@ -68,6 +111,10 @@ const ScheduleService = { for(const key of commonkeys){ taskblueprint[key] = blueprint[key]; } + taskblueprint.duration = moment.utc(taskblueprint.duration*1000).format('HH:mm:ss'); + taskblueprint.relative_start_time = moment.utc(taskblueprint.relative_start_time*1000).format('HH:mm:ss'); + taskblueprint.relative_stop_time = moment.utc(taskblueprint.relative_stop_time*1000).format('HH:mm:ss'); + //Add Blue print details to array scheduletasklist.push(taskblueprint); } diff --git a/SAS/TMSS/frontend/tmss_webapp/src/services/task.service.js b/SAS/TMSS/frontend/tmss_webapp/src/services/task.service.js index e55f34d594e5c81fd4aca1d819e9def4820155ac..bf908a57c61c92a9cb56d897a026f5ef52269b3a 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/services/task.service.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/services/task.service.js @@ -49,7 +49,8 @@ const TaskService = { }, getSchedulingUnit: async function(type, id) { try { - const response = await axios.get('/api/scheduling_unit_draft/' + id); + const url = `/api/scheduling_unit_${type}/${id}`; + const response = await axios.get(url); return response.data; } catch (error) { console.error(error);