@kit-data-manager/pid-component
Version:
The PID-Component is a web component that can be used to evaluate and display FAIR Digital Objects, PIDs, ORCiDs, and possibly other identifiers in a user-friendly way. It is easily extensible to support other identifier types.
192 lines (191 loc) • 12.5 kB
JavaScript
/*!
*
* Copyright 2024-2026 Karlsruhe Institute of Technology.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
import { h } from "@stencil/core";
import { GenericIdentifierType } from "../../utils/GenericIdentifierType";
import { FoldableItem } from "../../utils/FoldableItem";
import { FoldableAction } from "../../utils/FoldableAction";
export class RORType extends GenericIdentifierType {
constructor() {
super(...arguments);
this.relationshipTypes = {
parent: {
title: 'Parent Organization',
tooltip: 'Organization that this organization is part of',
},
child: {
title: 'Child Organization',
tooltip: 'Organization that is part of this organization',
},
related: {
title: 'Related Organization',
tooltip: 'Organization that is related to this organization',
},
predecessor: {
title: 'Predecessor Organization',
tooltip: 'Organization that preceded this organization',
},
successor: {
title: 'Successor Organization',
tooltip: 'Organization that succeeded this organization',
},
};
this.contentMappings = {
active: '🟢 Active',
inactive: '⚪️ Inactive',
withdrawn: '⚠️ Withdrawn',
education: '🏫 Education',
funder: '💰 Funder',
healthcare: '🏥 Healthcare',
company: '🏢 Company',
archive: '📚 Archive',
nonprofit: '🎗️ Nonprofit',
government: '🏛️ Government',
facility: '🔬 Facility',
other: 'Other',
unknown: '❓ Unknown',
};
}
get data() {
return this.rorData;
}
getSettingsKey() {
return 'RORType';
}
quickCheck() {
return RORType.FORMAT_REGEX.test(this.value);
}
async hasMeaningfulInformation() {
const rorId = this.getRorId();
try {
const response = await fetch(`https://api.ror.org/v2/organizations/${rorId}`);
if (!response.ok)
return false;
this.rorData = await response.json();
return this.rorData !== undefined;
}
catch (_a) {
return false;
}
}
async init() {
if (!this.rorData) {
const hasData = await this.hasMeaningfulInformation();
if (!hasData) {
this.items.push(new FoldableItem(0, 'Error', 'No ROR data available'));
return;
}
}
try {
if (!this.rorData.names || this.rorData.names.length === 0) {
this.label = 'Unknown';
this.items.push(new FoldableItem(0, 'Name', 'Unknown', 'No names available for this organization'));
return;
}
else {
for (const name of this.rorData.names) {
const types = name.types || [];
if (types.includes('acronym')) {
this.acronym = name.value;
this.items.push(new FoldableItem(20, 'Acronym', name.value, 'Short form of the organization name'));
}
else if (types.includes('ror_display')) {
this.label = name.value;
this.items.push(new FoldableItem(1, 'Display Name', name.value, 'Name used for display purposes'));
}
else if (types.includes('alias')) {
this.items.push(new FoldableItem(5, 'Alias', name.value, 'Alternative name for the organization'));
}
else if (types.includes('label')) {
this.items.push(new FoldableItem(15, 'Label', name.value, 'Name in another language or script'));
}
}
}
this.items.push(new FoldableItem(20, 'ROR ID', this.rorData.id, 'Unique identifier for the organization in the ROR registry', undefined, undefined, false));
this.actions.push(new FoldableAction(10, 'View on ROR', this.rorData.id, 'primary'));
this.items.push(new FoldableItem(30, 'Status', this.getOptimizedContent(this.rorData.status || 'unknown'), 'Current status of the organization in the ROR registry'));
if (!this.rorData.types || this.rorData.types.length === 0) {
this.items.push(new FoldableItem(25, 'Type', this.getOptimizedContent('unknown'), 'Type of organization'));
}
else {
for (const type of this.rorData.types) {
this.items.push(new FoldableItem(25, 'Type', this.getOptimizedContent(type), 'Type of organization'));
}
}
if (this.rorData.links && this.rorData.links.length > 0) {
for (const link of this.rorData.links) {
if (link.type) {
this.items.push(new FoldableItem(35, `Link to ${link.type}`, link.value, 'External link related to the organization'));
}
else {
this.items.push(new FoldableItem(35, `Link`, link.value, 'External link related to the organization'));
}
}
}
if (this.rorData.external_ids && this.rorData.external_ids.length > 0) {
for (const external of this.rorData.external_ids) {
const type = external.type;
const value = external.preferred || external.all[0];
this.items.push(new FoldableItem(40, `External ID: ${type}`, value, `Identifier from another system: ${type}`));
}
}
if (this.rorData.relationships && this.rorData.relationships.length > 0) {
for (const rel of this.rorData.relationships) {
const relationType = this.relationshipTypes[rel.type] || {
title: rel.type,
tooltip: `${rel.type} organization`,
};
this.items.push(new FoldableItem(90, relationType.title, rel.id, relationType.tooltip));
}
}
if (this.rorData.locations && this.rorData.locations.length > 0) {
for (const location of this.rorData.locations) {
const details = location.geonames_details;
if (details.country_code) {
this.items.push(new FoldableItem(50, 'Country', details.country_code, 'Country where the organization is located'));
}
if (details.lat && details.lng) {
this.items.push(new FoldableItem(55, 'Coordinates', `${details.lat}, ${details.lng}`, 'Geographic coordinates of the organization'));
const osmUrl = `https://www.openstreetmap.org/?mlat=${details.lat}&mlon=${details.lng}&zoom=15`;
this.actions.push(new FoldableAction(20, 'View on OpenStreetMap', osmUrl, 'secondary'));
}
}
}
}
catch (error) {
console.error('Error fetching ROR data:', error);
this.items.push(new FoldableItem(0, 'Error', `Failed to fetch data from ROR API: ${error.message}`));
}
}
renderPreview() {
if (!this.rorData) {
return h("span", { class: `font-mono text-sm` }, "Loading ROR: ", this.value, "...");
}
return (h("span", { class: `inline-flex flex-nowrap items-baseline font-mono min-w-0 max-w-full` }, h("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 164 118", version: "1.1", class: 'mr-1 h-4 flex-none px-0.5 self-center', style: { fillRule: 'evenodd', clipRule: 'evenodd', strokeLinejoin: 'round', strokeMiterlimit: '2' } }, h("g", { transform: "matrix(0.994301,0,0,0.989352,0,0)" }, h("rect", { x: "0", y: "0", width: "164.94", height: "119.27", style: { fill: 'white' } })), h("g", { transform: "matrix(1,0,0,1,-0.945,-0.815)" }, h("path", { d: "M68.65,4.16L56.52,22.74L44.38,4.16L68.65,4.16Z", style: { fill: 'rgb(83,186,161)', fillRule: 'nonzero' } }), h("path", { d: "M119.41,4.16L107.28,22.74L95.14,4.16L119.41,4.16Z", style: { fill: 'rgb(83,186,161)', fillRule: 'nonzero' } }), h("path", { d: "M44.38,115.47L56.52,96.88L68.65,115.47L44.38,115.47Z", style: { fill: 'rgb(83,186,161)', fillRule: 'nonzero' } }), h("path", { d: "M95.14,115.47L107.28,96.88L119.41,115.47L95.14,115.47Z", style: { fill: 'rgb(83,186,161)', fillRule: 'nonzero' } }), h("path", { d: "M145.53,63.71C149.83,62.91 153.1,61 155.33,57.99C157.57,54.98 158.68,51.32 158.68,47.03C158.68,43.47 158.06,40.51 156.83,38.13C155.6,35.75 153.93,33.86 151.84,32.45C149.75,31.05 147.31,30.04 144.53,29.44C141.75,28.84 138.81,28.54 135.72,28.54L112.16,28.54L112.16,47.37C111.97,46.82 111.77,46.28 111.55,45.74C109.92,41.79 107.64,38.42 104.71,35.64C101.78,32.86 98.32,30.72 94.3,29.23C90.29,27.74 85.9,26.99 81.14,26.99C76.38,26.99 72,27.74 67.98,29.23C63.97,30.72 60.5,32.86 57.57,35.64C54.95,38.13 52.85,41.1 51.27,44.54C51.04,42.07 50.46,39.93 49.53,38.13C48.3,35.75 46.63,33.86 44.54,32.45C42.45,31.05 40.01,30.04 37.23,29.44C34.45,28.84 31.51,28.54 28.42,28.54L4.87,28.54L4.87,89.42L18.28,89.42L18.28,65.08L24.9,65.08L37.63,89.42L53.71,89.42L38.24,63.71C42.54,62.91 45.81,61 48.04,57.99C48.14,57.85 48.23,57.7 48.33,57.56C48.31,58.03 48.3,58.5 48.3,58.98C48.3,63.85 49.12,68.27 50.75,72.22C52.38,76.17 54.66,79.54 57.59,82.32C60.51,85.1 63.98,87.24 68,88.73C72.01,90.22 76.4,90.97 81.16,90.97C85.92,90.97 90.3,90.22 94.32,88.73C98.33,87.24 101.8,85.1 104.73,82.32C107.65,79.54 109.93,76.17 111.57,72.22C111.79,71.69 111.99,71.14 112.18,70.59L112.18,89.42L125.59,89.42L125.59,65.08L132.21,65.08L144.94,89.42L161.02,89.42L145.53,63.71ZM36.39,50.81C35.67,51.73 34.77,52.4 33.68,52.83C32.59,53.26 31.37,53.52 30.03,53.6C28.68,53.69 27.41,53.73 26.2,53.73L18.29,53.73L18.29,39.89L27.06,39.89C28.26,39.89 29.5,39.98 30.76,40.15C32.02,40.32 33.14,40.65 34.11,41.14C35.08,41.63 35.89,42.33 36.52,43.25C37.15,44.17 37.47,45.4 37.47,46.95C37.47,48.6 37.11,49.89 36.39,50.81ZM98.74,66.85C97.85,69.23 96.58,71.29 94.91,73.04C93.25,74.79 91.26,76.15 88.93,77.13C86.61,78.11 84.01,78.59 81.15,78.59C78.28,78.59 75.69,78.1 73.37,77.13C71.05,76.16 69.06,74.79 67.39,73.04C65.73,71.29 64.45,69.23 63.56,66.85C62.67,64.47 62.23,61.85 62.23,58.98C62.23,56.17 62.67,53.56 63.56,51.15C64.45,48.74 65.72,46.67 67.39,44.92C69.05,43.17 71.04,41.81 73.37,40.83C75.69,39.86 78.28,39.37 81.15,39.37C84.02,39.37 86.61,39.86 88.93,40.83C91.25,41.8 93.24,43.17 94.91,44.92C96.57,46.67 97.85,48.75 98.74,51.15C99.63,53.56 100.07,56.17 100.07,58.98C100.07,61.85 99.63,64.47 98.74,66.85ZM143.68,50.81C142.96,51.73 142.06,52.4 140.97,52.83C139.88,53.26 138.66,53.52 137.32,53.6C135.97,53.69 134.7,53.73 133.49,53.73L125.58,53.73L125.58,39.89L134.35,39.89C135.55,39.89 136.79,39.98 138.05,40.15C139.31,40.32 140.43,40.65 141.4,41.14C142.37,41.63 143.18,42.33 143.81,43.25C144.44,44.17 144.76,45.4 144.76,46.95C144.76,48.6 144.4,49.89 143.68,50.81Z", style: { fill: 'rgb(32,40,38)', fillRule: 'nonzero' } }))), h("span", { class: `min-w-0 overflow-hidden text-ellipsis whitespace-nowrap` }, this.label, this.acronym ? ' (' + this.acronym + ')' : '')));
}
getRorId() {
return this.value.split('/').pop() || '';
}
getOptimizedContent(content) {
if (this.contentMappings[content.toLowerCase()]) {
return this.contentMappings[content.toLowerCase()];
}
return content;
}
}
RORType.FORMAT_REGEX = new RegExp('^https?://ror.org/[0-9a-z]{9}$', 'i');
//# sourceMappingURL=RORType.js.map