From: Lucas Di Pentima Date: Thu, 10 Feb 2022 21:17:56 +0000 (-0300) Subject: 18560: Adds vocabulary querying functions, with their tests. X-Git-Tag: 2.4.0~9^2~3 X-Git-Url: https://git.arvados.org/arvados-workbench2.git/commitdiff_plain/939593fbdd53bcca1c9c5e2247b3f279fdcf1523 18560: Adds vocabulary querying functions, with their tests. Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima --- diff --git a/src/models/vocabulary.test.ts b/src/models/vocabulary.test.ts index 18e2f19f..582af0ec 100644 --- a/src/models/vocabulary.test.ts +++ b/src/models/vocabulary.test.ts @@ -18,7 +18,8 @@ describe('Vocabulary', () => { strict: false, labels: [ {label: "Animal" }, - {label: "Creature"} + {label: "Creature"}, + {label: "Beast"}, ], values: { IDVALANIMALS1: { @@ -39,13 +40,13 @@ describe('Vocabulary', () => { labels: [{label: "Sizes"}], values: { IDVALSIZES1: { - labels: [{label: "Small"}] + labels: [{label: "Small"}, {label: "S"}, {label: "Little"}] }, IDVALSIZES2: { - labels: [{label: "Medium"}] + labels: [{label: "Medium"}, {label: "M"}] }, IDVALSIZES3: { - labels: [{label: "Large"}] + labels: [{label: "Large"}, {label: "L"}] }, IDVALSIZES4: { labels: [] @@ -61,23 +62,70 @@ describe('Vocabulary', () => { // Alphabetically ordered by label expect(tagKeys).toEqual([ {id: "IDKEYANIMALS", label: "Animal"}, + {id: "IDKEYANIMALS", label: "Beast"}, {id: "IDKEYANIMALS", label: "Creature"}, {id: "IDKEYCOMMENT", label: "IDKEYCOMMENT"}, {id: "IDKEYSIZES", label: "Sizes"}, ]); }); + it('returns the list of preferred tag keys', () => { + const preferredTagKeys = Vocabulary.getPreferredTags(vocabulary); + // Alphabetically ordered by label + expect(preferredTagKeys).toEqual([ + {id: "IDKEYANIMALS", label: "Animal", description: "Animal"}, + {id: "IDKEYCOMMENT", label: "IDKEYCOMMENT"}, + {id: "IDKEYSIZES", label: "Sizes", description: "Sizes"}, + ]); + }); + + it('returns the list of preferred tag keys with synonyms', () => { + const preferredTagKeys = Vocabulary.getPreferredTags(vocabulary, true); + // Alphabetically ordered by label + expect(preferredTagKeys).toEqual([ + {id: "IDKEYANIMALS", label: "Animal", description: "Animal (Creature, Beast)"}, + {id: "IDKEYCOMMENT", label: "IDKEYCOMMENT"}, + {id: "IDKEYSIZES", label: "Sizes", description: "Sizes"}, + ]); + }); + it('returns the tag values for a given key', () => { const tagValues = Vocabulary.getTagValues('IDKEYSIZES', vocabulary); // Alphabetically ordered by label expect(tagValues).toEqual([ {id: "IDVALSIZES4", label: "IDVALSIZES4"}, + {id: "IDVALSIZES3", label: "L"}, {id: "IDVALSIZES3", label: "Large"}, + {id: "IDVALSIZES1", label: "Little"}, + {id: "IDVALSIZES2", label: "M"}, {id: "IDVALSIZES2", label: "Medium"}, + {id: "IDVALSIZES1", label: "S"}, {id: "IDVALSIZES1", label: "Small"}, ]) }); + it('returns the preferred tag values for a given key', () => { + const preferredTagValues = Vocabulary.getPreferredTagValues('IDKEYSIZES', vocabulary); + // Alphabetically ordered by label + expect(preferredTagValues).toEqual([ + {id: "IDVALSIZES4", label: "IDVALSIZES4"}, + {id: "IDVALSIZES3", label: "Large", description: "Large"}, + {id: "IDVALSIZES2", label: "Medium", description: "Medium"}, + {id: "IDVALSIZES1", label: "Small", description: "Small"}, + ]) + }); + + it('returns the preferred tag values with synonyms for a given key', () => { + const preferredTagValues = Vocabulary.getPreferredTagValues('IDKEYSIZES', vocabulary, true); + // Alphabetically ordered by label + expect(preferredTagValues).toEqual([ + {id: "IDVALSIZES4", label: "IDVALSIZES4"}, + {id: "IDVALSIZES3", label: "Large", description: "Large (L)"}, + {id: "IDVALSIZES2", label: "Medium", description: "Medium (M)"}, + {id: "IDVALSIZES1", label: "Small", description: "Small (S, Little)"}, + ]) + }); + it('returns an empty list of values for an non-existent key', () => { const tagValues = Vocabulary.getTagValues('IDNONSENSE', vocabulary); expect(tagValues).toEqual([]); diff --git a/src/models/vocabulary.ts b/src/models/vocabulary.ts index 3c542844..55525c22 100644 --- a/src/models/vocabulary.ts +++ b/src/models/vocabulary.ts @@ -27,6 +27,7 @@ export interface Tag { export interface PropFieldSuggestion { id: string; label: string; + description?: string; } const VOCABULARY_VALIDATORS = [ @@ -64,9 +65,9 @@ const compare = (a: PropFieldSuggestion, b: PropFieldSuggestion) => { return 0; }; -export const getTagValues = (tagKeyID: string, vocabulary: Vocabulary) => { +export const getTagValues = (tagKeyID: string, vocabulary: Vocabulary): PropFieldSuggestion[] => { const tag = vocabulary.tags[tagKeyID]; - const ret = tag && tag.values + return tag && tag.values ? Object.keys(tag.values).map( tagValueID => tag.values![tagValueID].labels && tag.values![tagValueID].labels.length > 0 ? tag.values![tagValueID].labels.map( @@ -75,11 +76,27 @@ export const getTagValues = (tagKeyID: string, vocabulary: Vocabulary) => { .reduce((prev, curr) => [...prev, ...curr], []) .sort(compare) : []; - return ret; }; -export const getTags = ({ tags }: Vocabulary) => { - const ret = tags && Object.keys(tags) +export const getPreferredTagValues = (tagKeyID: string, vocabulary: Vocabulary, withSynonyms?: boolean): PropFieldSuggestion[] => { + const tag = vocabulary.tags[tagKeyID]; + return tag && tag.values + ? Object.keys(tag.values).map( + tagValueID => tag.values![tagValueID].labels && tag.values![tagValueID].labels.length > 0 + ? { + "id": tagValueID, + "label": tag.values![tagValueID].labels[0].label, + "description": tag.values![tagValueID].labels[0].label + ( + withSynonyms && tag.values![tagValueID].labels.length > 1 + ? ` (${tag.values![tagValueID].labels.slice(1).map(l => l.label).join(', ')})` + : '')} + : {"id": tagValueID, "label": tagValueID}) + .sort(compare) + : []; +}; + +export const getTags = ({ tags }: Vocabulary): PropFieldSuggestion[] => { + return tags && Object.keys(tags) ? Object.keys(tags).map( tagID => tags[tagID].labels && tags[tagID].labels.length > 0 ? tags[tagID].labels.map( @@ -88,7 +105,23 @@ export const getTags = ({ tags }: Vocabulary) => { .reduce((prev, curr) => [...prev, ...curr], []) .sort(compare) : []; - return ret; +}; + +export const getPreferredTags = ({ tags }: Vocabulary, withSynonyms?: boolean): PropFieldSuggestion[] => { + return tags && Object.keys(tags) + ? Object.keys(tags).map( + tagID => tags[tagID].labels && tags[tagID].labels.length > 0 + ? { + "id": tagID, + "label": tags[tagID].labels[0].label, + "description": tags[tagID].labels[0].label + ( + withSynonyms && tags[tagID].labels.length > 1 + ? ` (${tags[tagID].labels.slice(1).map(lbl => lbl.label).join(', ')})` + : '' + )} + : {"id": tagID, "label": tagID}) + .sort(compare) + : []; }; export const getTagKeyID = (tagKeyLabel:string, vocabulary: Vocabulary) =>