Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions backend/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -1281,6 +1281,47 @@ def query_SQL_endpoint(connection, query):
except Error as e:
app.logger.error(f"SQL query failed: {str(e)}")

def fetch_institutions_designations(institution_name):
"""
Returns a dictionary with the following keys:
institution_name: String
msi_designation: String
is_r1: Boolean
is_r2: Boolean
is_hsi: Boolean
is_pbi: Boolean
is_tcu: Boolean
is_annh: Boolean
is_hbcu: Boolean
is_nasnti: Boolean
is_non_msi: Boolean
is_aanapisi: Boolean
"""
query = """SELECT get_institutions_designations(%s);"""
app.logger.debug(f"Executing SQL query to fetch institution designations for: {institution_name}")
results = execute_query(query, (institution_name,))
if results:
app.logger.debug(f"Fetched the following institution designations for {institution_name}: {results[0][0]['data'][0]}")
return results[0][0]['data'][0]
app.logger.warning(f"No institution designations found for {institution_name}")
return {}

@app.route('/institutions-designations', methods=['POST'])
def get_institutions_designations():
data = request.json
if not data or 'institution_name' not in data:
app.logger.warning(f"Failed to get the institution name")
return {}

institution_name = data['institution_name']
app.logger.debug(f"Processing institution designations for: {institution_name}")
result = fetch_institutions_designations(institution_name)

if result:
return jsonify(result)
else:
return {}

