diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Workflow/qa.reporting.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Workflow/qa.reporting.js index 63855e672b7bf6b7e905344b9f0f5b78f49e41a5..6ea48a86a5fff8cbe77f49c4db9ea411de5f9c8d 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Workflow/qa.reporting.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Workflow/qa.reporting.js @@ -7,6 +7,7 @@ import { Checkbox } from 'primereact/checkbox'; import QaReportingTemplate from './qa.reporting.template'; import { Link } from 'react-router-dom'; import TaskAssigner from './task.assigner'; +import AppLoader from '../../layout/components/AppLoader'; //import katex from 'katex' // for mathematical operations on sun editor this component should be added //import 'katex/dist/katex.min.css' @@ -18,7 +19,8 @@ class QAreporting extends Component{ this.state={ content: '', assignTo: '', - operator_accept: true + operator_accept: true, + templateLoading: true }; this.Next = this.Next.bind(this); this.handleChange = this.handleChange.bind(this); @@ -26,8 +28,6 @@ class QAreporting extends Component{ } async componentDidMount() { - let defaultTemplate = await QaReportingTemplate.getReportTemplate(this.props.id) - this.setState({defaultTemplate : defaultTemplate}) if (this.props.readOnly) { const QAreportingresponse = await WorkflowService.getQAReportingTo(this.props.process.qa_reporting_to); this.setState({ @@ -36,8 +36,11 @@ class QAreporting extends Component{ assignTo: this.props.workflowTask?this.props.workflowTask.owner:'' // Temporary value. This should be taken from ProcessTask owner. }); } else { + const defaultTemplate = await QaReportingTemplate.getReportTemplate(this.props.id) const currentWorkflowTask = await this.props.getCurrentTaskDetails(); - this.setState({assignTo: currentWorkflowTask.fields.owner, currentWorkflowTask: currentWorkflowTask}); + this.setState({defaultTemplate: defaultTemplate, templateLoading: false, + assignTo: currentWorkflowTask.fields.owner, + currentWorkflowTask: currentWorkflowTask}); } } @@ -123,17 +126,24 @@ class QAreporting extends Component{ </>} </label> <div className="col-lg-12 col-md-12 col-sm-12"></div> - {!this.props.readOnly && <SunEditor setDefaultStyle="min-height: 250px; height: auto;" enableToolbar={true} disabled={this.props.readOnly} - onChange={ this.handleChange } - setContents={this.state.defaultTemplate} - setOptions={{ - buttonList: [ - ['undo', 'redo', 'bold', 'underline', 'fontColor', 'table', 'link', 'image', 'video', 'italic', 'strike', 'subscript', - 'superscript', 'outdent', 'indent', 'fullScreen', 'showBlocks', 'codeView', 'preview', 'print', 'removeFormat'] - ] - }} />} - {!this.state.showEditor && <div onClick={() => !this.props.readOnly && this.setState({ showEditor: !this.state.showEditor })} className="operator-report"></div>} - {this.props.readOnly &&<div class="comment-editor-content" dangerouslySetInnerHTML={{ __html: this.state.content }}></div>} + {!this.props.readOnly && + <> + {this.state.templateLoading?<AppLoader />: + <SunEditor setDefaultStyle="min-height: 250px; height: auto;" enableToolbar={true} disabled={this.props.readOnly} + onChange={ this.handleChange } + setContents={this.state.defaultTemplate} + setOptions={{ + buttonList: [ + ['undo', 'redo', 'bold', 'underline', 'fontColor', 'table', 'link', 'image', 'video', 'italic', 'strike', 'subscript', + 'superscript', 'outdent', 'indent', 'fullScreen', 'showBlocks', 'codeView', 'preview', 'print', 'removeFormat'] + ] + }} /> + } + </> + } + + {!this.state.showEditor && <div onClick={() => !this.props.readOnly && this.setState({ showEditor: !this.state.showEditor })} className="operator-report"></div>} + {this.props.readOnly &&<div class="comment-editor-content" dangerouslySetInnerHTML={{ __html: this.state.content }}></div>} </div> <div className="p-col-12"> <Checkbox disabled={this.props.readOnly} inputId="operator_accept" onChange={e => this.setState({operator_accept: e.checked})} checked={this.state.operator_accept}></Checkbox> diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Workflow/qa.reporting.template.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Workflow/qa.reporting.template.js index d4f2f26969318cb9a013c7a6f5324a232f953a56..68d40a07a634460d61a09992464cf9ef85d1b979 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Workflow/qa.reporting.template.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Workflow/qa.reporting.template.js @@ -14,22 +14,39 @@ const QaReportingTemplate = { */ getReportTemplate : async function(id) { const SUB = await ScheduleService.getSchedulingUnitExtended('blueprint', id); + let dataproducts = await ScheduleService.getSUDataproducts(id); let cycleName = SUB.scheduling_set_object.project.cycles_ids.join(", "); let tasks = SUB.task_blueprints; let project_id = SUB.scheduling_set_object.project_id; let observations = [] - for (let task of tasks){ + for (let task of tasks) { let observation = { pipeline: [] }; if (task.task_type === "observation") { const taskSuccessors = await TaskService.getTaskSuccessors('blueprint', task.id) + let taskDataproducts = _.find(dataproducts.task_blueprints, {'id': task.id}) for(const successor of taskSuccessors) { - if(successor.task_type === "pipeline"){ + if(successor.task_type === "pipeline") { observation.pipeline.push(successor.id); } } + let taskDP = []; + let completeness = []; + // From the dataproducts of all subtasks of the task filter the ones with feedback to get number of files with feedback. + // Calculate the completeness from the percentage written in the feedback + for (const subtask of taskDataproducts.subtasks) { + const dataproducts = _.filter(subtask.output_dataproducts, dataproduct => { + if (dataproduct.feedback_doc && dataproduct.feedback_doc.percentage_written) { + completeness.push(dataproduct.feedback_doc.percentage_written); + } + return dataproduct.feedback_doc?true:false; + }); + taskDP.push(...dataproducts); + } + observation.dataproducts = taskDP.length; + observation.completeness = _.mean(completeness) || 0; let subtasks = _.filter(task.subtasks, ['subtask_type', 'observation']); for (const subtask of subtasks) { observation.controlId = subtask.id; @@ -43,14 +60,10 @@ const QaReportingTemplate = { observation.targetname = task.specifications_doc.SAPs ? task.specifications_doc.SAPs.map(sap => sap.name): []; observation.targetname = observation.targetname.join(", "); - // TODO: Actual value has to be calculated - observation.completeness = "90%"; observation.subbands = task.specifications_doc.SAPs ? task.specifications_doc.SAPs.map(sap => sap.subbands.length): []; observation.subbands = observation.subbands.join(", "); - // TODO: Actual values ha to be identified - observation.dataproducts = subtask.output_dataproducts.length; - observations.push(observation) + observations.push(observation); } } } @@ -66,7 +79,7 @@ const QaReportingTemplate = { <td>${observation.project}</td> <td>${observation.targetname}</td> <td><a href="https://proxy.lofar.eu/inspect/HTML/${observation.controlId}/Stations/station_beamlets.html">BST</a></td> - <td><a href="https://proxy.lofar.eu/inspect/HTML/${observation.controlId}/index.html">90%</a></td> + <td><a href="https://proxy.lofar.eu/inspect/HTML/${observation.controlId}/index.html">${observation.completeness}%</a></td> <td>${observation.antenna}</td> <td>${observation.filter}</td> <td>${observation.startTime}</td> 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 740ec7b3f8c95ac01f47bc11f8632aa81ca94fbf..b30309c050fdb1f1c06c0791dcc3293c988c91ea 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/services/schedule.service.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/services/schedule.service.js @@ -1026,7 +1026,21 @@ const ScheduleService = { console.error('[schedule.services.updateSchedulingUnit]',"Mistake", error); return null } - } + }, + getSUDataproducts: async function (id) { + let response = {}; + try { + let url = `/api/scheduling_unit_blueprint/${id}/?expand=task_blueprints,task_blueprints.subtasks,task_blueprints.subtasks.output_dataproducts`+ + `&fields=task_blueprints.id,task_blueprints.subtasks.id,task_blueprints.subtasks.output_dataproducts.feedback_doc`; + response = await axios.get(url); + return response.data; + + } catch (error) { + console.error('[schedule.services.getSUDataproduct]', error); + return null; + } + } + }