Skip to content

Commit fa56e4b

Browse files
authored
Merge pull request #3357 from SeedCompany/add-ethnologue-to-search
Expose Ethnologue values to Global Search
2 parents c241f30 + 070aad6 commit fa56e4b

6 files changed

+46
-1
lines changed

src/components/language/language.gel.repository.ts

+6
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,10 @@ export class LanguageGelRepository
4949
const query = e.op('exists', lang.firstScriptureEngagement);
5050
return await this.db.run(query);
5151
}
52+
53+
async readOneByEth(ethnologueId: ID) {
54+
const ethnologue = e.cast(e.Ethnologue.Language, e.uuid(ethnologueId));
55+
const query = e.select(ethnologue.language, this.hydrate);
56+
return await this.db.run(query);
57+
}
5258
}

src/components/language/language.repository.ts

+18
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
DuplicateException,
1313
ID,
1414
labelForView,
15+
NotFoundException,
1516
ObjectView,
1617
ServerException,
1718
Session,
@@ -149,6 +150,23 @@ export class LanguageRepository extends DtoRepository<
149150
.run();
150151
}
151152

153+
async readOneByEth(ethnologueId: ID, session: Session) {
154+
const dto = await this.db
155+
.query()
156+
.match([
157+
node('eth', 'EthnologueLanguage', { id: ethnologueId }),
158+
relation('in', '', 'ethnologue', ACTIVE),
159+
node('node', 'Language'),
160+
])
161+
.apply(this.hydrate(session))
162+
.map('dto')
163+
.first();
164+
if (!dto) {
165+
throw new NotFoundException('No Language exists for this Ethnologue id');
166+
}
167+
return dto;
168+
}
169+
152170
protected hydrate(session: Session, view?: ObjectView) {
153171
return (query: Query) =>
154172
query

src/components/language/language.service.ts

+5
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ export class LanguageService {
6565
return languages.map((dto) => this.secure(dto, session));
6666
}
6767

68+
async readOneByEthId(ethnologueId: ID, session: Session) {
69+
const dto = await this.repo.readOneByEth(ethnologueId, session);
70+
return this.secure(dto, session);
71+
}
72+
6873
private secure(dto: UnsecuredDto<Language>, session: Session) {
6974
const ethnologue = this.ethnologueLanguageService.secure(
7075
dto.ethnologue,

src/components/search/dto/search-results.dto.ts

+1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ const publicSearchable = {
6464
// since they are expected to be used only for internal use.
6565
const privateSearchable = {
6666
PartnerByOrg: Partner,
67+
LanguageByEth: Language,
6768
} as const;
6869

6970
// Expand this to add more search types, but not result types.

src/components/search/search.module.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import { Module } from '@nestjs/common';
22
import { AuthorizationModule } from '../authorization/authorization.module';
3+
import { LanguageModule } from '../language/language.module';
34
import { PartnerModule } from '../partner/partner.module';
45
import { SearchRepository } from './search.repository';
56
import { SearchResolver } from './search.resolver';
67
import { SearchService } from './search.service';
78

89
@Module({
9-
imports: [PartnerModule, AuthorizationModule],
10+
imports: [PartnerModule, AuthorizationModule, LanguageModule],
1011
providers: [SearchResolver, SearchService, SearchRepository],
1112
exports: [SearchService],
1213
})

src/components/search/search.service.ts

+14
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { ValueOf } from 'type-fest';
55
import { ID, NotFoundException, ServerException, Session } from '~/common';
66
import { ResourceMap, ResourceResolver, ResourcesHost } from '~/core/resources';
77
import { Privileges } from '../authorization';
8+
import { LanguageService } from '../language';
89
import { PartnerService } from '../partner';
910
import {
1011
SearchableMap,
@@ -38,6 +39,10 @@ export class SearchService {
3839
...(await this.partners.readOnePartnerByOrgId(...args)),
3940
__typename: 'Partner',
4041
}),
42+
LanguageByEth: async (...args) => ({
43+
...(await this.languages.readOneByEthId(...args)),
44+
__typename: 'Language',
45+
}),
4146
};
4247
/* eslint-enable @typescript-eslint/naming-convention */
4348

@@ -46,6 +51,7 @@ export class SearchService {
4651
private readonly resourceResolver: ResourceResolver,
4752
private readonly privileges: Privileges,
4853
private readonly partners: PartnerService,
54+
private readonly languages: LanguageService,
4955
private readonly repo: SearchRepository,
5056
) {}
5157

@@ -70,6 +76,7 @@ export class SearchService {
7076
const resourceTypes = new Set<keyof ResourceMap>(types);
7177
// Include dependency types for types that have identifiers in sub-resources.
7278
types.has('Partner') && resourceTypes.add('Organization');
79+
types.has('Language') && resourceTypes.add('EthnologueLanguage');
7380

7481
// Search for nodes based on input, only returning their id and "type"
7582
// which is based on their first valid search label.
@@ -106,6 +113,13 @@ export class SearchService {
106113
: []),
107114
];
108115
}
116+
if (result.type === 'EthnologueLanguage') {
117+
return {
118+
type: 'LanguageByEth',
119+
id: result.id,
120+
matchedProps: ['ethnologue'],
121+
} as const;
122+
}
109123

110124
// This is a sanity/type check.
111125
// Functionally, we shouldn't have any results at this point that

0 commit comments

Comments
 (0)