Merge branch '16602-wb2-acr-version' refs #16602
[arvados-workbench2.git] / src / models / vocabulary.ts
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import { isObject, has, every } from 'lodash/fp';
6
7 export interface Vocabulary {
8     strict_tags: boolean;
9     tags: Record<string, Tag>;
10 }
11
12 export interface Label {
13     lang?: string;
14     label: string;
15 }
16
17 export interface TagValue {
18     labels: Label[];
19 }
20
21 export interface Tag {
22     strict?: boolean;
23     labels: Label[];
24     values?: Record<string, TagValue>;
25 }
26
27 export interface PropFieldSuggestion {
28     id: string;
29     label: string;
30 }
31
32 const VOCABULARY_VALIDATORS = [
33     isObject,
34     has('strict_tags'),
35     has('tags'),
36 ];
37
38 export const isVocabulary = (value: any) =>
39     every(validator => validator(value), VOCABULARY_VALIDATORS);
40
41 export const isStrictTag = (tagKeyID: string, vocabulary: Vocabulary) => {
42     const tag = vocabulary.tags[tagKeyID];
43     return tag ? tag.strict : false;
44 };
45
46 export const getTagValueID = (tagKeyID:string, tagValueLabel:string, vocabulary: Vocabulary) =>
47     (tagKeyID && vocabulary.tags[tagKeyID] && vocabulary.tags[tagKeyID].values)
48     ? Object.keys(vocabulary.tags[tagKeyID].values!).find(
49         k => vocabulary.tags[tagKeyID].values![k].labels.find(
50             l => l.label === tagValueLabel) !== undefined) || ''
51     : '';
52
53 export const getTagValueLabel = (tagKeyID:string, tagValueID:string, vocabulary: Vocabulary) =>
54     vocabulary.tags[tagKeyID] &&
55     vocabulary.tags[tagKeyID].values &&
56     vocabulary.tags[tagKeyID].values![tagValueID] &&
57     vocabulary.tags[tagKeyID].values![tagValueID].labels.length > 0
58         ? vocabulary.tags[tagKeyID].values![tagValueID].labels[0].label
59         : tagValueID;
60
61 const compare = (a: PropFieldSuggestion, b: PropFieldSuggestion) => {
62     if (a.label < b.label) {return -1;}
63     if (a.label > b.label) {return 1;}
64     return 0;
65 };
66
67 export const getTagValues = (tagKeyID: string, vocabulary: Vocabulary) => {
68     const tag = vocabulary.tags[tagKeyID];
69     const ret = tag && tag.values
70         ? Object.keys(tag.values).map(
71             tagValueID => tag.values![tagValueID].labels && tag.values![tagValueID].labels.length > 0
72                 ? tag.values![tagValueID].labels.map(
73                     lbl => Object.assign({}, {"id": tagValueID, "label": lbl.label}))
74                 : [{"id": tagValueID, "label": tagValueID}])
75             .reduce((prev, curr) => [...prev, ...curr], [])
76             .sort(compare)
77         : [];
78     return ret;
79 };
80
81 export const getTags = ({ tags }: Vocabulary) => {
82     const ret = tags && Object.keys(tags)
83         ? Object.keys(tags).map(
84             tagID => tags[tagID].labels && tags[tagID].labels.length > 0
85                 ? tags[tagID].labels.map(
86                     lbl => Object.assign({}, {"id": tagID, "label": lbl.label}))
87                 : [{"id": tagID, "label": tagID}])
88             .reduce((prev, curr) => [...prev, ...curr], [])
89             .sort(compare)
90         : [];
91     return ret;
92 };
93
94 export const getTagKeyID = (tagKeyLabel:string, vocabulary: Vocabulary) =>
95     Object.keys(vocabulary.tags).find(
96         k => vocabulary.tags[k].labels.find(
97             l => l.label === tagKeyLabel) !== undefined
98         ) || '';
99
100 export const getTagKeyLabel = (tagKeyID:string, vocabulary: Vocabulary) =>
101     vocabulary.tags[tagKeyID] && vocabulary.tags[tagKeyID].labels.length > 0
102     ? vocabulary.tags[tagKeyID].labels[0].label
103     : tagKeyID;