Implemented Concept Set editor for Feature Analysis and CC#2132
Conversation
There was a problem hiding this comment.
Great work. just a few comments and questions:
1: The shopping carts
Normally when we see the shopping charts, it means there's a connection from the search results (under vocabulary search) to the concept set that is either opened in the cohort definition editor or the concept set editor. I like that these shopping carts are isolated from that other 'global' functionailty, but I wonder, to eliminate confusion, what if those were instead checkboxes, and when there is at least 1 checkbox selected, you get another button in the UI allowing you to DELETE (if you are on the expression tab where the only logical thing to do is to remove the concept) or ADD (if you are on the Included Concepts tab where you want to add these concepts to the expression). I do not want to go too into the weeds, if this idea makes sense and is easily implemented, let's go for it, but if it's too complicated, I think the use of shopping carts to add/remove from the expression (that you have implemented here) is fine. However, one quirk of this behavior is if you do click a shopping cart on the expression (by accident, for example) the concept is gone, and you have to import the concept ID again if you lost it.
The Concept Sets tab
The position of the concept sets tab is always visible, regardless of the type of feature you're defining (criteria vs. Custom sql). IMO, i think it would make sense to put the tabs within the designer so that the criteria Expressions are in one tab, and the concept sets to edit are in another one. If you switch over to a 'custom sql' mode, then the tabs go away and you only have the textbox for editing the SQL. Let me know if you want me to mock up what I'm trying to describe here.
Errors
Related to the 'criteria vs. custom feature': If you open an existing feature with criteria-based features, and then click the 'custom' pill to make the feature a 'custom' feature, you get the following error in the console:

