Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement new features and improvements on the fundings-details dynamic page #191

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from
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
42 changes: 37 additions & 5 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

import details_page
from sources.gepris import org_details
from sources.cordis import project_details_cordis
import utils
import deduplicator

Expand Down Expand Up @@ -164,7 +165,7 @@ def organization_details(organization_id, organization_name):
else:
response.set_cookie('search-session', request.cookies['session'])"""

# Call the org_details function from the gepris module to fetch organization details by id
# Call the org_details function in the gepris module to fetch organization details
organization, sub_organization, sub_project = org_details(organization_id, organization_name)

if organization or sub_organization or sub_project:
Expand Down Expand Up @@ -194,17 +195,48 @@ def events_details():
return response


@app.route('/fundings-details')
def fundings_details():
response = make_response(render_template('fundings-details.html'))
@app.route('/fundings-details/<string:project_source>/<string:project_id>', methods=['GET'])
def fundings_details(project_source, project_id):

"""response = make_response(render_template('fundings-details.html'))
# Set search-session cookie to the session cookie value of the first visit
if request.cookies.get('search-session') is None:
if request.cookies.get('session') is None:
response.set_cookie('search-session', str(uuid.uuid4()))
else:
response.set_cookie('search-session', request.cookies['session'])

return response
return response"""
try:

if project_source == "CORDIS":
# Call the project_details function in the CORDIS module to fetch project details
project = project_details_cordis(project_id)

if project:
# Render the fundings-details.html template
return render_template('fundings-details.html', project = project)
else:
# Handle the case where project details are not found (e.g., return a 404 page)
return render_template('error.html',error_message='Project details not found.')

"""elif project_source == "GEPRIS":

# Call the project_details function from the GEPRIS module to fetch project details by id
project = project_details_gepris(project_id)

