diff --git a/assets/js/Components/UfixitModal.js b/assets/js/Components/UfixitModal.js
index cfa1e03f..5a51b043 100644
--- a/assets/js/Components/UfixitModal.js
+++ b/assets/js/Components/UfixitModal.js
@@ -32,6 +32,7 @@ class UfixitModal extends React.Component {
this.state = {
windowContents: 'preview',
expandExample: false,
+ issueDetailsPending: true
}
this.modalMessages = []
@@ -46,6 +47,22 @@ class UfixitModal extends React.Component {
this.handleManualScan = this.handleManualScan.bind(this)
}
+ componentDidMount() {
+ this.syncIssue(this.props.activeIssue)
+ }
+
+ componentDidUpdate(prevProps, prevState) {
+ if (prevProps.activeIssue.id != this.props.activeIssue.id) {
+ this.setState({
+ windowContents: 'preview',
+ expandExample: false,
+ issueDetailsPending: true
+ })
+
+ this.syncIssue(this.props.activeIssue)
+ }
+ }
+
findActiveIndex() {
if (this.props.filteredRows && this.props.activeIssue) {
for (const i in this.props.filteredRows) {
@@ -69,6 +86,7 @@ class UfixitModal extends React.Component {
newIndex = 0
}
this.clearMessages()
+ this.setState({ issueDetailsPending: true })
this.props.handleActiveIssue(this.props.filteredRows[newIndex].issue, newIndex)
}
@@ -87,14 +105,18 @@ class UfixitModal extends React.Component {
const pending = (this.props.activeIssue && (this.props.activeIssue.pending == '1'))
let activeIndex = this.findActiveIndex();
- const UfixitForm = returnIssueForm(activeIssue)
+ let code = ''
+ let UfixitForm
let showExample = false
if (!this.props.t(`rule.example.${activeIssue.scanRuleId}`).includes('rule.example')) {
showExample = true
}
- let code = this.prepareCode(activeIssue)
+ if (!this.state.issueDetailsPending) {
+ UfixitForm = ufixitService.returnIssueForm(activeIssue)
+ code = this.prepareCode(activeIssue)
+ }
return (
@@ -120,96 +142,103 @@ class UfixitModal extends React.Component {
-
-
-
- {ReactHtmlParser(this.props.t(`rule.desc.${activeIssue.scanRuleId}`), { preprocessNodes: (nodes) => Html.processStaticHtml(nodes, this.props.settings) })}
-
-
- {showExample &&
-
-
- {ReactHtmlParser(this.props.t(`rule.example.${activeIssue.scanRuleId}`), { preprocessNodes: (nodes) => Html.processStaticHtml(nodes, this.props.settings) })}
-
-
- }
-
-
-
-
-
+ {this.state.issueDetailsPending &&
+
+
- {('module' !== activeContentItem.contentType) &&
-
- {this.props.t('label.manual_resolution')}
- {this.props.t('label.resolved_description')}
-
- {('2' == activeIssue.pending) ?
-
- :
-
- }
+ }
+ {!this.state.issueDetailsPending &&
+
+
+
+ {ReactHtmlParser(this.props.t(`rule.desc.${activeIssue.scanRuleId}`), { preprocessNodes: (nodes) => Html.processStaticHtml(nodes, this.props.settings) })}
+
+
+ {showExample &&
+
+
+ {ReactHtmlParser(this.props.t(`rule.example.${activeIssue.scanRuleId}`), { preprocessNodes: (nodes) => Html.processStaticHtml(nodes, this.props.settings) })}
-
+
}
-
-
-
-
-
- {('preview' === this.state.windowContents) ?
- {this.props.t('label.preview')}
- :
- this.handleWindowToggle('preview')}>
- {this.props.t('label.preview')}
+
+
+
+
+
+
+ {('module' !== activeContentItem.contentType) &&
+
+ {this.props.t('label.manual_resolution')}
+ {this.props.t('label.resolved_description')}
+
+ {('2' == activeIssue.pending) ?
+
+ :
+
+ }
+
+
+ }
+
+
+
+
+
+ {('preview' === this.state.windowContents) ?
+ {this.props.t('label.preview')}
+ :
+ this.handleWindowToggle('preview')}>
+ {this.props.t('label.preview')}
+ }
+
+
+ {('html' === this.state.windowContents) ?
+ {this.props.t('label.view_source')}
+ :
+ this.handleWindowToggle('html')}>
+ {this.props.t('label.view_source')}
+ }
+
+
+
+ {('preview' === this.state.windowContents) &&
+
+
}
-
-
- {('html' === this.state.windowContents) ?
- {this.props.t('label.view_source')}
- :
- this.handleWindowToggle('html')}>
- {this.props.t('label.view_source')}
+ {('html' === this.state.windowContents) &&
+
}
-
-
-
- {('preview' === this.state.windowContents) &&
-
-
- }
- {('html' === this.state.windowContents) &&
-
+
+
+
+ {/* {this.props.t('label.source')} */}
+ {activeContentItem &&
+
+ {activeContentItem.contentType}
+ } iconPlacement="end">
+ {activeContentItem.title}
+
+
}
-
-
- {/* {this.props.t('label.source')} */}
- {activeContentItem &&
-
- {activeContentItem.contentType}
- } iconPlacement="end">
- {activeContentItem.title}
-
-
- }
-
-
-
+
+
+ }
@@ -280,7 +309,12 @@ class UfixitModal extends React.Component {
if (activeIssue.status) {
activeIssue.status = false
- activeIssue.newHtml = Html.toString(Html.removeClass(activeIssue.sourceHtml, 'phpally-ignore'))
+ activeIssue.newHtml = Html.toString(
+ Html.removeClass(activeIssue.sourceHtml, 'phpally-ignore')
+ )
+ activeIssue.newHtml = Html.toString(
+ Html.addClass(activeIssue.newHtml, `udoit-${activeIssue.id}`)
+ )
}
else {
activeIssue.status = 2
@@ -296,7 +330,6 @@ class UfixitModal extends React.Component {
if (response.data.issue) {
const newIssue = { ...activeIssue, ...response.data.issue }
- const newReport = response.data.report
// update activeIssue
newIssue.pending = false
@@ -304,16 +337,39 @@ class UfixitModal extends React.Component {
newIssue.sourceHtml = newIssue.newHtml
newIssue.newHtml = ''
// Get updated report
- api.scanContent(newIssue.contentItemId)
- .then((responseStr) => responseStr.json())
- .then((res) => {
- // update activeIssue
- this.props.handleActiveIssue(newIssue)
-
- this.props.handleIssueSave(newIssue, res.data)
- })
- }
- else {
+ api
+ .scanContent(newIssue.contentItemId)
+ .then((responseStr) => responseStr.json())
+ .then((scanResponse) => {
+ // If we just unresolved the issue
+ if (!newIssue.status) {
+ // Loop through report
+ for (var issue of scanResponse.data.issues) {
+ if (issue.scanRuleId === newIssue.scanRuleId) {
+ // Get issue details
+ api.syncIssue(issue)
+ .then((responseStr) => responseStr.json())
+ .then((res) => {
+ let issueDetails = res.data
+
+ if (issueDetails.sourceHtml === newIssue.sourceHtml) {
+ newIssue.id = issueDetails.id
+ newIssue.sourceHtml = Html.toString(
+ Html.removeClass(newIssue.sourceHtml, `udoit-${activeIssue.id}`)
+ )
+ newIssue.newHtml = ''
+ newIssue.previewHtml = issueDetails.previewHtml
+ }
+ })
+ }
+ }
+ }
+
+ this.props.handleActiveIssue(newIssue)
+ this.props.handleIssueSave(newIssue, scanResponse.data)
+
+ })
+ } else {
activeIssue.pending = false
this.props.handleActiveIssue(activeIssue)
}
@@ -432,6 +488,24 @@ class UfixitModal extends React.Component {
clearMessages() {
this.modalMessages = [];
}
+
+ syncIssue(issue) {
+ let api = new Api(this.props.settings)
+
+ api.syncIssue(issue)
+ .then((response) => response.json())
+ .then((response) => {
+ const newIssue = { ...issue, ...response.data }
+
+ // set messages
+ response.messages.forEach((msg) => this.addMessage(msg))
+
+ if (newIssue.id === this.props.activeIssue.id) {
+ this.props.handleActiveIssue(newIssue)
+ this.setState({ issueDetailsPending: false });
+ }
+ })
+ }
}
export default UfixitModal;
diff --git a/assets/js/Services/Api.js b/assets/js/Services/Api.js
index 3ace069d..a1943c63 100644
--- a/assets/js/Services/Api.js
+++ b/assets/js/Services/Api.js
@@ -6,6 +6,7 @@ export default class Api {
getReport: '/api/courses/{course}/reports/{report}',
getReportHistory: '/api/courses/{course}/reports',
saveIssue: '/api/issues/{issue}/save',
+ syncIssue: '/api/issues/{issue}',
resolveIssue: '/api/issues/{issue}/resolve',
reviewFile: '/api/files/{file}/review',
postFile: '/api/files/{file}/post',
@@ -90,6 +91,21 @@ export default class Api {
})
}
+ syncIssue(issue) {
+ const authToken = this.getAuthToken();
+
+ let url = `${this.apiUrl}${this.endpoints.syncIssue}`;
+ url = url.replace('{issue}', issue.id);
+
+ return fetch(url, {
+ method: 'GET',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'X-AUTH-TOKEN': authToken,
+ },
+ });
+ }
+
resolveIssue(issue) {
const authToken = this.getAuthToken()
diff --git a/src/Controller/IssuesController.php b/src/Controller/IssuesController.php
index c003334a..ce5f13cf 100644
--- a/src/Controller/IssuesController.php
+++ b/src/Controller/IssuesController.php
@@ -21,6 +21,22 @@ public function __construct(ManagerRegistry $doctrine)
$this->doctrine = $doctrine;
}
+ #[Route(path: '/api/issues/{issue}', name: 'get_issue')]
+ public function getIssue(Issue $issue)
+ {
+ $apiResponse = new ApiResponse();
+
+ $apiResponse->setData([
+ 'id' => $issue->getId(),
+ 'sourceHtml' => $issue->getHtml(),
+ 'previewHtml' => $issue->getPreviewHtml(),
+ 'metadata' => $issue->getMetadata(),
+ 'status' => $issue->getStatus(),
+ ]);
+
+ return new JsonResponse($apiResponse);
+ }
+
// Save change to issue HTML to LMS
#[Route('/api/issues/{issue}/save', name: 'save_issue')]
public function saveIssue(
diff --git a/src/Entity/Issue.php b/src/Entity/Issue.php
index b8f5af2d..1b1ed2c8 100644
--- a/src/Entity/Issue.php
+++ b/src/Entity/Issue.php
@@ -92,9 +92,6 @@ public function jsonSerialize(): array
"contentItemId" => $this->contentItem->getId(),
"scanRuleId" => $this->scanRuleId,
"type" => $this->type,
- "sourceHtml" => $this->html,
- "previewHtml" => $this->previewHtml,
- "metadata" => $this->metadata,
];
}