Skip to content

Commit

Permalink
Add support to record form app for searching internal mint records (#…
Browse files Browse the repository at this point in the history
…2211)

* Refactor vocab service to use new vocab config structure

* Initial refactor of vocab controller and service for searching the new internal Mint records

* Refactor vocab controller and service for direct database search

* Add bruno test for database internal mint search

* Refactor vocab controller and service to search internal solr index

* Add bruno test for search mint internal solr index

* Refactor bruno tests that create mint harvest record and fix mint internal solr search

* Rename MintInternal routes and methods to Records

* Fix bad request error in solr query

* Fix bruno solr index test given solr schema not including mint mock test record fields

* Add lodash for result obejct mapping template processing

* Add source type query to field vocab component in dmp form app

* Add cotributor component example using new internal search index

* Add vocab query config model type class

* Refactor vocab controller and service to use vocab query config model type class

* Add result max rows property to vocab component
  • Loading branch information
alejandro-bulgaris-qcif authored Jun 5, 2024
1 parent 61e66cd commit f617227
Show file tree
Hide file tree
Showing 12 changed files with 500 additions and 34 deletions.
90 changes: 89 additions & 1 deletion angular-legacy/shared/form/field-vocab.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ export class VocabField extends FieldBase<any> {
public restrictToSelection: boolean;
public storeLabelOnly: boolean;
public provider: string;
public vocabQueryId: string;
public vocabQueryResultMaxRows: string;
public resultArrayProperty: string;
public unflattenFlag: boolean;
public exactMatchString: boolean;
Expand Down Expand Up @@ -93,6 +95,8 @@ export class VocabField extends FieldBase<any> {
this.restrictToSelection = _.isUndefined(options['restrictToSelection']) ? (_.isUndefined(options['forceLookupOnly']) ? false : options['forceLookupOnly']) : options['restrictToSelection'];
this.storeLabelOnly = options['storeLabelOnly'] ? options['storeLabelOnly'] : false;
this.provider = options['provider'] ? options['provider'] : '';
this.vocabQueryId = options['vocabQueryId'] ? options['vocabQueryId'] : '';
this.vocabQueryResultMaxRows = options['vocabQueryResultMaxRows'] ? options['vocabQueryResultMaxRows'] : '50';
this.resultArrayProperty = options['resultArrayProperty'] ? options['resultArrayProperty'] : '';
this.unflattenFlag = _.isUndefined(options['unflattenFlag']) ? false : options['unflattenFlag'];
this.exactMatchString = _.isUndefined(options['exactMatchString']) ? false : options['exactMatchString'];
Expand Down Expand Up @@ -214,8 +218,18 @@ export class VocabField extends FieldBase<any> {
this.titleFieldArr,
this.titleFieldDelim
);
} else if (this.sourceType == "query") {
const url = this.lookupService.getRedboxLookupServiceUrl(this.vocabQueryId);
this.dataService = new ReDBoxQueryLookupDataService(
url,
this.lookupService.http,
this.resultArrayProperty,
this.titleFieldName,
this.titleFieldArr,
this.titleFieldDelim,
this.vocabQueryResultMaxRows
);
}

}

