diff --git a/js/pages/cohort-definitions/cohort-definition-manager.css b/js/pages/cohort-definitions/cohort-definition-manager.css
index a4f0e9175..db5777dc3 100644
--- a/js/pages/cohort-definitions/cohort-definition-manager.css
+++ b/js/pages/cohort-definitions/cohort-definition-manager.css
@@ -56,4 +56,35 @@
.cohort-conceptset-button-pane .btn-success.disabled {
color: #f3f3f3;
-}
\ No newline at end of file
+}
+
+.sampleCreatingForm label {
+ font-weight: bold !important;
+}
+
+.myCustomInputError {
+ border-color: #a94442
+}
+
+.myCustomInputSuccess {
+ border-color: #3c763d
+}
+
+.myCustomTextError {
+ color: #a94442 !important
+}
+
+.myCustomTextSuccess {
+ color: #3c763d !important
+}
+
+.sample-list.fa-trash {
+ color: red;
+ cursor: pointer;
+}
+
+.sample-list.fa-refresh {
+ color: #265a88;
+ cursor: pointer;
+}
+
\ No newline at end of file
diff --git a/js/pages/cohort-definitions/cohort-definition-manager.html b/js/pages/cohort-definitions/cohort-definition-manager.html
index c3c8dfe75..8e77ed440 100644
--- a/js/pages/cohort-definitions/cohort-definition-manager.html
+++ b/js/pages/cohort-definitions/cohort-definition-manager.html
@@ -26,7 +26,7 @@
-
@@ -44,6 +44,10 @@
Generation
+
+ Samples
+
+
Reporting
@@ -354,8 +358,186 @@ Appendix 1: Concept Set Definitions
+
+
+
+
+
+ Sample Selections
+
+
+
+
+
+ Add new sample
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Cohort Not Generated
+
+
+ This cohort has not been generated in the data source you selected. Please return to the generation tab to generate the cohort before accessing samples.
+
+
+
+
+
+
+
+
+
-
+
\ No newline at end of file
diff --git a/js/pages/cohort-definitions/cohort-definition-manager.js b/js/pages/cohort-definitions/cohort-definition-manager.js
index 59ddea809..ebdf30eaf 100644
--- a/js/pages/cohort-definitions/cohort-definition-manager.js
+++ b/js/pages/cohort-definitions/cohort-definition-manager.js
@@ -16,6 +16,7 @@ define(['jquery', 'knockout', 'text!./cohort-definition-manager.html',
'atlas-state',
'clipboard',
'd3',
+ 'services/Sample',
'services/Jobs',
'services/job/jobDetail',
'services/JobDetailsService',
@@ -76,6 +77,7 @@ define(['jquery', 'knockout', 'text!./cohort-definition-manager.html',
sharedState,
clipboard,
d3,
+ sampleService,
jobService,
jobDetail,
jobDetailsService,
@@ -108,6 +110,81 @@ define(['jquery', 'knockout', 'text!./cohort-definition-manager.html',
return (textA < textB) ? -1 : (textA > textB) ? 1 : 0;
}
+ function gender(code) {
+ if(code==8507) return 'Male'
+ if(code==8532) return 'Female'
+ else return "Other"
+ }
+
+ function mapSampleListData(originalData) {
+ return originalData.map(el => {
+ let selectionCriteria;
+ let mode;
+ if(el.age) {
+ switch (el.age.mode) {
+ case 'between':
+ mode = 'Between'
+ break;
+ case 'notBetween':
+ mode = 'Not between'
+ break;
+ case 'lessThan':
+ mode= 'Less than'
+ break;
+ case 'lessThanOrEqual':
+ mode= 'Less than or equal'
+ break;
+ case 'equalTo':
+ mode= 'Equal'
+ break;
+ case 'greaterThan':
+ mode= 'Greater than'
+ break;
+ case 'greaterThanOrEqual':
+ mode= 'Greater than or equal'
+ break;
+ default:
+ break;
+ }
+ } else {
+ mode = ''
+ }
+ if((mode=='Between'||mode=='Not between')&& el.age) {
+ selectionCriteria = `${mode} ${el.age.min} and ${el.age.max}`
+ } else if(el.age) {
+ selectionCriteria = `${mode} ${el.age.value}`
+ } else {
+ selectionCriteria = 'Any age'
+ }
+ if(el.gender.otherNonBinary&&el.gender.conceptIds.length==2) {
+ selectionCriteria =`Any Gender, ${selectionCriteria}`
+ } else {
+ if (el.gender.otherNonBinary) {
+ selectionCriteria = `Other, ${selectionCriteria}`
+ }
+ if (el.gender.conceptIds[0]) {
+ selectionCriteria = `${gender(el.gender.conceptIds[0])}, ${selectionCriteria}`
+ }
+ if (el.gender.conceptIds[1]) {
+ selectionCriteria = `${gender(el.gender.conceptIds[1])}, ${selectionCriteria}`
+ }
+ }
+ const sampleId = el.id;
+ const sampleName = el.name || ''
+ const patientCounts = el.size
+ const createdBy = el.createdBy && el.createdBy.name || ''
+ const createdOn = new Date(el.createdDate).toLocaleString()
+ return {
+ sampleId,
+ sampleName,
+ selectionCriteria,
+ patientCounts,
+ createdBy,
+ createdOn,
+ }
+ })
+ }
+
class CohortDefinitionManager extends AutoBind(Clipboard(Page)) {
constructor(params) {
super(params);
@@ -123,7 +200,7 @@ define(['jquery', 'knockout', 'text!./cohort-definition-manager.html',
this.cohortDefinitionSourceInfo = sharedState.CohortDefinition.sourceInfo;
this.dirtyFlag = sharedState.CohortDefinition.dirtyFlag;
this.conceptSets = ko.computed(() => this.currentCohortDefinition() && this.currentCohortDefinition().expression().ConceptSets);
- this.conceptSetStore = ConceptSetStore.getStore(ConceptSetStore.sourceKeys().cohortDefinition);
+ this.conceptSetStore = ConceptSetStore.getStore(ConceptSetStore.sourceKeys().cohortDefinition);
this.sourceAnalysesStatus = {};
this.reportCohortDefinitionId = ko.observable();
this.reportSourceKey = ko.observable();
@@ -136,11 +213,124 @@ define(['jquery', 'knockout', 'text!./cohort-definition-manager.html',
this.service = cohortDefinitionService;
this.defaultName = globalConstants.newEntityNames.cohortDefinition;
this.isReportGenerating = ko.observable(false);
- this.cdmSources = ko.computed(() => {
+
+ // sample states
+ this.showSampleCreatingModal = ko.observable(false);
+ this.sampleSourceKey = ko.observable();
+ this.isSampleGenerating = ko.observable(false);
+ this.isLoadingSampleData = ko.observable(false);
+ this.cohortDefinitionIdOnRoute=ko.observable();
+ // new sample state
+ this.newSampleCreatingLoader = ko.observable(false);
+ this.sampleName=ko.observable('');
+ this.patientCount=ko.observable();
+ this.sampleAgeType = ko.observable('');
+ this.firstAge = ko.observable();
+ this.secondAge = ko.observable();
+ this.isMaleSample=ko.observable(false);
+ this.isFeMaleSample=ko.observable(false);
+ this.isOtherGenderSample=ko.observable(false);
+ //error state
+ this.sampleNameError=ko.pureComputed(() => this.sampleName().trim() == "");
+ this.patientCountError=ko.pureComputed(() => !(this.patientCount() > 0)); // this works because null == 0
+ this.isAgeRange =ko.pureComputed(() => ['between','notBetween'].includes(this.sampleAgeType()));
+ this.firstAgeError = ko.pureComputed(() => this.firstAge() != null && this.firstAge() < 0);
+ this.isAgeRangeError = ko.pureComputed(() => this.isAgeRange() // age range selected
+ && !(this.firstAge() == null && this.secondAge() == null) // one is non-null
+ && (this.firstAge() == null || this.secondAge() == null || this.firstAge() < 0 || this.secondAge() < 0 || this.firstAge() == this.secondAge())); // has invalid value
+
+ //sampleSourceKey changes => get list of samples
+ this.trackSub(this.sampleSourceKey.subscribe(val => {
+ const cohortId = this.currentCohortDefinition()?
+ this.currentCohortDefinition().id():
+ this.cohortDefinitionIdOnRoute()
+ if(!val) {
+ history.pushState(null, '', `#/cohortdefinition/${cohortId}/samples`)
+ return
+ };
+ history.pushState(null, '', `#/cohortdefinition/${cohortId}/samples/${val}`)
+ this.getSampleList(cohortId)
+ }));
+
+ //validation input value
+
+ //sample list
+ this.sampleListCols = [
+ {
+ title: 'Sample Id',
+ data:'sampleId',
+ visible: false,
+ },
+ {
+ title: 'Sample name',
+ render: datatableUtils.getLinkFormatter(d => ({
+ label: d['sampleName'],
+ linkish: true,
+ })),
+ },
+ {
+ title: 'Number of patients',
+ data: 'patientCounts',
+ },
+ {
+ title: 'Selection criteria',
+ data: 'selectionCriteria',
+ },
+ {
+ title: 'Created by',
+ data: 'createdBy',
+ },
+ {
+ title: 'Created on',
+ data: 'createdOn'
+ },
+ {
+ title: 'Action',
+ sortable: false,
+ render: function() {return ` `}
+ }
+ ]
+ this.sampleList = ko.observableArray()
+
+ // Sample data table
+ this.sampleCols = [
+ {
+ title: 'Person ID',
+ render: datatableUtils.getLinkFormatter(d => ({
+ label: d['personId'],
+ linkish: true,
+ })),
+ },
+ {
+ title: 'Gender',
+ data: 'gender',
+ },
+ {
+ title: 'Age at index',
+ data: 'ageIndex',
+ }
+ ];
+
+ this.selectedSampleId = ko.observable('');
+ this.selectedSampleName = ko.observable('');
+ this.sampleDataLoading = ko.observable(false);
+ this.sampleData =ko.observableArray([]);
+
+ this.isCohortGenerated = ko.pureComputed(() => {
+ const sourceInfo = this.cohortDefinitionSourceInfo().find(d => d.sourceKey == this.sampleSourceKey());
+ if (sourceInfo&&this.getStatusMessage(sourceInfo) == 'COMPLETE') {
+ return true;
+ }
+ return false;
+ });
+
+ //end of sample states
+
+ this.cdmSources = ko.pureComputed(() => {
return sharedState.sources().filter((source) => commonUtils.hasCDM(source) && authApi.hasSourceAccess(source.sourceKey));
});
- this.cohortDefinitionCaption = ko.computed(() => {
+ this.cohortDefinitionCaption = ko.pureComputed(() => {
if (this.currentCohortDefinition()) {
if (this.currentCohortDefinition().id() === 0 || this.currentCohortDefinition().id() === null) {
return this.defaultName;
@@ -149,20 +339,20 @@ define(['jquery', 'knockout', 'text!./cohort-definition-manager.html',
}
}
});
- this.isNameFilled = ko.computed(() => {
+ this.isNameFilled = ko.pureComputed(() => {
return this.currentCohortDefinition() && this.currentCohortDefinition().name() && this.currentCohortDefinition().name().trim();
});
- this.isNameCharactersValid = ko.computed(() => {
+ this.isNameCharactersValid = ko.pureComputed(() => {
return this.isNameFilled() && commonUtils.isNameCharactersValid(this.currentCohortDefinition().name());
});
- this.isNameLengthValid = ko.computed(() => {
+ this.isNameLengthValid = ko.pureComputed(() => {
return this.isNameFilled() && commonUtils.isNameLengthValid(this.currentCohortDefinition().name());
});
- this.isDefaultName = ko.computed(() => {
+ this.isDefaultName = ko.pureComputed(() => {
return this.isNameFilled() && this.currentCohortDefinition().name().trim() === this.defaultName;
});
- this.isNameCorrect = ko.computed(() => {
+ this.isNameCorrect = ko.pureComputed(() => {
return this.isNameFilled() && !this.isDefaultName() && this.isNameCharactersValid() && this.isNameLengthValid();
});
this.isAuthenticated = ko.pureComputed(() => {
@@ -242,7 +432,7 @@ define(['jquery', 'knockout', 'text!./cohort-definition-manager.html',
this.sourcecodes = ko.observable();
this.conceptLoading = ko.observable(false);
this.conceptSetName = ko.observable();
- this.tabPath = ko.computed(() => {
+ this.tabPath = ko.pureComputed(() => {
var path = this.tabMode();
if (path === 'export') {
path += '/' + this.exportTabMode();
@@ -319,7 +509,7 @@ define(['jquery', 'knockout', 'text!./cohort-definition-manager.html',
this.selectedSource = ko.observable();
this.selectedReportSource = ko.observable();
- this.sortedConceptSets = ko.computed((d) => {
+ this.sortedConceptSets = ko.pureComputed((d) => {
if (this.currentCohortDefinition() != null) {
var clone = this.currentCohortDefinition().expression().ConceptSets().slice(0);
return clone.sort(conceptSetSorter);
@@ -382,7 +572,7 @@ define(['jquery', 'knockout', 'text!./cohort-definition-manager.html',
},
]
};
-
+
this.stopping = ko.pureComputed(() => this.cohortDefinitionSourceInfo().reduce((acc, target) => ({...acc, [target.sourceKey]: ko.observable(false)}), {}));
this.isSourceStopping = (source) => this.stopping()[source.sourceKey];
@@ -443,7 +633,7 @@ define(['jquery', 'knockout', 'text!./cohort-definition-manager.html',
}).length > 0;
});
- this.cohortDefinitionLink = ko.computed(() => {
+ this.cohortDefinitionLink = ko.pureComputed(() => {
if (this.currentCohortDefinition()) {
return commonUtils.normalizeUrl(this.config.api.url, "cohortdefinition", this.currentCohortDefinition().id());
}
@@ -471,7 +661,7 @@ define(['jquery', 'knockout', 'text!./cohort-definition-manager.html',
}
});
- this.reportingState = ko.computed(() => {
+ this.reportingState = ko.pureComputed(() => {
// require a data source selection
if (this.reportSourceKey() == undefined) {
this.generateReportsEnabled(false);
@@ -546,7 +736,7 @@ define(['jquery', 'knockout', 'text!./cohort-definition-manager.html',
return "unknown_cohort_report_state";
});
- this.showReportNameDropdown = ko.computed(() => {
+ this.showReportNameDropdown = ko.pureComputed(() => {
return this.reportSourceKey() != undefined &&
this.reportingState() != 'checking_status' &&
this.reportingState() != 'cohort_not_generated' &&
@@ -608,14 +798,15 @@ define(['jquery', 'knockout', 'text!./cohort-definition-manager.html',
this.analysisTypesOpened = ko.observable(false);
this.currentConceptSet = this.conceptSetStore.current;
- this.reportSourceKeySub = this.reportSourceKey.subscribe(source => {
+ this.trackSub(this.reportSourceKey.subscribe(source => {
PollService.stop(this.pollId);
this.reportReportName(null);
this.reportingSourceStatusAvailable(false);
this.reportingAvailableReports.removeAll();
const cd = this.currentCohortDefinition();
source && this.startPolling(cd, source);
- });
+ }));
+
this.reportsManagerComponentParams = {
reportSourceKey: this.reportSourceKey,
@@ -623,10 +814,19 @@ define(['jquery', 'knockout', 'text!./cohort-definition-manager.html',
PermissionService.decorateComponent(this, {
entityTypeGetter: () => entityType.COHORT_DEFINITION,
entityIdGetter: () => this.currentCohortDefinition().id(),
- createdByUsernameGetter: () => this.currentCohortDefinition() && this.currentCohortDefinition().createdBy()
+ createdByUsernameGetter: () => this.currentCohortDefinition() && this.currentCohortDefinition().createdBy()
&& this.currentCohortDefinition().createdBy().login
});
+// todo: look into if this subscription is necessary
+ this.trackSub(this.tabMode.subscribe(mode => {
+ if(mode&&this.currentCohortDefinition()&&mode!=='samples') {
+ const cohortId = this.currentCohortDefinition().id()
+ // use push state to prevent the component to re-render
+ history.pushState(null, '', `#/cohortdefinition/${cohortId}`)
+ }
+ }));
+
this.pollForInfoPeriodically();
this.subscriptions.push(
@@ -658,676 +858,871 @@ define(['jquery', 'knockout', 'text!./cohort-definition-manager.html',
}
}
- delete () {
- if (!confirm("Delete cohort definition? Warning: deletion can not be undone!"))
- return;
+ delete () {
+ if (!confirm("Delete cohort definition? Warning: deletion can not be undone!"))
+ return;
- this.isDeleting(true);
-
- // reset view after save
- cohortDefinitionService.deleteCohortDefinition(this.currentCohortDefinition().id()).
- then( (result) => {
- this.currentCohortDefinition(null);
- PollService.stop(this.pollTimeoutId);
- this.dirtyFlag().reset();
- this.close();
- }, (error) => {
- console.log("Error: " + error);
- if(error.status == 409) {
- alert("Cohort definition cannot be deleted because it is referenced in some analysis");
- this.isDeleting(false);
- } else {
- authApi.handleAccessDenied(error);
- }
- });
- }
+ this.isDeleting(true);
- async save () {
- this.isSaving(true);
+ // reset view after save
+ cohortDefinitionService.deleteCohortDefinition(this.currentCohortDefinition().id()).
+ then( (result) => {
+ this.currentCohortDefinition(null);
+ PollService.stop(this.pollTimeoutId);
+ this.dirtyFlag().reset();
+ this.close();
+ }, (error) => {
+ console.log("Error: " + error);
+ if(error.status == 409) {
+ alert("Cohort definition cannot be deleted because it is referenced in some analysis");
+ this.isDeleting(false);
+ } else {
+ authApi.handleAccessDenied(error);
+ }
+ });
+ }
- let cohortDefinitionName = this.currentCohortDefinition().name();
- this.currentCohortDefinition().name(cohortDefinitionName.trim());
+ async save () {
+ this.sampleSourceKey(null)
+ this.isSaving(true);
- // Next check to see that a cohort definition with this name does not already exist
- // in the database. Also pass the id so we can make sure that the
- // current Cohort Definition is excluded in this check.
+ let cohortDefinitionName = this.currentCohortDefinition().name();
+ this.currentCohortDefinition().name(cohortDefinitionName.trim());
- try {
- const results = await cohortDefinitionService.exists(this.currentCohortDefinition().name(), this.currentCohortDefinition().id());
- if (results > 0) {
- alert('A cohort definition with this name already exists. Please choose a different name.');
- } else {
- this.conceptSetStore.clear();
+ // Next check to see that a cohort definition with this name does not already exist
+ // in the database. Also pass the id so we can make sure that the
+ // current Cohort Definition is excluded in this check.
- // If we are saving a new cohort definition (id === 0) then clear
- // the id field before saving
- if (this.currentCohortDefinition().id() === "0") {
- this.currentCohortDefinition().id(undefined);
- }
- var definition = ko.toJS(this.currentCohortDefinition());
- // reset view after save
- const savedDefinition = await cohortDefinitionService.saveCohortDefinition(definition);
- definition = new CohortDefinition(savedDefinition);
- const redirectWhenComplete = definition.id() != this.currentCohortDefinition().id();
- this.currentCohortDefinition(definition);
- if (redirectWhenComplete) {
- commonUtils.routeTo(constants.paths.details(definition.id()));
- }
+ try {
+ const results = await cohortDefinitionService.exists(this.currentCohortDefinition().name(), this.currentCohortDefinition().id());
+ if (results > 0) {
+ alert('A cohort definition with this name already exists. Please choose a different name.');
+ } else {
+ this.conceptSetStore.clear();
+
+ // If we are saving a new cohort definition (id === 0) then clear
+ // the id field before saving
+ if (this.currentCohortDefinition().id() === "0") {
+ this.currentCohortDefinition().id(undefined);
+ }
+ var definition = ko.toJS(this.currentCohortDefinition());
+ // reset view after save
+ const savedDefinition = await cohortDefinitionService.saveCohortDefinition(definition);
+ definition = new CohortDefinition(savedDefinition);
+ const redirectWhenComplete = definition.id() != this.currentCohortDefinition().id();
+ this.currentCohortDefinition(definition);
+ if (redirectWhenComplete) {
+ commonUtils.routeTo(constants.paths.details(definition.id()));
}
- sharedState.CohortDefinition.lastUpdatedId(this.currentCohortDefinition().id());
- } catch (e) {
- alert('An error occurred while attempting to save a cohort definition.');
- } finally {
- this.isSaving(false);
}
+ sharedState.CohortDefinition.lastUpdatedId(this.currentCohortDefinition().id());
+ } catch (e) {
+ alert('An error occurred while attempting to save a cohort definition.');
+ } finally {
+ this.isSaving(false);
}
+ }
- close () {
- if (this.dirtyFlag().isDirty() && !confirm("Your cohort changes are not saved. Would you like to continue?")) {
- return;
- } else {
- this.conceptSetStore.clear();
- this.currentCohortDefinition(null);
- this.dirtyFlag().reset();
- this.reportCohortDefinitionId(null);
- this.reportReportName(null);
- this.reportSourceKey(null);
- commonUtils.routeTo('/cohortdefinitions');
- }
+ close () {
+ if (this.dirtyFlag().isDirty() && !confirm("Your cohort changes are not saved. Would you like to continue?")) {
+ return;
+ } else {
+ this.conceptSetStore.clear();
+ this.currentCohortDefinition(null);
+ this.dirtyFlag().reset();
+ this.reportCohortDefinitionId(null);
+ this.reportReportName(null);
+ this.reportSourceKey(null);
+ commonUtils.routeTo('/cohortdefinitions');
}
+ }
- async copy () {
- this.isCopying(true);
- // reset view after save
- try {
- const result = await cohortDefinitionService.copyCohortDefinition(this.currentCohortDefinition().id());
- PollService.stop(this.pollTimeoutId);
- document.location = "#/cohortdefinition/" + result.id;
- } finally {
- this.isCopying(false);
- }
+ async copy () {
+ this.isCopying(true);
+ // reset view after save
+ try {
+ const result = await cohortDefinitionService.copyCohortDefinition(this.currentCohortDefinition().id());
+ PollService.stop(this.pollTimeoutId);
+ document.location = "#/cohortdefinition/" + result.id;
+ } finally {
+ this.isCopying(false);
}
+ }
- isSourceRunning(source) {
- if (source) {
- switch (source.status()) {
- case 'COMPLETE':
- return false;
- break;
- case 'n/a':
- return false;
- break;
- default:
- return true;
- }
- } else {
- return false;
+ isSourceRunning(source) {
+ if (source) {
+ switch (source.status()) {
+ case 'COMPLETE':
+ return false;
+ break;
+ case 'n/a':
+ return false;
+ break;
+ default:
+ return true;
}
+ } else {
+ return false;
}
+ }
- isCancelDisabled(source) {
- return this.isSourceStopping(source)() || this.isProcessingByAnother(source);
- }
+ isCancelDisabled(source) {
+ return this.isSourceStopping(source)() || this.isProcessingByAnother(source);
+ }
- isProcessingByAnother(source) {
- return !this.isMine(source) && source.status() !== "COMPLETE" && source.status() !== "FAILED";
- }
+ isProcessingByAnother(source) {
+ return !this.isMine(source) && source.status() !== "COMPLETE" && source.status() !== "FAILED";
+ }
- isMine(source) {
- return source.createdBy() ? authApi.subject() === source.createdBy() : false;
- }
+ isMine(source) {
+ return source.createdBy() ? authApi.subject() === source.createdBy() : false;
+ }
- async exportSql({ expression = {} } = {}) {
+ async exportSql({ expression = {} } = {}) {
- return await this.service.getSql(ko.toJS(expression, pruneJSON));
- }
+ return await this.service.getSql(ko.toJS(expression, pruneJSON));
+ }
- getSourceKeyInfo (sourceKey) {
- return this.cohortDefinitionSourceInfo().filter((d) => {
- return d.sourceKey == sourceKey
- })[0];
- }
+ getSourceKeyInfo (sourceKey) {
+ return this.cohortDefinitionSourceInfo().filter((d) => {
+ return d.sourceKey == sourceKey
+ })[0];
+ }
- getSourceId (sourceKey) {
- return sharedState.sources().find(source => source.sourceKey === sourceKey).sourceId;
- }
+ getSourceId (sourceKey) {
+ return sharedState.sources().find(source => source.sourceKey === sourceKey).sourceId;
+ }
- generateCohort (source) {
- this.stopping()[source.sourceKey](false);
- this.getSourceKeyInfo(source.sourceKey).status(globalConstants.generationStatuses.PENDING);
- this.getSourceKeyInfo(source.sourceKey).createdBy(authApi.subject());
- if (this.selectedSource() && this.selectedSource().sourceId === source.sourceId) {
- this.toggleCohortReport(null);
- }
- cohortDefinitionService.generate(this.currentCohortDefinition().id(), source.sourceKey)
- .catch(this.authApi.handleAccessDenied)
- .then(({data}) => {
- jobDetailsService.createJob(data);
- });
+ generateCohort (source) {
+ this.stopping()[source.sourceKey](false);
+ this.getSourceKeyInfo(source.sourceKey).status(globalConstants.generationStatuses.PENDING);
+ this.getSourceKeyInfo(source.sourceKey).createdBy(authApi.subject());
+ if (this.selectedSource() && this.selectedSource().sourceId === source.sourceId) {
+ this.toggleCohortReport(null);
}
+ cohortDefinitionService.generate(this.currentCohortDefinition().id(), source.sourceKey)
+ .catch(this.authApi.handleAccessDenied)
+ .then(({data}) => {
+ jobDetailsService.createJob(data);
+ });
+ }
- cancelGenerate (source) {
- this.stopping()[source.sourceKey](true);
- cohortDefinitionService.cancelGenerate(this.currentCohortDefinition().id(), source.sourceKey);
- };
+ cancelGenerate (source) {
+ this.stopping()[source.sourceKey](true);
+ cohortDefinitionService.cancelGenerate(this.currentCohortDefinition().id(), source.sourceKey);
+ };
- hasCDM (source) {
- for (var d = 0; d < source.daimons.length; d++) {
- if (source.daimons[d].daimonType == 'CDM') {
- return true;
- }
+ hasCDM (source) {
+ for (var d = 0; d < source.daimons.length; d++) {
+ if (source.daimons[d].daimonType == 'CDM') {
+ return true;
}
- return false;
}
+ return false;
+ }
- hasResults (source) {
- for (var d = 0; d < source.daimons.length; d++) {
- if (source.daimons[d].daimonType == 'Results') {
- return true;
- }
+ hasResults (source) {
+ for (var d = 0; d < source.daimons.length; d++) {
+ if (source.daimons[d].daimonType == 'Results') {
+ return true;
}
- return false;
}
+ return false;
+ }
- removeConceptSet(id) {
- this.currentCohortDefinition().expression().ConceptSets.remove(
- function (item) {
- return item.id === id;
- }
- );
- }
+ removeConceptSet(id) {
+ this.currentCohortDefinition().expression().ConceptSets.remove(
+ function (item) {
+ return item.id === id;
+ }
+ );
+ }
- removeInclusionRule(name) {
- this.currentCohortDefinition().expression().InclusionRules.remove(
- (item) => item.name() === name
- );
- }
+ removeInclusionRule(name) {
+ this.currentCohortDefinition().expression().InclusionRules.remove(
+ (item) => item.name() === name
+ );
+ }
- fixConceptSet(warning) {
- if (warning.type === 'ConceptSetWarning' && warning.conceptSetId >= 0) {
- this.removeConceptSet(warning.conceptSetId);
- } else if (warning.type === 'IncompleteRuleWarning' && warning.ruleName) {
- this.removeInclusionRule(warning.ruleName);
- }
+ fixConceptSet(warning) {
+ if (warning.type === 'ConceptSetWarning' && warning.conceptSetId >= 0) {
+ this.removeConceptSet(warning.conceptSetId);
+ } else if (warning.type === 'IncompleteRuleWarning' && warning.ruleName) {
+ this.removeInclusionRule(warning.ruleName);
}
+ }
- diagnose() {
- if (this.currentCohortDefinition()) {
- return cohortDefinitionService.runDiagnostics(this.currentCohortDefinition().expression());
- }
+ diagnose() {
+ if (this.currentCohortDefinition()) {
+ return cohortDefinitionService.runDiagnostics(this.currentCohortDefinition().expression());
}
+ }
- showSaveConceptSet () {
- this.newConceptSetName(this.currentConceptSet().name());
- this.saveConceptSetShow(true);
- };
+ showSaveConceptSet () {
+ this.newConceptSetName(this.currentConceptSet().name());
+ this.saveConceptSetShow(true);
+ };
- saveConceptSet () {
- this.saveConceptSetShow(false);
- var conceptSet = {
- id: 0,
- name: this.newConceptSetName()
- };
- var conceptSetItems = conceptSetUitls.toRepositoryConceptSetItems(this.selectedConcepts());
- conceptSetService.saveConceptSet(conceptSet)
- .then((data) => {
- const conceptSetId = data.data.id;
- return conceptSetService.saveConceptSetItems(conceptSetId, conceptSetItems);
- });
+ saveConceptSet () {
+ this.saveConceptSetShow(false);
+ var conceptSet = {
+ id: 0,
+ name: this.newConceptSetName()
};
-
- viewReport (sourceKey, reportName) {
- // TODO: Should we prevent running an analysis on an unsaved cohort definition?
- if (this.currentCohortDefinition().id() > 0) {
- this.reportCohortDefinitionId(this.currentCohortDefinition().id());
- this.reportReportName(reportName);
- this.reportSourceKey(sourceKey);
- this.reportTriggerRun(true);
- }
+ var conceptSetItems = conceptSetUitls.toRepositoryConceptSetItems(this.selectedConcepts());
+ conceptSetService.saveConceptSet(conceptSet)
+ .then((data) => {
+ const conceptSetId = data.data.id;
+ return conceptSetService.saveConceptSetItems(conceptSetId, conceptSetItems);
+ });
+ };
+
+ viewReport (sourceKey, reportName) {
+ // TODO: Should we prevent running an analysis on an unsaved cohort definition?
+ if (this.currentCohortDefinition().id() > 0) {
+ this.reportCohortDefinitionId(this.currentCohortDefinition().id());
+ this.reportReportName(reportName);
+ this.reportSourceKey(sourceKey);
+ this.reportTriggerRun(true);
}
+ }
- onRouterParamsChanged(params) {
- let { cohortDefinitionId, conceptSetId, selectedSourceId, mode = 'definition', sourceKey } = params;
- // cohortDefinitionId can be undefined in case of following links fron notifications
- // when another tab of the same cohort definition is selected
- if (!cohortDefinitionId && this.currentCohortDefinition()) {
- cohortDefinitionId = this.currentCohortDefinition().id();
- }
- this.tabMode(mode);
- if (!this.checkifDataLoaded(cohortDefinitionId, conceptSetId, sourceKey)) {
- this.prepareCohortDefinition(cohortDefinitionId, conceptSetId, selectedSourceId, sourceKey);
- } else if (selectedSourceId) {
- let source = this.sharedState.sources().find(s => s.sourceId === selectedSourceId)
- if (source) {
- let selectedSourceInfo = this.cohortDefinitionSourceInfo().find(s => s.sourceKey === source.sourceKey)
- this.expandSelectedSection(selectedSourceInfo);
- }
- } else {
- this.selectedReportSource(null);
- }
+ onRouterParamsChanged(params) {
+ let { cohortDefinitionId, conceptSetId, selectedSourceId, mode = 'definition', sourceKey, sampleId } = params;
+ this.cohortDefinitionIdOnRoute(cohortDefinitionId)
+ // cohortDefinitionId can be undefined in case of following links fron notifications
+ // when another tab of the same cohort definition is selected
+ if (!cohortDefinitionId && this.currentCohortDefinition()) {
+ cohortDefinitionId = this.currentCohortDefinition().id();
}
-
- expandSelectedSection(item) {
- this.selectedReportSource(item);
+ this.tabMode(mode);
+ if(sourceKey) {
+ this.sampleSourceKey(sourceKey)
}
-
- getSourceInfo(source) {
- const info = this.currentCohortDefinitionInfo();
- for (var i = 0; i < info.length; i++) {
- if (info[i].id.sourceId == source.sourceId) {
- return info[i];
- }
- }
+ if(sampleId) {
+ this.selectedSampleId(sampleId)
+ this.fetchSampleData({sampleId, sourceKey, cohortDefinitionId})
}
-
- getCDSI(source, sourceInfo) {
- let cdsi = {};
- cdsi.name = source.sourceName;
- cdsi.sourceKey = source.sourceKey;
- if (sourceInfo != null) {
- cdsi.isValid = ko.observable(sourceInfo.isValid);
- cdsi.isCanceled = ko.observable(sourceInfo.isCanceled);
- cdsi.sourceId = sourceInfo.id.sourceId;
- cdsi.status = ko.observable(sourceInfo.status);
- const date = new Date(sourceInfo.startTime);
- cdsi.startTime = ko.observable(momentApi.formatDateTime(date));
- cdsi.executionDuration = ko.observable(momentApi.formatDuration(sourceInfo.executionDuration));
- const commaFormatted = d3.format(",");
- if (sourceInfo.personCount == null) {
- cdsi.personCount = ko.observable('...');
- } else {
- cdsi.personCount = ko.observable(commaFormatted(sourceInfo.personCount));
- }
- if (sourceInfo.recordCount) {
- cdsi.recordCount = ko.observable(commaFormatted(sourceInfo.recordCount));
- } else {
- cdsi.recordCount = ko.observable('...');
- }
- cdsi.failMessage = ko.observable(sourceInfo.failMessage);
- cdsi.createdBy = ko.observable(sourceInfo.createdBy);
- } else {
- cdsi.isValid = ko.observable(false);
- cdsi.isCanceled = ko.observable(false);
- cdsi.status = ko.observable('n/a');
- cdsi.startTime = ko.observable('n/a');
- cdsi.executionDuration = ko.observable('n/a');
- cdsi.personCount = ko.observable('n/a');
- cdsi.recordCount = ko.observable('n/a');
- cdsi.failMessage = ko.observable(null);
- cdsi.createdBy = ko.observable(null);
+ if (!this.checkifDataLoaded(cohortDefinitionId, conceptSetId, sourceKey)) {
+ this.prepareCohortDefinition(cohortDefinitionId, conceptSetId, selectedSourceId, sourceKey);
+ } else if (selectedSourceId) {
+ let source = this.sharedState.sources().find(s => s.sourceId === selectedSourceId)
+ if (source) {
+ let selectedSourceInfo = this.cohortDefinitionSourceInfo().find(s => s.sourceKey === source.sourceKey)
+ this.expandSelectedSection(selectedSourceInfo);
}
- return cdsi;
+ } else {
+ this.selectedReportSource(null);
}
+ }
- async loadRequiredData(conceptSetId, selectedSourceId, sourceKey) {
- if (this.currentCohortDefinition()) {
- try {
- // now that we have required information lets compile them into data objects for our view
- const cdmSources = sharedState.sources().filter(commonUtils.hasCDM);
- let results = [];
- let selectedSourceInfo = null;
- for (let s = 0; s < cdmSources.length; s++) {
- const source = cdmSources[s];
- this.sourceAnalysesStatus[source.sourceKey] = ko.observable({
- ready: false,
- checking: false
- });
- const sourceInfo = this.getSourceInfo(source);
- let cdsi = this.getCDSI(source, sourceInfo);
- results.push(cdsi);
-
- if (selectedSourceId && source.sourceId === selectedSourceId) {
- selectedSourceInfo = cdsi;
- }
- }
- this.cohortDefinitionSourceInfo(results);
-
- if (selectedSourceInfo) {
- this.expandSelectedSection(selectedSourceInfo);
- }
+ expandSelectedSection(item) {
+ this.selectedReportSource(item);
+ }
- if (conceptSetId != null) {
- await this.loadConceptSet(conceptSetId);
- return;
- } else {
- this.reportSourceKey(sourceKey);
- }
- } catch(er) {
- console.error(er);
- }
+ getSourceInfo(source) {
+ const info = this.currentCohortDefinitionInfo();
+ for (var i = 0; i < info.length; i++) {
+ if (info[i].id.sourceId == source.sourceId) {
+ return info[i];
}
}
+ }
-
- async prepareCohortDefinition(cohortDefinitionId, conceptSetId, selectedSourceId, sourceKey) {
- this.isLoading(true);
- if(parseInt(cohortDefinitionId) === 0) {
- this.setNewCohortDefinition();
+ getCDSI(source, sourceInfo) {
+ let cdsi = {};
+ cdsi.name = source.sourceName;
+ cdsi.sourceKey = source.sourceKey;
+ if (sourceInfo != null) {
+ cdsi.isValid = ko.observable(sourceInfo.isValid);
+ cdsi.isCanceled = ko.observable(sourceInfo.isCanceled);
+ cdsi.sourceId = sourceInfo.id.sourceId;
+ cdsi.status = ko.observable(sourceInfo.status);
+ const date = new Date(sourceInfo.startTime);
+ cdsi.startTime = ko.observable(momentApi.formatDateTime(date));
+ cdsi.executionDuration = ko.observable(momentApi.formatDuration(sourceInfo.executionDuration));
+ const commaFormatted = d3.format(",");
+ if (sourceInfo.personCount == null) {
+ cdsi.personCount = ko.observable('...');
+ } else {
+ cdsi.personCount = ko.observable(commaFormatted(sourceInfo.personCount));
+ }
+ if (sourceInfo.recordCount) {
+ cdsi.recordCount = ko.observable(commaFormatted(sourceInfo.recordCount));
} else {
- await this.loadExistingCohortDefinition(cohortDefinitionId);
+ cdsi.recordCount = ko.observable('...');
}
- await this.loadRequiredData(conceptSetId, selectedSourceId, sourceKey);
- this.isLoading(false);
+ cdsi.failMessage = ko.observable(sourceInfo.failMessage);
+ cdsi.createdBy = ko.observable(sourceInfo.createdBy);
+ } else {
+ cdsi.isValid = ko.observable(false);
+ cdsi.isCanceled = ko.observable(false);
+ cdsi.status = ko.observable('n/a');
+ cdsi.startTime = ko.observable('n/a');
+ cdsi.executionDuration = ko.observable('n/a');
+ cdsi.personCount = ko.observable('n/a');
+ cdsi.recordCount = ko.observable('n/a');
+ cdsi.failMessage = ko.observable(null);
+ cdsi.createdBy = ko.observable(null);
}
+ return cdsi;
+ }
- setNewCohortDefinition() {
- this.currentCohortDefinition(new CohortDefinition({ id: 0, name: 'New Cohort Definition' }));
- this.currentCohortDefinitionInfo([]);
+ async loadRequiredData(conceptSetId, selectedSourceId, sourceKey) {
+ if (this.currentCohortDefinition()) {
+ try {
+ // now that we have required information lets compile them into data objects for our view
+ const cdmSources = sharedState.sources().filter(commonUtils.hasCDM);
+ let results = [];
+ let selectedSourceInfo = null;
+ for (let s = 0; s < cdmSources.length; s++) {
+ const source = cdmSources[s];
+ this.sourceAnalysesStatus[source.sourceKey] = ko.observable({
+ ready: false,
+ checking: false
+ });
+ const sourceInfo = this.getSourceInfo(source);
+ let cdsi = this.getCDSI(source, sourceInfo);
+ results.push(cdsi);
- }
+ if (selectedSourceId && source.sourceId === selectedSourceId) {
+ selectedSourceInfo = cdsi;
+ }
+ }
+ this.cohortDefinitionSourceInfo(results);
- async loadExistingCohortDefinition(id) {
- try {
- const cohortDefinition = await cohortDefinitionService.getCohortDefinition(id);
- const generationInfo = await cohortDefinitionService.getInfo(id);
- this.currentCohortDefinition(new CohortDefinition(cohortDefinition));
- this.currentCohortDefinitionInfo(generationInfo);
- } catch (err) {
- console.error(err);
- }
- }
+ if (selectedSourceInfo) {
+ this.expandSelectedSection(selectedSourceInfo);
+ }
- checkifDataLoaded(cohortDefinitionId, conceptSetId, sourceKey) {
- if (this.currentCohortDefinition() && this.currentCohortDefinition().id() == cohortDefinitionId) {
- if (this.currentConceptSet() && this.currentConceptSet().id == conceptSetId) {
- this.reportSourceKey(sourceKey);
- return true;
- } else if (conceptSetId != null) {
- this.loadConceptSet(conceptSetId);
- return true;
+ if (conceptSetId != null) {
+ await this.loadConceptSet(conceptSetId);
+ return;
} else {
this.reportSourceKey(sourceKey);
- return true;
}
+ } catch(er) {
+ console.error(er);
}
- return false;
}
+ }
- loadConceptSet(conceptSetId) {
- this.conceptSetStore.current(this.conceptSets()().find(item => item.id == conceptSetId));
- this.conceptSetStore.isEditable(this.canEdit());
- commonUtils.routeTo(`/cohortdefinition/${this.currentCohortDefinition().id()}/conceptsets/`);
- }
-
- reload () {
- if (this.modifiedJSON.length > 0) {
- var updatedExpression = JSON.parse(this.modifiedJSON);
- this.currentCohortDefinition().expression(new CohortExpression(updatedExpression));
- }
+
+ async prepareCohortDefinition(cohortDefinitionId, conceptSetId, selectedSourceId, sourceKey) {
+ this.isLoading(true);
+ if(parseInt(cohortDefinitionId) === 0) {
+ this.setNewCohortDefinition();
+ } else {
+ await this.loadExistingCohortDefinition(cohortDefinitionId);
}
+ await this.loadRequiredData(conceptSetId, selectedSourceId, sourceKey);
+ this.isLoading(false);
+ }
- exportConceptSetsCSV () {
- return FileService.loadZip(`${config.api.url}cohortdefinition/${this.currentCohortDefinition().id()}/export/conceptset`,
- `cohortdefinition-conceptsets-${this.currentCohortDefinition().id()}.zip`);
+ setNewCohortDefinition() {
+ this.currentCohortDefinition(new CohortDefinition({ id: 0, name: 'New Cohort Definition' }));
+ this.currentCohortDefinitionInfo([]);
+
+ }
+
+ async loadExistingCohortDefinition(id) {
+ try {
+ const cohortDefinition = await cohortDefinitionService.getCohortDefinition(id);
+ const generationInfo = await cohortDefinitionService.getInfo(id);
+ this.currentCohortDefinition(new CohortDefinition(cohortDefinition));
+ this.currentCohortDefinitionInfo(generationInfo);
+ } catch (err) {
+ console.error(err);
}
+ }
- toggleCohortReport(item) {
- if (this.selectedReportSource() && this.selectedReportSource().sourceKey === item.sourceKey) {
- this.selectedReportSource(null);
- commonUtils.routeTo('/cohortdefinition/' + this.currentCohortDefinition().id() + '/generation');
+ checkifDataLoaded(cohortDefinitionId, conceptSetId, sourceKey) {
+ if (this.currentCohortDefinition() && this.currentCohortDefinition().id() == cohortDefinitionId) {
+ if (this.currentConceptSet() && this.currentConceptSet().id == conceptSetId) {
+ this.reportSourceKey(sourceKey);
+ return true;
+ } else if (conceptSetId != null) {
+ this.loadConceptSet(conceptSetId);
+ return true;
} else {
- this.selectedReportSource(item);
- commonUtils.routeTo('/cohortdefinition/' + this.currentCohortDefinition().id() + '/generation/' + item.sourceId);
+ this.reportSourceKey(sourceKey);
+ return true;
}
}
+ return false;
+ }
- selectTab(key) {
- this.tabMode(key);
- return commonUtils.routeTo('/cohortdefinition/' + this.currentCohortDefinition().id() + '/' + key);
+ loadConceptSet(conceptSetId) {
+ this.conceptSetStore.current(this.conceptSets()().find(item => item.id == conceptSetId));
+ this.conceptSetStore.isEditable(this.canEdit());
+ commonUtils.routeTo(`/cohortdefinition/${this.currentCohortDefinition().id()}/conceptsets/`);
+ }
+
+ reload () {
+ if (this.modifiedJSON.length > 0) {
+ var updatedExpression = JSON.parse(this.modifiedJSON);
+ this.currentCohortDefinition().expression(new CohortExpression(updatedExpression));
}
+ }
- getStatusMessage (info) {
- if (info.status() === "COMPLETE" && !info.isValid())
- return !info.isCanceled() ? "FAILED" : "CANCELED";
- else
- // replace 'COMPLETE' with 'COMPLETED' to match other complete statuses
- return info.status() === 'COMPLETE' ? 'COMPLETED' : info.status();
- }
+ exportConceptSetsCSV () {
+ return FileService.loadZip(`${config.api.url}cohortdefinition/${this.currentCohortDefinition().id()}/export/conceptset`,
+ `cohortdefinition-conceptsets-${this.currentCohortDefinition().id()}.zip`);
+ }
- getStatusTemplate(item) {
- return item.status === 'FAILED' ? 'failed-status-tmpl' : 'success-status-tmpl';
+ toggleCohortReport(item) {
+ if (this.selectedReportSource() && this.selectedReportSource().sourceKey === item.sourceKey) {
+ this.selectedReportSource(null);
+ commonUtils.routeTo('/cohortdefinition/' + this.currentCohortDefinition().id() + '/generation');
+ } else {
+ this.selectedReportSource(item);
+ commonUtils.routeTo('/cohortdefinition/' + this.currentCohortDefinition().id() + '/generation/' + item.sourceId);
}
+ }
- showExitMessage(sourceKey) {
- const info = this.cohortDefinitionSourceInfo().find(i => i.sourceKey === sourceKey) || { failMessage: 'Failed without any message' };
- this.exitMessage(info.failMessage);
- this.isExitMessageShown(true);
- }
+ selectTab(key) {
+ this.tabMode(key);
+ return commonUtils.routeTo('/cohortdefinition/' + this.currentCohortDefinition().id() + '/' + key);
+ }
- async generateAnalyses ({ descr, duration, analysisIdentifiers, runHeraclesHeel, periods, rollupUtilizationVisit, rollupUtilizationDrug }) {
- if (!confirm(`This will run ${descr} and may take about ${duration}. Are you sure?`)) {
- return;
- }
+ getStatusMessage (info) {
+ if (info.status() === "COMPLETE" && !info.isValid())
+ return !info.isCanceled() ? "FAILED" : "CANCELED";
+ else
+ // replace 'COMPLETE' with 'COMPLETED' to match other complete statuses
+ return info.status() === 'COMPLETE' ? 'COMPLETED' : info.status();
+ }
- this.generateReportsEnabled(false);
- analysisIdentifiers = _.uniq(analysisIdentifiers);
- var cohortDefinitionId = this.currentCohortDefinition().id();
- var cohortJob = {};
-
- cohortJob.jobName = `HERACLES_COHORT_${cohortDefinitionId}_${this.reportSourceKey()}`;
- cohortJob.sourceKey = this.reportSourceKey();
- cohortJob.smallCellCount = 5;
- cohortJob.cohortDefinitionIds = [];
- cohortJob.cohortDefinitionIds.push(cohortDefinitionId);
- cohortJob.analysisIds = analysisIdentifiers;
- cohortJob.runHeraclesHeel = runHeraclesHeel;
- cohortJob.cohortPeriodOnly = false;
-
- // set concepts
- cohortJob.conditionConceptIds = [];
- cohortJob.drugConceptIds = [];
- cohortJob.procedureConceptIds = [];
- cohortJob.observationConceptIds = [];
- cohortJob.measurementConceptIds = [];
-
- cohortJob.periods = periods;
-
- cohortJob.rollupUtilizationVisit = rollupUtilizationVisit;
- cohortJob.rollupUtilizationDrug = rollupUtilizationDrug;
-
- this.createReportJobFailed(false);
- try {
- this.isReportGenerating(true);
- const { data } = await cohortDefinitionService.getCohortAnalyses(cohortJob);
- jobDetailsService.createJob(data);
- } catch (err) {
- this.createReportJobFailed(true);
- const { status, data } = err;
- const createReportJobErrorPackage = {
- status,
- error: data.payload,
- };
- this.createReportJobError(JSON.stringify(createReportJobErrorPackage));
-
- // reset button to allow generation attempt
- this.generateReportsEnabled(true);
- this.generateButtonCaption('Generate');
- }
- await this.queryHeraclesJob(this.currentCohortDefinition(), this.reportSourceKey());
- this.isReportGenerating(false);
- }
+ getStatusTemplate(item) {
+ return item.status === 'FAILED' ? 'failed-status-tmpl' : 'success-status-tmpl';
+ }
- generateQuickAnalysis () {
- this.generateAnalyses({
- descr: 'minimal analyses set to provide a quick overview of the cohort',
- duration: '10 minutes',
- analysisIdentifiers: cohortReportingService.getQuickAnalysisIdentifiers(),
- runHeraclesHeel: false
- });
+ showExitMessage(sourceKey) {
+ const info = this.cohortDefinitionSourceInfo().find(i => i.sourceKey === sourceKey) || { failMessage: 'Failed without any message' };
+ this.exitMessage(info.failMessage);
+ this.isExitMessageShown(true);
+ }
+
+ async generateAnalyses ({ descr, duration, analysisIdentifiers, runHeraclesHeel, periods, rollupUtilizationVisit, rollupUtilizationDrug }) {
+ if (!confirm(`This will run ${descr} and may take about ${duration}. Are you sure?`)) {
+ return;
}
- selectHealthcareAnalyses () {
- this.showUtilizationToRunModal(true);
+ this.generateReportsEnabled(false);
+ analysisIdentifiers = _.uniq(analysisIdentifiers);
+ var cohortDefinitionId = this.currentCohortDefinition().id();
+ var cohortJob = {};
+
+ cohortJob.jobName = `HERACLES_COHORT_${cohortDefinitionId}_${this.reportSourceKey()}`;
+ cohortJob.sourceKey = this.reportSourceKey();
+ cohortJob.smallCellCount = 5;
+ cohortJob.cohortDefinitionIds = [];
+ cohortJob.cohortDefinitionIds.push(cohortDefinitionId);
+ cohortJob.analysisIds = analysisIdentifiers;
+ cohortJob.runHeraclesHeel = runHeraclesHeel;
+ cohortJob.cohortPeriodOnly = false;
+
+ // set concepts
+ cohortJob.conditionConceptIds = [];
+ cohortJob.drugConceptIds = [];
+ cohortJob.procedureConceptIds = [];
+ cohortJob.observationConceptIds = [];
+ cohortJob.measurementConceptIds = [];
+
+ cohortJob.periods = periods;
+
+ cohortJob.rollupUtilizationVisit = rollupUtilizationVisit;
+ cohortJob.rollupUtilizationDrug = rollupUtilizationDrug;
+
+ this.createReportJobFailed(false);
+ try {
+ this.isReportGenerating(true);
+ const { data } = await cohortDefinitionService.getCohortAnalyses(cohortJob);
+ jobDetailsService.createJob(data);
+ } catch (err) {
+ this.createReportJobFailed(true);
+ const { status, data } = err;
+ const createReportJobErrorPackage = {
+ status,
+ error: data.payload,
+ };
+ this.createReportJobError(JSON.stringify(createReportJobErrorPackage));
+
+ // reset button to allow generation attempt
+ this.generateReportsEnabled(true);
+ this.generateButtonCaption('Generate');
}
+ await this.queryHeraclesJob(this.currentCohortDefinition(), this.reportSourceKey());
+ this.isReportGenerating(false);
+ }
- generateHealthcareAnalyses () {
- const analysisIds = this.utilReportOptions.reports.selectedOptions().reduce((acc, ids) => [...acc, ...ids], []);
- this.generateAnalyses({
- descr: 'the Cost and Utilization analyses',
- duration: '10-45 minutes',
- analysisIdentifiers: analysisIds,
- runHeraclesHeel: false,
- periods: this.utilReportOptions.periods.selectedOptions(),
- ...this.utilReportOptions.rollups.selectedOptions().reduce((acc, current) => { acc[current] = true; return acc }, {}),
- });
+ generateQuickAnalysis () {
+ this.generateAnalyses({
+ descr: 'minimal analyses set to provide a quick overview of the cohort',
+ duration: '10 minutes',
+ analysisIdentifiers: cohortReportingService.getQuickAnalysisIdentifiers(),
+ runHeraclesHeel: false
+ });
+ }
- this.showUtilizationToRunModal(false);
- };
+ selectHealthcareAnalyses () {
+ this.showUtilizationToRunModal(true);
+ }
- generateAllAnalyses () {
- this.generateAnalyses({
- descr: 'all analyses',
- duration: '60-90 minutes',
- analysisIdentifiers: cohortReportingService.getAnalysisIdentifiers(),
- runHeraclesHeel: true
- });
- };
+ generateHealthcareAnalyses () {
+ const analysisIds = this.utilReportOptions.reports.selectedOptions().reduce((acc, ids) => [...acc, ...ids], []);
+ this.generateAnalyses({
+ descr: 'the Cost and Utilization analyses',
+ duration: '10-45 minutes',
+ analysisIdentifiers: analysisIds,
+ runHeraclesHeel: false,
+ periods: this.utilReportOptions.periods.selectedOptions(),
+ ...this.utilReportOptions.rollups.selectedOptions().reduce((acc, current) => { acc[current] = true; return acc }, {}),
+ });
- // dispose subscriptions / cleanup computed observables (non-pureComputeds)
- dispose () {
- super.dispose();
- this.cohortDefinitionLink.dispose();
- this.cohortDefinitionCaption.dispose();
- this.tabPath.dispose();
- this.sortedConceptSets.dispose();
- this.reportingState.dispose();
- this.showReportNameDropdown.dispose();
- this.reportSourceKeySub.dispose();
- PollService.stop(this.pollId);
+ this.showUtilizationToRunModal(false);
+ };
+
+ generateAllAnalyses () {
+ this.generateAnalyses({
+ descr: 'all analyses',
+ duration: '60-90 minutes',
+ analysisIdentifiers: cohortReportingService.getAnalysisIdentifiers(),
+ runHeraclesHeel: true
+ });
+ };
+
+ // track subscriptions
+ trackSub(sub) {
+ this.subscriptions.push(sub);
+ }
+
+ // dispose subscriptions / cleanup computed observables (non-pureComputeds)
+ dispose () {
+ super.dispose();
+ PollService.stop(this.pollId);
+ }
+
+ getCriteriaIndexComponent (data) {
+ data = ko.utils.unwrapObservable(data);
+ if (!data) return;
+ if (data.hasOwnProperty("ConditionOccurrence"))
+ return "condition-occurrence-criteria-viewer";
+ else if (data.hasOwnProperty("ConditionEra"))
+ return "condition-era-criteria-viewer";
+ else if (data.hasOwnProperty("DrugExposure"))
+ return "drug-exposure-criteria-viewer";
+ else if (data.hasOwnProperty("DrugEra"))
+ return "drug-era-criteria-viewer";
+ else if (data.hasOwnProperty("DoseEra"))
+ return "dose-era-criteria-viewer";
+ else if (data.hasOwnProperty("ProcedureOccurrence"))
+ return "procedure-occurrence-criteria-viewer";
+ else if (data.hasOwnProperty("Observation"))
+ return "observation-criteria-viewer";
+ else if (data.hasOwnProperty("VisitOccurrence"))
+ return "visit-occurrence-criteria-viewer";
+ else if (data.hasOwnProperty("DeviceExposure"))
+ return "device-exposure-criteria-viewer";
+ else if (data.hasOwnProperty("Measurement"))
+ return "measurement-criteria-viewer";
+ else if (data.hasOwnProperty("Specimen"))
+ return "specimen-criteria-viewer";
+ else if (data.hasOwnProperty("ObservationPeriod"))
+ return "observation-period-criteria-viewer";
+ else if (data.hasOwnProperty("PayerPlanPeriod"))
+ return "payer-plan-period-criteria-viewer";
+ else if (data.hasOwnProperty("Death"))
+ return "death-criteria-viewer";
+ else if (data.hasOwnProperty("LocationRegion"))
+ return "location-region-viewer";
+ else
+ return "unknownCriteriaType";
+ };
+
+ copyExpressionToClipboard () {
+ this.copyToClipboard('#btnCopyExpressionClipboard', '#copyExpressionToClipboardMessage');
+ }
+
+ copyIdentifierListToClipboard () {
+ this.copyToClipboard('#btnCopyIdentifierListClipboard', '#copyIdentifierListMessage');
+ }
+
+ copyIncludedConceptIdentifierListToClipboard () {
+ this.copyToClipboard('#btnCopyIncludedConceptIdentifierListClipboard', '#copyIncludedConceptIdentifierListMessage');
+ }
+
+ copyTextViewToClipboard() {
+ let columns = [
+ {
+ title: 'Concept Id',
+ data: 'CONCEPT_ID'
+ },
+ {
+ title: 'Concept Name',
+ data: 'CONCEPT_NAME'
+ },
+ {
+ title: 'Domain',
+ data: 'DOMAIN_ID'
+ },
+ {
+ title: 'Vocabulary',
+ data: 'VOCABULARY_ID'
}
+ ];
+ let setsText = '';
+ this.sortedConceptSets().forEach((set) => {
+ setsText += '\n' + set.name() + '\n';
+ columns.forEach((c) => {
+ setsText += c.title + '\t';
+ });
+ setsText += 'Excluded\tDescendants\tMapped' + '\n';
+ set.expression.items().forEach((item) => {
+ columns.forEach((c) => {
+ setsText += item.concept[c.data] + '\t';
+ });
+ setsText += (item.isExcluded() ? 'YES' : 'NO') + '\t';
+ setsText += (item.includeDescendants() ? 'YES' : 'NO') + '\t';
+ setsText += (item.includeMapped() ? 'YES' : 'NO') + '\n';
+ });
+ });
+ this.copyToClipboard('#btnCopyTextViewClipboard', '#copyTextViewMessage', setsText);
+ }
- getCriteriaIndexComponent (data) {
- data = ko.utils.unwrapObservable(data);
- if (!data) return;
- if (data.hasOwnProperty("ConditionOccurrence"))
- return "condition-occurrence-criteria-viewer";
- else if (data.hasOwnProperty("ConditionEra"))
- return "condition-era-criteria-viewer";
- else if (data.hasOwnProperty("DrugExposure"))
- return "drug-exposure-criteria-viewer";
- else if (data.hasOwnProperty("DrugEra"))
- return "drug-era-criteria-viewer";
- else if (data.hasOwnProperty("DoseEra"))
- return "dose-era-criteria-viewer";
- else if (data.hasOwnProperty("ProcedureOccurrence"))
- return "procedure-occurrence-criteria-viewer";
- else if (data.hasOwnProperty("Observation"))
- return "observation-criteria-viewer";
- else if (data.hasOwnProperty("VisitOccurrence"))
- return "visit-occurrence-criteria-viewer";
- else if (data.hasOwnProperty("DeviceExposure"))
- return "device-exposure-criteria-viewer";
- else if (data.hasOwnProperty("Measurement"))
- return "measurement-criteria-viewer";
- else if (data.hasOwnProperty("Specimen"))
- return "specimen-criteria-viewer";
- else if (data.hasOwnProperty("ObservationPeriod"))
- return "observation-period-criteria-viewer";
- else if (data.hasOwnProperty("PayerPlanPeriod"))
- return "payer-plan-period-criteria-viewer";
- else if (data.hasOwnProperty("Death"))
- return "death-criteria-viewer";
- else if (data.hasOwnProperty("LocationRegion"))
- return "location-region-viewer";
- else
- return "unknownCriteriaType";
- };
+ copyCohortExpressionJSONToClipboard () {
+ this.copyToClipboard('#btnCopyExpressionJSONClipboard', '#copyCohortExpressionJSONMessage');
+ }
- copyExpressionToClipboard () {
- this.copyToClipboard('#btnCopyExpressionClipboard', '#copyExpressionToClipboardMessage');
+ getExpressionJson() {
+ if (!this.currentCohortDefinition()) {
+ return ko.toJSON(null);
}
+ return ko.toJSON(this.currentCohortDefinition().expression(), (key, value) => {
+ // UseEventEnd is a speical case: always include this key in the result.
+ if (value === 0 || value || ['UseEventEnd'].indexOf(key) > -1) {
+ return value;
+ } else {
+ return;
+ }
+ }, 2);
+ }
- copyIdentifierListToClipboard () {
- this.copyToClipboard('#btnCopyIdentifierListClipboard', '#copyIdentifierListMessage');
+ setExpressionJson(value) {
+ this.modifiedJSON = value;
+ }
+
+ getAuthorship() {
+ const cohortDef = this.currentCohortDefinition();
+ const createdDate = commonUtils.formatDateForAuthorship(cohortDef.createdDate);
+ const modifiedDate = commonUtils.formatDateForAuthorship(cohortDef.modifiedDate);
+ return {
+ createdBy: cohortDef.createdBy() ? cohortDef.createdBy().name : '',
+ createdDate: createdDate,
+ modifiedBy: cohortDef.modifiedBy() ? cohortDef.modifiedBy().name : '',
+ modifiedDate: modifiedDate,
}
+ }
- copyIncludedConceptIdentifierListToClipboard () {
- this.copyToClipboard('#btnCopyIncludedConceptIdentifierListClipboard', '#copyIncludedConceptIdentifierListMessage');
+ async refreshPrintFriendly() {
+ this.printFriendlyLoading(true);
+ try {
+ const printFriendlyHtml = await cohortDefinitionService.getCohortPrintFriendly(ko.toJS(this.currentCohortDefinition().expression()));
+ this.printFriendlyHtml(printFriendlyHtml.data);
+ } catch(error) {
+ console.error("Problem loading print-friendly output.", error);
+ }finally {
+ this.printFriendlyLoading(false);
}
+ }
- copyTextViewToClipboard() {
- let columns = [
- {
- title: 'Concept Id',
- data: 'CONCEPT_ID'
- },
- {
- title: 'Concept Name',
- data: 'CONCEPT_NAME'
- },
- {
- title: 'Domain',
- data: 'DOMAIN_ID'
- },
- {
- title: 'Vocabulary',
- data: 'VOCABULARY_ID'
- }
- ];
- let setsText = '';
- this.sortedConceptSets().forEach((set) => {
- setsText += '\n' + set.name() + '\n';
- columns.forEach((c) => {
- setsText += c.title + '\t';
- });
- setsText += 'Excluded\tDescendants\tMapped' + '\n';
- set.expression.items().forEach((item) => {
- columns.forEach((c) => {
- setsText += item.concept[c.data] + '\t';
- });
- setsText += (item.isExcluded() ? 'YES' : 'NO') + '\t';
- setsText += (item.includeDescendants() ? 'YES' : 'NO') + '\t';
- setsText += (item.includeMapped() ? 'YES' : 'NO') + '\n';
- });
- });
- this.copyToClipboard('#btnCopyTextViewClipboard', '#copyTextViewMessage', setsText);
+ // samples methods
+ clickSampleTab() {
+ this.tabMode('samples');
+ const cohortId = this.currentCohortDefinition().id();
+ history.pushState(null, '', `#/cohortdefinition/${cohortId}/samples`);
+ }
+ addNewSample() {
+ this.resetSampleForm();
+ this.showSampleCreatingModal(true);
+ }
+
+ isSampleFormValid() {
+ // if a mandotory field is not yet filled at all, it should be error
+ return !(this.sampleNameError() || this.patientCountError() || this.firstAgeError() || this.isAgeRangeError());
+ }
+
+ resetSampleForm() {
+ this.sampleName('')
+ this.patientCount('')
+ this.sampleAgeType('lessThan')
+ this.firstAge(null);
+ this.secondAge(null);
+ this.isMaleSample(false);
+ this.isFeMaleSample(false);
+ this.isOtherGenderSample(false);
+ }
+
+ async createNewSample() {
+
+ if (!this.isSampleFormValid()) { // do nothing
+ return;
}
- copyCohortExpressionJSONToClipboard () {
- this.copyToClipboard('#btnCopyExpressionJSONClipboard', '#copyCohortExpressionJSONMessage');
+ const cohortDefinitionId =this.currentCohortDefinition().id();
+ const sourceKey=this.sampleSourceKey()
+ const name = this.sampleName();
+ const size = Number(this.patientCount());
+ const ageMode = this.sampleAgeType();
+ let conceptIds = [];
+ let otherNonBinary = false;
+ const selectAllGender = !this.isMaleSample()&&!this.isFeMaleSample()&&!this.isOtherGenderSample()
+ if(this.isMaleSample()||selectAllGender) {
+ conceptIds.push(8507);
+ }
+ if(this.isFeMaleSample()||selectAllGender) {
+ conceptIds.push(8532);
+ }
+ if(this.isOtherGenderSample()||selectAllGender) {
+ otherNonBinary = true;
}
- getExpressionJson() {
- if (!this.currentCohortDefinition()) {
- return ko.toJSON(null);
+ const firstAge = this.firstAge();
+ const secondAge = this.secondAge();
+ let age;
+ if((this.isAgeRange() && (firstAge==null && secondAge==null)) || (!this.isAgeRange() && firstAge == null)) {
+ age = null;
+ } else {
+ age = {
+ value: this.isAgeRange()?null:firstAge,
+ mode: ageMode,
+ min:this.isAgeRange()? firstAge {
- // UseEventEnd is a speical case: always include this key in the result.
- if (value === 0 || value || ['UseEventEnd'].indexOf(key) > -1) {
- return value;
- } else {
- return;
- }
- }, 2);
}
- setExpressionJson(value) {
- this.modifiedJSON = value;
+ const payload = {
+ name,
+ size,
+ age,
+ gender: {otherNonBinary, conceptIds}
+ };
+ this.newSampleCreatingLoader(true);
+ try {
+ const res = await sampleService.createSample(payload, {cohortDefinitionId, sourceKey});
+ const newData= mapSampleListData([res]);
+ this.sampleList.unshift(...newData);
+ this.showSampleCreatingModal(false);
+ } catch(error) {
+ console.error(error);
+ alert('Error when creating sample, please try again later');
+ } finally {
+ this.newSampleCreatingLoader(false);
}
+ }
- getAuthorship() {
- const cohortDef = this.currentCohortDefinition();
- const createdDate = commonUtils.formatDateForAuthorship(cohortDef.createdDate);
- const modifiedDate = commonUtils.formatDateForAuthorship(cohortDef.modifiedDate);
- return {
- createdBy: cohortDef.createdBy() ? cohortDef.createdBy().name : '',
- createdDate: createdDate,
- modifiedBy: cohortDef.modifiedBy() ? cohortDef.modifiedBy().name : '',
- modifiedDate: modifiedDate,
+ getSampleList(cohortId) {
+ this.isLoadingSampleData(true);
+ const cohortDefinitionId= cohortId || this.currentCohortDefinition().id();
+ // if (cohortDefinitionId==0) return
+ const sourceKey=this.sampleSourceKey();
+ sampleService.getSampleList({cohortDefinitionId, sourceKey})
+ .then(res => {
+ if(res.generationStatus!="COMPLETE") {
+ this.sampleSourceKey(null);
+ alert('Cohort should be generated before creating samples');
+ return;
}
- }
+ const sampleListData = mapSampleListData(res.samples);
+ this.sampleList(sampleListData);
+ })
+ .catch(error=>{
+ console.error(error);
+ alert('Error when fetching sample list, please try again later');
+ })
+ .finally(() => {
+ this.isLoadingSampleData(false)
+ })
+ }
- async refreshPrintFriendly() {
- this.printFriendlyLoading(true);
- try {
- const printFriendlyHtml = await cohortDefinitionService.getCohortPrintFriendly(ko.toJS(this.currentCohortDefinition().expression()));
- this.printFriendlyHtml(printFriendlyHtml.data);
- } catch(error) {
- console.error("Problem loading print-friendly output.", error);
- }finally {
- this.printFriendlyLoading(false);
+ onSampleListRowClick(d, e) {
+ // find index of click
+ const {sampleId} = d;
+ const rowIndex = this.sampleList().findIndex(el=>el.sampleId == sampleId);
+
+ const cohortDefinitionId= this.currentCohortDefinition().id();
+ const sourceKey=this.sampleSourceKey();
+ if(e.target.className=='sample-list fa fa-trash') {
+ // todo: close existing sample
+ if (this.selectedSampleId() == sampleId) {
+ this.sampleData([]);
+ this.selectedSampleId(null);
+ commonUtils.routeTo(`/cohortdefinition/${cohortDefinitionId}/samples/${sourceKey}/`);
}
+ sampleService.deleteSample({cohortDefinitionId, sourceKey, sampleId})
+ .then(res=>{
+ if(res.ok) {
+ this.sampleList.splice(rowIndex, 1);
+ }
+ })
+ .catch(() => {
+ alert('Error when deleting sample, please try again later');
+ })
+ } else if (e.target.className == 'sample-list fa fa-refresh') {
+ this.sampleDataLoading(true);
+ this.refreshSample({sampleId, sourceKey, cohortDefinitionId})
+ .then(res => {
+ this.showSampleDataTable(res.elements);
+ })
+ .finally(() => {
+ this.sampleDataLoading(false);
+ });
+ } else {
+ this.fetchSampleData({sampleId, sourceKey, cohortDefinitionId});
}
+ }
+
+ fetchSampleData({sampleId, sourceKey, cohortDefinitionId}) {
+ this.sampleDataLoading(true)
+ sampleService.getSample({ cohortDefinitionId, sourceKey, sampleId })
+ .then(res=>{
+ this.selectedSampleId(sampleId);
+ this.selectedSampleName(res.name);
+ this.showSampleDataTable(res.elements);
+ history.pushState(null, '', `#/cohortdefinition/${cohortDefinitionId}/samples/${sourceKey}/${sampleId}`);
+ })
+ .catch(error => {
+ console.error(error);
+ alert('Error when fetching sample data, please try again later');
+ })
+ .finally(() => {
+ this.sampleDataLoading(false);
+ })
+ }
+
+ refreshSample({sampleId, sourceKey, cohortDefinitionId}) {
+ return sampleService.refreshSample({cohortDefinitionId, sourceKey, sampleId})
+ .catch(() => {
+ alert('Error when refreshing sample, please try again later');
+ })
+ }
+
+ onSampleDataClick(d) {
+ const sampleId = this.selectedSampleId();
+ const cohortDefinitionId= this.currentCohortDefinition().id();
+ const sourceKey=this.sampleSourceKey();
+ window.open(`#/profiles/${sourceKey}/${d.personId}/${cohortDefinitionId}/${sampleId}`);
+ }
+
+ showSampleDataTable(sample) {
+ const transformedSampleData = sample.map(el => ({
+ personId: el.personId,
+ gender: gender(el.genderConceptId),
+ ageIndex: el.age
+ }));
+
+ this.sampleData(transformedSampleData);
+ }
}
return commonUtils.build('cohort-definition-manager', CohortDefinitionManager, view);
diff --git a/js/pages/cohort-definitions/routes.js b/js/pages/cohort-definitions/routes.js
index 28bf6fbf2..c46cb4755 100644
--- a/js/pages/cohort-definitions/routes.js
+++ b/js/pages/cohort-definitions/routes.js
@@ -14,7 +14,77 @@ define(
router.setCurrentView('cohort-definitions');
});
}),
- '/cohortdefinition/:cohortDefinitionId/conceptsets/:conceptSetId/:mode': new AuthorizedRoute((cohortDefinitionId, conceptSetId, mode) => {
+
+ '/cohortdefinition/:cohortDefinitionId/samples': new AuthorizedRoute(
+ cohortDefinitionId => {
+ require([
+ 'components/conceptset/ConceptSetStore',
+ 'components/cohortbuilder/CohortDefinition',
+ 'components/atlas.cohort-editor',
+ './cohort-definitions',
+ './cohort-definition-manager',
+ 'components/cohort-definition-browser',
+ 'conceptset-editor',
+ './components/reporting/cost-utilization/report-manager',
+ 'components/explore-cohort',
+ ], function() {
+ // not re-render component if it was rendered already
+ router.setCurrentView('cohort-definition-manager', {
+ cohortDefinitionId,
+ mode: 'samples',
+ })
+ sharedState.CohortDefinition.mode('samples')
+ })
+ }
+ ),
+
+ '/cohortdefinition/:cohortDefinitionId/samples/:sourceKey': new AuthorizedRoute(
+ (cohortDefinitionId, sourceKey) => {
+ require([
+ 'components/cohortbuilder/CohortDefinition',
+ 'components/atlas.cohort-editor',
+ './cohort-definitions',
+ './cohort-definition-manager',
+ 'components/cohort-definition-browser',
+ 'conceptset-editor',
+ './components/reporting/cost-utilization/report-manager',
+ 'components/explore-cohort',
+ ], function() {
+ router.setCurrentView('cohort-definition-manager', {
+ cohortDefinitionId,
+ sourceKey,
+ mode: 'samples',
+ })
+ sharedState.CohortDefinition.mode('samples')
+ })
+ }
+ ),
+
+ '/cohortdefinition/:cohortDefinitionId/samples/:sourceKey/:sampleId': new AuthorizedRoute(
+ (cohortDefinitionId, sourceKey, sampleId) => {
+ require([
+ 'components/cohortbuilder/CohortDefinition',
+ 'components/atlas.cohort-editor',
+ './cohort-definitions',
+ './cohort-definition-manager',
+ 'components/cohort-definition-browser',
+ 'conceptset-editor',
+ './components/reporting/cost-utilization/report-manager',
+ 'components/explore-cohort',
+ ], function() {
+ router.setCurrentView('cohort-definition-manager', {
+ cohortDefinitionId,
+ sampleId,
+ sourceKey,
+ mode: 'samples',
+ })
+ sharedState.CohortDefinition.mode('samples')
+ })
+ }
+ ),
+
+ '/cohortdefinition/:cohortDefinitionId/conceptsets/:conceptSetId/:mode': new AuthorizedRoute(
+ (cohortDefinitionId, conceptSetId, mode) => {
require([
'components/conceptset/ConceptSetStore',
'components/cohortbuilder/CohortDefinition',
@@ -24,10 +94,10 @@ define(
'components/cohort-definition-browser',
'conceptset-editor',
'./components/reporting/cost-utilization/report-manager',
- 'explore-cohort',
- ], function (ConceptSetStore) {
- sharedState.CohortDefinition.mode('conceptsets');
- sharedState.activeConceptSet(ConceptSetStore.cohortDefinition());
+ 'components/explore-cohort',
+ ], function(ConceptSetStore) {
+ sharedState.CohortDefinition.mode('conceptsets')
+ sharedState.activeConceptSet(ConceptSetStore.cohortDefinition())
router.setCurrentView('cohort-definition-manager', {
cohortDefinitionId,
mode: 'conceptsets',
@@ -44,9 +114,9 @@ define(
'components/cohort-definition-browser',
'conceptset-editor',
'./components/reporting/cost-utilization/report-manager',
- 'explore-cohort',
+ 'components/explore-cohort',
'components/conceptset/concept-modal',
- ], function () {
+ ], function() {
// Determine the view to show on the cohort manager screen based on the path
path = path.split("/");
let view = 'definition';
diff --git a/js/services/Sample.js b/js/services/Sample.js
new file mode 100644
index 000000000..f6bc2ad6e
--- /dev/null
+++ b/js/services/Sample.js
@@ -0,0 +1,50 @@
+define(['services/http', 'appConfig'], function(httpService, config) {
+ function createSample(payload, { cohortDefinitionId, sourceKey }) {
+ return httpService
+ .doPost(
+ `${config.webAPIRoot}cohortsample/${cohortDefinitionId}/${sourceKey}`,
+ {
+ ...payload,
+ }
+ ).then(res => res.data);
+ }
+
+ function getSampleList({ cohortDefinitionId, sourceKey }) {
+ return httpService
+ .doGet(
+ `${config.webAPIRoot}cohortsample/${cohortDefinitionId}/${sourceKey}`
+ )
+ .then(res => res.data)
+ }
+
+ function getSample({ cohortDefinitionId, sourceKey, sampleId }) {
+ return httpService
+ .doGet(
+ `${config.webAPIRoot}cohortsample/${cohortDefinitionId}/${sourceKey}/${sampleId}`
+ )
+ .then(res => res.data)
+ }
+
+ function refreshSample({ cohortDefinitionId, sourceKey, sampleId }) {
+ return httpService
+ .doPost(
+ `${config.webAPIRoot}cohortsample/${cohortDefinitionId}/${sourceKey}/${sampleId}/refresh`,
+ null
+ )
+ .then(res => res.data)
+ }
+
+ function deleteSample({ cohortDefinitionId, sourceKey, sampleId }) {
+ return httpService.doDelete(
+ `${config.webAPIRoot}cohortsample/${cohortDefinitionId}/${sourceKey}/${sampleId}`
+ )
+ }
+
+ return {
+ createSample,
+ getSampleList,
+ getSample,
+ deleteSample,
+ refreshSample
+ }
+})
diff --git a/js/settings.js b/js/settings.js
index fa7b24e84..6f2a71bbc 100644
--- a/js/settings.js
+++ b/js/settings.js
@@ -171,7 +171,6 @@ const settingsObject = {
"conceptset-modal": "components/conceptsetmodal/conceptSetSaveModal",
"user-bar": "components/userbar/user-bar",
"faceted-datatable": "components/faceted-datatable",
- "explore-cohort": "components/explore-cohort",
"r-manager": "components/r-manager",
"home": "components/home",
"welcome": "components/welcome",