diff --git a/SAS/TMSS/frontend/tmss_webapp/src/App.css b/SAS/TMSS/frontend/tmss_webapp/src/App.css index 6d1f1131b5899107f7cd9aa8889252455cd26e0a..766fff47baad6747a35c03a164125f8d181f5956 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/App.css +++ b/SAS/TMSS/frontend/tmss_webapp/src/App.css @@ -45,6 +45,10 @@ h3, .h3 { font-size: 1.25rem; } +h5, .h5 { + font-size: 15px !important; +} + a{ margin-bottom: 10px; } @@ -86,6 +90,20 @@ p { margin-bottom: 5px; } +.p-field { + margin-bottom: 0.5rem; +} + +.p-inputtext { + padding-top: 0.25em !important; + padding-bottom: 0.25em !important; + padding-left: 0.25em !important; +} + +.act-btn-grp { + margin-top: 20px; +} + .task-list { padding-inline-start: 0px; } diff --git a/SAS/TMSS/frontend/tmss_webapp/src/components/ViewTable.js b/SAS/TMSS/frontend/tmss_webapp/src/components/ViewTable.js index 6d8f5516ebaed9f3790fffaaeb7759868db37748..0ba1cc0c61175380c24f5c078a564fd718f3fbd8 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/components/ViewTable.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/components/ViewTable.js @@ -199,6 +199,8 @@ function Table({ columns, data, defaultheader, optionalheader }) { {row.cells.map(cell => { if(cell.column.id !== 'actionpath') return <td {...cell.getCellProps()} >{cell.render('Cell')}</td> + else + return ""; })} </tr> ) 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 aa608dabcab94707ddd8f5e515c550a4afbe8efd..c1d9019421ff16c5570e3371e8ff338342b404f7 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/ResourceInputList.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/ResourceInputList.js @@ -36,7 +36,7 @@ export class ResourceInputList extends Component { <> {this.props.list.length>0 && this.props.list.map((item, index) => ( <React.Fragment key={index+10}> - <label key={'label1-'+ index} className="col-lg-3 col-md-3 col-sm-12">{item.name}</label> + <label key={'label1-'+ index} className="col-lg-2 col-md-2 col-sm-12">{item.name}</label> <div key={'div1-'+ index} className="col-lg-3 col-md-3 col-sm-12"> <InputNumber key={'item1-'+ index} id={'item1-'+ index} name={'item1-'+ index} suffix={` ${this.props.unitMap[item.quantity_value]?this.props.unitMap[item.quantity_value].display:''}`} @@ -49,6 +49,7 @@ export class ResourceInputList extends Component { <button className="p-link" data-testid={`${item.name}-btn`} onClick={(e) => this.removeInput(item.name)}> <i className="fa fa-trash pi-error"></i></button> </div> + <div className="col-lg-1 col-md-1 col-sm-12"></div> </React.Fragment> ))} </> diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/create.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/create.js index fc07f034438730eef9d48d1691e7f8d219cafa03..e8df560a75cc56560d2eb39adc94a404697e259d 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/create.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/create.js @@ -18,6 +18,7 @@ import AppLoader from '../../layout/components/AppLoader'; import CycleService from '../../services/cycle.service'; import ProjectService from '../../services/project.service'; import UnitConverter from '../../utils/unit.converter'; +import UIConstants from '../../utils/ui.constants'; /** * Component to create a new Project @@ -61,7 +62,7 @@ export class ProjectCreate extends Component { this.projectResourceDefaults = {}; // Default values for default resources this.resourceUnitMap = UnitConverter.resourceUnitMap; // Resource unit conversion factor and constraints this.cycleOptionTemplate = this.cycleOptionTemplate.bind(this); // Template for cycle multiselect - this.tooltipOptions = {position: 'left', event: 'hover', className:"p-tooltip-custom"}; + this.tooltipOptions = UIConstants.tooltipOptions; this.setProjectQuotaDefaults = this.setProjectQuotaDefaults.bind(this); this.setProjectParams = this.setProjectParams.bind(this); @@ -349,13 +350,13 @@ export class ProjectCreate extends Component { <div className="p-fluid"> <div className="p-field p-grid" style={{display: 'none'}}> <label htmlFor="projectId" className="col-lg-2 col-md-2 col-sm-12">URL </label> - <div className="col-lg-4 col-md-4 col-sm-12"> + <div className="col-lg-3 col-md-3 col-sm-12"> <input id="projectId" data-testid="projectId" value={this.state.project.url} /> </div> </div> <div className="p-field p-grid"> <label htmlFor="projectName" className="col-lg-2 col-md-2 col-sm-12">Name <span style={{color:'red'}}>*</span></label> - <div className="col-lg-4 col-md-4 col-sm-12"> + <div className="col-lg-3 col-md-3 col-sm-12"> <InputText className={this.state.errors.name ?'input-error':''} id="projectName" data-testid="name" tooltip="Enter name of the project" tooltipOptions={this.tooltipOptions} maxLength="128" value={this.state.project.name} @@ -365,8 +366,9 @@ export class ProjectCreate extends Component { {this.state.errors.name ? this.state.errors.name : "Max 128 characters"} </label> </div> + <div className="col-lg-1 col-md-1 col-sm-12"></div> <label htmlFor="description" className="col-lg-2 col-md-2 col-sm-12">Description <span style={{color:'red'}}>*</span></label> - <div className="col-lg-4 col-md-4 col-sm-12"> + <div className="col-lg-3 col-md-3 col-sm-12"> <InputTextarea className={this.state.errors.description ?'input-error':''} rows={3} cols={30} tooltip="Short description of the project" tooltipOptions={this.tooltipOptions} maxLength="128" data-testid="description" value={this.state.project.description} @@ -379,9 +381,9 @@ export class ProjectCreate extends Component { </div> <div className="p-field p-grid"> <label htmlFor="triggerPriority" className="col-lg-2 col-md-2 col-sm-12">Trigger Priority </label> - <div className="col-lg-4 col-md-4 col-sm-12" data-testid="trig_prio"> + <div className="col-lg-3 col-md-3 col-sm-12" data-testid="trig_prio"> <InputNumber inputId="trig_prio" name="trig_prio" value={this.state.project.trigger_priority} - tooltip="Priority of this project w.r.t. triggers" tooltipOptions={this.tooltipOptions} + tooltip="Priority of this project with respect to triggers" tooltipOptions={this.tooltipOptions} mode="decimal" showButtons min={0} max={1001} step={10} useGrouping={false} onChange={(e) => this.setProjectParams('trigger_priority', e.value)} onBlur={(e) => this.setProjectParams('trigger_priority', e.target.value, 'NUMBER')} /> @@ -390,8 +392,9 @@ export class ProjectCreate extends Component { {this.state.errors.trigger_priority ? this.state.errors.trigger_priority : ""} </label> </div> + <div className="col-lg-1 col-md-1 col-sm-12"></div> <label htmlFor="trigger" className="col-lg-2 col-md-2 col-sm-12">Allows Trigger Submission</label> - <div className="col-lg-4 col-md-4 col-sm-12" data-testid="trigger"> + <div className="col-lg-3 col-md-3 col-sm-12" data-testid="trigger"> <Checkbox inputId="trigger" role="trigger" tooltip="Is this project allowed to supply observation requests on the fly, possibly interrupting currently running observations (responsive telescope)?" tooltipOptions={this.tooltipOptions} @@ -400,7 +403,7 @@ export class ProjectCreate extends Component { </div> <div className="p-field p-grid"> <label htmlFor="projCat" className="col-lg-2 col-md-2 col-sm-12">Project Category </label> - <div className="col-lg-4 col-md-4 col-sm-12" data-testid="projCat" > + <div className="col-lg-3 col-md-3 col-sm-12" data-testid="projCat" > <Dropdown inputId="projCat" optionLabel="value" optionValue="url" tooltip="Project Category" tooltipOptions={this.tooltipOptions} value={this.state.project.project_category} @@ -408,8 +411,9 @@ export class ProjectCreate extends Component { onChange={(e) => {this.setProjectParams('project_category', e.value)}} placeholder="Select Project Category" /> </div> + <div className="col-lg-1 col-md-1 col-sm-12"></div> <label htmlFor="periodCategory" className="col-lg-2 col-md-2 col-sm-12">Period Category</label> - <div className="col-lg-4 col-md-4 col-sm-12"> + <div className="col-lg-3 col-md-3 col-sm-12"> <Dropdown data-testid="period-cat" id="period-cat" optionLabel="value" optionValue="url" tooltip="Period Category" tooltipOptions={this.tooltipOptions} value={this.state.project.period_category} @@ -420,7 +424,7 @@ export class ProjectCreate extends Component { </div> <div className="p-field p-grid"> <label htmlFor="triggerPriority" className="col-lg-2 col-md-2 col-sm-12">Cycle(s)</label> - <div className="col-lg-4 col-md-4 col-sm-12"> + <div className="col-lg-3 col-md-3 col-sm-12"> <MultiSelect data-testid="cycle" id="cycle" optionLabel="name" optionValue="url" filter={true} tooltip="Cycle(s) to which this project belongs" tooltipOptions={this.tooltipOptions} value={this.state.project.cycles} @@ -429,10 +433,11 @@ export class ProjectCreate extends Component { /> </div> + <div className="col-lg-1 col-md-1 col-sm-12"></div> <label htmlFor="projRank" className="col-lg-2 col-md-2 col-sm-12">Project Rank <span style={{color:'red'}}>*</span></label> - <div className="col-lg-4 col-md-4 col-sm-12" data-testid="proj-rank" > + <div className="col-lg-3 col-md-3 col-sm-12" data-testid="proj-rank" > <InputNumber inputId="proj-rank" name="rank" data-testid="rank" value={this.state.project.priority_rank} - tooltip="Priority of this project w.r.t. other projects. Projects can interrupt observations of lower-priority projects." + tooltip="Priority of this project with respect to other projects. Projects can interrupt observations of lower-priority projects." tooltipOptions={this.tooltipOptions} mode="decimal" showButtons min={0} max={100} onChange={(e) => this.setProjectParams('priority_rank', e.value)} @@ -446,18 +451,20 @@ export class ProjectCreate extends Component { {this.defaultResourcesEnabled && this.state.resourceList && <div className="p-fluid"> <div className="p-field p-grid"> - <div className="col-lg-3 col-md-3 col-sm-112"> + <div className="col-lg-2 col-md-2 col-sm-112"> <h5 data-testid="resource_alloc">Resource Allocations</h5> </div> <div className="col-lg-3 col-md-3 col-sm-10"> <Dropdown optionLabel="name" optionValue="name" + tooltip="Resources to be allotted for the project" + tooltipOptions={this.tooltipOptions} value={this.state.newResource} options={this.state.resourceList} onChange={(e) => {this.setState({'newResource': e.value})}} placeholder="Add Resources" /> </div> <div className="col-lg-2 col-md-2 col-sm-2"> - <Button label="" className="p-button-primary" icon="pi pi-plus" onClick={this.addNewResource} data-testid="add_res_btn" /> + <Button label="" className="p-button-primary" icon="pi pi-plus" onClick={this.addNewResource} disabled={!this.state.newResource} data-testid="add_res_btn" /> </div> </div> <div className="p-field p-grid resource-input-grid"> @@ -469,7 +476,7 @@ export class ProjectCreate extends Component { } </div> </div> - <div className="p-grid p-justify-start"> + <div className="p-grid p-justify-start act-btn-grp"> <div className="col-lg-1 col-md-2 col-sm-6"> <Button label="Save" className="p-button-primary" id="save-btn" data-testid="save-btn" icon="pi pi-check" onClick={this.saveProject} disabled={!this.state.validForm} /> </div> diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/edit.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/edit.js index 54672a71a6834f7fb9be9875e28f95ecd065979b..78b443a5c2d1eb457b3806a0cc4fe89e3fd2ab99 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/edit.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/edit.js @@ -18,6 +18,7 @@ import AppLoader from '../../layout/components/AppLoader'; import CycleService from '../../services/cycle.service'; import ProjectService from '../../services/project.service'; import UnitConverter from '../../utils/unit.converter'; +import UIConstants from '../../utils/ui.constants'; export class ProjectEdit extends Component { constructor(props) { @@ -57,6 +58,7 @@ export class ProjectEdit extends Component { {name:'LOFAR Support hours'} ]; this.projectResourceDefaults = {}; this.resourceUnitMap = UnitConverter.resourceUnitMap; + this.tooltipOptions = UIConstants.tooltipOptions; this.getProjectDetails = this.getProjectDetails.bind(this); this.cycleOptionTemplate = this.cycleOptionTemplate.bind(this); @@ -156,8 +158,9 @@ export class ProjectEdit extends Component { if (this.state.newResource) { let resourceList = this.state.resourceList; const newResource = _.remove(resourceList, {'name': this.state.newResource}); - let resources = this.state.resources; + let resources = this.state.resources?this.state.resources:[]; resources.push(newResource[0]); + console.log(resources); this.setState({resources: resources, resourceList: resourceList, newResource: null}); } } @@ -372,30 +375,34 @@ export class ProjectEdit extends Component { <div className="p-fluid"> <div className="p-field p-grid"> <label htmlFor="projectName" className="col-lg-2 col-md-2 col-sm-12">Name <span style={{color:'red'}}>*</span></label> - <div className="col-lg-4 col-md-4 col-sm-12"> + <div className="col-lg-3 col-md-3 col-sm-12"> <InputText className={this.state.errors.name ?'input-error':''} id="projectName" data-testid="name" + tooltip="Enter name of the project" tooltipOptions={this.tooltipOptions} maxLength="128" value={this.state.project.name} onChange={(e) => this.setProjectParams('name', e.target.value)} onBlur={(e) => this.setProjectParams('name', e.target.value)}/> - <label className="error"> - {this.state.errors.name ? this.state.errors.name : ""} + <label className={this.state.errors.name?"error":"info"}> + {this.state.errors.name ? this.state.errors.name : "Max 128 characters"} </label> </div> + <div className="col-lg-1 col-md-1 col-sm-12"></div> <label htmlFor="description" className="col-lg-2 col-md-2 col-sm-12">Description <span style={{color:'red'}}>*</span></label> - <div className="col-lg-4 col-md-4 col-sm-12"> + <div className="col-lg-3 col-md-3 col-sm-12"> <InputTextarea className={this.state.errors.description ?'input-error':''} rows={3} cols={30} + tooltip="Short description of the project" tooltipOptions={this.tooltipOptions} maxLength="128" data-testid="description" value={this.state.project.description} onChange={(e) => this.setProjectParams('description', e.target.value)} onBlur={(e) => this.setProjectParams('description', e.target.value)}/> - <label className="error"> - {this.state.errors.description ? this.state.errors.description : ""} + <label className={this.state.errors.description ?"error":"info"}> + {this.state.errors.description ? this.state.errors.description : "Max 255 characters"} </label> </div> </div> <div className="p-field p-grid"> <label htmlFor="triggerPriority" className="col-lg-2 col-md-2 col-sm-12">Trigger Priority </label> - <div className="col-lg-4 col-md-4 col-sm-12"> + <div className="col-lg-3 col-md-3 col-sm-12"> <InputNumber inputId="trig_prio" name="trig_prio" className={this.state.errors.name ?'input-error':''} + tooltip="Priority of this project with respect to triggers" tooltipOptions={this.tooltipOptions} value={this.state.project.trigger_priority} showButtons min={0} max={1001} step={10} useGrouping={false} onChange={(e) => this.setProjectParams('trigger_priority', e.value)} @@ -404,23 +411,30 @@ export class ProjectEdit extends Component { {this.state.errors.trigger_priority ? this.state.errors.trigger_priority : ""} </label> </div> + <div className="col-lg-1 col-md-1 col-sm-12"></div> <label htmlFor="trigger" className="col-lg-2 col-md-2 col-sm-12">Allows Trigger Submission</label> - <div className="col-lg-4 col-md-4 col-sm-12"> - <Checkbox inputId="trigger" role="trigger" checked={this.state.project.can_trigger} onChange={e => this.setProjectParams('can_trigger', e.target.checked)}></Checkbox> + <div className="col-lg-3 col-md-3 col-sm-12"> + <Checkbox inputId="trigger" role="trigger" + tooltip="Is this project allowed to supply observation requests on the fly, possibly interrupting currently running observations (responsive telescope)?" + tooltipOptions={this.tooltipOptions} + checked={this.state.project.can_trigger} onChange={e => this.setProjectParams('can_trigger', e.target.checked)}></Checkbox> </div> </div> <div className="p-field p-grid"> <label htmlFor="projCategory" className="col-lg-2 col-md-2 col-sm-12">Project Category </label> - <div className="col-lg-4 col-md-4 col-sm-12"> + <div className="col-lg-3 col-md-3 col-sm-12"> <Dropdown inputId="projCat" optionLabel="value" optionValue="url" + tooltip="Project Category" tooltipOptions={this.tooltipOptions} value={this.state.project.project_category} options={this.state.projectCategories} onChange={(e) => {this.setProjectParams('project_category', e.value)}} placeholder="Select Project Category" /> </div> + <div className="col-lg-1 col-md-1 col-sm-12"></div> <label htmlFor="periodCategory" className="col-lg-2 col-md-2 col-sm-12">Period Category</label> - <div className="col-lg-4 col-md-4 col-sm-12"> + <div className="col-lg-3 col-md-3 col-sm-12"> <Dropdown data-testid="period-cat" id="period-cat" optionLabel="value" optionValue="url" + tooltip="Period Category" tooltipOptions={this.tooltipOptions} value={this.state.project.period_category} options={this.state.periodCategories} onChange={(e) => {this.setProjectParams('period_category',e.value)}} @@ -429,17 +443,21 @@ export class ProjectEdit extends Component { </div> <div className="p-field p-grid"> <label htmlFor="triggerPriority" className="col-lg-2 col-md-2 col-sm-12">Cycle(s)</label> - <div className="col-lg-4 col-md-4 col-sm-12"> + <div className="col-lg-3 col-md-3 col-sm-12"> <MultiSelect data-testid="cycle" id="cycle" optionLabel="name" optionValue="url" filter={true} + tooltip="Cycle(s) to which this project belongs" tooltipOptions={this.tooltipOptions} value={this.state.project.cycles} options={this.state.cycles} onChange={(e) => {this.setProjectParams('cycles',e.value)}} /> </div> + <div className="col-lg-1 col-md-1 col-sm-12"></div> <label htmlFor="projRank" className="col-lg-2 col-md-2 col-sm-12">Project Rank <span style={{color:'red'}}>*</span></label> - <div className="col-lg-4 col-md-4 col-sm-12"> + <div className="col-lg-3 col-md-3 col-sm-12"> <InputNumber inputId="proj-rank" name="rank" data-testid="rank" value={this.state.project.priority_rank} + tooltip="Priority of this project with respect to other projects. Projects can interrupt observations of lower-priority projects." + tooltipOptions={this.tooltipOptions} mode="decimal" showButtons min={0} max={100} onChange={(e) => this.setProjectParams('priority_rank', e.value)} onBlur={(e) => this.setProjectParams('priority_rank', e.target.value, 'NUMBER')} /> @@ -451,32 +469,34 @@ export class ProjectEdit extends Component { {this.state.resourceList && <div className="p-fluid"> <div className="p-field p-grid"> - <div className="col-lg-3 col-md-3 col-sm-112"> + <div className="col-lg-2 col-md-2 col-sm-12"> <h5>Resource Allocations:</h5> </div> <div className="col-lg-3 col-md-3 col-sm-10"> <Dropdown optionLabel="name" optionValue="name" + tooltip="Resources to be allotted for the project" + tooltipOptions={this.tooltipOptions} value={this.state.newResource} options={_.sortBy(this.state.resourceList, ['name'])} onChange={(e) => {this.setState({'newResource': e.value})}} placeholder="Add Resources" /> </div> <div className="col-lg-2 col-md-2 col-sm-2"> - <Button label="" className="p-button-primary" icon="pi pi-plus" onClick={this.addNewResource} data-testid="add_res_btn" /> + <Button label="" className="p-button-primary" icon="pi pi-plus" onClick={this.addNewResource} disabled={!this.state.newResource} data-testid="add_res_btn" /> </div> </div> - {_.keys(this.state.projectQuota).length>0 && + {/* {_.keys(this.state.projectQuota).length>0 && */} <div className="p-field p-grid resource-input-grid"> <ResourceInputList list={this.state.resources} unitMap={this.resourceUnitMap} projectQuota={this.state.projectQuota} callback={this.setProjectQuotaParams} removeInputCallback={this.removeResource} /> </div> - } + {/* } */} </div> } </div> </div> - <div className="p-grid p-justify-start"> + <div className="p-grid p-justify-start act-btn-grp"> <div className="p-col-1"> <Button label="Save" className="p-button-primary" id="save-btn" data-testid="save-btn" icon="pi pi-check" onClick={this.saveProject} disabled={!this.state.validForm} /> </div> diff --git a/SAS/TMSS/frontend/tmss_webapp/src/services/project.service.js b/SAS/TMSS/frontend/tmss_webapp/src/services/project.service.js index 36bc7a17016df8168cc36f7167a20d0c38e1aee2..18598cc1c90e304931d4f4e55c1a4c39a4d6c69e 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/services/project.service.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/services/project.service.js @@ -183,7 +183,8 @@ const ProjectService = { project['actionpath']= '/project/view'; projects[index] = project; } - }) + return pro; + }); } }); results.projects = projects; diff --git a/SAS/TMSS/frontend/tmss_webapp/src/utils/ui.constants.js b/SAS/TMSS/frontend/tmss_webapp/src/utils/ui.constants.js new file mode 100644 index 0000000000000000000000000000000000000000..732079588cf68c3938c6dc9efb8e86d029b3bb98 --- /dev/null +++ b/SAS/TMSS/frontend/tmss_webapp/src/utils/ui.constants.js @@ -0,0 +1,5 @@ +const UIConstants = { + tooltipOptions: {position: 'left', event: 'hover', className:"p-tooltip-custom"} +} + +export default UIConstants; \ No newline at end of file