public getTitle(data: any): string {
Expand Down Expand Up @@ -417,6 +431,76 @@ export function objectRequired(): ValidationErrors|null {

}

class ReDBoxQueryLookupDataService extends Subject<CompleterItem[]> implements CompleterData {
storedEventData:any = null;

constructor(private url: string,
private http: Http,
private arrayProperty: string,
private compositeTitleName: string,
private titleFieldArr: string[],
private titleFieldDelim: string,
private maxRows: string) {
super();
}

public search(term: string): void {
let that = this;
this.http.get(`${this.url}?search=${term}&start=0&rows=${this.maxRows}`).map((res: any, index: number) => {
let data = res.json();
let arrayPath = that.arrayProperty;
let itemArray = [];
if (_.isUndefined(arrayPath) || _.isEmpty(arrayPath)) {
itemArray = data;
} else {
itemArray = _.get(data, arrayPath);
}
// Convert the result to CompleterItem[]
let matches: CompleterItem[] = [];
_.each(itemArray, item => {
matches.push(this.convertToItem(item));
});

this.next(matches);
}).subscribe();
}

public cancel() {
// Handle cancel
}

public convertToItem(data: any): CompleterItem | null {
if (!data) {
return null;
}
let completerItem = {};
completerItem[this.compositeTitleName] = this.getTitle(data);
completerItem['originalObject'] = data;
return completerItem as CompleterItem;
}

getTitle(data: any): string {
let title = '';
if (data == null) {
if(this.storedEventData != null) {
data = _.clone(this.storedEventData);
}
this.storedEventData = null;
}

if(data){
if (_.isString(this.titleFieldDelim)) {
_.forEach(this.titleFieldArr, (titleFld: string) => {
const titleVal = _.get(data, titleFld);
if (titleVal) {
title = `${title}${_.isEmpty(title) ? '' : this.titleFieldDelim}${titleVal}`;
}
});
}
}
return title;
}
}

class ExternalLookupDataService extends Subject<CompleterItem[]> implements CompleterData {
storedEventData:any = null;
Expand Down Expand Up @@ -654,6 +738,10 @@ export class VocabFieldLookupService extends BaseService {
return `${this.brandingAndPortalUrl}/external/vocab/${provider}`;
}

getRedboxLookupServiceUrl(vocabQueryId: string) {
return `${this.brandingAndPortalUrl}/query/vocab/${vocabQueryId}`;
}


}

Expand Down
1 change: 1 addition & 0 deletions config/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ module.exports.routes = {
'get /:branding/:portal/vocab/:vocabId': 'VocabController.get',
'get /:branding/:portal/ands/vocab/resourceDetails': 'VocabController.rvaGetResourceDetails',
'get /:branding/:portal/mint/:mintSourceType': 'VocabController.getMint',
'get /:branding/:portal/query/vocab/:queryId': 'VocabController.getRecords',
'post /:branding/:portal/external/vocab/:provider': {
controller: 'VocabController',
action: 'searchExternalService',
Expand Down
30 changes: 29 additions & 1 deletion config/vocab.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,41 @@ module.exports.vocab = {
rootUrl: 'http://vocabs.ardc.edu.au/repository/api/lda/',
conceptUri: 'concept.json?_view=all',
cacheExpiry: 31536000, // one year in seconds
providers: {
external: {
geonames: {
method: 'get',
url: "http://mint:9001/geonames/search?func=search&q=${query}&format=json",
options: {

}
}
},
queries: {
party: {
querySource: 'solr',
searchQuery: {
searchCore: 'default',
baseQuery : 'metaMetadata_type:rdmp'
},
queryField: {
property: 'title',
type: 'text'
},
resultObjectMapping: {
fullName: '<%= _.get(record,"contributor_ci.text_full_name","") %>',
email: '<%= _.get(record,"contributor_ci.email","") %>',
orcid: '<%= _.get(record,"contributor_ci.orcid","") %>'
}
},
rdmp: {
querySource: 'database',
databaseQuery: {
queryName: 'listRDMPRecords',
},
queryField: {
property: 'title',
type: 'text'
}
}
}
};
29 changes: 29 additions & 0 deletions core/src/model/config/VocabQueryConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
export class VocabQueryConfig {
querySource: VocabQuerySource = VocabQuerySource.solr;
databaseQuery: VocabDatabaseQueryConfig;
searchQuery: VocabSolrQueryConfig;
queryField: VocabQueryFieldConfig;
resultObjectMapping: {
[key: string]: string;
};
}

export enum VocabQuerySource {
solr = 'solr',
database = 'database'
}

export class VocabDatabaseQueryConfig {
queryName: string;
}

export class VocabSolrQueryConfig {
baseQuery: string;
searchCore: string = 'default';
}

export class VocabQueryFieldConfig {
property: string;
type: string;
}

3 changes: 2 additions & 1 deletion core/src/model/config/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './SolrConfig';
export * from './ReportConfig';
export * from './ReportConfig';
export * from './VocabQueryConfig';
92 changes: 91 additions & 1 deletion form-config/default-1.0-draft.js
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,8 @@ module.exports = {
definition: {
id: "people",
label: "@dmpt-people-tab",
fields: [{
fields: [
{
class: 'ContributorField',
showHeader: true,
showRole: false,
Expand Down Expand Up @@ -630,6 +631,95 @@ module.exports = {
}
}
}
},
{
class: 'ContributorField',
showHeader: true,
showRole: false,
definition: {
name: 'contributor_ci_internal',
required: false,
label: 'People lookup in index based of record title for contributor component',
help: "Upon typing the string will be matched to title field and will show the primary investigator of each record",
role: "@dmpt-people-tab-ci-role",
freeText: false,
forceLookupOnly: true,
vocabQueryId: 'party',
sourceType: 'query',
fieldNames: [
{
'text_full_name': 'fullName'
}, {
'email': 'email'
}, {
'orcid': 'orcid'
}
],
searchFields: 'title',
titleFieldArr: ['fullName'],
titleFieldDelim: '',
nameColHdr: '@dmpt-people-tab-name-hdr',
emailColHdr: '@dmpt-people-tab-email-hdr',
orcidColHdr: '@dmpt-people-tab-orcid-hdr',
validation_required_name: '@dmpt-people-tab-validation-name-required',
validation_required_email: '@dmpt-people-tab-validation-email-required',
validation_invalid_email: '@dmpt-people-tab-validation-email-invalid',
publish: {
onValueUpdate: {
modelEventSource: 'valueChanges'
}
}
}
},
{
class: 'RepeatableContainer',
compClass: 'RepeatableVocabComponent',
definition: {
name: 'people-lookup-in-index-based-of-record-title',
label: "People lookup in index based of record title",
help: "Upon typing the string will be matched to title field and will show the primary investigator of each record",
forceClone: ['lookupService', 'completerService'],
fields: [
{
class: 'VocabField',
definition: {
disableEditAfterSelect: false,
vocabQueryId: 'party',
vocabQueryResultMaxRows: '30',
sourceType: 'query',
titleFieldName: 'title',
titleFieldArr: ['fullName','email','orcid'],
fieldNames:['fullName','email','orcid'],
stringLabelToField: 'fullName'
}
}
]
}
},
{
class: 'RepeatableContainer',
compClass: 'RepeatableVocabComponent',
definition: {
name: 'people-lookup-in-db-based-of-record-title',
label: "People lookup in database based of record title",
help: "Upon typing the string will be matched to title field and will show the primary investigator of each record",
forceClone: ['lookupService', 'completerService'],
fields: [
{
class: 'VocabField',
definition: {
disableEditAfterSelect: false,
vocabQueryId: 'rdmp',
sourceType: 'query',
titleFieldName: 'title',
titleFieldArr: ['metadata.contributor_ci'],
fieldNames:['metadata.contributor_ci'],
stringLabelToField: 'metadata.contributor_ci',
resultArrayProperty: 'records'
}
}
]
}
}
]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ body:json {
"metadata": {
"data": {
"ID": "s123456",
"GIVEN_NAME": "Andrew",
"GIVEN_NAME": "Ant",
"OTHER_NAMES": "",
"FAMILY_NAME": "S",
"PREF_NAME": "",
Expand All @@ -36,14 +36,29 @@ body:json {
"PERSONAL_HOMEPAGE": "",
"STAFF_PROFILE_HOMEPAGE": "",
"DESCRIPTION": "",
"RESEARCH_ELEMENTS_USER_ID": "12345678"
"RESEARCH_ELEMENTS_USER_ID": "12345678",
"title": "Mock mint record type rdmp integration test",
"contributor_ci": {
"text_full_name": "Prof Ant Season",
"email": "[email protected]",
"orcid": "http://orcid.org/0000-0000-0000-000"
},
"contributor_data_manager": {
"text_full_name": "Prof Ant Season",
"email": "[email protected]",
"orcid": "http://orcid.org/0000-0000-0000-000"
}
}
}
}
]
}
}

assert {
res.body[0].harvestId: eq s123456
}

tests {

test("Status code is 200", function () {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ body:json {
"recordRequest": {
"metadata": {
"ID": "s123456",
"GIVEN_NAME": "Andrew",
"GIVEN_NAME": "Ant",
"OTHER_NAMES": "",
"FAMILY_NAME": "S",
"PREF_NAME": "",
Expand All @@ -36,7 +36,18 @@ body:json {
"PERSONAL_HOMEPAGE": "",
"STAFF_PROFILE_HOMEPAGE": "",
"DESCRIPTION": "",
"RESEARCH_ELEMENTS_USER_ID": "12345678"
"RESEARCH_ELEMENTS_USER_ID": "12345678",
"title": "Mock mint record type rdmp integration test",
"contributor_ci": {
"text_full_name": "Prof Ant Season",
"email": "[email protected]",
"orcid": "http://orcid.org/0000-0000-0000-000"
},
"contributor_data_manager": {
"text_full_name": "Prof Ant Season",
"email": "[email protected]",
"orcid": "http://orcid.org/0000-0000-0000-000"
}
}
}
}
Expand All @@ -58,7 +69,9 @@ tests {
test("Test harvestId exists and value is as expected", function () {
var jsonData = res.getBody();
expect(jsonData[0]).to.have.property('harvestId');
expect(jsonData[0]).to.have.property('message');
expect(jsonData[0].harvestId).to.equal('s123456');
expect(jsonData[0].message).to.equal('Record updated successfully');
});

}
Loading

0 comments on commit f617227

Please sign in to comment.