if project:
# Render the fundings-details.html template
return render_template('fundings-details.html', project = project)
else:
# Handle the case where project details are not found (e.g., return a 404 page)
return render_template('error.html',error_message='Project details not found.')"""

except ValueError as ve:
return render_template('error.html', error_message= str(ve))
except Exception as e:
return render_template('error.html', error_message='An error occurred: ' + str(e))



@app.route('/details', methods=['POST', 'GET'])
Expand Down
44 changes: 41 additions & 3 deletions objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,32 @@ class thing:
@dataclass
class Organization(thing):
address: str = ""
aggregateRating: str = ""
areaServed: str = ""
award: str = ""
brand: str = ""
contactPoint: str = ""
dissolutionDate: str = ""
event: str = ""
email: str = ""
founder: str = ""
funding: str = ""
foundingDate: str = ""
foundingLocation: str = ""
globalLocationNumber: str = ""
hasCredential: str = ""
leiCode: str = ""
legalName: str = ""
location: str = ""
logo: str = "" # url
member: str = ""
memberOf: str = ""
nonprofitStatus: str = ""
numberOfEmployees: str = ""
parentOrganization: str = ""
subOrganization: str = ""
taxID: str = ""
review: str = ""
telephone: str = ""
foundingDate: str = ""
keywords: List[str] = field(default_factory=list)
Expand Down Expand Up @@ -99,19 +120,36 @@ class Dataset(CreativeWork):

#The 'Project' is a new addition to schema.org, and as of now, there are no defined properties for it
@dataclass
class Project(Organization):
class Project(Organization):
abstract: str = ""
acronym: str = ""
coordinatorOrganization: str = ""
description: str = ""
dateStart: str = ""
dateEnd: str = ""
dateLastModified : str = ""
abstract: str = ""
duration: str = ""
inLanguage: List[str] = field(default_factory=list)
availableLanguages: List[str] = field(default_factory=list)
availableLanguage: List[str] = field(default_factory=list)
objective: str = ""
status: str = ""
author: List[Union[Organization, Person]] = field(default_factory=list)
funder: List[Union[
Organization, Person]] = field(
default_factory=list) # Organization | Person # we can use pipe operator for Union in Python >= 3.10
totalCost: str =""
doi: str = ""



def __post_init__(self):
# Loop through the fields
for field in fields(self):
# If there is a default and the value of the field is none we can assign a value
if not isinstance(field.default, dataclasses._MISSING_TYPE) and getattr(self, field.name) is None:
setattr(self, field.name, field.default)


@dataclass
class SoftwareApplication(CreativeWork):
distribution: str = ""
Expand Down
123 changes: 116 additions & 7 deletions sources/cordis.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import logging
import os
import utils
import xml.etree.ElementTree as ET

logger = logging.getLogger('nfdi_search_engine')

Expand Down Expand Up @@ -76,19 +77,19 @@ def search(search_term, results):
if isinstance(languages_available, list):
# If languages_available is a list, add each language to fundings.languages_available
for language in languages_available:
fundings.availableLanguages.append(language)
fundings.availableLanguage.append(language)
else:
# If languages is a single string, directly append it to fundings.inLanguage
fundings.availableLanguages.append(languages_available)
fundings.availableLanguage.append(languages_available)

else:
# Handle the case when `hit` is not a dictionary
fundings = Project()
fundings.identifier = ''
fundings.name = ''
fundings.url = ''
fundings.date_start = ''
fundings.date_end = ''
fundings.dateStart = ''
fundings.dateEnd = ''
fundings.description = ''

except KeyError as e:
Expand All @@ -98,8 +99,8 @@ def search(search_term, results):
fundings.identifier = None
fundings.name = None
fundings.url = None
fundings.date_start = None
fundings.date_end = None
fundings.dateStart = None
fundings.dateEnd = None
fundings.description = None


Expand All @@ -117,4 +118,112 @@ def search(search_term, results):
results['timedout_sources'].append('CORDIS')

except Exception as ex:
logger.error(f'Exception: {str(ex)}')
logger.error(f'Exception: {str(ex)}')


#This function retrive deatials information of project from CORDIS
def project_details_cordis(project_id):

try:
# the URL of the XML data
url = f"https://cordis.europa.eu/project/id/{project_id}?format=xml"

# Send a GET request to the URL
response = requests.get(url)

# Check if the request was successful
response.raise_for_status()

# Parse the XML content and define namespaces
namespaces = {"ns": "http://cordis.europa.eu"}
root = ET.fromstring(response.content)

# Create a Project instance
project = Project()

# Extract project information using namespaces
project.source = 'CORDIS'
project.identifier = root.find(".//ns:id", namespaces).text if root.find(".//ns:id", namespaces) is not None else None
project.acronym = root.find(".//ns:acronym", namespaces).text if root.find(".//ns:acronym", namespaces) is not None else None
project.name = root.find(".//ns:title", namespaces).text if root.find(".//ns:title", namespaces) is not None else None
project.abstract = root.find(".//ns:teaser", namespaces).text if root.find(".//ns:teaser", namespaces) is not None else None
project.objective = root.find(".//ns:objective", namespaces).text if root.find(".//ns:objective", namespaces) is not None else None
project.totalCost = root.find(".//ns:totalCost", namespaces).text if root.find(".//ns:totalCost", namespaces) is not None else None
project.dateStart = root.find(".//ns:startDate", namespaces).text if root.find(".//ns:startDate", namespaces) is not None else None
project.dateEnd = root.find(".//ns:endDate", namespaces).text if root.find(".//ns:endDate", namespaces) is not None else None
project.duration = root.find(".//ns:duration", namespaces).text if root.find(".//ns:duration", namespaces) is not None else None
project.status = root.find(".//ns:status", namespaces).text if root.find(".//ns:status", namespaces) is not None else None
project.keywords = root.find(".//ns:keywords", namespaces).text if root.find(".//ns:keywords", namespaces) is not None else None
project.doi = root.find(".//ns:grantDoi", namespaces).text if root.find(".//ns:grantDoi", namespaces) is not None else None
project.url = f'https://cordis.europa.eu/project/id/{project_id}'
project.inLanguage = root.find(".//ns:language", namespaces).text if root.find(".//ns:language", namespaces) is not None else None

# Find the category element with the specified attributes
category_element = root.find(".//ns:category[@classification='source'][@type='isProvidedBy']", namespaces)

if category_element is not None:
available_languages_element = category_element.find(".//ns:availableLanguages", namespaces)
if available_languages_element is not None:
project.availableLanguage = available_languages_element.text if available_languages_element is not None else None
else:
project.availableLanguage = None
else:
project.availableLanguage = None

# Find all organization elements with type="coordinator"
coordinator_organizations = root.findall(".//ns:organization[@type='coordinator']", namespaces)

coordinator_orgs_list = []

for coordinator_organization in coordinator_organizations:
coordinator_org = coordinator_organization.find(".//ns:legalName", namespaces)
if coordinator_org is not None:
coordinator_orgs_list.append(coordinator_org.text)
else:
coordinator_orgs_list.append(None)

project.coordinatorOrganization = coordinator_orgs_list

# Find the Sponsored by or Funded by program or organizaion
programme_element = root.find(".//ns:programme[@type='relatedLegalBasis']", namespaces)
if programme_element is not None:
title_element = programme_element.find(".//ns:title", namespaces)
if title_element is not None:
project.funder = title_element.text
else:
project.funder = None
else:
project.funder = None

# Find the region element
region_element = root.find(".//ns:regions/ns:region[@type='relatedNutsCode']", namespaces)

region_hierarchy = []

while region_element is not None:
region_name_element = region_element.find(".//ns:name", namespaces)
if region_name_element is not None:
region_name = region_name_element.text
region_hierarchy.insert(0, region_name)
parent_region_element = region_element.find(".//ns:parents/ns:region", namespaces)
if parent_region_element is not None:
region_element = parent_region_element
else:
region_element = None

if region_hierarchy:
complete_region = ' '.join(region_hierarchy)
project.region = complete_region # region obj/property should be defined according to schema.org
else:
project.region = None

return project

except requests.exceptions.RequestException as e:
print("Request Exception:", e)
except ET.ElementTree.ParseError as e:
print("XML Parse Error:", e)
except Exception as e:
print("An error occurred:", e)

return None
2 changes: 2 additions & 0 deletions templates/components/fundings.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
<div class="row">
<div class="col-11 fs-6">
<div class="row mb-2">
<div class="col-lg-12 fs-5">
<a class="text-secondary fw-bold" href='/fundings-details/{{ fundings.source }}/{{ fundings.identifier }}' target='_blank'>
<div class="col-12 fs-5">
<a class="text-secondary fw-bold" href='/fundings-details' target='_blank'>
{{fundings.name}}</a>
Expand Down
Loading