diff --git a/modules/conflict_resolver/jsx/.unresolved_filterabledatatable.js.swp b/modules/conflict_resolver/jsx/.unresolved_filterabledatatable.js.swp
new file mode 100644
index 00000000000..e559d351889
Binary files /dev/null and b/modules/conflict_resolver/jsx/.unresolved_filterabledatatable.js.swp differ
diff --git a/modules/conflict_resolver/jsx/fix_conflict_form.js b/modules/conflict_resolver/jsx/fix_conflict_form.js
index 8590304ac6a..2da0e68a949 100644
--- a/modules/conflict_resolver/jsx/fix_conflict_form.js
+++ b/modules/conflict_resolver/jsx/fix_conflict_form.js
@@ -16,7 +16,7 @@ import PropTypes from 'prop-types';
* dropdown is removed to prevent the user from sending a POST request with an empty
* value.
*
- * Knowned issue: When sorting the datatable, previouly fixed conflicts are
+ * Known issue: When sorting the datatable, previouly fixed conflicts are
* considered unresolved; there is no green checkmark beside the dropdown anymore.
*/
class FixConflictForm extends Component {
@@ -28,7 +28,26 @@ class FixConflictForm extends Component {
constructor(props) {
super(props);
- this.fix = this.fix.bind(this);
+ this.state = {
+ success: false,
+ error: false,
+ emptyOption: true,
+ };
+
+ this.resolveConflict = this.resolveConflict.bind(this);
+ }
+
+ componentDidUpdate(prevProps, prevState) {
+ if (this.state.error) {
+ setTimeout(() => {
+ this.setState({error: false});
+ }, 3000);
+ }
+ if (this.state.success) {
+ setTimeout(() => {
+ this.setState({success: false});
+ }, 3000);
+ }
}
/**
@@ -41,22 +60,12 @@ class FixConflictForm extends Component {
* beside the dropdown. On error, a red cross will be displayed as well as a
* sweetalert (swal) with the error message.
*
- * @param {Event} e - The onChange event.
+ * @param {string} name
+ * @param {string} value
*/
- fix(e) {
- const conflictid = e.target.name;
- const correctanswer = e.target.value;
-
- const feedbackicon = e.target.parentElement.getElementsByTagName('span')[0];
+ resolveConflict(name, value) {
// Hide any previously displayed icon.
- feedbackicon.style.display = 'none';
-
- try {
- // Remove the empty option from the options to prevent sending an empty value.
- e.target.querySelector('option[name="0"]').remove();
- } catch (error) {
- // TypeError when already removed. Do nothing.
- }
+ this.setState({success: false, error: false, emptyOption: false});
fetch(loris.BaseURL.concat('/conflict_resolver/unresolved'), {
method: 'POST',
@@ -64,58 +73,49 @@ class FixConflictForm extends Component {
headers: {
'Content-Type': 'application/json',
},
- body: JSON.stringify({conflictid: conflictid, correctanswer: correctanswer}),
+ body: JSON.stringify({conflictid: name, correctanswer: value}),
})
.then((resp) => {
return resp.ok ? {} : resp.json();
})
.then((json) => {
- if (json.error) {
- throw json.error;
- }
- // Set feedback icon to green checkmark
- setTimeout(() => {
- feedbackicon.className = 'glyphicon glyphicon-ok-circle';
- feedbackicon.style.color = 'green';
- feedbackicon.style.display = 'inline';
- }, 200);
+ if (json.error) {
+ throw json.error;
+ }
+ this.setState({success: true});
})
.catch((error) => {
swal('Error!', error, 'error');
- // Set feedback icon to red cross
- setTimeout(() => {
- feedbackicon.className = 'glyphicon glyphicon-remove-sign';
- feedbackicon.style.color = 'red';
- feedbackicon.style.display = 'inline';
- }, 200);
+ this.setState({error: true});
});
- }
+ }
render() {
- const options = [
- ,
- ,
- ,
- ];
+ const {success, error, emptyOption} = this.state;
+ const iconStyle = {
+ opacity: success || error ? 1 : 0,
+ color: success ? 'green' : (error ? 'red' : 'white'),
+ transition: 'opacity 2s, color 2s',
+ };
+ const iconClass = 'glyphicon glyphicon-' + (success ? 'ok' : 'remove')
+ + '-circle';
return (
-
+
+
|
);
}
}
FixConflictForm.propTypes = {
- conflictid: PropTypes.string.isRequired,
- values: PropTypes.arrayOf(PropTypes.shape({
- name: PropTypes.string.isRequired,
- value: PropTypes.string.isRequired,
- })).isRequired,
+ conflictId: PropTypes.string.isRequired,
+ options: PropTypes.object.isRequired,
};
export default FixConflictForm;
diff --git a/modules/conflict_resolver/jsx/unresolved_filterabledatatable.js b/modules/conflict_resolver/jsx/unresolved_filterabledatatable.js
index 9e58d56904c..86938687f99 100644
--- a/modules/conflict_resolver/jsx/unresolved_filterabledatatable.js
+++ b/modules/conflict_resolver/jsx/unresolved_filterabledatatable.js
@@ -34,12 +34,15 @@ class UnresolvedFilterableDataTable extends Component {
formatColumn(column, cell, rowData, rowHeaders) {
switch (column) {
case 'Correct Answer':
- const values = [
- {name: '1', value: rowData['Value 1']},
- {name: '2', value: rowData['Value 2']},
- ];
+ const options = {
+ 1: rowData['Value 1'],
+ 2: rowData['Value 2'],
+ };
return (
-
+
);
}
return (
@@ -52,7 +55,8 @@ class UnresolvedFilterableDataTable extends Component {
* @return {object}
*/
fetchData() {
- return fetch(loris.BaseURL.concat('/conflict_resolver/unresolved'), {credentials: 'same-origin'})
+ const url = loris.BaseURL.concat('/conflict_resolver/unresolved');
+ return fetch(url, {credentials: 'same-origin'})
.then((resp) => resp.json())
.then((json) => {
if (json.error) {
diff --git a/modules/conflict_resolver/php/conflict_resolver.class.inc b/modules/conflict_resolver/php/conflict_resolver.class.inc
index 2e39cd038d5..b3583cdd77c 100644
--- a/modules/conflict_resolver/php/conflict_resolver.class.inc
+++ b/modules/conflict_resolver/php/conflict_resolver.class.inc
@@ -53,9 +53,9 @@ class Conflict_Resolver extends \NDB_Page
$deps = parent::getJSDependencies();
return array_merge(
$deps,
- array(
- $baseURL . '/conflict_resolver/js/conflict_resolver.js',
- )
+ [
+ $baseURL . '/conflict_resolver/js/conflict_resolver.js',
+ ]
);
}
}
diff --git a/modules/conflict_resolver/php/endpoints/resolved.class.inc b/modules/conflict_resolver/php/endpoints/resolved.class.inc
index ecd11434709..769e6cb4d8c 100644
--- a/modules/conflict_resolver/php/endpoints/resolved.class.inc
+++ b/modules/conflict_resolver/php/endpoints/resolved.class.inc
@@ -85,12 +85,12 @@ class Resolved extends Endpoint implements ETagCalculator
$visitlabels = array_values(\Utility::getVisitList());
$projects = array_values(\Utility::getProjectList());
- return array(
+ return [
'site' => array_combine($sites, $sites),
'instrument' => \Utility::getAllInstruments(),
'visitLabel' => array_combine($visitlabels, $visitlabels),
'project' => array_combine($projects, $projects),
- );
+ ];
}
/**
@@ -133,7 +133,7 @@ class Resolved extends Endpoint implements ETagCalculator
$provisioner = (new ResolvedProvisioner())
->filter(
new HasAnyPermissionOrUserSiteMatch(
- array('access_all_profiles')
+ ['access_all_profiles']
)
)
->filter(new UserProjectMatch());
@@ -143,10 +143,10 @@ class Resolved extends Endpoint implements ETagCalculator
->withDataFrom($provisioner)
->toArray($user);
- $body = array(
+ $body = [
'data' => $conflicts,
'fieldOptions' => $this->_getFieldOptions(),
- );
+ ];
$this->_cache = new \LORIS\Http\Response\JsonResponse($body);
diff --git a/modules/conflict_resolver/php/endpoints/unresolved.class.inc b/modules/conflict_resolver/php/endpoints/unresolved.class.inc
index 786d084aeb1..205b6b7f36e 100644
--- a/modules/conflict_resolver/php/endpoints/unresolved.class.inc
+++ b/modules/conflict_resolver/php/endpoints/unresolved.class.inc
@@ -77,10 +77,10 @@ class Unresolved extends Endpoint implements ETagCalculator
*/
protected function allowedMethods() : array
{
- return array(
+ return [
'GET',
'POST',
- );
+ ];
}
/**
@@ -94,12 +94,12 @@ class Unresolved extends Endpoint implements ETagCalculator
$visitlabels = array_values(\Utility::getVisitList());
$projects = array_values(\Utility::getProjectList());
- return array(
+ return [
'site' => array_combine($sites, $sites),
'instrument' => \Utility::getAllInstruments(),
'visitLabel' => array_combine($visitlabels, $visitlabels),
'project' => array_combine($projects, $projects),
- );
+ ];
}
/**
@@ -145,7 +145,7 @@ class Unresolved extends Endpoint implements ETagCalculator
$provisioner = (new UnresolvedProvisioner())
->filter(
new HasAnyPermissionOrUserSiteMatch(
- array('access_all_profiles')
+ ['access_all_profiles']
)
)
->filter(new UserProjectMatch());
@@ -155,10 +155,10 @@ class Unresolved extends Endpoint implements ETagCalculator
->withDataFrom($provisioner)
->toArray($user);
- $body = array(
+ $body = [
'data' => $conflicts,
'fieldOptions' => $this->_getFieldOptions(),
- );
+ ];
$this->_cache = new \LORIS\Http\Response\JsonResponse($body);
@@ -219,10 +219,10 @@ class Unresolved extends Endpoint implements ETagCalculator
WHERE
ConflictID = :v_conflictid
',
- array(
+ [
'v_conflictid' => $conflictid,
'v_value' => $correctanswer,
- )
+ ]
);
if (empty($conflict)) {
@@ -239,8 +239,9 @@ class Unresolved extends Endpoint implements ETagCalculator
false
);
- $instrument->_saveValues(array($conflict['FieldName'] => $correctanswer));
+ $instrument->_saveValues([$conflict['FieldName'] => $correctanswer]);
+ // TODO: UNCOMMENT THE FOLLOWING LINES BEFORE SUBMITTING PR.
// Using an output buffer because the score function prints to STDOUT
ob_start();
$instrument->score();
@@ -313,11 +314,11 @@ class Unresolved extends Endpoint implements ETagCalculator
);
$success = $stmt->execute(
- array(
+ [
'v_username' => $user->getUsername(),
'v_newvalue' => $correctanswer,
'v_conflictid' => $conflictid,
- )
+ ]
);
if (!$success) {
@@ -325,7 +326,7 @@ class Unresolved extends Endpoint implements ETagCalculator
}
// Delete from conflicts_unresolved
- $db->delete('conflicts_unresolved', array('ConflictID' => $conflictid));
+ $db->delete('conflicts_unresolved', ['ConflictID' => $conflictid]);
return new \LORIS\Http\Response();
}
diff --git a/modules/conflict_resolver/php/models/resolveddto.class.inc b/modules/conflict_resolver/php/models/resolveddto.class.inc
index 2b4284af021..29af31e4adf 100644
--- a/modules/conflict_resolver/php/models/resolveddto.class.inc
+++ b/modules/conflict_resolver/php/models/resolveddto.class.inc
@@ -36,21 +36,21 @@ class ResolvedDTO implements \LORIS\Data\DataInstance
public function jsonSerialize(): array
{
return [
- 'ResolvedID' => $this->resolvedid,
- 'Project' => $this->project,
- 'Site' => $this->site,
- 'CandID' => $this->candid,
- 'PSCID' => $this->pscid,
- 'Visit Label' => $this->visitlabel,
- 'Instrument' => $this->instrument,
- 'Question' => $this->question,
- 'Value 1' => $this->value1,
- 'Value 2' => $this->value2,
- 'Correct Answer' => $this->correctanswer,
- 'User 1' => $this->user1,
- 'User 2' => $this->user2,
- 'Resolver' => $this->resolver,
- 'ResolutionTimestamp' => $this->resolutiontimestamp,
+ 'ResolvedID' => $this->resolvedid,
+ 'Project' => $this->project,
+ 'Site' => $this->site,
+ 'CandID' => $this->candid,
+ 'PSCID' => $this->pscid,
+ 'Visit Label' => $this->visitlabel,
+ 'Instrument' => $this->instrument,
+ 'Question' => $this->question,
+ 'Value 1' => $this->value1,
+ 'Value 2' => $this->value2,
+ 'Correct Answer' => $this->correctanswer,
+ 'User 1' => $this->user1,
+ 'User 2' => $this->user2,
+ 'Resolver' => $this->resolver,
+ 'ResolutionTimestamp' => $this->resolutiontimestamp,
];
}
diff --git a/modules/conflict_resolver/php/module.class.inc b/modules/conflict_resolver/php/module.class.inc
index 1357da51f4e..a4b6b0f2f41 100644
--- a/modules/conflict_resolver/php/module.class.inc
+++ b/modules/conflict_resolver/php/module.class.inc
@@ -131,18 +131,18 @@ class Module extends \Module
'conflict_resolver'
)
];
- case 'candidate':
- $factory = \NDB_Factory::singleton();
- $baseURL = $factory->settings()->getBaseURL();
- $DB = $factory->database();
+ case 'candidate':
+ $factory = \NDB_Factory::singleton();
+ $baseURL = $factory->settings()->getBaseURL();
+ $DB = $factory->database();
- $candidate = $options['candidate'];
- if ($candidate === null) {
- return [];
- }
+ $candidate = $options['candidate'];
+ if ($candidate === null) {
+ return [];
+ }
- $candID = $candidate->getCandID();
- $results = $DB->pselect(
+ $candID = $candidate->getCandID();
+ $results = $DB->pselect(
"SELECT f1.Test_name, s1.Visit_label, COUNT(*) as Conflicts
FROM conflicts_unresolved cu
LEFT JOIN flag f1 ON (f1.CommentID=cu.CommentId1)
@@ -151,29 +151,29 @@ class Module extends \Module
LEFT JOIN session s2 ON (f2.SessionID=s2.ID)
WHERE (s1.CandID=:cand1 OR s2.CandID=:cand2)
GROUP BY f1.Test_name, s1.Visit_label
- ORDER BY s1.Visit_label, f1.Test_name",
- ['cand1' => $candID, 'cand2' => $candID],
- );
- // Do not show the conflicts card if there are no conflicts
- if (empty($results)) {
- return [];
- }
+ ORDER BY s1.Visit_label, f1.Test_name",
+ ['cand1' => $candID, 'cand2' => $candID],
+ );
+ // Do not show the conflicts card if there are no conflicts
+ if (empty($results)) {
+ return [];
+ }
- $width = 1;
- if (count($results) > 10) {
- $width = 2;
- }
- return [
- new \LORIS\candidate_profile\CandidateWidget(
- "Unresolved Conflicts",
- $baseURL . "/conflict_resolver/js/CandidateConflictsWidget.js",
- "lorisjs.conflict_resolver.CandidateConflictsWidget.default",
- [
- 'Conflicts' => $results,
- ],
- $width,
- 1,
- )
+ $width = 1;
+ if (count($results) > 10) {
+ $width = 2;
+ }
+ return [
+ new \LORIS\candidate_profile\CandidateWidget(
+ "Unresolved Conflicts",
+ $baseURL . "/conflict_resolver/js/CandidateConflictsWidget.js",
+ "lorisjs.conflict_resolver.CandidateConflictsWidget.default",
+ [
+ 'Conflicts' => $results,
+ ],
+ $width,
+ 1,
+ )
];
}
diff --git a/modules/conflict_resolver/php/provisioners/resolvedprovisioner.class.inc b/modules/conflict_resolver/php/provisioners/resolvedprovisioner.class.inc
index 24a50a731e0..b0c5f41be2d 100644
--- a/modules/conflict_resolver/php/provisioners/resolvedprovisioner.class.inc
+++ b/modules/conflict_resolver/php/provisioners/resolvedprovisioner.class.inc
@@ -58,7 +58,7 @@ class ResolvedProvisioner extends \LORIS\Data\Provisioners\DBObjectProvisioner
LEFT JOIN psc ON (session.CenterID = psc.CenterID)
WHERE session.Active="Y" AND candidate.Active ="Y"
',
- array(),
+ [],
'\LORIS\conflict_resolver\Models\ResolvedDTO'
);
}
diff --git a/modules/conflict_resolver/php/provisioners/unresolvedprovisioner.class.inc b/modules/conflict_resolver/php/provisioners/unresolvedprovisioner.class.inc
index 24adfaef385..2da636927e5 100644
--- a/modules/conflict_resolver/php/provisioners/unresolvedprovisioner.class.inc
+++ b/modules/conflict_resolver/php/provisioners/unresolvedprovisioner.class.inc
@@ -53,7 +53,7 @@ class UnresolvedProvisioner extends \LORIS\Data\Provisioners\DBObjectProvisioner
LEFT JOIN psc ON (session.CenterID = psc.CenterID)
WHERE session.Active="Y" AND candidate.Active ="Y"
',
- array(),
+ [],
'\LORIS\conflict_resolver\Models\UnresolvedDTO'
);
}
diff --git a/modules/conflict_resolver/test/conflict_resolverTest.php b/modules/conflict_resolver/test/conflict_resolverTest.php
index 004918a43a9..51af08c835c 100644
--- a/modules/conflict_resolver/test/conflict_resolverTest.php
+++ b/modules/conflict_resolver/test/conflict_resolverTest.php
@@ -89,7 +89,7 @@ function tearDown()
*/
function testConflictResolverPermission()
{
- $this->setupPermissions(array("conflict_resolver"));
+ $this->setupPermissions(["conflict_resolver"]);
$this->safeGet($this->url . "/conflict_resolver");
$this->webDriver->wait()->until(
\WebDriverExpectedCondition::presenceOfElementLocated(
@@ -106,7 +106,7 @@ function testConflictResolverPermission()
*/
function testConflictResolverWithoutPermission()
{
- $this->setupPermissions(array());
+ $this->setupPermissions([]);
$this->safeGet($this->url . "/conflict_resolver");
$bodyText = $this->webDriver->findElement(
\WebDriverBy::id('lorisworkspace')
diff --git a/webpack.config.js b/webpack.config.js
index 3ccd8c309cd..0757af9150c 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -190,7 +190,10 @@ const config = [
'ConsentWidget',
]),
lorisModule('configuration', ['SubprojectRelations']),
- lorisModule('conflict_resolver', ['conflict_resolver']),
+ lorisModule('conflict_resolver', [
+ 'conflict_resolver',
+ 'CandidateConflictsWidget',
+ ]),
lorisModule('battery_manager', ['batteryManagerIndex']),
lorisModule('bvl_feedback', ['react.behavioural_feedback_panel']),
lorisModule('behavioural_qc', ['behavioural_qc_module']),