Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Atlas Cohort Definition Validation Feature #2593

Draft
wants to merge 50 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
3d9cea1
Merge Annotation V2 changes
charhart Feb 1, 2021
a2261d1
Merge pull request #1 from cahilton/annotation-v2
charhart Feb 9, 2021
d5a2b3a
adding validation files, Also added Validation tab back to cohort-def…
Mar 8, 2021
45a2e06
adding more files that needed merged in
Mar 8, 2021
07cf6ab
small fixes for validationTool creation
Mar 8, 2021
8b91a5a
fixed indentation, removed unecessary tags
Mar 9, 2021
f5c95c2
adding lines to gitignore to ignore resultant files when building bro…
Mar 23, 2021
9602001
Cleanup JS errors on validationtool; call validationTool as observable
charhart Mar 24, 2021
10ceb01
revert canEdit change
charhart Mar 24, 2021
45928f8
Add annotation linking to sample UI
charhart May 18, 2021
7971ed1
rename annotationSetId
charhart May 18, 2021
4f249df
on validation page, go directly to question set screen
charhart May 19, 2021
570820b
progress on validate page - add list
charhart May 20, 2021
277e651
progress on validate page - improvements to question set UI
charhart May 21, 2021
ed475c9
annotations - check for results.
charhart May 21, 2021
d6eac91
annotations - fix toggle issue on annotations
charhart May 21, 2021
0f1d8b0
annotations - fix resize issue on annotation widget
charhart May 24, 2021
083e319
annotations - fix observable display issue
charhart May 24, 2021
4995883
annotations - fix observable display issue
charhart May 24, 2021
32a5790
annotations - fix observable init issue
charhart May 24, 2021
a9cc5e6
annotations - fix saving question set
charhart May 25, 2021
8b8ac5d
annotations - fix creating study behavior; show annotation window by …
charhart May 28, 2021
19730fd
fix next / last validation annotation
charhart Jun 7, 2021
0ecc46b
add view to show annotation study results
charhart Aug 5, 2021
644804c
updates to profile annotation buttons
charhart Aug 5, 2021
3291c6b
add loading of previously saved items
charhart Aug 13, 2021
a985a46
update sampleName to cohortSampleId
charhart Aug 13, 2021
207da60
add launch study window from sample window
charhart Aug 14, 2021
c74f72a
fix question form
charhart Aug 15, 2021
4dd8583
make case questions false by default
charhart Aug 15, 2021
ce6b86a
fix annotation set launching
charhart Aug 15, 2021
76788a2
view for question sets
charhart Aug 16, 2021
43c9d6e
disabled delete for now
charhart Aug 16, 2021
51066d6
add create study window on validation window from question sets
charhart Aug 16, 2021
1d65d57
fix linking samples from question sets on validation
charhart Aug 16, 2021
360d00f
fix profile launching with question set id route
charhart Aug 17, 2021
37b7090
add answer value and answer text on study results
charhart Aug 17, 2021
5d911ea
add date and numeric types
charhart Aug 18, 2021
cba5283
fix number annotation type
charhart Aug 18, 2021
284406f
add button/functionality for deleting question sets
charhart Aug 20, 2021
d40b879
Updated alert wording
jduke99 Aug 20, 2021
e1beb24
rename case status to case question on annotation tool
charhart Aug 20, 2021
6b85ce1
Merge branch 'master' of https://github.com/cahilton/Atlas
charhart Aug 20, 2021
925cc6d
fix route issue
charhart Aug 21, 2021
dc8b177
merge latest from OHDSI Atlas master; fix conflicts in cohort-definit…
charhart Aug 22, 2021
ed91892
fixes / testing after updates to corresponding WebAPI feature
charhart Aug 23, 2021
e442811
minor code cleanup on feature specific JS files
charhart Aug 23, 2021
dad58ca
Merge remote-tracking branch 'remotes/upstream/master' into annotatio…
chrisknoll Nov 8, 2021
290d805
Updated end points to 'annotation'.
chrisknoll Nov 10, 2021
70f116b
Merge pull request #2 from cahilton/annotation-cknoll
charhart Nov 16, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
/js/assets/fonts
/js/assets/images
js/config-local.js
js/config-gis.js
js/version.js
package-lock.json
.vscode
.vscode
.DS_Store
75 changes: 75 additions & 0 deletions js/pages/cohort-definitions/Validation/QuestionSet.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
define(['knockout', 'services/Validation', './QuestionSetForm'], function (ko, ValidationService, QuestionSetForm) {
function QuestionSet(id, cohortName, qSetId, qSetName, qSetQuestions, mode) {
const self = this;
self.qsetName = ko.observable(qSetName);
self.setId = ko.observable(qSetId);
self.setQuestions = ko.observableArray(qSetQuestions);
self.mode = ko.observable(mode);
self.questionItems = ko.observableArray([]);

self.questionSetForm = new QuestionSetForm(id, cohortName);

self.goBack = function (parent) {
setTimeout(() => {
parent.valTabMode(parent.default_view);
// if you don't do this, ko complains.
}, 1000);


};

self.resetValues = function (id, cohortName, qSetId, qSetName, qSetQuestions, mode) {
self.qsetName(qSetName);
self.setId(qSetId);
self.setQuestions(qSetQuestions);
self.mode(mode);
self.showSelectedQset();
};

self.submitQsetForm = function (sn) {
return self.questionSetForm.createQuestionSet(sn);
};

self.initialize = function () {
self.questionSetForm.initialize();
};


self.showSelectedQset = function () {
self.questionItems([]);
for (let i = 0; i < self.setQuestions().length; i++) {
let qs = {};
let qsAnswers = [];
let cq = self.setQuestions()[i];
let qnum = "Question " + (i + 1) + ': ';

if (cq !== undefined) {
qs['text'] = qnum + cq.text;
qs['type'] = 'Question Type: ' + cq.type;
qs['caseQ'] = 'Case Question: ' + cq.caseQuestion;
qs['req'] = 'Required: ' + cq.required;
for (let j = 0; j < cq.answers.length; j++) {
if (cq.type !== 'TEXTAREA') {
qsAnswers.push(cq.answers[j].text);
} else {
qsAnswers.push("None");
}
}
} else {
qs['text'] = qnum + '';
qs['type'] = 'Question Type: ' + '';
qs['caseQ'] = 'Case Question: ' + '';
qs['req'] = 'Required: ' + '';
}
qs['answers'] = qsAnswers;
self.questionItems.push(qs);
}
};


}

QuestionSet.prototype.constructor = QuestionSet;
return QuestionSet;

});
174 changes: 174 additions & 0 deletions js/pages/cohort-definitions/Validation/QuestionSetForm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
define(['knockout', 'services/Validation'], function (ko, ValidationService) {
function QuestionSetForm(id, cohortName) {
const self = this;
self.questions = ko.observableArray([]);
self.questionSetName = ko.observable();
self.questionTypes = ko.observableArray(['Text', 'Radio Button', 'Checkbox', 'Numeric', 'Date']);
self.bools = ko.observableArray(['false', 'true']);
self.caseBools = ko.observableArray(['false', 'true']);
self.errorMessage = ko.observable();


function Answer() {
const self = this;
self.text = ko.observable();
self.value = '';
// self.helpText = ko.observable()
}

function Question() {
const self = this;
self.text = ko.observable('');
// self.helpText = ko.observable('');
self.type = ko.observable('');
self.caseQuestion = ko.observable('');
self.required = ko.observable('');
self.answers = ko.observableArray([]);

self.addAnswer = function () {
if ((self.type() !== 'Text' && self.type() !== 'Numeric' && self.type() !== 'Date') && self.type() !== undefined) {
self.answers.push(new Answer());
}
};
self.removeAnswer = function (item) {
self.answers.remove(item);
};

self.questionTypeChanged = function (obj, evt) {
if (obj !== 'Text' && obj !== 'Numeric' && obj !== 'Date') {
if (self.answers().length === 0) {
self.addAnswer();
}
}
};
}

self.addQuestion = function () {
self.questions.push(new Question());
};

self.initialize = function () {
self.addQuestion();
};


self.removeQuestion = function (item) {
self.questions.remove(item);
};

self.createQuestionSet = function (sampleSourceKey) {
if (self.errorMessage() != null) {
self.errorMessage('');
}

//check that qset name is not undefined
if (self.questionSetName() === undefined) {
self.errorMessage('Please enter question set name.');
return null;
}

if (self.questions().length === 0) {
self.errorMessage("Please include at least one question");
return null;
}

let numCaseQuestions = 0;
let currentAnswer = null;
let i;
let j = 0;
for (i = 0; i < self.questions().length; i++) {

let currentQuestion = self.questions()[i];
let numAnswers = self.questions()[i].answers().length;
let currentQuestionType = self.questions()[i].type();


//check that questions are not null or unselected
if (currentQuestion.text() == null ||
// currentQuestion.helpText() == null ||
currentQuestion.type() == null ||
currentQuestion.caseQuestion() == null ||
currentQuestion.required() == null) {
self.errorMessage('Please do not leave any question field blank or unselected.');
break;
}

const multipleAnswerType = (currentQuestionType !== 'Text' && currentQuestionType !== 'Numeric' && currentQuestionType !== 'Date');
//enforce that all have answers unless text
if (numAnswers === 0 && multipleAnswerType) {
self.errorMessage('Checkbox and radio button questions must have answers');
break;
}

//check that answers don't have null values
for (j = 0; j < self.questions()[i].answers().length; j++) {
currentAnswer = self.questions()[i].answers()[j];
if (currentAnswer.text() == null && // || currentAnswer.helpText() == null) &&
multipleAnswerType) {
self.errorMessage('Please do not leave answers blank.');
break;
}
}


//check that only one question is a case question
if (currentQuestion.caseQuestion() === 'true') {
if (++numCaseQuestions > 1) {
self.errorMessage('Only one question can be a case question.');
break;
}
}

}

if (self.errorMessage()) {
return null;
}

for (i = 0; i < self.questions().length; i++) {
if (self.questions()[i].type() === 'Text') {
self.questions()[i].answers.push(new Answer());
self.questions()[i].answers()[0].text = '';
self.questions()[i].type = 'TEXTAREA';
} else if (self.questions()[i].type() === 'Numeric') {
self.questions()[i].answers.push(new Answer());
self.questions()[i].answers()[0].text = '';
self.questions()[i].type = 'NUMERIC';
} else if (self.questions()[i].type() === 'Date') {
self.questions()[i].answers.push(new Answer());
self.questions()[i].answers()[0].text = '';
self.questions()[i].type = 'DATE';
} else if (self.questions()[i].type() === "Checkbox") {
self.questions()[i].type = 'MULTI_SELECT';
for (j = 0; j < self.questions()[i].answers().length; j++) {
currentAnswer = self.questions()[i].answers()[j];
currentAnswer.value = currentAnswer.text();
}
} else if (self.questions()[i].type() === "Radio Button") {
self.questions()[i].type = 'SINGLE_SELECT';
for (j = 0; j < self.questions()[i].answers().length; j++) {
currentAnswer = self.questions()[i].answers()[j];
currentAnswer.value = j;
}
}
}

const data = {
cohortName: cohortName,
cohortSource: sampleSourceKey,
cohortId: id,
name: self.questionSetName(),
questions: ko.toJS(self.questions())
};
return ValidationService.submitQuestionSet(JSON.stringify(data));


};

self.initialize();
}

QuestionSetForm.prototype.constructor = QuestionSetForm;
return QuestionSetForm;

});
Loading