// Copyright (C) The Arvados Authors. All rights reserved. // // SPDX-License-Identifier: AGPL-3.0 import { isObject, has, every } from 'lodash/fp'; export interface Vocabulary { strict_tags: boolean; tags: Record; } export interface Label { lang?: string; label: string; } export interface TagValue { labels: Label[]; } export interface Tag { strict?: boolean; labels: Label[]; values?: Record; } export interface PropFieldSuggestion { id: string; label: string; description?: string; } const VOCABULARY_VALIDATORS = [ isObject, has('strict_tags'), has('tags'), ]; export const isVocabulary = (value: any) => every(validator => validator(value), VOCABULARY_VALIDATORS); export const isStrictTag = (tagKeyID: string, vocabulary: Vocabulary) => { const tag = vocabulary.tags[tagKeyID]; 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 getTagValueLabel = (tagKeyID:string, tagValueID:string, vocabulary: Vocabulary) => vocabulary.tags[tagKeyID] && vocabulary.tags[tagKeyID].values && vocabulary.tags[tagKeyID].values![tagValueID] && vocabulary.tags[tagKeyID].values![tagValueID].labels.length > 0 ? vocabulary.tags[tagKeyID].values![tagValueID].labels[0].label : tagValueID; const compare = (a: PropFieldSuggestion, b: PropFieldSuggestion) => { if (a.label < b.label) {return -1;} if (a.label > b.label) {return 1;} return 0; }; export const getTagValues = (tagKeyID: string, vocabulary: Vocabulary): 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 ? tag.values![tagValueID].labels.map( lbl => Object.assign({}, {"id": tagValueID, "label": lbl.label})) : [{"id": tagValueID, "label": tagValueID}]) .reduce((prev, curr) => [...prev, ...curr], []) .sort(compare) : []; }; 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( lbl => Object.assign({}, {"id": tagID, "label": lbl.label})) : [{"id": tagID, "label": tagID}]) .reduce((prev, curr) => [...prev, ...curr], []) .sort(compare) : []; }; 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) => Object.keys(vocabulary.tags).find( k => 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 ? vocabulary.tags[tagKeyID].labels[0].label : tagKeyID;