diff --git a/assets/less/cds-rdm/globals/site.overrides b/assets/less/cds-rdm/globals/site.overrides index 55a14288..2169e74b 100644 --- a/assets/less/cds-rdm/globals/site.overrides +++ b/assets/less/cds-rdm/globals/site.overrides @@ -6,10 +6,27 @@ width: 100px; } +.theme-default{ + .rdm-logo{ + padding: 0.3em .3em .3em 0; + } + +} + + +.theme-default{ + #invenio-nav.ui.menu .ui.menu .item.active{ + background-color: #FFFFFF; + } +} + .outer-navbar { z-index: 1; background-color: transparent !important; + &.theme-default { + background-color: #3b4a5717 !important; + } & > * { z-index: 3; position: relative; diff --git a/invenio.cfg b/invenio.cfg index a42d31f2..f4592037 100644 --- a/invenio.cfg +++ b/invenio.cfg @@ -14,6 +14,7 @@ from datetime import datetime, timedelta from invenio_i18n import lazy_gettext as _ from cds_rdm import schemes +from cds_rdm.communities.views import communities_home from cds_rdm.custom_fields import CUSTOM_FIELDS, CUSTOM_FIELDS_UI, NAMESPACES from cds_rdm.permissions import ( CDSCommunitiesPermissionPolicy, @@ -25,7 +26,9 @@ from cds_rdm.inspire_harvester.reader import InspireHTTPReader from cds_rdm.inspire_harvester.transformer import InspireJsonTransformer from cds_rdm.inspire_harvester.writer import InspireWriter from celery.schedules import crontab -from invenio_app_rdm.config import STATS_EVENTS as _APP_RDM_STATS_EVENTS, STATS_AGGREGATIONS as _APP_RDM_STATS_AGGREGATIONS, APP_RDM_ROUTES +from invenio_app_rdm.config import STATS_EVENTS as _APP_RDM_STATS_EVENTS, \ + STATS_AGGREGATIONS as _APP_RDM_STATS_AGGREGATIONS, APP_RDM_ROUTES, \ + RDM_COMMUNITIES_ROUTES from invenio_vocabularies.services.custom_fields import VocabularyCF from invenio_records_resources.services.custom_fields import KeywordCF from invenio_rdm_records.config import ( @@ -463,3 +466,13 @@ _APP_RDM_STATS_EVENTS["record-view"]["params"]["suffix"] = "%Y" # Override the index_interval to be year _APP_RDM_STATS_AGGREGATIONS["file-download-agg"]["params"]["index_interval"] = "year" _APP_RDM_STATS_AGGREGATIONS["record-view-agg"]["params"]["index_interval"] = "year" + + +# Branded Communities +# =================== + + +RDM_COMMUNITIES_ROUTES["community-home"] = ( + "/communities//", + communities_home, +) \ No newline at end of file diff --git a/site/cds_rdm/communities/__init__.py b/site/cds_rdm/communities/__init__.py new file mode 100644 index 00000000..81599f55 --- /dev/null +++ b/site/cds_rdm/communities/__init__.py @@ -0,0 +1,7 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2019-2025 CERN. +# +# Invenio App RDM is free software; you can redistribute it and/or modify it +# under the terms of the MIT License; see LICENSE file for more details. +"""Community views module.""" diff --git a/site/cds_rdm/communities/views.py b/site/cds_rdm/communities/views.py new file mode 100644 index 00000000..35dab228 --- /dev/null +++ b/site/cds_rdm/communities/views.py @@ -0,0 +1,167 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2019-2025 CERN. +# +# CDS-RDM is free software; you can redistribute it and/or modify it +# under the terms of the MIT License; see LICENSE file for more details. +"""Community views module.""" + +from flask import g, redirect, request, url_for +from invenio_communities.views.communities import ( + HEADER_PERMISSIONS, + render_community_theme_template, +) +from invenio_communities.views.decorators import pass_community +from invenio_rdm_records.proxies import ( + current_community_records_service, + current_rdm_records, +) +from invenio_rdm_records.resources.serializers import UIJSONSerializer +from invenio_records_resources.services.errors import PermissionDeniedError + + +def publications_metric_blr(results): + """Publications metric for BLR.""" + resource_types = results._results.aggregations.resource_types.buckets + valid_pubication_types = [ + "publication-article", + "publication-book", + "publication-section", + "publication-datamanagementplan", + ] + publications = 0 + for resource_type in resource_types: + if resource_type.key in valid_pubication_types: + publications += resource_type.doc_count + return publications + + +def images_metric_blr(results): + """Images metric for BLR.""" + resource_types = results._results.aggregations.resource_types.buckets + images = 0 + for resource_type in resource_types: + if resource_type.key.startswith("image"): + images += resource_type.doc_count + return images + + +def treatments_metric_blr(results): + """Treatments metric for BLR.""" + resource_types = results._results.aggregations.resource_types.buckets + for resource_type in resource_types: + if resource_type.key == "publication-taxonomictreatment": + return resource_type.doc_count + + +def tables_metric_blr(results): + """Tables metric for BLR.""" + resource_types = results._results.aggregations.resource_types.buckets + for resource_type in resource_types: + if resource_type.key == "dataset": + return resource_type.doc_count + + +METRICS = { + "total_grants": { + "name": "total_grants", + "type": "cardinality", + "kwargs": {"field": "metadata.funding.award.id"}, + }, + "total_data": { + "name": "total_data", + "type": "sum", + "kwargs": {"field": "files.totalbytes"}, + }, + "total_views": { + "name": "total_views", + "type": "sum", + "kwargs": {"field": "stats.all_versions.unique_views"}, + }, + "total_downloads": { + "name": "total_downloads", + "type": "sum", + "kwargs": {"field": "stats.all_versions.unique_downloads"}, + }, + "resource_types": { + "name": "resource_types", + "type": "terms", + "kwargs": {"field": "metadata.resource_type.id"}, + }, +} + + +THEME_METRICS = { + "horizon": {"total_data": "total_data", "total_grants": "total_grants"}, + "biosyslit": { + "total_views": "total_views", + "total_downloads": "total_downloads", + "publications": publications_metric_blr, + "images": images_metric_blr, + "tables": tables_metric_blr, + "treatments": treatments_metric_blr, + }, +} + + +def _get_metric_from_search(result, metric): + """Get metric from search result.""" + return result._results.aggregations[metric].value + + +@pass_community(serialize=True) +def communities_home(pid_value, community, community_ui): + """Community home page.""" + query_params = request.args + collections_service = current_rdm_records.collections_service + permissions = community.has_permissions_to(HEADER_PERMISSIONS) + if not permissions["can_read"]: + raise PermissionDeniedError() + + theme_enabled = community._record.theme and community._record.theme.get( + "enabled", False + ) + + if query_params or not theme_enabled: + url = url_for( + "invenio_app_rdm_communities.communities_detail", + pid_value=community.data["slug"], + **request.args, + ) + return redirect(url) + + if theme_enabled: + recent_uploads = current_community_records_service.search( + community_id=pid_value, + identity=g.identity, + params={"sort": "newest", "size": 3, "metrics": METRICS}, + expand=True, + ) + + collections = collections_service.list_trees(g.identity, community.id, depth=0) + + # TODO resultitem does not expose aggregations except labelled facets + metrics = { + "total_records": recent_uploads.total, + } + for metric, getter in THEME_METRICS.get( + community._record.theme["brand"], {} + ).items(): + if type(getter) == str: + metrics[metric] = _get_metric_from_search(recent_uploads, getter) + else: + metrics[metric] = getter(recent_uploads) or 0 + + records_ui = UIJSONSerializer().dump_list(recent_uploads.to_dict())["hits"][ + "hits" + ] + + return render_community_theme_template( + "invenio_communities/details/home/index.html", + theme=community_ui.get("theme", {}), + community=community_ui, + permissions=permissions, + records=records_ui, + metrics=metrics, + collections=collections.to_dict(), + ) \ No newline at end of file diff --git a/site/cds_rdm/templates/semantic-ui/cds_rdm/macro/record_item.html b/site/cds_rdm/templates/semantic-ui/cds_rdm/macro/record_item.html new file mode 100644 index 00000000..dc505ea4 --- /dev/null +++ b/site/cds_rdm/templates/semantic-ui/cds_rdm/macro/record_item.html @@ -0,0 +1,156 @@ +{# + Copyright (C) 2024 CERN. + + CDS-RDM is free software; you can redistribute it and/or modify it + under the terms of the MIT License; see LICENSE file for more details. +#} + + + +{% macro record_item(record=None, themed_community=None, use_theme_banner=False) %} +
  • +
    + {# Compute community theme styling #} + {# FIXME: Uncomment to enable themed banner #} + {# {% set themed_community = themed_community or ( + (record.parent.communities.entries or []) + | selectattr("id", "==", record.parent.communities.default) + | first + ) %} #} + + {% set bg_style = "" %} + {% set font_style = "" %} + {% if use_theme_banner and themed_community %} + {% set style = themed_community.get("theme", {}).get("style") %} + {% if style.primaryColor %} + {% set bg_style = "background-color: " ~ style.primaryColor ~ ";" %} + {% set font_style = "color: " ~ style.primaryColor ~ ";" %} + {% endif %} + {% endif %} + + {# Themed community banner #} + {% if use_theme_banner and themed_community.theme %} + + {{ themed_community.metadata.title }} + + + {% endif %} + {# Top labels #} +
    +
    + {{ record.ui.publication_date_l10n_long }} ({{ record.ui.version }}) +
    +
    + {{ record.ui.resource_type.title_l10n }} +
    + + {% set access_status_id = record.ui.access_status.get("id", "open") %} + {% set access_status = record.ui.access_status.get("title_l10n", "Open") %} + {% set access_status_icon = record.ui.access_status.get("icon", "unlock") %} + +
    + + {{ access_status }} +
    +
    + + {# Title #} + + + {# Creators #} +
    + {% set creators_list = record.ui.creators.creators %} + {% set creators_sliced = creators_list[:3] %} + +
    + + {# Description #} +

    + {% set description = record.ui.get("description_stripped", "") %} + + {{ description | truncate(length=350, end='...') }} +

    + +
    +
    + {# Publishing details #} + {% set created_date = record.ui.created_date_l10n_long %} + {% set publishing_journal = record.ui.publishing_information.get("journal") if record.ui.publishing_information %} +
    +

    + + {% if created_date %} + {{ _("Uploaded on")}} {{ created_date }} + {% endif %} + +

    + + {# Communities list #} +

    + + {% set communities_entries = record.parent.communities.entries %} + {# Filter out the themed community #} + {% if themed_community %} + {% set communities_entries = communities_entries | rejectattr("id", "==", themed_community.id) | list %} + {% endif %} + + +

    +

    + + {% if publishing_journal %} + {{ _("Published in") }} {{ publishing_journal }} + {% endif %} + +

    + + {# Versions info desktop/tablet #} + {% if record.versions.index > 1 %} + {% set num_versions = record.versions.index %} + {% set text_content = _("more versions exist for this record") %} + {% if num_versions == 2 %} + {% set text_content = _("more version exist for this record") %} + {% endif %} + +

    + {{ record.versions.index - 1 }} {{ text_content }} +

    + {% endif %} +
    + + {# Statistics #} + {% set downloads = record.stats.all_versions.unique_downloads %} + {% set views = record.stats.all_versions.unique_views %} + + {% if views is defined %} +
    + + {{ views }} + +
    + {% endif %} + + {% if downloads is defined %} +
    + + {{ downloads}} + +
    + {% endif %} +
    +
    +
    +
    +
  • +{% endmacro %} \ No newline at end of file diff --git a/templates/semantic-ui/invenio_communities/community_theme_template.css b/templates/semantic-ui/invenio_communities/community_theme_template.css new file mode 100644 index 00000000..cda072b7 --- /dev/null +++ b/templates/semantic-ui/invenio_communities/community_theme_template.css @@ -0,0 +1,65 @@ +.page-subheader-outer { + background-color: {{ theme.mainHeaderBackgroundColor }} !important; +} + +.theme-secondary, .ui.secondary.button { + background-color: {{ theme.secondaryColor }} !important; + color: {{ theme.secondaryTextColor }} !important; +} + +.invenio-page-body .ui.search.button { + background-color: {{ theme.secondaryColor }} !important; + color: {{ theme.secondaryTextColor }} !important; +} + +.theme-primary a, .theme-primary h1, .theme-primary h2, .theme-primary p { + color: {{ theme.primaryTextColor }} !important; +} + +.theme-primary.pointing.menu .item.active { + border-color: {{ theme.secondaryColor }} !important; +} + +.theme-primary-menu .item.active { + background-color: {{ theme.primaryColor }} !important; +} + +.theme-primary .item, .theme-primary-menu, .page-subheader-outer{ + font-family: {{ theme.font.family }} !important; + font-weight: {{ theme.font.weight }} !important; + font-size: {{ theme.font.size }}; +} + +.theme-primary { + background-color: {{ theme.primaryColor }} !important; +} + +.theme-primary-text a, +.theme-primary-text h1 { + color: {{ theme.primaryTextColor }} !important; +} + +.theme-secondary-text a, +.theme-secondary-text h1 { + color: {{ theme.secondaryTextColor }} !important; +} + +.theme-tertiary-text a, +.theme-tertiary-text h1 { + color: {{ theme.tertiaryTextColor }} !important; +} + + +.theme-tertiary, .ui.tertiary.button { + background-color: {{ theme.tertiaryColor }} !important; + color: {{ theme.tertiaryTextColor }}; +} + +.invenio-accordion-field .title, .ui.primary.button{ + background-color: {{ theme.primaryColor }} !important; + color: {{ theme.primaryTextColor }} !important; +} + +.theme-font h1 { + font-weight: {{theme.font.weight}} !important; +} diff --git a/templates/themes/cern-sis/invenio_communities/details/header.html b/templates/themes/cern-sis/invenio_communities/details/header.html new file mode 100644 index 00000000..8d211573 --- /dev/null +++ b/templates/themes/cern-sis/invenio_communities/details/header.html @@ -0,0 +1,134 @@ +{# -*- coding: utf-8 -*- + + Copyright (C) 2024 CERN. + + CDS-RDM is free software; you can redistribute it and/or modify it + under the terms of the MIT License; see LICENSE file for more details. +#} + +{%- from "invenio_theme/macros/truncate.html" import truncate_text %} +{%- from "invenio_communities/details/macros/access-status-label.html" import access_status_label -%} + +
    +
    +
    +
    +
    +
    + + +
    +
    + + +

    + {{ community.metadata.title }} +

    +
    + + {% if community.access.visibility == 'restricted' %} +
    + {{ access_status_label() }} +
    + {% endif %} +
    + +
    + {% if community.access.visibility == 'restricted' %} +
    + {{ access_status_label() }} +
    + {% endif %} + + {% if community.metadata.organizations %} + {% for org in community.metadata.organizations %} + {% set ror_id = org.id %} + {% set name = org.name %} + +
    + {% if loop.index == 1 %} + by + {% endif %} + + {{ name }} + + + + + {{ ", " if not loop.last }} +
    + {% endfor %} + {% endif %} + + {% if community.metadata.website %} + + {% endif %} + +
    +
    +
    +
    + + +
    +
    +
    +
    +
    + Scientific research output +
    +
    + +
    +
    \ No newline at end of file diff --git a/templates/themes/cern-sis/invenio_communities/details/home/index.html b/templates/themes/cern-sis/invenio_communities/details/home/index.html new file mode 100644 index 00000000..3a889355 --- /dev/null +++ b/templates/themes/cern-sis/invenio_communities/details/home/index.html @@ -0,0 +1,302 @@ +{# -*- coding: utf-8 -*- + + Copyright (C) 2024 CERN. + + CDS-RDM is free software; you can redistribute it and/or modify it + under the terms of the MIT License; see LICENSE file for more details. +#} + + +{% extends "invenio_communities/details/base.html" %} +{% from "cds_rdm/macro/record_item.html" import record_item %} + +{%- set title = community.metadata.title -%} +{% set active_community_header_menu_item = 'home' %} +{% from "invenio_communities/collections/macros.html" import render_depth_one_collection %} + + +{%- block page_body %} + {{ super() }} +
    +
    +
    +
    +

    {{ _("Repository for CERN Scientific information") }}

    +

    {{ _("Research data from scientific publications") }}

    +
    +
    +
    +
    + +
    +
    +
    +
    +
    + + +
    +
    +
    +
    +

    {{ _("Advanced Search") }}

    +
    +
    +
    +
    +
    +
    + +
    +
    + +

    {{ _("CERN Scientific Information Service") }}

    +
    +
    +
    +
    +

    {{ _("The CERN Scientific Information Service aims at efficiently managing, preserving and disseminating scientific information to make it openly accessible and reusable to CERN and the worldwide High-Energy Physics community.") }}

    +
    +
    +
    + +
    +
    +
    + + +
    +
    + +

    {{ _("CERN Library Catalogue") }}

    +
    +
    +
    +
    +

    "Searching for scientific resources for your next research?
    Try CERN Library Catalogue!

    +
    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    +
    +
    + + +
    +
    + +

    {{ _("Archives") }}

    +
    +
    +
    +
    +

    The CERN Archives is a repository for historical records about all aspects of CERN's activities, from the creation of CERN until the present day.

    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + + + + {% set icon_map = { + "total_records": {"icon": "file", "title": _( "RECORDS"), "row": 1}, + "total_views": {"icon": "eye", "title": _( "VIEWS"), "row": 1}, + "total_downloads": {"icon": "download", "title": _( "DOWNLOADS"), "row": 1}, + "publications": {"icon": "book", "title": _( "PUBLICATIONS"), "row": 2}, + "treatments": {"icon": "newspaper outline", "title": _( "TREATMENTS"), "row": 2}, + "images": {"icon": "images", "title": _( "FIGURES"), "row": 2}, + "tables": {"icon": "table", "title": _( "TABLES"), "row": 2}, +} %} + +
    +
    +
    +

    {{ _( "Summary") }}

    +
    +
    + + {% for row_number in [1, 2] %} +
    +
    + {% for key, value in icon_map.items() if value['row'] == row_number and key in metrics %} +
    +
    +

    + + {{ metrics[key] | compact_number(max_value=1_000_000) }} +

    +
    +

    {{ value['title'] }}

    +
    + {% endfor %} +
    +
    + {% endfor %} +
    +
    + + + {% if records %} +
    +
    +
    +

    {{ _("Recent uploads") }}

    +
    +
    + +
    + {% for record in records %} +
      + {{ record_item(record=record, themed_community=community) }} +
    + {% endfor %} +
    +
    +
    + {% endif %} + +
    +
    +
    +

    {{ _("How it works") }}

    +
    +
    +
    +
    +
    +

    {{ _("Submit your research") }}

    +
    + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus urna + nisi, ultrices id condimentum ut, fringilla eget justo. Mauris lobortis + diam sit amet efficitur porta. Aliquam imperdiet ligula nec turpis + mattis lobortis. Integer pulvinar orci id massa fermentum, id ornare + enim accumsan. Sed molestie mauris non ligula consequat, a laoreet est + ultrices. Nulla fermentum eget lorem a rutrum. Phasellus eget augue et + dui pretium sollicitudin eget sit amet ipsum. Cras a viverra odio. Donec + eu pretium nulla, ut ornare nibh. Aenean consequat leo libero, eu mattis + sapien tristique vel. + +
    +
    +
    +
    +
    +

    Submit thesis

    +
    + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus urna + nisi, ultrices id condimentum ut, fringilla eget justo. Mauris lobortis + diam sit amet efficitur porta. Aliquam imperdiet ligula nec turpis + mattis lobortis. Integer pulvinar orci id massa fermentum, id ornare + enim accumsan. Sed molestie mauris non ligula consequat, a laoreet est + ultrices. Nulla fermentum eget lorem a rutrum. Phasellus eget augue et + dui pretium sollicitudin eget sit amet ipsum. Cras a viverra odio. Donec + eu pretium nulla, ut ornare nibh. Aenean consequat leo libero, eu mattis + sapien tristique vel. + +
    +
    +
    +
    +
    +

    {{ _("About") }}

    +
    + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus urna + nisi, ultrices id condimentum ut, fringilla eget justo. Mauris lobortis + diam sit amet efficitur porta. Aliquam imperdiet ligula nec turpis + mattis lobortis. Integer pulvinar orci id massa fermentum, id ornare + enim accumsan. Sed molestie mauris non ligula consequat, a laoreet est + ultrices. Nulla fermentum eget lorem a rutrum. Phasellus eget augue et + dui pretium sollicitudin eget sit amet ipsum. Cras a viverra odio. Donec + eu pretium nulla, ut ornare nibh. Aenean consequat leo libero, eu mattis + sapien tristique vel. + +
    +
    +
    +
    +
    +
    +
    +{%- endblock page_body -%} + +{%- block javascript %} + {{ super() }} +{%- endblock %} \ No newline at end of file