It looks like the copyAnalysisSqlTemplateToClipboard was removed from the component.
Dirty flag not updating properly
Inside a criteria feature, If you go to a concept set, and look at the descendants, and then add a few descendants to the main concept set expression, the criteria feature does not show 'dirty' and the save button is disabled. HOWEVER, the overall application dirty flag (the flag that shows the * in the open tab) does indicate that you have unsaved changes. so, somehow the save button's dirty flag is not looking at the concept set's dirty flag.
|
Actually, just an update to my first item on Shopping Charts: But, there's some confusion here: if i have an open Criteria Feature concept set, and then I open up a Concept Set from the repository, toggling the shopoping charts does modify the last thing that I opened, but there are also shopping carts that are 'lit up' from the original concept set that was opened. So there is some confusion in the UI about which concepts belong to which concept sets. It is this confusion that I originally said that the 'shopping cart' design should be thrown out and we should instead have context-local concept set vocabulary searching. As you can see from the complexity of the code, every time we have a new source of concept sets, we have to go back to the main app.js and define a new set of IF statemets about which concept set from which 'nav' we're dealing with, and sometimes you can have multiple concept sets in a single nav (such as a concept set under CC and a concept set under FE). I think it's great what you've managed to get working this far, but the architecture of the vocabulary search + concept set editor coupling leads to some very challenging problems when you try to make it work for any concept set from any Atlas asset. |
|
@chrisknoll Thank you for such deep review and detailed explanation. It's really helpful. |
|
Thanks @wivern. I know this is complicated, but maybe there's a simple solution: What if each nav-module maintained their own This is a very high-level idea and may have some cases where I didn't think of, but I am trying to think of a way forward that wouldn't require you to rewrite the entire search UI and instead just make the searchUI aware of the conceptSets that could be edited based on the concept sets that were opened in the nav-module. |
|
Any updates on this PR? |
@chrisknoll Unfortunately no. Thank you for review and suggestions. It's really helpful. |
|
Ok, Thanks for the update. Please let me know if you would like any assistance on this. |
|
I am looking at this, but this PR also is paired with a PR related to WebAPI, and I have some open questions on the code changes over there. So, I will be working on those 2 PRs in parallel. |
|
@chrisknoll Hello! Thanks for reply. I think we should also wait until some of other opened PRs in Atlas will be merged and then i'll update this one again according to the latest master because this PR affects many things. |
|
Hi, @vlbe. I'm under a bit of time constraint and prioritization, and I'd really like to focus on getting these 2 prs done. In my mind, it woudl be easier to get this large chunk of code updated, and update the other smaller PRs to adjust,t hen to make a lot of smaller PR changes and have to revisit this one a dozen times. Let's focus on getting this one finalized and committed, and then worry about the impact the the others. |
|
Ok, we can make this way. Thank you |
| function toConceptSetItems(selectedConcepts){ | ||
| var conceptSetItems = []; | ||
| const conceptSetItems = []; | ||
|
|
||
| for (var i = 0; i < selectedConcepts.length; i++) { | ||
| var item = selectedConcepts[i]; | ||
| for (let i = 0; i < selectedConcepts.length; i++) { | ||
| const item = selectedConcepts[i]; | ||
| conceptSetItems.push({ | ||
| conceptId: item.concept.CONCEPT_ID, | ||
| isExcluded: +item.isExcluded(), | ||
| includeDescendants: +item.includeDescendants(), | ||
| includeMapped: +item.includeMapped() | ||
| isExcluded: +ko.unwrap(item.isExcluded), | ||
| includeDescendants: +ko.unwrap(item.includeDescendants), | ||
| includeMapped: +ko.unwrap(item.includeMapped) |
There was a problem hiding this comment.
I'm concerned about loosing the observable of the conceptSetItems. We bind to these properties in the UI such that changing the checkboxes updates the underlying model.
| 'text!./feature-analysis-view-edit.html', | ||
| 'appConfig', | ||
| 'atlas-state', | ||
| 'services/EventEmitter', |
There was a problem hiding this comment.
Note on the 'EventEmitter': in the framework we're using, we have capabilities for pub-sub notificaiton via observable, or computedObservable, which you can subscribe and valueHasMutated to signal. I'd prefer if we didn't add a new dependency to the application that effectively does the same thing, but in a different way.
|
|
||
|
|
||
| function savePreviousConceptSet() { | ||
| return true; |
There was a problem hiding this comment.
This doesn't seem to do anything with an immedate 'return true'.
|
I added some high-level comments to specific lines of code. I haven't dug into specific testing yet but I will be doing that next. I also wanted to ask about a potential change to the way 'shopping carts' are use, and if what I propose below is something we can implement since we're doing many changes here anyway. The issues with the shopping carts are as follows:
So, what I am suggesting is not a massive (but it is definitely work) from shopping carts to checkboxes where the user is presented the search results with checkboxes (and not shopping carts) and the user selects the concepts they want to add to the 'activeConceptSet', and decides to add them as 'with descendnats' or 'as exclusions' (or both). We'd still use most of the current implementation that keeps track of the ConceptIDs that are in a concept set (this is currently used to determine if the Shopping Cart is 'lit' on a given row of the search results). Instead, we can highlight the row of the table if the concept exists in the concept set, but drop shopping carts in favor of checkboxes. And the user can choose what to do with the selected concepts: add (as exlusion/with desendants) or remove. This prevents the accidental 'unselect-select' issues that I referred to above. This will also mean we can remove those global handlers on when the shopping cart is clicked. Instead, the concept set editing is encapsulated in the context of the concept list that we're presenting (whether it be from a vocabulary search, or the 'included concepts'). If this sounds simple, let's go for it. If you prefer that we just get the basic functionality implemented and merged, we can do that first, and revisit shopping carts later. |
|
I ran across an error that I think is new since I last checked the origional PR: I don't see js/version.js in master branch, and i don't see a version.js file in the set of files for this PR...what is version.js? Edit: nevermind: found it: there's a new npm command 'genversion' that produces this file, and I had to generate it via |
|
@chrisknoll Generation of version.js was done in #2134 As for you proposal, i think we should implement checkbox in this PR so I think it's better to wait final version to review this. I looked through the code once again and found some issues with. I have also several questions about implementing checkboxes. |
|
Thanks. It becomes more clear to me. So actually we have 2 tasks to do with these shopping carts:
Just a small question about mechanism of storing active conceptsets. As you could see from the code. I decided to move with current realisation where we have only one ConceptSet in the state and store another active/opened conceptsets in another variable(for now HashedConceptSets). So we have some keys for pages that have conceptsets functionality(repository/cohort-characterization/feature-analysis/etc). So when we move from one page to another. The activeConceptSetSource will change which leads to saving currentConceptSet data to HashedConceptSets. Then we just replace currentConceptSet with new one from HashedConceptSets. When we close some entity - conceptset will be removed from HashedConceptsets object and new CurrentConceptSet will be repository or the first from the list in HashedConceptsets. Is it ok for you? P.S. Actually i've already started to work on implementing checkboxes) so if you don't mind let's just finish this in one pr |
Conflicts: js/components/circe/components/CohortConceptSetBrowserTemplate.html js/components/conceptsetbuilder/components/IncludedConcepts.js js/components/conceptsetbuilder/components/MappedConcepts.js js/pages/cohort-definitions/cohort-definition-manager.js js/pages/concept-sets/conceptset-manager.js js/pages/incidence-rates/ir-manager.html
|
@chrisknoll - from our offline discussion, the changes here look great! I noted a few items that I'm hoping @vlbe can resolve so we can merge this in right away:
And here is the code reference for the error above: https://github.com/OHDSI/Atlas/blob/issue-1595-fa-concept-set/js/pages/concept-sets/concept-manager.js#L257. @olga-ganina - If there are any questions on this items or others this week, please direct them to me. Thanks all! |
|
@vlbe - thanks for making these updates. The feedback after pressing the button works well and I was able to use the I had a question while reviewing this PR. Here is my scenario: I've opened a cohort definition in ATLAS that contains > 1 concept sets. I've navigated to the Concept Sets tab and opened an existing concept set. I then use the "Add Concepts" button which then brings me to the vocabulary search page. I search for a term and when the results are shown, I can select a concept to add to the concept set. I would have expected that the "Add to New Concept Set" section (shown below) would contain a drop down for the concept sets in my active cohort definition? Do I have this correct? To be clear: I'm not requesting changes but just want to make sure if I understand the current behavior and if that is aligned to the design discussions you've had with Chris. |
|
@anthonysena , I think you have a real issue (and this behavior was working once, but with the conflicts and merges, something may have broken, so thank you for calling this out): The proper behavior is on the vocabulary search results page, it should give you the dropdown for any open concept sets, or if there's none, it should give you the 'new concept set' option. When clicking 'add concepts' from the entity's concept set (such as cohort def, cc, feature analysis, or IR), that concept set (where you clicked add concepts) should become an 'active' concept set and be pre-selected in the choices of open concept sets. So, something is not working right. If @vlbe doesn't get to it first, I'll figure out what's happening. |
|
@chrisknoll @anthonysena Pushed a commit to fix this. As we discussed with @chrisknoll i added isEditable field to ConceptSetStore to filter out conceptsets from dropdown if entity which contains concept sets is "read only". |
|
Thanks @chrisknoll and @vlbe for this. I pulled down the recent change and now I'm able to toggle between concept sets but now face a challenge when adding the concept set. I'm testing this with security disabled so that could be part of the reason. Here is the display where I've selected 2 items from the search - the "Add To Concept Set" button is disabled despite having selected some items to add: |
|
@anthonysena Hm, that's strange. I've just disabled security and 'Add to concept set' button is active. Could you please provide steps to reproduce it. |
|
@anthonysena fyi, the last commit is fixing another 2 issues with list of active concept sets in dropdown:
|
|
Would like to clarify this one:
So, I don't think we do this blindly: if we have 3 different concept sets open (ex: Repository, Cohort Def, IR), if we were in the Cohort Def one and clicked 'Add Concept' which set the sharedState.activeConceptSet to the Cohort Definition's conceptSetStore, and then go to the IR view, and close a conept set there, I think the activeConceptSet should remain the 'CohortDefinition' one. Maybe there needs to be a reference check such that: Note: this is just pseudo code, I forget what we called the current page's currentConceptSetStore property... |
|
@chrisknoll I am not sure that we need this check because we are setting active concept set when select concept set in the list https://github.com/OHDSI/Atlas/pull/2132/files#diff-68f52280a6354d182ce786a86e8e5610R167 |
Remove dead/commented code.
|
Here's the steps to reproduce:
After my latest commit, it will only clear the active concept set store if the closed one is the active one. Note: only catch is that when you click on the Concept Set navigation item, it re-selects the active concept set to the Repository (unlike other navs where it does not do that). So, I'd not make any changes for this, but just be aware of the behavior. |
anthonysena
left a comment
There was a problem hiding this comment.
Thanks all for the updates - from my testing, this is working well!





Resolves #1595