@app.route('/autofill-institutions', methods=['POST'])
def autofill_institutions():
"""
Expand Down
11 changes: 11 additions & 0 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"react-router-dom": "^6.23.1",
"react-scripts": "5.0.1",
"react-use": "^17.5.0",
"schema-dts": "^1.1.2",
"typescript": "^4.9.5",
"web-vitals": "^2.1.4",
"yup": "^1.4.0"
Expand Down
209 changes: 149 additions & 60 deletions frontend/src/components/InstitutionMetadata.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,81 +2,170 @@ import React from 'react';

import { Box, Flex, Text } from '@chakra-ui/react';

import { ResearchDataInterface } from '../utils/interfaces';
import { ResearchDataInterface, InstitutionDesignations } from '../utils/interfaces';

import { Organization, Thing, WithContext } from 'schema-dts';

export function JsonLd<T extends Thing>(json: WithContext<T>): string {
return `<script type="application/ld+json">
${JSON.stringify(json)}
</script>`;
}

const InstitutionMetadata = ({
data,
setTopic,
institutionDesignations,
}: {
data: ResearchDataInterface;
institutionDesignations: InstitutionDesignations;
setTopic: React.Dispatch<React.SetStateAction<string>>;
}) => {
const memberOf = [];
if (data?.is_hbcu) {
memberOf.push({
"@type": "Organization" as const,
"name": "Historically Black Colleges and Universities"
});
}
if (institutionDesignations?.is_r1) {
memberOf.push({
"@type": "Organization" as const,
"name": "R1 Doctoral Universities"
});
}
if (institutionDesignations?.is_r2) {
memberOf.push({
"@type": "Organization" as const,
"name": "R2 Doctoral Universities"
});
}
if (institutionDesignations?.is_tcu) {
memberOf.push({
"@type": "Organization" as const,
"name": "Tribal Colleges and Universities"
});
}
if (institutionDesignations?.is_non_msi) {
memberOf.push({
"@type": "Organization" as const,
"name": "Non Minority Serving Institutions"
});
}
if (institutionDesignations?.is_aanapisi) {
memberOf.push({
"@type": "Organization" as const,
"name": "Asian American Native American Pacific Islander Serving Institutions"
});
}
if (institutionDesignations?.is_pbi) {
memberOf.push({
"@type": "Organization" as const,
"name": "Predominantly Black Institutions"
});
}
if (institutionDesignations?.is_hsi) {
memberOf.push({
"@type": "Organization" as const,
"name": "Hispanic Serving Institutions"
});
}
if (institutionDesignations?.is_nasnti) {
memberOf.push({
"@type": "Organization" as const,
"name": "Native American-Serving Non-Tribal Institutions"
});
}
if (institutionDesignations?.is_aanh) {
memberOf.push({
"@type": "Organization" as const,
"name": "Alaska Native and Native Hawaiian Serving Institutions"
});
}

const structuredData: WithContext<Organization> = {
"@context": "https://schema.org",
"@type": "Organization",
"name": data?.institution_name,
"url": data?.institution_url,
"sameAs": [
data?.open_alex_link,
data?.ror_link,
].filter((url): url is string => url !== null && url !== undefined),
...(memberOf.length > 0 && { memberOf })
// TODO: Add more properties
};
return (
<Flex
<Box>
<div
dangerouslySetInnerHTML={{ __html: JsonLd(structuredData) }}
/>
<Flex
display={{base: 'block', lg: 'flex'}}
justifyContent={'space-between'}
mt='0.6rem'
className='list-map'
>
<Box w={{lg: '34%'}}>
<button className='topButton'>List Map</button>
<h2>
{data?.institution_name}
{data?.is_hbcu ? ' - HBCU' : ''}
</h2>
<a
target='_blank'
rel='noreferrer'
className='ror'
href={data?.institution_url}
>
{data?.institution_url}
</a>
<p>Total {data?.author_count} authors</p>
<p>Total {data?.works_count} works</p>
<p>Total {data?.cited_count} citations</p>
<a target='_blank' rel='noreferrer' href={data?.open_alex_link}>
View on OpenAlex
</a>
<a
target='_blank'
rel='noreferrer'
className='ror'
href={data?.ror_link}
>
RORID -{' '}
{data?.ror_link?.split('/')[data?.ror_link?.split('/')?.length - 1]}
</a>
</Box>
<Box w={{lg: '64%'}} mt={{base: '.9rem', lg: 0}}>
<Box display={'flex'} justifyContent={'space-between'}>
<Text fontSize={'18px'} fontWeight={600} w='72%'>
Topic
</Text>
<Text fontSize={'18px'} fontWeight={600} w='26%'>
No of people
</Text>
>
<Box w={{lg: '34%'}}>
<button className='topButton'>List Map</button>
<h2>
{data?.institution_name}
{data?.is_hbcu ? ' - HBCU' : ''}
</h2>
<a
target='_blank'
rel='noreferrer'
className='ror'
href={data?.institution_url}
>
{data?.institution_url}
</a>
<p>Total {data?.author_count} authors</p>
<p>Total {data?.works_count} works</p>
<p>Total {data?.cited_count} citations</p>
<a target='_blank' rel='noreferrer' href={data?.open_alex_link}>
View on OpenAlex
</a>
<a
target='_blank'
rel='noreferrer'
className='ror'
href={data?.ror_link}
>
RORID -{' '}
{data?.ror_link?.split('/')[data?.ror_link?.split('/')?.length - 1]}
</a>
</Box>
<Box mt='.5rem'>
{data?.topics?.map((topic) => (
<Flex justifyContent={'space-between'}>
<Text
fontSize='14px'
w='72%'
onClick={() => setTopic(topic[0])}
textDecoration={'underline'}
cursor='pointer'
>
{topic[0]}
</Text>
<Text fontSize='14px' w='26%'>
{topic[1]}
</Text>
</Flex>
))}
<Box w={{lg: '64%'}} mt={{base: '.9rem', lg: 0}}>
<Box display={'flex'} justifyContent={'space-between'}>
<Text fontSize={'18px'} fontWeight={600} w='72%'>
Topic
</Text>
<Text fontSize={'18px'} fontWeight={600} w='26%'>
No of people
</Text>
</Box>
<Box mt='.5rem'>
{data?.topics?.map((topic) => (
<Flex justifyContent={'space-between'}>
<Text
fontSize='14px'
w='72%'
onClick={() => setTopic(topic[0])}
textDecoration={'underline'}
cursor='pointer'
>
{topic[0]}
</Text>
<Text fontSize='14px' w='26%'>
{topic[1]}
</Text>
</Flex>
))}
</Box>
</Box>
</Box>
</Flex>
</Flex>
</Box>
);
};

Expand Down
27 changes: 24 additions & 3 deletions frontend/src/pages/Search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ import Suggested from '../components/Suggested';
import TopicInstitutionMetadata from '../components/TopicInstitutionMetadata';
import TopicMetadata from '../components/TopicMetadata';
import TopicResearcherMetadata from '../components/TopicResearcherMetadata';
import {baseUrl, handleAutofill, initialValue} from '../utils/constants';
import {ResearchDataInterface, SearchType} from '../utils/interfaces';
import { baseUrl, handleAutofill, initialValue, initialInstitutionDesignationsValues } from '../utils/constants';
import { ResearchDataInterface, SearchType, InstitutionDesignations } from '../utils/interfaces';

const Search = () => {
let [searchParams] = useSearchParams();
Expand All @@ -34,6 +34,7 @@ const Search = () => {
const [researcherType, setResearcherType] = useState(researcher || '');
const [researcherType2, setResearcherType2] = useState('');
const [data, setData] = useState<ResearchDataInterface>(initialValue);
const [institutionDesignations, setInstitutionDesignations] = useState<InstitutionDesignations[]>([initialInstitutionDesignationsValues]);
const [isLoading, setIsLoading] = useState(false);
const [isAddOrgChecked, setIsAddOrgChecked] = useState(false);
const [orgList, setOrgList] = useState<File | null>(null);
Expand Down Expand Up @@ -198,10 +199,29 @@ const Search = () => {
});
};

const institutionDesignationSearch = (universityName: string) => {
fetch(`${baseUrl}/institutions-designations`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ institution_name: universityName }),
})
.then(res => res.json())
.then((data) => {
console.log(data);
setInstitutionDesignations(data);
})
.catch((error) => {
console.log(error);
setInstitutionDesignations([initialInstitutionDesignationsValues]);
setIsLoading(false);
});
}

const handleSearch = () => {
setIsLoading(true);
if (topicType && universityName && researcherType) {
sendSearchRequest('all-three-search');
institutionDesignationSearch(universityName);
} else if (
(topicType && researcherType) ||
(researcherType && universityName) ||
Expand All @@ -221,6 +241,7 @@ const Search = () => {
? 'institution'
: 'researcher';
sendSearchRequest(search);
institutionDesignationSearch(universityName);
} else {
fetch(`${baseUrl}/get-default-graph`, {
method: 'POST',
Expand Down Expand Up @@ -518,7 +539,7 @@ const Search = () => {
) : isNetworkMap === 'list' ? (
<div>
{data?.search === 'institution' ? (
<InstitutionMetadata data={data} setTopic={setTopicType} />
<InstitutionMetadata data={data} setTopic={setTopicType} institutionDesignations={institutionDesignations[0]} />
) : data?.search === 'topic' ? (
<TopicMetadata data={data} setInstitution={setUniversityName} />
) : data?.search === 'researcher' ? (
Expand Down
Loading