Merge branch '18848-upgrade-yarn3'. Closes #18848
[arvados-workbench2.git] / src / models / vocabulary.ts
index 3c5428446cf589ec183a29793a6a0bbf219f48fe..c913bd65124544b475d7816a73db6d5728104535 100644 (file)
@@ -2,6 +2,7 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
+import { escapeRegExp } from 'common/regexp';
 import { isObject, has, every } from 'lodash/fp';
 
 export interface Vocabulary {
@@ -27,6 +28,7 @@ export interface Tag {
 export interface PropFieldSuggestion {
     id: string;
     label: string;
+    synonyms?: string[];
 }
 
 const VOCABULARY_VALIDATORS = [
@@ -43,12 +45,17 @@ export const isStrictTag = (tagKeyID: string, vocabulary: Vocabulary) => {
     return tag ? tag.strict : false;
 };
 
-export const getTagValueID = (tagKeyID:string, tagValueLabel:string, vocabulary: Vocabulary) =>
-    (tagKeyID && vocabulary.tags[tagKeyID] && vocabulary.tags[tagKeyID].values)
-    ? Object.keys(vocabulary.tags[tagKeyID].values!).find(
-        k => vocabulary.tags[tagKeyID].values![k].labels.find(
-            l => l.label.toLowerCase() === tagValueLabel.toLowerCase()) !== undefined) || ''
-    : '';
+export const getTagValueID = (tagKeyID:string, tagValueLabel:string, vocabulary: Vocabulary) => {
+    if (tagKeyID && vocabulary.tags[tagKeyID] && vocabulary.tags[tagKeyID].values) {
+        const values = vocabulary.tags[tagKeyID].values!;
+        return Object.keys(values).find(k =>
+            (k.toLowerCase() === tagValueLabel.toLowerCase())
+            || values[k].labels.find(
+                l => l.label.toLowerCase() === tagValueLabel.toLowerCase()) !== undefined)
+            || '';
+    };
+    return '';
+};
 
 export const getTagValueLabel = (tagKeyID:string, tagValueID:string, vocabulary: Vocabulary) =>
     vocabulary.tags[tagKeyID] &&
@@ -64,9 +71,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 +82,30 @@ 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, withMatch?: string): PropFieldSuggestion[] => {
+    const tag = vocabulary.tags[tagKeyID];
+    const regex = !!withMatch ? new RegExp(escapeRegExp(withMatch), 'i') : undefined;
+    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,
+                    "synonyms": !!withMatch && tag.values![tagValueID].labels.length > 1
+                        ? tag.values![tagValueID].labels.slice(1)
+                            .filter(l => !!regex ? regex.test(l.label) : true)
+                            .map(l => l.label)
+                        : []
+                }
+                : {"id": tagValueID, "label": tagValueID, "synonyms": []})
+            .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,14 +114,32 @@ export const getTags = ({ tags }: Vocabulary) => {
             .reduce((prev, curr) => [...prev, ...curr], [])
             .sort(compare)
         : [];
-    return ret;
 };
 
-export const getTagKeyID = (tagKeyLabel:string, vocabulary: Vocabulary) =>
-    Object.keys(vocabulary.tags).find(
-        k => vocabulary.tags[k].labels.find(
-            l => l.label.toLowerCase() === tagKeyLabel.toLowerCase()) !== undefined
-        ) || '';
+export const getPreferredTags = ({ tags }: Vocabulary, withMatch?: string): PropFieldSuggestion[] => {
+    const regex = !!withMatch ? new RegExp(escapeRegExp(withMatch), 'i') : undefined;
+    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,
+                    "synonyms": !!withMatch && tags[tagID].labels.length > 1
+                        ? tags[tagID].labels.slice(1)
+                                .filter(l => !!regex ? regex.test(l.label) : true)
+                                .map(lbl => lbl.label)
+                        : []
+                }
+                : {"id": tagID, "label": tagID, "synonyms": []})
+            .sort(compare)
+        : [];
+};
+
+export const getTagKeyID = (tagKeyLabel: string, vocabulary: Vocabulary) =>
+    Object.keys(vocabulary.tags).find(k => (k.toLowerCase() === tagKeyLabel.toLowerCase())
+        || vocabulary.tags[k].labels.find(
+            l => l.label.toLowerCase() === tagKeyLabel.toLowerCase()) !== undefined)
+        || '';
 
 export const getTagKeyLabel = (tagKeyID:string, vocabulary: Vocabulary) =>
     vocabulary.tags[tagKeyID] && vocabulary.tags[tagKeyID].labels.length > 0