Skip to content

Commit 2ce5422

Browse files
authored
Merge branch 'main' into dicom_archive_siteproject_main
2 parents 68c9763 + 108491c commit 2ce5422

File tree

33 files changed

+186
-94
lines changed

33 files changed

+186
-94
lines changed

.eslintignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ node_modules/*
22
vendor/*
33
project/*
44
babel.config.js
5+
webpack.config.ts
56

67
# compiled js ignored since it is run on the jsx directory
78
modules/*/js/*

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ the `Data` key instead of `$InstrumentName` (PR #7857)
167167
- Fixed broken DB calls in `assign_missing_instruments` and `instruments` (PR #8162)
168168
- Add support for PHP 8.1 (PR #7989)
169169
- Fix Project tab of Configuration module to give correct errors, and prevent saving without Alias (PR #8349)
170+
- Fix BVL feedback summary in instruments (PR #8889)
170171
### Modules
171172
#### API
172173
- Ability to use PSCID instead of the CandID in the candidates API (PR #8138)

SQL/0000-00-03-ConfigTables.sql

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,6 @@ INSERT INTO Config (ConfigID, Value) SELECT ID, "365" FROM ConfigSettings WHERE
211211

212212
INSERT INTO Config (ConfigID, Value) SELECT ID, "/data/%PROJECTNAME%/data/" FROM ConfigSettings WHERE Name="imagePath";
213213
INSERT INTO Config (ConfigID, Value) SELECT ID, "%LORISROOT%" FROM ConfigSettings WHERE Name="base";
214-
INSERT INTO Config (ConfigID, Value) SELECT ID, "%LORISROOT%" FROM ConfigSettings WHERE Name="DownloadPath";
215214
INSERT INTO Config (ConfigID, Value) SELECT ID, "tools/logs/" FROM ConfigSettings WHERE Name="log";
216215
INSERT INTO Config (ConfigID, Value) SELECT ID, "/data/%PROJECTNAME%/bin/mri/" FROM ConfigSettings WHERE Name="MRICodePath";
217216
INSERT INTO Config (ConfigID, Value) SELECT ID, "/data/incoming/" FROM ConfigSettings WHERE Name="MRIUploadIncomingPath";

docs/wiki/99_Developers/Code_Customization.md

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
# Code customization
22
## The project/ directory
33

4-
The `project/` directory is designed to house project-specific code and some data such as documents. This includes instrument forms, instrument table schemas, and any customizations to other pages or modules in the Loris codebase.
4+
The `project/` directory is designed to house project-specific code and some data such as documents. This includes instrument forms, instrument table schemas, and any customizations to other pages or modules in the Loris codebase.
55
The `project/` folder and its subdirectories are created by the install script, which also installs the `_config.xml_` file there.
66

7-
[[Instrument forms|Behavioural-Database]] (_.linst_ or php) should be stored under `project/instruments/` and their table schemas (.sql) should be stored under `project/tables_sql/`
7+
[[Instrument forms|Behavioural-Database]] (_.linst_ or php) should be stored under `project/instruments/` and their table schemas (.sql) should be stored under `project/tables_sql/`
88

99
## Backing up `project/`
1010

1111
* Important: Commit your project/ directory and its contents to a separate private repo - e.g. on GitHub
12-
* Equally Important: Exclude all data and the _config.xml_ file (which contains a database credential) stored under project/ from commits/backups to your online repo (such as on GitHub). Back up this data and the config file elsewhere on another server, using a cronjob.
12+
* Equally Important: Exclude all data and the _config.xml_ file (which contains a database credential) stored under project/ from commits/backups to your online repo (such as on GitHub). Back up this data and the config file elsewhere on another server, using a cronjob.
1313

1414
## Tracking changes
1515

@@ -25,5 +25,29 @@ i.e. `/var/www/loris/project/libraries/_filename.class.inc` will override `/var/
2525

2626
## Module override
2727

28-
For projects wishing to customize existing modules, the recommended best practice is to copy _all_ module code from `$lorisroot/modules/_module_name_/*` to a new `project/modules/` subdirectory (project/modules/_module_name_/* ) and modify code there.
29-
This will use the `project/` override functionality of Loris. These changes should be added and committed to your project-specific private repo.
28+
For projects wishing to customize existing modules, the recommended best practice is to copy _all_ module code from `$lorisroot/modules/_module_name_/*` to a new `project/modules/` subdirectory (project/modules/_module_name_/* ) and modify code there.
29+
This will use the `project/` override functionality of Loris. These changes should be added and committed to your project-specific private repo.
30+
31+
32+
## Manage additional dependencies
33+
34+
### Additional composer dependencies
35+
36+
In case your project requires additional composer dependencies or different dependency version requirements, you can create a `composer.json` file in `project/` folder by running `composer init`. Any existing or new dependencies in this file will be merged with the main composer dependencies in `vendor/` after `composer update` has been run. For any change in the `project/composer.json` file, run `composer update` again in the root folder.
37+
38+
### Additional npm dependencies
39+
40+
To add new npm packages to your project, you can create a `package.json` file in `project/` by running `npm init`. Any dependencies in this file will be automatically installed under `project/` when make or npm ci/npm install is run from loris root.
41+
42+
## Webpack compilation
43+
44+
Modules overriden js files will automatically compile and replace the file they intend to modify. On the other hand, new js files will need to be registered in order to be compiled with `npm run compile`. To register, for example, a new React components located in `project/modules/_new_module_name_/jsx/_react_component_.js` you can create `project/webpack-project.config.js` with the following template:
45+
46+
```
47+
const entry = {
48+
'_new_module_name_': [
49+
'_react_component_',
50+
],
51+
};
52+
module.exports = entry;
53+
```

htdocs/bootstrap/css/custom-css.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -928,3 +928,8 @@ legend {
928928
.highlighted {
929929
animation: highlight ease 3s;
930930
}
931+
932+
select[multiple].input-sm.resizable {
933+
height: 100px;
934+
resize: both;
935+
}

modules/candidate_list/jsx/candidateListIndex.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ class CandidateListIndex extends Component {
6565
* Called by React when the component has been rendered on the page.
6666
*/
6767
componentDidMount() {
68-
fetch('options',
68+
fetch(loris.BaseURL+'/candidate_list/options',
6969
{credentials: 'same-origin'}).then(
7070
(resp) => resp.json()
7171
).then(

modules/dataquery/php/endpoints/queries/query/run.class.inc

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,16 @@ class Run extends \LORIS\Http\Endpoint
8080
$rowsBinary,
8181
bool $end
8282
) use (&$values, &$db, &$runid) {
83-
$values[] = join(
84-
',',
85-
[$runid, $candid, $db->quote(json_encode($rowsArray))]
86-
);
83+
$values[] = "SELECT "
84+
. $runid . ","
85+
. "c.ID, "
86+
. $db->quote(json_encode($rowsArray))
87+
. " FROM candidate c"
88+
. " WHERE c.CandID=" . intval($candid);
8789
if ((count($values) >= 2000 || $end) && count($values) > 0) {
8890
$insertstmt = "INSERT INTO dataquery_run_results
89-
(RunID, CandID, RowData) VALUES "
90-
. " (" . join('),(', $values) . ')';
91+
(RunID, CandidateID, RowData) "
92+
. join(' UNION ', $values);
9193
$q = $db->prepare($insertstmt);
9294
$q->execute([]);
9395
$values = [];

modules/electrophysiology_browser/jsx/react-series-data-viewer/src/series/components/ResponsiveViewer.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ const ResponsiveViewer : FunctionComponent<CProps> = ({
5353
const layers = React.Children.toArray(children).map(provision);
5454

5555
const domain = window.EEGLabSeriesProviderStore[chunksURL]?.getState().bounds.domain;
56+
// Data not loaded yet
57+
if (!domain) return null;
58+
5659
const amplitude = [0, 1];
5760
const eventScale = [
5861
scaleLinear()

modules/electrophysiology_browser/jsx/react-series-data-viewer/tsconfig.json

Lines changed: 0 additions & 6 deletions
This file was deleted.

modules/electrophysiology_browser/test/electrophysiologyBrowserTest.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,9 @@ function testSessionsProjectPermissions()
535535
*/
536536
function testSessionsNavigation()
537537
{
538+
$this->markTestSkipped(
539+
'rewrite later'
540+
);
538541
$this->safeGet($this->url . "/electrophysiology_browser/sessions/999999");
539542
$link = self::$nextLink;
540543
$this->safeClick(WebDriverBy::cssSelector($link));

modules/electrophysiology_uploader/jsx/ElectrophysiologyUploader.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ export default function ElectrophysiologyUploader(props) {
4646
});
4747
};
4848

49+
const refreshForm = () => {
50+
setData({});
51+
fetchData();
52+
};
53+
4954
if (!isLoaded) {
5055
return <Loader />;
5156
}
@@ -74,6 +79,7 @@ export default function ElectrophysiologyUploader(props) {
7479
<TabPane TabId={tabList[1].id}>
7580
<UploadForm
7681
uploadURL={`${props.DataURL}/upload`}
82+
refreshPage={refreshForm}
7783
/>
7884
</TabPane>
7985
</Tabs>

modules/electrophysiology_uploader/jsx/UploadForm.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,14 @@ export default function UploadForm(props) {
4646
newFormData.pscid = ids[0];
4747
newFormData.candID = ids[1];
4848
newFormData.visit = ids[2];
49+
50+
// Clear possible error messages from previous file selection
51+
setErrorMessage({
52+
eegFile: null,
53+
candID: null,
54+
pscid: null,
55+
visit: null,
56+
});
4957
}
5058

5159
setFormData(newFormData);
@@ -149,6 +157,10 @@ export default function UploadForm(props) {
149157
title: 'Upload Successful!',
150158
text: text,
151159
type: 'success',
160+
}).then((result) => {
161+
if (result.value) {
162+
this.props.refreshPage();
163+
}
152164
});
153165

154166
resetForm();

modules/examiner/jsx/examinerIndex.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ class ExaminerIndex extends Component {
146146

147147
switch (column) {
148148
case 'Examiner':
149-
if (this.state.data.useCertification) {
149+
if (this.state.data.fieldOptions.useCertification) {
150150
const url = loris.BaseURL + '/examiner/editExaminer/?identifier=' +
151151
row.ID;
152152
result = <td><a href={url}>{cell}</a></td>;

modules/imaging_browser/jsx/imagingBrowserIndex.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ class ImagingBrowserIndex extends Component {
170170
{label: 'Entity Type', show: false, filter: {
171171
name: 'entityType',
172172
type: 'multiselect',
173-
option: options.entityType,
173+
options: options.entityType,
174174
}},
175175
];
176176
/**

modules/imaging_uploader/php/imaging_uploader.class.inc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ class Imaging_Uploader extends \NDB_Menu_Filter_Form
9696
'Visit_label' => 's.Visit_label',
9797
'IsPhantom' => 'mu.IsPhantom',
9898
];
99+
$this->order_by ="UploadDate DESC";
99100
}
100101
/**
101102
* Sets up the menu filter items for the imaging uploader

modules/instruments/php/instrumentqueryengine.class.inc

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,7 @@ class InstrumentQueryEngine implements \LORIS\Data\Query\QueryEngine
371371
$candData[$dict->getName()] = [];
372372
}
373373
$sid = $loadedInstrument->getSessionID();
374+
374375
switch ($dict->fieldname) {
375376
case 'Administration':
376377
case 'Data_entry':
@@ -383,16 +384,39 @@ class InstrumentQueryEngine implements \LORIS\Data\Query\QueryEngine
383384
];
384385
break;
385386
default:
386-
$candData[$dict->getName()][$sid->__toString()] = [
387-
'VisitLabel' => $loadedInstrument->getVisitLabel(),
388-
'SessionID' => $sid->__toString(),
389-
'value' => $loadedInstrument
390-
->getDictionaryValue($dict),
391-
];
387+
if ($dict->getCardinality()->__toString() == "many") {
388+
$candData[$dict->getName()][$sid->__toString()] = [
389+
'keytype' => $dict->getName() . " response",
390+
'VisitLabel' => $loadedInstrument->getVisitLabel(),
391+
'SessionID' => $sid->__toString(),
392+
'values' => [],
393+
];
394+
$i = 1;
395+
396+
// Line length work-arounds
397+
$candData =& $candData[$dict->getName()];
398+
$vals =& $candData[$sid->__toString()]['values'];
399+
400+
$values = explode(
401+
'{@}',
402+
$loadedInstrument->getDictionaryValue($dict)
403+
);
404+
foreach ($values as $value) {
405+
$vals["Response $i"] = $value;
406+
$i++;
407+
}
408+
} else {
409+
$candData[$dict->getName()][$sid->__toString()] = [
410+
'VisitLabel' => $loadedInstrument->getVisitLabel(),
411+
'SessionID' => $sid->__toString(),
412+
'value' =>
413+
$loadedInstrument->getDictionaryValue($dict),
414+
];
415+
}
392416
}
393417
}
418+
yield "$iCandID" => $candData;
394419
}
395-
yield "$iCandID" => $candData;
396420
}
397421
}
398422
}

modules/issue_tracker/php/edit.class.inc

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -984,19 +984,23 @@ class Edit extends \NDB_Page implements ETagCalculator
984984
) {
985985
$db = $this->loris->getDatabaseConnection();
986986
$baseurl = \NDB_Factory::singleton()->settings()->getBaseURL();
987+
$study = \NDB_Factory::singleton()->config()->getSetting('title');
987988

988-
$title = $db->pSelectOne(
989-
"SELECT title FROM issues
989+
$emailItems = $db->pselectRow(
990+
"SELECT `title`,`priority`,`status` FROM issues
990991
WHERE issueID=:issueID",
991992
['issueID' => $issueID]
992993
);
993994

994995
$msg_data = [];
996+
$msg_data['study'] = $study;
995997
$msg_data['url'] = $baseurl .
996998
"/issue_tracker/issue/" . $issueID;
997999
$msg_data['issueID'] = $issueID;
9981000
$msg_data['currentUser'] = $user->getUsername();
999-
$msg_data['title'] = $title;
1001+
$msg_data['title'] = $emailItems['title'] ?? null;
1002+
$msg_data['priority'] = $emailItems['priority'] ?? null;
1003+
$msg_data['status'] = $emailItems['status'] ?? null;
10001004
$msg_data['comment'] = $values['comment'];
10011005

10021006
if (isset($changed_assignee) && $new_assignee_tag == 'false') {

modules/server_processes_manager/php/mriuploadserverprocess.class.inc

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,25 +52,25 @@ class MriUploadServerProcess extends AbstractServerProcess
5252
private $_sourceLocation;
5353

5454
/**
55-
* Root of the MRI files directory.
55+
* The value of MRICodePath config setting.
5656
*
5757
* @var string
5858
*/
5959
private $_mriCodePath;
6060

6161
/**
62-
* Path of the environment file (relative to $_mriCodePath).
62+
* The value of MriConfigFile config setting.
6363
*
6464
* @var string
6565
*/
66-
private $_environmentFile;
66+
private $_prodFile;
6767

6868
/**
69-
* Path of the prod file (relative to $_mriCodePath/dicom-archive/.loris-mri).
69+
* The value of EnvironmentFile config setting.
7070
*
7171
* @var string
7272
*/
73-
private $_prodFile;
73+
private $_environmentFile;
7474

7575
/**
7676
* Builds a new MriUploadServerProcess
@@ -99,7 +99,7 @@ class MriUploadServerProcess extends AbstractServerProcess
9999
$config =& \NDB_Config::singleton();
100100
if (is_null($config)) {
101101
throw new \RuntimeException(
102-
"Cannot construct MriUploadTask: unable to instantiate
102+
"Cannot construct MriUploadTask: unable to instantiate
103103
configuration object"
104104
);
105105
}

modules/server_processes_manager/php/serverprocessesmonitor.class.inc

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -72,14 +72,14 @@ class ServerProcessesMonitor
7272
* whatever is stored in the database for that process, the information
7373
* stored in the database is updated to reflect the current process state.
7474
*
75-
* @param array $idsToMonitor IDs of the server processes to monitor.
76-
* If null, then the state of all the processes
77-
* stored in the database is returned.
78-
* @param string $userid only the processes run by the user with name
79-
* $userid are considered. If null, then the userid
80-
* check is not performed.
81-
* @param string $type the type of server processes to retrieve. If null
82-
* then all types are considered.
75+
* @param array $idsToMonitor IDs of the server processes to monitor.
76+
* If null, then the state of all the processes
77+
* stored in the database is returned.
78+
* @param string|null $userid Only the processes run by the user with name
79+
* $userid are considered. If null, then the
80+
* userid check is not performed.
81+
* @param string|null $type The type of server processes to retrieve. If
82+
* null then all types are considered.
8383
*
8484
* @return array (associative) of the current state of the processes.
8585
* @throws \DatabaseException if connection to the database cannot be
@@ -93,7 +93,7 @@ class ServerProcessesMonitor
9393
//------------------------------------------------------
9494
$db = $this->getDatabaseProvider()->getDatabase();
9595

96-
$query = "SELECT id, pid, type, userid, stdout_file, stderr_file,
96+
$query = "SELECT id, pid, type, userid, stdout_file, stderr_file,
9797
exit_code_file, exit_code, start_time, end_time,
9898
exit_text
9999
FROM server_processes

modules/user_accounts/php/edit_user.class.inc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -814,6 +814,7 @@ class Edit_User extends \NDB_Form
814814
'Sites',
815815
$siteOptions,
816816
[
817+
'class' => 'form-control input-sm resizable',
817818
'multiple' => 'multiple',
818819
'required' => true,
819820
]
@@ -833,6 +834,7 @@ class Edit_User extends \NDB_Form
833834
'Projects',
834835
$projectOptions,
835836
[
837+
'class' => 'form-control input-sm resizable',
836838
'multiple' => 'multiple',
837839
'required' => true,
838840
]

npm-postinstall.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const getPath = (p) => {
1414

1515
if (
1616
pathParts[0] === 'modules' &&
17-
fs.existsSync(path.join(__dirname, 'project', 'modules', pathParts[1]))
17+
fs.existsSync(path.join(__dirname, 'project', ...pathParts))
1818
) {
1919
return path.join('project', p);
2020
}

0 commit comments

Comments
 (0)