ErrorReport-Working.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. //© 2019 Dublin City University, Trinity College Dublin. All rights reserved. This material may not be reproduced, displayed, modified or distributed without the express prior written permission of the copyright holder.
  2. import React, { Component } from 'react';
  3. import {
  4. Modal,
  5. ModalHeader,
  6. ModalBody,
  7. ModalFooter,
  8. Button,
  9. Row,
  10. Col,
  11. ListGroup,
  12. TabContent,
  13. Card,
  14. CardBody
  15. } from 'reactstrap';
  16. import { connect } from 'react-redux';
  17. import { read } from '../../../services/tripleStoreAPIs/readFromTripleStore';
  18. import { getErrorReportForModelDefault } from '../../../services/tripleStoreAPIs/sparql/problemReport/getErrorReportForModelDefault';
  19. import { getErrorReportForModelProblematicTriple } from '../../../services/tripleStoreAPIs/sparql/problemReport/getErrorReportForModelProblematicTriple';
  20. import { getErrorReportForResource } from '../../../services/tripleStoreAPIs/sparql/problemReport/getErrorReportForResource';
  21. import { getErrorReportForQuad } from '../../../services/tripleStoreAPIs/sparql/problemReport/getErrorReportForQuad';
  22. import ListOfProblems from './ListOfProblems';
  23. import ResourcesFailedForProblem from './ResourcesFailedForProblem';
  24. import LoadingSpinner from '../loading';
  25. import LoadingFailed from '../loadingFailed';
  26. import metricExceptionMapping from '../../../config/metricKnowledgeBaseMapping';
  27. class ErrorReport extends Component {
  28. constructor(props) {
  29. super(props);
  30. this.state = {
  31. isloading: false,
  32. loadFailed: false,
  33. totalNumberOfTriplesWithProblem: 0,
  34. listOfExceptionsWithCount: [],
  35. listOfProblematicThings: [],
  36. listOfRelatedFailedMetrics:[],
  37. activeTab: 0
  38. }
  39. }
  40. toggleActiveTab = (tab) => {
  41. if (this.state.activeTab !== tab) {
  42. this.setState({
  43. activeTab: tab,
  44. listOfRelatedFailedMetrics:[]
  45. });
  46. }
  47. }
  48. componentDidMount() {
  49. let indexOfMetric = this.props.datasetDetailsCache[0].lastAssessmentMetrics.findIndex((assessment) => { return assessment.Metric.value === this.props.metricURI });
  50. if (this.props.datasetDetailsCache[0].lastAssessmentMetrics[indexOfMetric].errorReport === undefined) {
  51. this.setState({ isloading: true }, () => {
  52. this.prepareErrorReportCache(indexOfMetric, this.props.datasetDetailsCache[0].lastAssessmentMetrics[indexOfMetric].ProblemStructure.value.split("#")[1], this.props.datasetDetailsCache[0].lastAssessmentMetrics[indexOfMetric].Metric.value.split("#")[1]).then(() => {
  53. this.setState(
  54. {
  55. isloading: false
  56. }, () => {
  57. if (this.props.datasetDetailsCache[0].lastAssessmentMetrics[indexOfMetric].errorReport !== undefined) {
  58. this.prepareUI(indexOfMetric);
  59. }
  60. }
  61. );
  62. })
  63. });
  64. }
  65. else {
  66. if (this.props.datasetDetailsCache[0].lastAssessmentMetrics[indexOfMetric].errorReport !== undefined) {
  67. this.prepareUI(indexOfMetric);
  68. }
  69. }
  70. }
  71. prepareUI = async (indexOfMetric) => {
  72. let totalNumberOfTriplesWithProblem = await this.prepareTotalNumberOfTriplesWithProblem(indexOfMetric);
  73. let listOfExceptionsWithCount = await this.prepareListOfExceptionsWithCount(indexOfMetric);
  74. let listOfProblematicThings = await this.prepareListOfProblematicThings(indexOfMetric);
  75. this.setState({
  76. totalNumberOfTriplesWithProblem: totalNumberOfTriplesWithProblem,
  77. listOfExceptionsWithCount: listOfExceptionsWithCount,
  78. listOfProblematicThings: listOfProblematicThings
  79. });
  80. }
  81. prepareTotalNumberOfTriplesWithProblem = (indexOfMetric) => {
  82. let exceptions = Object.keys(this.props.datasetDetailsCache[0].lastAssessmentMetrics[indexOfMetric].errorReport);
  83. let count = 0;
  84. for (let exception of exceptions) {
  85. count += this.props.datasetDetailsCache[0].lastAssessmentMetrics[indexOfMetric].errorReport[exception].count;
  86. }
  87. return count;
  88. }
  89. prepareListOfExceptionsWithCount = (indexOfMetric) => {
  90. let exceptions = Object.keys(this.props.datasetDetailsCache[0].lastAssessmentMetrics[indexOfMetric].errorReport);
  91. let listOfExceptions = [];
  92. for (let exception of exceptions) {
  93. listOfExceptions.push({
  94. [exception]: this.props.datasetDetailsCache[0].lastAssessmentMetrics[indexOfMetric].errorReport[exception].count
  95. });
  96. }
  97. return listOfExceptions;
  98. }
  99. prepareListOfProblematicThings = (indexOfMetric) => {
  100. let exceptions = Object.keys(this.props.datasetDetailsCache[0].lastAssessmentMetrics[indexOfMetric].errorReport);
  101. let listOfProblematicThings = [];
  102. for (let exception of exceptions) {
  103. let problematicThings = Object.keys(this.props.datasetDetailsCache[0].lastAssessmentMetrics[indexOfMetric].errorReport[exception].ProblematicThing);
  104. for (let problematicThing of problematicThings) {
  105. listOfProblematicThings.push({
  106. [problematicThing]: [(this.props.datasetDetailsCache[0].lastAssessmentMetrics[indexOfMetric].errorReport[exception].ProblematicThing[problematicThing].filter(resource => resource !== "")).length,exception]
  107. });
  108. }
  109. }
  110. return listOfProblematicThings;
  111. }
  112. prepareErrorReportCache = async (index, problemStrucure, metricURI) => {
  113. let errorReport = null;
  114. if (problemStrucure === "ModelContainer") {
  115. let functionToCall = getErrorReportForModelDefault;
  116. let listOfExceptions = "";
  117. let listOfHasExceptions = "";
  118. switch (metricURI) {
  119. case "UsageOfIncorrectDomainOrRangeDatatypesMetric":
  120. functionToCall = getErrorReportForModelProblematicTriple;
  121. break;
  122. default:
  123. functionToCall = getErrorReportForModelDefault;
  124. if(metricExceptionMapping.knowledgeBaseMapping[metricURI]!==undefined)
  125. {
  126. let exceptions = Object.keys(metricExceptionMapping.knowledgeBaseMapping[metricURI]).map((exception)=> "dqm-prob:"+exception);
  127. listOfExceptions = exceptions.join(", ") ;
  128. let hasExceptions = Object.keys(metricExceptionMapping.knowledgeBaseMapping[metricURI]).map((exception)=> "dqm-prob:has"+exception);
  129. listOfHasExceptions = hasExceptions.join(", ");
  130. }
  131. }
  132. if(listOfExceptions==="")
  133. {
  134. errorReport = await read(functionToCall(this.props.datasetDetailsCache[0].lastAssessmentMetrics[index].ProblemGraph.value, this.props.datasetDetailsCache[0].lastAssessmentMetrics[index].ObservationURI.value)).then((response) => {
  135. if (response) {
  136. if (response.results.bindings.length > 0) {
  137. return response;
  138. }
  139. }
  140. return null;
  141. });
  142. }
  143. else
  144. {
  145. errorReport = await read(functionToCall(this.props.datasetDetailsCache[0].lastAssessmentMetrics[index].ProblemGraph.value, this.props.datasetDetailsCache[0].lastAssessmentMetrics[index].ObservationURI.value, listOfExceptions, listOfHasExceptions)).then((response) => {
  146. if (response) {
  147. if (response.results.bindings.length > 0) {
  148. return response;
  149. }
  150. }
  151. return null;
  152. });
  153. }
  154. }
  155. else if (problemStrucure === "ResourceContainer") {
  156. errorReport = await read(getErrorReportForResource(this.props.datasetDetailsCache[0].lastAssessmentMetrics[index].ProblemGraph.value, this.props.datasetDetailsCache[0].lastAssessmentMetrics[index].ObservationURI.value)).then((response) => {
  157. if (response) {
  158. if (response.results.bindings.length > 0) {
  159. return response;
  160. }
  161. }
  162. return null;
  163. });
  164. }
  165. else if (problemStrucure === "QuadContainer") {
  166. errorReport = await read(getErrorReportForQuad(this.props.datasetDetailsCache[0].lastAssessmentMetrics[index].ProblemGraph.value, this.props.datasetDetailsCache[0].lastAssessmentMetrics[index].ObservationURI.value)).then((response) => {
  167. if (response) {
  168. if (response.results.bindings.length > 0) {
  169. return response;
  170. }
  171. }
  172. return null;
  173. });
  174. }
  175. if (errorReport !== null) {
  176. let cache = {};
  177. for (let error of errorReport.results.bindings) {
  178. let exception = error.Exception.value;
  179. let problematicThing = "";
  180. if (error.ProblematicThing !== undefined) {
  181. problematicThing = error.ProblematicThing.value;
  182. }
  183. let problematicThingResource = "";
  184. if (error.ProblematicThingResource !== undefined) {
  185. problematicThingResource = error.ProblematicThingResource.value;
  186. }
  187. //Exception Key doesn't exists
  188. if (!(exception in cache)) {
  189. cache[exception] = {
  190. count: 1,
  191. ProblematicThing: {
  192. [problematicThing]: [problematicThingResource]
  193. }
  194. };
  195. }
  196. else {
  197. cache[exception].count += 1;
  198. //Exception Key exists but problematicThing doesn't exists
  199. if (!(problematicThing in cache[exception].ProblematicThing)) {
  200. cache[exception].ProblematicThing = {
  201. ...cache[exception].ProblematicThing,
  202. [problematicThing]: [problematicThingResource]
  203. };
  204. }
  205. else {
  206. cache[exception].ProblematicThing[problematicThing].push(problematicThingResource);
  207. }
  208. }
  209. }
  210. await this.props.updateErrorReportCache(cache, Number(this.props.datasetID), index);
  211. }
  212. return;
  213. }
  214. listRelatedProblems=(listOfRelatedMetrics)=>{
  215. this.setState({
  216. listOfRelatedFailedMetrics:listOfRelatedMetrics
  217. });
  218. }
  219. render() {
  220. //console.log(this.state);
  221. let listOfRelatedFailedMetricsToDisplay=null;
  222. if(this.state.listOfRelatedFailedMetrics.length>0)
  223. {
  224. if(this.state.listOfRelatedFailedMetrics.length===1 & this.state.listOfRelatedFailedMetrics[0]==="")
  225. {
  226. //Nothing to do
  227. }
  228. else {
  229. listOfRelatedFailedMetricsToDisplay= this.state.listOfRelatedFailedMetrics.map((metric, index) => {
  230. if(metric!=="")
  231. {
  232. return <li key={index}>{metric}</li>
  233. }
  234. });
  235. }
  236. }
  237. return (
  238. <Modal isOpen={true} className="modal-dialog-centered modal-lg">
  239. <ModalHeader style={{ margin: 'auto' }}>Problem Report</ModalHeader>
  240. <ModalBody>
  241. <Row>
  242. <Col xs="4">
  243. <Card className="w-100" style={{overflow: 'scroll', height:'43rem'}}>
  244. <p className="text-center font-weight-bold">List of Problematic Instances</p>
  245. <ListGroup id="problemList" role="tablist" className="flex-column align-items-start">
  246. <ListOfProblems toggle={this.toggleActiveTab} activeTab={this.state.activeTab} listOfProblems={this.state.listOfProblematicThings} />
  247. </ListGroup>
  248. </Card>
  249. </Col>
  250. <Col xs="8">
  251. <Row>
  252. <Card className="w-100">
  253. <p className="text-center font-weight-bold">Problematic Instance Details</p>
  254. <TabContent activeTab={this.state.activeTab}>
  255. <ResourcesFailedForProblem listOfProblems={this.state.listOfProblematicThings} datasetID={this.props.datasetDetailsCache[0].datasetID} metricURI={this.props.metricURI} activeTab={this.state.activeTab} callBack={this.listRelatedProblems}/>
  256. </TabContent>
  257. </Card>
  258. </Row>
  259. <Row>
  260. <Card className="w-100" style={{overflow: 'scroll', height:'10rem'}}>
  261. <p className="text-center font-weight-bold">All Metric(s) failed for the selected Resource</p>
  262. <CardBody>
  263. {listOfRelatedFailedMetricsToDisplay}
  264. </CardBody>
  265. </Card>
  266. </Row>
  267. </Col>
  268. </Row>
  269. </ModalBody>
  270. {this.state.isloading ? <LoadingSpinner /> : null}
  271. <ModalFooter>
  272. <Button color="secondary" onClick={this.props.onCloseButtonClick}>Close</Button>
  273. </ModalFooter>
  274. </Modal>
  275. );
  276. }
  277. }
  278. const mapStateToProps = (state, ownProps) => {
  279. let datasetID = Number(ownProps.datasetID);
  280. let datasetDetails = state.datasetDetailsCache.filter((dataset) => { if (dataset.datasetID === datasetID) { return dataset; } return null; });
  281. return (
  282. {
  283. datasetDetailsCache: datasetDetails
  284. }
  285. );
  286. }
  287. const mapDispatchToProps = (dispatch) => {
  288. return ({
  289. updateErrorReportCache: (errorReport, datasetID, metricIndex) => { return dispatch({ type: 'UPDATE_METRIC_ERROR_REPORT_CACHE', payLoad: { errorReport: errorReport, datasetID: datasetID, metricIndex: metricIndex } }); }
  290. }
  291. );
  292. }
  293. export default connect(mapStateToProps, mapDispatchToProps)(ErrorReport);