Skip to content
Snippets Groups Projects
Commit cd2eb16c authored by Luciano Frizzera's avatar Luciano Frizzera
Browse files

Merge branch 'gnd-sample-implementation' into 'main'

Example implementation of gnd lookup

See merge request calincs/cwrc/leaf-writer/leaf-writer!50
parents f0a690ce 9b5c6625
No related branches found
No related tags found
No related merge requests found
......@@ -13,7 +13,7 @@ export type NamedEntityType =
| 'title'
| 'thing'
| 'concept';
export type Authority = 'dbpedia' | 'geonames' | 'getty' | 'lgpn' | 'viaf' | 'wikidata';
export type Authority = 'dbpedia' | 'geonames' | 'getty' | 'lgpn' | 'viaf' | 'wikidata' | 'gnd';
export type LookupService = 'LINCS' | 'internal' | 'custom';
export interface AuthorityService {
......
......@@ -8,6 +8,7 @@ import {
lgpnFind,
viafFind,
wikidataFind,
gndFind
} from '../lookups/services';
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
......@@ -142,6 +143,14 @@ export const state: EditorStateType = {
name: 'LGPN',
priority: 5,
lookupService: 'internal',
},gnd: {
enabled: true,
entities: { person: true, place: true, organization: true, title: true, rs: true },
find: gndFind,
id: 'gnd',
name: 'GND',
priority: 5,
lookupService: 'internal',
},
},
};
import axios from 'axios';
import type { AuthorityLookupResult } from '../../../dialogs/entityLookups/types';
import { log } from './../../../utilities';
import { type AuthorityLookupParams } from './type';
type NamedEntityType = 'Person' | 'PlaceOrGeographicName' | 'CorporateBody' | 'Work' | 'SubjectHeading';
interface Doc {
id: string;
preferredName: string;
biographicalOrHistoricalInformation: string[];
}
interface GNDResults {
member: Doc[];
}
const baseURL = 'https://lobid.org/gnd';
const FORMAT = 'json';
const MAX_HITS = 25; // default: 100; but it breaks at 45+
const timeout = 3_000;
const axiosInstance = axios.create({ baseURL, timeout });
export const find = async ({ query, type }: AuthorityLookupParams) => {
if (type === 'person') return await callGND(query, 'Person');
if (type === 'place') return await callGND(query, 'PlaceOrGeographicName');
if (type === 'organization') return await callGND(query, 'CorporateBody');
if (type === 'title') return await callGND(query, 'Work');
if (type === 'rs') return await callGND(query, 'SubjectHeading');
if (type === 'thing') return await callGND(query, 'SubjectHeading');
if (type === 'concept') return await callGND(query, 'SubjectHeading');
log.warn(`GND: Entity type ${type} invalid`);
};
const callGND = async (query: string, type: NamedEntityType) => {
const encodeQueryString = encodeURIComponent(query);
const params = new URLSearchParams({
q: query,
filter: "type:" + type,
format: FORMAT,
size: MAX_HITS.toString(),
});
const urlQuery = `search?${params}`;
const response = await axiosInstance.get<GNDResults>(urlQuery).catch((error) => {
return {
status: 500,
statusText: `The request exeeded the timeout (${timeout})`,
data: undefined,
};
});
if (response.status >= 400) {
const errorMsg = `
Something wrong with the call to lobid-gnd, possibly a problem with the network or the server.
HTTP error: ${response.statusText}
`;
log.warn(errorMsg);
return [];
}
const data = response.data;
if (!data) return [];
// const mapResponse = responseJson.docs.map(
const results: AuthorityLookupResult[] = data.member.map(( entry:Doc ) => {
//? assuming first instance of description, name and uri;
const description = entry.biographicalOrHistoricalInformation?.[0] ?? 'No description available';
const name = entry.preferredName ?? '';
const uri = entry.id;
return { description, id: uri ?? '', name, repository: 'gnd', query, type, uri: uri ?? '' };
});
return results;
};
......@@ -4,3 +4,4 @@ export { find as gettyFind } from './getty';
export { find as lgpnFind } from './lgpn';
export { find as viafFind } from './viaf';
export { find as wikidataFind } from './wikidata';
export { find as gndFind} from './gnd';
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment