-
Notifications
You must be signed in to change notification settings - Fork 76
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
OCLOMRS-967: Pick concepts from a dictionary (in addition to sources) #712
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added quite a few comments, including one that should fix the build error.
underline: { | ||
"&&&:before": { | ||
borderBottom: "none" | ||
}, | ||
"&&:after": { | ||
borderBottom: "none" | ||
} | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume this should be restored as well?
dictionaryIcon:{ | ||
marginRight: "0.2rem", | ||
fill: "#8080809c" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't really need a separate dictionaryIcon
class... This can be shared with sourceIcon
(at least until we develop a need to style the icons differently)
@@ -36,24 +38,21 @@ const useStyles = makeStyles((theme: Theme) => | |||
}, | |||
textField: { | |||
padding: "0.2rem 1rem", | |||
cursor: "none" | |||
cursor: "none", | |||
width: "100%" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why this change?
sourceUrl, | ||
false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is in the wrong order. sourceUrl
should be the last argument.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, we should do away with this copy of recursivelyFetchToConcepts()
since we're using that below, right?
); | ||
|
||
const groupedConcepts = groupBy(concepts.sourceUrl), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const groupedConcepts = groupBy(concepts.sourceUrl), | |
const groupedConcepts = groupBy(concepts.sourceUrl); |
); | ||
|
||
const groupedConcepts = groupBy(concepts.sourceUrl), | ||
const referencesToAdd = Object.entries(groupedConcepts).map(([source, concepts]) => recursivelyFetchToConcepts( | ||
concepts.sourceUrl, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The sourceUrl
should be the source
argument. Remember, however, that the sourceUrl
now needs to be the last argument to this, if we're re-arranging the argument order for recursivelyFetchToConcepts()
@@ -78,7 +78,7 @@ describe("action", () => { | |||
expect(indexedAction).toHaveBeenCalledWith("sources/retrieveSources", 1); | |||
}); | |||
|
|||
it("for public sources should use action index as 2 along with the corresponding actionType and api", () => { | |||
it("for All Public Concepts should use action index as 2 along with the corresponding actionType and api", () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't replace this text... We only need things to read "All Public Concepts" in the UI or where we're testing something about the UI.
@@ -1,9 +1,9 @@ | |||
import { getSourceTypeFromPreviousPath } from "../utils"; | |||
|
|||
describe("getSourceTypeFromPreviousPath", () => { | |||
it("should return public sources for /sources/", () => { | |||
it("should returnAll Public Concepts for /sources/", () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto on not needing "All Public Concepts" here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ibacher thanks for the review. Let me fix the proposed changes.
@jwnasambu why do we have two PRS for this work, can you please close one and maintain one? |
@hadijahkyampeire sorry for the confusion caused! After shifting to a new pr I forgot to close the later. Hopefully its fixed now. |
@jwnasambu we can still see two PRs for this work, please close one that you are not working on and maintain one which we can review. |
This is meant to cover the case where unit tests fail
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jwnasambu I've added some comments on a few points here. I'm not entirely sure this is all the changes necessary, but please try them out an let me know.
{!showAddConcepts ? null : ( | ||
{showAddConcepts ? null : ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see what you're doing here, but this should actually still be:
{!showAddConcepts ? null : (
Because it's still possible to be viewing concepts without a dictionary to add them to
// const referencesToAdd = await recursivelyFetchToConcepts( | ||
// concepts.map(concept => concept.id), | ||
// updateProgress, | ||
// false, | ||
// sourceUrl | ||
// ); | ||
|
||
const referencesToAdd = await recursivelyFetchToConcepts( | ||
'/sources/CIEL/', | ||
concepts.map(concept => concept.id), | ||
updateProgress | ||
); | ||
|
||
const groupedConcepts = groupBy(concepts, "source"); | ||
console.log(groupedConcepts) | ||
// const referencesToAdd = await Object.entries(groupedConcepts).map(([source, concepts]) => recursivelyFetchToConcepts( | ||
// source, | ||
// concepts.map((concept: { id: any; }) => concept.id), | ||
// updateProgress,1, | ||
// )); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright so this is very confusing, but here's what I think the implementation should look like:
const groupedConcepts = groupBy(concepts, "source_url");
const referencesToAdd = flatten(
await Promise.all(
Object.entries(groupedConcepts).map(([source, concepts]) =>
recursivelyFetchToConcepts(
source,
concepts.map((concept) => concept.id),
updateProgress
)
)
)
);
The trick here is that by calling map()
we're building an array of... whatever the return value is. In this case, it's the return value of the call to recursivelyFetchToConcepts()
which actually returns a Promise<string[]>
(a Promise to return an array of strings at a later point).
In the currently working version, the await
before the recursivelyFetchToConcepts()
waits until the call to recursivelyFetchToConcepts()
returns. Since we're returning an array of promises, (one for each call to recursivelyFetchToConcepts()
, i.e., one for each source), we need to wait until all those promises are finished. Promise.all()
allows us to do this, turning an array of Promises into a promise that resolves with an array of results. We can safely await
that.
Finally, I used lodash
's flatten
function to transform the return time from string[][]
(an array of arrays of strings) to a single array, that should look much like the one that existed before all these changes.
dictionaryUrl: string, | ||
rawConcepts: (APIConcept | string)[], | ||
bulk: boolean = false | ||
bulk: boolean = false, | ||
sourceUrl?: string | ||
) => { | ||
return async (dispatch: Function, getState: Function) => { | ||
const concepts = rawConcepts.map(concept => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To address my previous concern, this should look like this:
if (!!!sourceUrl && !!rawConcepts.find((c) => typeof c === "string")) {
throw {
message: "Cannot load string-only concepts without a source url",
};
}
const concepts = rawConcepts.map((concept) =>
typeof concept === "string"
? {
id: concept,
url: `${sourceUrl}concepts/${concept}/`,
source_url: sourceUrl,
}
: concept
);
Note that this throws an error if rawConcepts
contains any strings an no sourceUrl was provided. It also adds the source_url
property to our concepts so we can use this in the groupBy
below.
function getState(): import("../../../redux").AppState { | ||
throw new Error("Function not implemented."); | ||
} | ||
|
||
function dispatch(arg0: { type: string; actionIndex: number; meta: any[]; }) { | ||
throw new Error("Function not implemented."); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove these... see my note above.
@@ -70,7 +70,7 @@ export const EnhancedTableToolbar = (props: EnhancedTableToolbarProps) => { | |||
)} | |||
{numSelected > 0 ? ( | |||
<> | |||
{showAddConcepts ? null : ( | |||
{!showAddConcepts ? null : ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line should read:
{showAddConcepts ? null : (
We need to change the conditions under which showAddConcepts
is true, not just negate it (if we keep this in, this will show the add concepts
part where we don't want to do that, i.e., where the user didn't start from their own dictionary).
} | ||
: concept | ||
); | ||
return async (dispatch: Function, getState: function) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the small typo it's complaining about:
return async (dispatch: Function, getState: function) => { | |
return async (dispatch: Function, getState: Function) => { |
function
is a keyword Function
is a type, if that makes any sense an here (after the :
) this is serving as a type annotation.
… into OCLOMRS-967
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Thanks @jwnasambu!
@ibacher thanks for your guidance you gave me a glimpse on how to work on a high level ticket and think out of the box. |
JIRA TICKET NAME:
Pick concepts from a dictionary (in addition to sources)
Summary:
I worked on a feature that allows a user to create a dictionary that contains concepts from another dictionary.