diff --git a/CHANGES.rst b/CHANGES.rst index b50166550488f47e2c1a336cf8a55bfbd8ff0377..f7fbd1b7852bb4f0e09fcb4415c3738b5766d6b2 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -12,6 +12,8 @@ Changes Version <next> - Reverse order of listed users on admin endpoint +- Footer: Add `About` page +- Add following subpages to the `About` page: `API Docs`, `About VRE`, `About DAMAP` Version v2025.1.9 (released 2025-03-11) diff --git a/invenio_theme_tuw/theme/assets/semantic-ui/js/invenio_theme_tuw/clipboard/index.js b/invenio_theme_tuw/theme/assets/semantic-ui/js/invenio_theme_tuw/clipboard/index.js new file mode 100644 index 0000000000000000000000000000000000000000..0cb698aee151a74ababc92133d84667db658a929 --- /dev/null +++ b/invenio_theme_tuw/theme/assets/semantic-ui/js/invenio_theme_tuw/clipboard/index.js @@ -0,0 +1,35 @@ +// Copyright (C) 2025 TU Wien. +// +// Invenio Theme TUW is free software; you can redistribute it and/or modify it +// under the terms of the MIT License; see LICENSE file for more details. + +document.addEventListener("DOMContentLoaded", () => { + document.querySelectorAll(".code-block").forEach((block) => { + const button = block.querySelector(".copy-btn"); + const codeText = block.innerText.trim(); + + // Skip this block if the required elements are missing + if (!button) return; + + const resetTooltip = (btn) => { + btn.setAttribute("data-tooltip", "Copy to clipboard"); + btn.querySelector("i").classList.replace("check", "copy"); + }; + + const handleCopy = () => { + navigator.clipboard + .writeText(codeText) + .then(() => onCopySuccess(button)) + .catch((error) => console.error("Failed to copy: ", error)); + }; + + const onCopySuccess = (btn) => { + btn.setAttribute("data-tooltip", "Copied!"); + btn.querySelector("i").classList.replace("copy", "check"); + + setTimeout(resetTooltip, 2000, btn); + }; + + button.addEventListener("click", handleCopy); + }); +}); diff --git a/invenio_theme_tuw/theme/assets/semantic-ui/less/invenio_theme_tuw/theme/custom/about.less b/invenio_theme_tuw/theme/assets/semantic-ui/less/invenio_theme_tuw/theme/custom/about.less new file mode 100644 index 0000000000000000000000000000000000000000..8db687b131825ce04a5238186904919e048fc69b --- /dev/null +++ b/invenio_theme_tuw/theme/assets/semantic-ui/less/invenio_theme_tuw/theme/custom/about.less @@ -0,0 +1,41 @@ +/* ------------------ */ +/* About page styling */ +/* ------------------ */ + +.about.container { + + .code-container { + position: relative; + display: inline-block; + width: 100%; + margin-bottom: 2em; + + .code-block { + position: relative; + background: #f8f9fa; + padding: 10px; + border-radius: 5px; + font-family: monospace; + white-space: pre-wrap; + word-wrap: break-word; + display: flex; + align-items: center; + justify-content: space-between; + + .copy-btn { + background: none !important; + border: none; + padding: 5px; + display: flex; + align-items: center; + transition: color 0.3s ease; + + i { + font-size: 16px; + color: black !important; + margin: 0 !important; + } + } + } + } +} diff --git a/invenio_theme_tuw/theme/assets/semantic-ui/less/invenio_theme_tuw/theme/globals/site.overrides b/invenio_theme_tuw/theme/assets/semantic-ui/less/invenio_theme_tuw/theme/globals/site.overrides index 574ed6a50fa5f836d04e7599437d9f9ec56be690..b4137025ed7c040186e08f00f42e10f770dc99f4 100644 --- a/invenio_theme_tuw/theme/assets/semantic-ui/less/invenio_theme_tuw/theme/globals/site.overrides +++ b/invenio_theme_tuw/theme/assets/semantic-ui/less/invenio_theme_tuw/theme/globals/site.overrides @@ -4,6 +4,7 @@ @import "@less/invenio_app_rdm/theme/globals/site.overrides"; +@import "../custom/about.less"; @import "../custom/contact.less"; @import "../custom/flip-card.less"; @import "../custom/file-list.less"; diff --git a/invenio_theme_tuw/theme/templates/semantic-ui/invenio_theme_tuw/about.html b/invenio_theme_tuw/theme/templates/semantic-ui/invenio_theme_tuw/about.html new file mode 100644 index 0000000000000000000000000000000000000000..14e80b20976cc73c523160f93be11aa466d1d834 --- /dev/null +++ b/invenio_theme_tuw/theme/templates/semantic-ui/invenio_theme_tuw/about.html @@ -0,0 +1,78 @@ +{# -*- coding: utf-8 -*- + + Copyright (C) 2025 TU Wien. + + Invenio Theme TUW 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 config.BASE_TEMPLATE %} + +{%- block page_hero %} + <section id="hero" class="policies no-shrink"></section> +{%- endblock page_hero %} + +{%- block page_body %} + <section class="ui about container rel-mt-3"> + <h1>{{ _("About %(sitename)s", sitename=config.THEME_SITENAME) }}</h1> + <p> + {%- trans trimmed sitename=config.THEME_SITENAME, package_version=package_version -%} + {{ sitename }} (powered by {{ package_version }}) is an institution-wide platform for TU Wien researchers to share and preserve their research output. + It meets institutional and legal requirements for data storage, long-term preservation, and sharing, in compliance with the <a href="https://www.go-fair.org/fair-principles/">FAIR principles</a>, <a href="https://www.bmbwf.gv.at/Themen/HS-Uni/Hochschulgovernance/Leitthemen/Digitalisierung/Open-Science.html">Open Science</a>, and funders' demands. + {%- endtrans -%} + </p> + <p> + {{ _("Key features of the repository %(sitename)s are:", sitename=config.THEME_SITENAME) }} + <ul> + <li><strong>{{ _("Data Management") }}:</strong> {{ _("Upload and describe datasets with appropriate metadata;") }}</li> + <li><strong>{{ _("Persistent Identifiers") }}:</strong> {{ _("Get DOIs for your datasets;") }}</li> + <li><strong>{{ _("Access Control") }}:</strong> {{ _("Share data publicly, with selected collaborators, or keep it private.") }}</li> + </ul> + </p> + + <h2>{{ _("Further features") }}</h2> + <strong>{{ _("Programmatic access:") }}</strong> + <p> + {%- trans trimmed sitename=config.THEME_SITENAME %} + We provide a set of REST APIs that allow researchers and developers to integrate data access capabilities directly into their workflows and systems. + Our APIs range from querying metadata and performing advanced searches to automating data ingestion. + Data-altering operations, such as creating or updating records, can be performed with token-based authentication. + Read-only operations, such as retrieving metadata or performing searches, are openly accessible. + This is consistent with the principles of transparent access to research data. + {%- endtrans %} + </p> + <p> + {%- trans trimmed api_page_link = url_for("invenio_theme_tuw.tuw_about_api") %} + For step-by-step instructions, code examples, and advanced use cases, please visit the <a href="{{ api_page_link }}">API Documentation</a> page. + {%- endtrans %} + </p> + + <strong>{{ _("Connecting to Virtual Research Environments (VREs):") }}</strong> + <p> + {%- trans trimmed %} + For direct access to data in our repository, we provide a plugin (the VRE Repository Connector) that integrates our repository with Jupyter Notebooks. + {%- endtrans %} + </p> + <p> + {{ _("Once the VRE extension is installed and users authenticate with their repository access token, they can") }} + <ul> + <li>{{ _("Search for datasets using advanced query parameters;") }}</li> + <li>{{ _("Retrieve detailed metadata for analysis;") }}</li> + <li>{{ _("Download files directly to notebook environments;") }}</li> + <li>{{ _("Upload new datasets or update existing records.") }}</li> + </ul> + </p> + <p> + {%- trans trimmed vre_page_link = url_for("invenio_theme_tuw.tuw_about_vre") %} + Visit our dedicated <a href="{{ vre_page_link }}">VRE Repository Connector page</a> for usage instructions and examples. + {%- endtrans %} + </p> + + <h2>{{ _("Support and contact information") }}</h2> + <p> + {%- trans trimmed contact_page_link = url_for("invenio_theme_tuw.tuw_contact") %} + If you have further questions, please refer to the <a href={{ contact_page_link }}>contact page</a>. + {%- endtrans %} + </p> + </section> +{%- endblock page_body %} diff --git a/invenio_theme_tuw/theme/templates/semantic-ui/invenio_theme_tuw/about_api.html b/invenio_theme_tuw/theme/templates/semantic-ui/invenio_theme_tuw/about_api.html new file mode 100644 index 0000000000000000000000000000000000000000..ac204e3a4c22c44bfa37f88d49ee23c9b83a6b4c --- /dev/null +++ b/invenio_theme_tuw/theme/templates/semantic-ui/invenio_theme_tuw/about_api.html @@ -0,0 +1,790 @@ +{# -*- coding: utf-8 -*- + + Copyright (C) 2025 TU Wien. + + Invenio Theme TUW 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 config.BASE_TEMPLATE %} + +{# These links are used multiple times throughout this page. #} +{% set inveniordm_api_ref_link = "https://inveniordm.docs.cern.ch/reference/rest_api_index/" %} +{% set token_link = url_for("invenio_oauth2server_settings.token_new") %} + +{# NOTE: Set API cases text here (sequentially) #} +{% + set api_cases_text = [ + "Retrieve a Dataset's Metadata", + "Search for Datasets", + "Upload a New Dataset", + "Attach a File to an Existing Record", + "File Download", + ] +%} + +{%- block page_hero %} + <section id="hero" class="policies no-shrink"></section> +{%- endblock page_hero %} + +{%- block page_body %} + <section class="ui about container rel-mt-3"> + <a href="{{ url_for('invenio_theme_tuw.tuw_about') }}">â¬…ï¸ {{ _("To parent page") }}</a> + + <h1>{{ _("API Documentation") }}</h1> + <p> + {{ _("The %(sitename)s API provides programmatic access to datasets, metadata, search functionalities, and more.", sitename=config.THEME_SITENAME) }} + {{ _("This API lets you automate data management tasks, integrate with external systems, or build custom workflows for data analysis and visualization.") }} + </p> + <p> + {{ _("In this page we list the most common API operations which include:") }} + </p> + <ul> + {% for case in api_cases_text %} + {% set index = loop.index %} + <li> + {%- trans trimmed case_link = "#case" ~ index %} + <a href="{{ case_link }}"> + Case {{ index }} - {{ case }} + </a> + {%- endtrans %} + </li> + {% endfor %} + </ul> + <p> + {{ _("While our customized implementation inherits all the core functionalities from a vanilla InvenioRDM instance, it introduces several enhancements to better serve the research community:") }} + </p> + <ul> + <li> + <strong> {{ _("Custom Permissions:") }}</strong> + {{ _("Unlike the standard InvenioRDM, our instance enforces enhanced permission settings.") }} + {{ _("For instance, an extra \"guard\" ensures that users can't create drafts in the system without being granted access by an administrator.") }} + {{ _("Moreover, records prior to publication go also through an administrative review, thus ensuring that only curated high-quality content can be publicly available.") }} + </li> + <li> + <strong> {{ _("Curation Workflow:") }}</strong> + {{ _("A thorough review system now includes new ways to interact through the interface.") }} + {{ _("These endpoints allow curators to review submissions, add annotations, and approve records before they are published, ensuring compliance with data quality and regulatory standards.") }} + <!-- These additions let reviewers examine entries, make notes besides validate records prior to release, which keeps data accurate and follows rules. --> + </li> + <li> + <strong> {{ _("Invenio-DAMAP Integration:") }}</strong> + {{ _("Our deployment includes extended functionality through the Invenio-DAMAP package.") }} + {%- trans trimmed tuw_dmp_tool_link = config.DAMAP_BASE_URL or "#" %} + This is the additional fine layer of advanced digital asset management such as automatic population of DMP fields and enriched file-specific metadata in the <a href="{{ tuw_dmp_tool_link }}">TU Wien DMP Tool</a>. + {%- endtrans %} + </li> + </ul> + <p> + {%- trans trimmed tuw_customizations_link = "#tuw_customizations" %} + For detailed examples of our enhanced Curation Workflow and Invenio-DAMAP integration, please see the <a href={{ tuw_customizations_link }}>Additional Customizations</a> section below. + {%- endtrans %} + </p> + + <h2>{{ _("Authentication") }}</h2> + <p> + {%- trans trimmed token_link = token_link %} + <strong>Note: </strong>Operations such as creating records or attaching files require an access token. You can generate one + <a href="{{ token_link }}">here</a>. + Other operations (like retrieving metadata) are public. + {%- endtrans %} + </p> + + <h2>{{ _("Common Query Parameters") }}</h2> + <p> + {{ _("For search endpoints, the most relevant parameters include:") }} + </p> + <ul> + <li><code>q</code>: {{ _("The search query") }} ({{ _("e.g.") }}, <code>q=title:climate</code>).</li> + <li><code>sort</code>: {{ _("Sorting criteria") }} ({{ _("e.g.") }}, <code>sort=newest</code>).</li> + <li><code>size</code>: {{ _("Results size per page") }} ({{ _("e.g.") }}, <code>size=50</code>).</li> + <li><code>page</code>: {{ _("Pagination control") }} ({{ _("e.g.") }}, <code>page=1</code>).</li> + </ul> + <p> + {%- trans trimmed inveniordm_api_ref_link = inveniordm_api_ref_link %} + More details about query parameters can be found in the official <a href="{{ inveniordm_api_ref_link }}" target="_blank" rel="noopener">InvenioRDM API Documentation</a>. + {%- endtrans %} + </p> + + <h2>{{ _("API Usage Examples") }}</h2> + {# TODO: This could be reworked with a loop, use the 'api_cases_text' list defined above? #} + {# If possible, then readjust translation strings: should be marked only with the 2nd sentence here due to trans property above. #} + + <!-- Case 1--> + <h3 id="case1">{{ _("Case 1 - Retrieve a Dataset's Metadata: Quickly fetch detailed metadata for a dataset using its persistent identifier.") }}</h3> + <p> + <strong>{{ _("User Story:") }}</strong> + <i>{{ _("As a researcher, I want to quickly retrieve detailed metadata for a dataset using its unique identifier so that I can verify its relevance and incorporate accurate information into my analysis.") }}</i> + </p> + <p><strong>{{ _("Endpoint:") }} </strong><code>GET /api/records/{record_id}</code></p> + <p><strong>{{ _("Token Required:") }} </strong>{{ _("No") }}</p> + + <p><strong>cURL:</strong></p> + <div class="ui code-container"> + <pre class="ui segment code-block"> +{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} +curl "{{ config.SITE_API_URL }}/records/abcde-12345" +{#- ################## PREFORMATTED AREA TEXT END ################## -#} + <button class="ui button copy-btn" data-tooltip="Copy to clipboard"> + <i class="copy icon"></i> + </button> + </pre> + </div> + + <p><strong>Python (requests):</strong></p> + <div class="ui code-container"> + <pre class="ui segment code-block"> +{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} +import requests +url = "{{ config.SITE_API_URL }}/records/abcde-12345" + +response = requests.get(url) +print(response.json()) +{#- ################## PREFORMATTED AREA TEXT END ################## -#} + <button class="ui button copy-btn" data-tooltip="Copy to clipboard"> + <i class="copy icon"></i> + </button> + </pre> + </div> + + <p><strong>{{ _("Example Response") }} (HTTP 200 - OK):</strong></p> + <div class="ui code-container"> + <pre class="ui segment code-block"> +{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} +{ + "id": "abcde-12345", + "metadata": { + "title": "Dataset Title", + "creators": [{"name": "Doe, John"}], + "publication_date": "2025-01-09", + "resource_type": {"id": "dataset", "title": {"en": "Dataset"}} + }, + "links": { + "self": "{{ config.SITE_API_URL }}/records/abcde-12345", + "files": "{{ config.SITE_API_URL }}/records/abcde-12345/files" + } +} +{#- ################## PREFORMATTED AREA TEXT END ################## -#} + <button class="ui button copy-btn" data-tooltip="Copy to clipboard"> + <i class="copy icon"></i> + </button> + </pre> + </div> + + <!-- Example 2: Search for Datasets --> + <h3 id="case2">{{ _("Case 2 - Search for Datasets: Execute advanced searches with filters (keywords, authors, dates, etc.).") }} </h3> + <p> + <strong>{{ _("User Story:") }}</strong> + <i>{{ _("As a data scientist, I want to search for datasets using keywords and publication ranges, or author names so that I can find data that matches my research criteria without browsing through irrelevant records.") }}</i> + </p> + <p><strong>{{ _("Endpoint:") }} </strong><code>GET /api/records</code></p> + <p><strong>{{ _("Token Required:") }} </strong>{{ _("No") }}</p> + <p><strong>{{ _("Query Parameters:") }} </strong><code>q</code>, <code>sort</code>, and <code>page</code></p> + <p><strong>cURL:</strong></p> + + <div class="ui code-container"> + <pre class="ui segment code-block"> +{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} +curl -G "{{ config.SITE_API_URL }}/records" \ + --data-urlencode "q=climate AND metadata.publication_date:[2023 TO 2025]" \ + --data-urlencode "sort=newest" \ + --data-urlencode "page=1" +{#- ################## PREFORMATTED AREA TEXT END ################## -#} + <button class="ui button copy-btn" data-tooltip="Copy to clipboard"> + <i class="copy icon"></i> + </button> + </pre> + </div> + + <p><strong>Python (requests):</strong></p> + + <div class="ui code-container"> + <pre class="ui segment code-block"> +{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} +import requests +params = { + "q": "climate AND metadata.publication_date=[2023 TO 2025]", + "sort": "newest", + "page": 1 +} +url = "{{ config.SITE_API_URL }}/records" + +response = requests.get(url, params=params) +print(response.json()) +{#- ################## PREFORMATTED AREA TEXT END ################## -#} + <button class="ui button copy-btn" data-tooltip="Copy to clipboard"> + <i class="copy icon"></i> + </button> + </pre> + </div> + + <p><strong>{{ _("Example Response") }} (HTTP 200 - OK):</strong></p> + + <div class="ui code-container"> + <pre class="ui segment code-block"> +{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} +{ + "hits": { + "total": 2, + "hits": [ + { + "id": "abcde-12345", + "metadata": { + "title": "Climate Change Data", + "publication_date": "2025-01-01" + } + }, + { + "id": "efgh-5678", + "metadata": { + "title": "Temperature Records", + "publication_date": "2024-12-25" + } + } + ] + }, + "links": { + "self": "{{ config.SITE_API_URL }}/records?q=climate&sort=newest&page=1", + "next": "{{ config.SITE_API_URL }}/records?q=climate&sort=newest&page=2" + } +} +{#- ################## PREFORMATTED AREA TEXT END ################## -#} + <button class="ui button copy-btn" data-tooltip="Copy to clipboard"> + <i class="copy icon"></i> + </button> + </pre> + </div> + <p> + 💡 + {%- trans trimmed search_link = url_for("invenio_app_rdm.help_search") %} + Hint: You can refer to our <a href="{{ search_link }}">search guide</a> for further details on how to construct simple or advanced search queries.</p> + {%- endtrans %} + </p> + + <!-- Example 3: Upload a New Dataset --> + <h3 id="case3">{{ _("Case 3 - Upload a New Dataset: Automate metadata submissions and record creation.") }}</h3> + <p> + <strong>{{ _("User Story:") }}</strong> + <i>{{ _("As a lab scientist, I want to automate the upload of new datasets along with detailed metadata so that my research outputs are quickly published, discoverable, and citable through an assigned DOI.") }}</i> + </p> + <div> + <strong>{{ _("Workflow:") }}</strong> + <ol> + <li> + <p>{{ _("Create a new draft:") }}</p> + <p><strong>{{ _("Endpoint:") }} </strong><code>POST /api/records</code></p> + <p> + <strong>{{ _("Token Required:") }} </strong> + {%- trans trimmed token_link = token_link %} + Yes — generate one <a href="{{ token_link }}">here</a>. + {%- endtrans %} + </p> + </li> + <br> + <li> + {{ _("Request a DOI:") }} + <p><br><strong>{{ _("Endpoint:") }} </strong><code>POST /api/records/{record_id}/draft/pids/doi</code></p> + <p> + <strong>{{ _("Token Required:") }} </strong> + {%- trans trimmed token_link = token_link %} + Yes — generate one <a href="{{ token_link }}">here</a>. + {%- endtrans %} + </p> + </li> + </ol> + </div> + <br> + <div> + <p><strong>cURL {{ _("Snippets") }}:</strong></p> + + <p>{{ _("Step 1: Create a new draft") }}</p> + + <div class="ui code-container"> + <pre class="ui segment code-block"> +{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} +curl -X POST "{{ config.SITE_API_URL }}/records" \ + -H "Authorization: Bearer {your-access-token}" \ + -H "Content-Type: application/json" \ + -d ' +{ + "metadata": { + "creators": [ + { + "person_or_org": { + "family_name": "Doe", + "given_name": "Jane", + "type": "personal" + } + } + ], + "publication_date": "2025-01-09", + "publisher": "TU Wien", + "resource_type": {"id": "dataset"}, + "title": "New Dataset Title" + }, + "files": {"enabled": true} +}' +{#- ################## PREFORMATTED AREA TEXT END ################## -#} + <button class="ui button copy-btn" data-tooltip="Copy to clipboard"> + <i class="copy icon"></i> + </button> + </pre> + </div> + + <p>{{ _("Step 2: Request a DOI") }}</p> + + <div class="ui code-container"> + <pre class="ui segment code-block"> +{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} +curl -X POST "{{ config.SITE_API_URL }}/records/abcde-12345/draft/pids/doi" \ + -H "Authorization: Bearer {your-access-token}" +{#- ################## PREFORMATTED AREA TEXT END ################## -#} + <button class="ui button copy-btn" data-tooltip="Copy to clipboard"> + <i class="copy icon"></i> + </button> + </pre> + </div> + + <p><strong>Python (requests) {{ _("Snippets") }}:</strong></p> + <p>{{ _("Step 1: Create a new draft") }}</p> + + <div class="ui code-container"> + <pre class="ui segment code-block"> +{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} +import requests +url = "{{ config.SITE_API_URL }}/records" +headers = { + "Authorization": "Bearer {your-access-token}", + "Content-Type": "application/json" +} +data = { + "metadata": { + "creators": [ + { + "person_or_org": { + "family_name": "Doe", + "given_name": "Jane", + "type": "personal", + } + } + ], + "publication_date": "2025-01-09", + "publisher": "TU Wien", + "resource_type": {"id": "dataset"}, + "title": "New Dataset Title", + }, + "files": {"enabled": True}, +} + +response = requests.post(url, json=data, headers=headers) +print(response.json()) +{#- ################## PREFORMATTED AREA TEXT END ################## -#} + <button class="ui button copy-btn" data-tooltip="Copy to clipboard"> + <i class="copy icon"></i> + </button> + </pre> + </div> + + <p>{{ _("Step 2: Request a DOI") }}</p> + + <div class="ui code-container"> + <pre class="ui segment code-block"> +{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} +import requests +url = "{{ config.SITE_API_URL }}/records/abcde-12345/draft/pids/doi" +headers = { + "Authorization": "Bearer {your-access-token}", +} + +response = requests.post(url, headers=headers) +print(response.json()) +{#- ################## PREFORMATTED AREA TEXT END ################## -#} + <button class="ui button copy-btn" data-tooltip="Copy to clipboard"> + <i class="copy icon"></i> + </button> + </pre> + </div> + + <!-- Example 4: Attach a File to an Existing Record --> + <h3 id="case4">{{ _("Case 4 - Attach a File to an Existing Record: Enrich records by associating files using a multi-step upload process.") }}</h3> + <p> + <strong>{{ _("User Story:") }}</strong> + <i>{{ _("As a project manager, I want to attach supplementary files (like additional data or documentation) to an existing dataset record so that all components of the research project are organized and accessible in one place.") }}</i> + </p> + <div> + <strong>{{ _("Workflow:") }}</strong> + <ol> + <li> + <p>{{ _("Initialize the file upload:") }}</p> + <p><strong>{{ _("Endpoint:") }}: </strong><code>POST /api/records/{record_id}/draft/files</code></p> + <p> + <strong>{{ _("Token Required:") }} </strong> + {%- trans trimmed token_link = token_link %} + Yes — generate one <a href="{{ token_link }}">here</a>. + {%- endtrans %} + </p> + </li> + <br> + <li> + <p>{{ _("Upload the file content:") }}</p> + <p><strong>{{ _("Endpoint:") }} </strong><code>PUT /api/records/{record_id}/draft/files/{file_name}/content</code></p> + <p> + <strong>{{ _("Token Required:") }} </strong> + {%- trans trimmed token_link = token_link %} + Yes — generate one <a href="{{ token_link }}">here</a>. + {%- endtrans %} + </p> + </li> + <br> + <li> + <p>{{ _("Commit draft file upload:") }}</p> + <p><strong>{{ _("Endpoint:") }} </strong><code>POST /api/records/{record_id}/draft/files/{file_name}/commit</code></p> + <p> + <strong>{{ _("Token Required:") }} </strong> + {%- trans trimmed token_link = token_link %} + Yes — generate one <a href="{{ token_link }}">here</a>. + {%- endtrans %} + </p> + </li> + <br> + <li> + <p> + {%- trans trimmed tuw_customizations_link = "#tuw_customizations" %} + Publish the draft: (After curation request has been accepted - See <a href="{{ tuw_customizations_link }}" rel="noopener">curation endpoint</a>)</p> + {%- endtrans %} + <p><strong>{{ _("Endpoint:") }} </strong><code>POST /api/records/{record_id}/draft/actions/publish</code></p> + <p> + <strong>{{ _("Token Required:") }} </strong> + {%- trans trimmed token_link = token_link %} + Yes — generate one <a href="{{ token_link }}">here</a>. + {%- endtrans %} + </p> + </li> + </ol> + </div> + <br> + <div> + <p><strong>cURL {{ _("Snippets") }}:</strong></p> + <p>{{ _("Step 1: Initialize File Upload") }}</p> + + <div class="ui code-container"> + <pre class="ui segment code-block"> +{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} +curl -X POST "{{ config.SITE_API_URL }}/records/abcde-12345/draft/files" \ + -H "Authorization: Bearer {your-access-token}" \ + -H "Content-Type: application/json" \ + -d ' +{ + "files": [{"key": "example_dataset.csv"}] +}' +{#- ################## PREFORMATTED AREA TEXT END ################## -#} + <button class="ui button copy-btn" data-tooltip="Copy to clipboard"> + <i class="copy icon"></i> + </button> + </pre> + </div> + + <p>{{ _("Step 2: Upload File Content") }}</p> + + <div class="ui code-container"> + <pre class="ui segment code-block"> +{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} +curl -X PUT "{{ config.SITE_API_URL }}/records/abcde-12345/draft/files/example_dataset.csv/content" \ + -H "Authorization: Bearer {your-access-token}" \ + -H "Content-Type: application/octet-stream" \ + --data-binary @example_dataset.csv +{#- ################## PREFORMATTED AREA TEXT END ################## -#} + <button class="ui button copy-btn" data-tooltip="Copy to clipboard"> + <i class="copy icon"></i> + </button> + </pre> + </div> + + <p>{{ _("Step 3: Commit Draft File Upload") }}</p> + + <div class="ui code-container"> + <pre class="ui segment code-block"> +{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} +curl -X POST "{{ config.SITE_API_URL }}/records/abcde-12345/draft/files/example_dataset.csv/commit" \ + -H "Authorization: Bearer {your-access-token}" +{#- ################## PREFORMATTED AREA TEXT END ################## -#} + <button class="ui button copy-btn" data-tooltip="Copy to clipboard"> + <i class="copy icon"></i> + </button> + </pre> + </div> + + <p> + {%- trans trimmed tuw_customizations_link = "#tuw_customizations" %} + Step 4: Publish the Draft (After curation request has been accepted - See <a href="{{ tuw_customizations_link }}" rel="noopener">curation endpoint</a>) + {%- endtrans %} + </p> + + <div class="ui code-container"> + <pre class="ui segment code-block"> +{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} +curl -X POST "{{ config.SITE_API_URL }}/records/abcde-12345/draft/actions/publish" \ + -H "Authorization: Bearer {your-access-token}" +{#- ################## PREFORMATTED AREA TEXT END ################## -#} + <button class="ui button copy-btn" data-tooltip="Copy to clipboard"> + <i class="copy icon"></i> + </button> + </pre> + </div> + + <p><strong>Python (requests) {{ _("Snippets") }}:</strong></p> + <p>{{ _("Step 1: Initialize File Upload") }}</p> + + <div class="ui code-container"> + <pre class="ui segment code-block"> +{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} +import requests +url = "{{ config.SITE_API_URL }}/records/abcde-12345/draft/files" +headers = { + "Authorization": "Bearer {your-access-token}", + "Content-Type": "application/json" +} +data = [ + { + "key": "example_dataset.csv" + } +] + +response = requests.post(url, json=data, headers=headers) +print(response.json()) +{#- ################## PREFORMATTED AREA TEXT END ################## -#} + <button class="ui button copy-btn" data-tooltip="Copy to clipboard"> + <i class="copy icon"></i> + </button> + </pre> + </div> + + <p>{{ _("Step 2: Upload File Content") }}</p> + + <div class="ui code-container"> + <pre class="ui segment code-block"> +{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} +import requests +url = "{{ config.SITE_API_URL }}/records/abcde-12345/draft/files/example_dataset.csv/content" +headers = { + "Authorization": "Bearer {your-access-token}", + "Content-Type": "application/octet-stream" +} + +with open("example_dataset.csv", "rb") as file_data: + response = requests.put(url, headers=headers, data=file_data) + +print(response.json()) +{#- ################## PREFORMATTED AREA TEXT END ################## -#} + <button class="ui button copy-btn" data-tooltip="Copy to clipboard"> + <i class="copy icon"></i> + </button> + </pre> + </div> + + <p>{{ _("Step 3: Commit Draft File Upload") }}</p> + + <div class="ui code-container"> + <pre class="ui segment code-block"> +{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} +import requests +url = "{{ config.SITE_API_URL }}/records/abcde-12345/draft/files/example_dataset.csv/commit" +headers = { + "Authorization": "Bearer {your-access-token}", +} + +response = requests.post(url, headers=headers) +print(response.json()) +{#- ################## PREFORMATTED AREA TEXT END ################## -#} + <button class="ui button copy-btn" data-tooltip="Copy to clipboard"> + <i class="copy icon"></i> + </button> + </pre> + </div> + + <p> + {%- trans trimmed tuw_customizations_link = "#tuw_customizations" %} + Step 4: Publish the Draft (After curation request has been accepted - See <a href="{{ tuw_customizations_link }}" rel="noopener">curation endpoint</a>) + {%- endtrans %} + </p> + + <div class="ui code-container"> + <pre class="ui segment code-block"> +{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} +import requests +url = "{{ config.SITE_API_URL }}/records/abcde-12345/draft/actions/publish" +headers = { + "Authorization": "Bearer {your-access-token}", +} +data = { + "metadata": { + "title": "New Dataset Title", + "creators": [{"name": "Doe, Jane"}], + "publication_date": "2025-01-09", + "resource_type": {"id": "dataset"} + }, + "files": {"enabled": True} +} + +response = requests.post(url, json=data, headers=headers) +print(response.json()) +{#- ################## PREFORMATTED AREA TEXT END ################## -#} + <button class="ui button copy-btn" data-tooltip="Copy to clipboard"> + <i class="copy icon"></i> + </button> + </pre> + </div> + + <!-- Example 5: File Download --> + <h3 id="case5">{{ _("Case 5 - File Download: Retrieving Contents from a Record.") }}</h3> + <p> + <strong>{{ _("User Story:") }}</strong> + <i>{{ _("As a researcher, I want to download an individual file from a dataset so that I can analyze its contents locally without navigating through multiple interfaces.") }}</i> + </p> + <p><strong>{{ _("Endpoint:") }} </strong><code>GET /api/records/{record_id}/files/{filename}/content</code></p> + <p><strong>{{ _("Token Required:") }} </strong>{{ _("No") }}</p> + + <p><strong>cURL:</strong></p> + <div class="ui code-container"> + <pre class="ui segment code-block"> +{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} +curl -JO "{{ config.SITE_API_URL }}/records/abcde-12345/files/example_dataset.csv/content" +{#- ################## PREFORMATTED AREA TEXT END ################## -#} + <button class="ui button copy-btn" data-tooltip="Copy to clipboard"> + <i class="copy icon"></i> + </button> + </pre> + </div> + + <p><strong>Python (requests):</strong></p> + <div class="ui code-container"> + <pre class="ui segment code-block"> +{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} +import os, re, requests +url = "{{ config.SITE_API_URL }}/records/abcde-12345/files/example_dataset.csv/content" +response = requests.get(url, stream=True) + +content_disposition = response.headers.get("Content-Disposition", "") +filename = re.search(r'filename="([^"]+)"', content_disposition).group(1) + +with open(filename, "wb") as f: + for chunk in response.iter_content(chunk_size=8192): + _ = f.write(chunk) + +print("File saved at: ", os.path.abspath(filename)) +{#- ################## PREFORMATTED AREA TEXT END ################## -#} + <button class="ui button copy-btn" data-tooltip="Copy to clipboard"> + <i class="copy icon"></i> + </button> + </pre> + </div> + + <p><strong>{{ _("Example Response Headers") }} (HTTP 200 - OK):</strong></p> + <div class="ui code-container"> + <pre class="ui segment code-block"> +{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} +Content-Disposition: attachment; filename="example_dataset.csv" +Content-Length: 5577907 +Content-Type: application/octet-stream +Date: Mon, 28 Fri 2025 13:56:29 GMT +ETag: "674c65f3-551cb3" +Last-Modified: Sun, 01 Dec 2024 13:34:43 GMT +{#- ################## PREFORMATTED AREA TEXT END ################## -#} + <button class="ui button copy-btn" data-tooltip="Copy to clipboard"> + <i class="copy icon"></i> + </button> + </pre> + </div> + + <h2 id="tuw_customizations">{{ _("Additional Customizations") }}</h2> + <h3>{{ _("Extended Functionality: Custom Endpoints") }}</h3> + <p> + {{ _("Our customized instance of the repository comes with additional endpoints that differ from what would be expected from a standard Invenio RDM installation.") }} + {{ _("These improvements cover the following:") }} + </p> + <ul> + <li> + <strong>{{ _("Curation Workflow Requests:") }}</strong> + <p> + {{ _("We offer an API that supports a custom curation process. Custom endpoints assign curators to records, review submissions, add curation notes, and allow publishing of curated content.") }} + {{ _("This workflow guarantees that data quality and compliance standards are met prior to data being made public.") }} + </p> + <p>{{ _("Create a new curation request:") }}</p> + <p><strong>{{ _("Endpoint:") }} </strong><code>POST /api/curations/</code></p> + <p> + <strong>{{ _("Token Required:") }} </strong> + {%- trans trimmed token_link = token_link %} + Yes — generate one <a href="{{ token_link }}">here</a>. + {%- endtrans %} + </p> + + <p><strong>cURL:</strong></p> + <div class="ui code-container"> + <pre class="ui segment code-block"> +{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} +curl -X POST "{{ config.SITE_API_URL }}/curations/" \ + -H "Authorization: Bearer {your-access-token}" \ + -H "Content-Type: application/json" \ + -d ' +{ + "topic":{ + "record": "fghij-54321" + } +}' +{#- ################## PREFORMATTED AREA TEXT END ################## -#} + <button class="ui button copy-btn" data-tooltip="Copy to clipboard"> + <i class="copy icon"></i> + </button> + </pre> + </div> + + <p><strong>Python (requests):</strong></p> + <div class="ui code-container"> + <pre class="ui segment code-block"> +{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} +import requests +url = "{{ config.SITE_API_URL }}/curations/" +headers = { + "Authorization": "Bearer {your-access-token}", +} +data = { + "topic":{ + "record": "fghij-54321" + } +} + +response = requests.post(url, json=data, headers=headers) +print(response.json()) +{#- ################## PREFORMATTED AREA TEXT END ################## -#} + <button class="ui button copy-btn" data-tooltip="Copy to clipboard"> + <i class="copy icon"></i> + </button> + </pre> + </div> + </li> + <li> + <strong>Invenio-DAMAP {{ _("Endpoints") }}:</strong> + <p> + Additionally, we provide extra endpoints that ship with the <a href="https://github.com/fair-data-austria/invenio-damap" target="_blank" rel="noopener">Invenio-DAMAP package</a>. + {{ _("They allow to directly link your record to a DAMAP-based system, by automatically filling specific DMP fields, saving you time and effort.") }} + {%- trans trimmed damap_page_link = url_for("invenio_theme_tuw.tuw_about_damap") %} + For further details about this integration, visit the dedicated <a href="{{ damap_page_link }}">DAMAP page</a>. + {%- endtrans %} + </p> + </li> + </ul> + + <h2>{{ _("Additional Resources") }}</h2> + <p> + {%- trans trimmed inveniordm_api_ref_link = inveniordm_api_ref_link %} + For further details, please refer to the official <a href="{{ inveniordm_api_ref_link }}" target="_blank" rel="noopener">InvenioRDM API Documentation</a>. + {%- endtrans %} + </p> + </section> + + {%- block javascript %} + {{ super() }} + {{ webpack["invenio-theme-tuw-clipboard.js"] }} + {%- endblock javascript %} + +{%- endblock page_body %} diff --git a/invenio_theme_tuw/theme/templates/semantic-ui/invenio_theme_tuw/about_damap.html b/invenio_theme_tuw/theme/templates/semantic-ui/invenio_theme_tuw/about_damap.html new file mode 100644 index 0000000000000000000000000000000000000000..6468d81b7543260f267e63f6f6dff644fb1e9c31 --- /dev/null +++ b/invenio_theme_tuw/theme/templates/semantic-ui/invenio_theme_tuw/about_damap.html @@ -0,0 +1,182 @@ +{# -*- coding: utf-8 -*- + + Copyright (C) 2025 TU Wien. + + Invenio Theme TUW 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 config.BASE_TEMPLATE %} + +{# This link is used multiple times throughout this page. #} +{% set token_link = url_for("invenio_oauth2server_settings.token_new") %} + +{%- block page_hero %} + <section id="hero" class="policies no-shrink"></section> +{%- endblock page_hero %} + +{%- block page_body %} + <section class="ui about container rel-mt-3"> + <a href="{{ url_for("invenio_theme_tuw.tuw_about_api") }}">â¬…ï¸ {{ _("To parent page") }}</a> + + <h1>{{ _("About DAMAP") }}</h1> + <ul> + <li> + <p>{{ _("Fetch your maDMPs:") }}</p> + <p><strong>{{ _("Endpoint:") }} </strong><code>GET /api/invenio_damap/damap/dmp</code></p> + <p> + <strong>{{ _("Token Required:") }}</strong> + {% trans trimmed token_link = token_link %} + Yes — generate one <a href="{{ token_link }}">here</a>. + {% endtrans %} + </p> + + <p><strong>cURL:</strong></p> + <div class="ui code-container"> + <pre class="ui segment code-block"> +{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} +curl "{{ config.SITE_API_URL }}/invenio_damap/damap/dmp" \ + -H "Authorization: Bearer {your-access-token}" +{#- ################## PREFORMATTED AREA TEXT END ################## -#} + <button class="ui button copy-btn" data-tooltip="{{ _("Copy to clipboard") }}"> + <i class="copy icon"></i> + </button> + </pre> + </div> + + <p><strong>Python (requests):</strong></p> + <div class="ui code-container"> + <pre class="ui segment code-block"> +{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} +import requests +url = "{{ config.SITE_API_URL }}/invenio_damap/damap/dmp" +headers = { + "Authorization": "Bearer {your-access-token}", +} +response = requests.post(url, headers=headers) +print(response.json()) +{#- ################## PREFORMATTED AREA TEXT END ################## -#} + <button class="ui button copy-btn" data-tooltip="Copy to clipboard"> + <i class="copy icon"></i> + </button> + </pre> + </div> + + <p><strong>{{ _("Example Response") }} (HTTP 200 - OK):</strong></p> + <div class="ui code-container"> + <pre class="ui segment code-block"> +{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} +{ + "hits": { + "hits": [ + { + "id": 4002, + "created": "2025-02-10T11:28:03.472Z", + "project": { + "id": 4002, + "description": "A very important chemistry project.", + "title": "Advanced Chemical Reactions Study" + }, + "datasets": [], + "links": {} + }, + { + "id": 4001, + "created": "2025-01-10T14:07:26.234Z", + "project": { + "id": 4001, + "description": "A very important climate project.", + "title": "Global Climate Change Analysis" + }, + "datasets": [], + "links": {} + } + ], + "total": 10 + }, + "links": { + "self": "{{ config.SITE_API_URL }}/invenio_damap/damap/dmp?facets=%7B%7D" + } +} +{#- ################## PREFORMATTED AREA TEXT END ################## -#} + <button class="ui button copy-btn" data-tooltip="{{ _("Copy to clipboard") }}"> + <i class="copy icon"></i> + </button> + </pre> + </div> + </li> + + <li> + <p>{{ _("Link your selected InvenioRDM record to the target maDMP:") }}</p> + <p><strong>{{ _("Endpoint:") }} </strong><code>POST /api/invenio_damap/damap/dmp/{dmp_id}/dataset/{record_id}</code></p> + <p> + <strong>{{ _("Token Required:") }}</strong> + {% trans trimmed token_link = token_link %} + Yes — generate one <a href="{{ token_link }}">here</a>. + {% endtrans %} + </p> + + <p><strong>cURL:</strong></p> + <div class="ui code-container"> + <pre class="ui segment code-block"> +{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} +curl -X POST "{{ config.SITE_API_URL }}/invenio_damap/dmp/1337/dataset/abcde-12345" \ + -H "Authorization: Bearer {your-access-token}" +{#- ################## PREFORMATTED AREA TEXT END ################## -#} + <button class="ui button copy-btn" data-tooltip="{{ _("Copy to clipboard") }}"> + <i class="copy icon"></i> + </button> + </pre> + </div> + + <p><strong>Python (requests):</strong></p> + <div class="ui code-container"> + <pre class="ui segment code-block"> +{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} +import requests +url = "{{ config.SITE_API_URL }}/invenio_damap/dmp/1337/dataset/abcde-12345" +headers = { + "Authorization": "Bearer {your-access-token}", +} +response = requests.post(url, headers=headers) +print(response.json()) +{#- ################## PREFORMATTED AREA TEXT END ################## -#} + <button class="ui button copy-btn" data-tooltip="{{ _("Copy to clipboard") }}"> + <i class="copy icon"></i> + </button> + </pre> + </div> + + <p><strong>{{ _("Example Response") }} (HTTP 201 - CREATED):</strong></p> + <div class="ui code-container"> + <pre class="ui segment code-block"> +{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} +{ + "id": "abcde-12345", + "metadata": { + "title": "New Dataset Title", + "creators": [{"name": "Doe, Jane"}], + "publication_date": "2025-01-09", + "resource_type": {"id": "dataset"} + }, + "links": { + "self": "{{ config.SITE_API_URL }}/records/abcde-12345", + "files": "{{ config.SITE_API_URL }}/records/abcde-12345/files" + } +} +{#- ################## PREFORMATTED AREA TEXT END ################## -#} + <button class="ui button copy-btn" data-tooltip="{{ _("Copy to clipboard") }}"> + <i class="copy icon"></i> + </button> + </pre> + </div> + </li> + </ul> + </section> + + {%- block javascript %} + {{ super() }} + {{ webpack["invenio-theme-tuw-clipboard.js"] }} + {%- endblock javascript %} + +{%- endblock page_body %} diff --git a/invenio_theme_tuw/theme/templates/semantic-ui/invenio_theme_tuw/about_vre.html b/invenio_theme_tuw/theme/templates/semantic-ui/invenio_theme_tuw/about_vre.html new file mode 100644 index 0000000000000000000000000000000000000000..a6467b43809cd787267eab531cf8742d0ce39058 --- /dev/null +++ b/invenio_theme_tuw/theme/templates/semantic-ui/invenio_theme_tuw/about_vre.html @@ -0,0 +1,86 @@ +{# -*- coding: utf-8 -*- + + Copyright (C) 2025 TU Wien. + + Invenio Theme TUW 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 config.BASE_TEMPLATE %} + +{%- block page_hero %} + <section id="hero" class="policies no-shrink"></section> +{%- endblock page_hero %} + +{%- block page_body %} + <section class="ui about container rel-mt-3"> + <a href="{{ url_for("invenio_theme_tuw.tuw_about") }}">â¬…ï¸ {{ _("To parent page") }}</a> + + <h1>{{ _("About the VRE extension") }}</h1> + <p> + {{ _("The VRE extension can be easily installed via") }} + <code>pip install vre-repository-connector</code>. + </p> + <p> + <strong>{{ _("Why Use It?") }}</strong> + <ul> + <li><strong>{{ _("Easy Integration:") }}</strong> {{ _("Access repository datasets straight from your notebook. No need to download files manually—just pull the data and dive in.") }}</li> + <li><strong>{{ _("Interactive Data Exploration:") }}</strong> {{ _("Search, filter, and preview datasets in real time. Write simple code that interacts with the repository's API and get instant results.") }}</li> + <li><strong>{{ _("Smoother Workflows:") }}</strong> {{ _("Automate repetitive tasks like retrieving metadata, cleaning data, and processing files, so you can focus on the actual research.") }}</li> + </ul> + </p> + <br> + <p> + <strong>{{ _("Use Case Example:") }}</strong> + {{ _("Assume, for instance, that you are a climate scientist who must examine the most recent temperature data.") }} + {{ _("With the VRE Repository Connector, you can write a few lines of Python code in your Jupyter Notebook to retrieve the dataset and start analyzing it immediately:") }} + </p> + + <div class="ui code-container"> + <pre class="ui segment code-block"> +{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} +# Example Jupyter Notebook using the VRE Connector +[1]: pip install vre-repository-connector +[1]: ... + +[2]: import vre_repository_connector as vrc + doi = "https://doi.org/10.12345/abcde-12345" + +# Retrieve a specific dataset's file by its DOI +[3]: vrc.download(doi) +[3]: 1) x.zip + 2) y.zip + 3) z.zip + Select [1-3]: 2 + '/tmp/tmpj8huipi7/abcde-12345/y.zip' + +# Proceed with your analysis using libraries like pandas or matplotlib +{#- ################## PREFORMATTED AREA TEXT END ################## -#} + <button class="ui button copy-btn" data-tooltip="{{ _("Copy to clipboard") }}"> + <i class="copy icon"></i> + </button> + </pre> + </div> + + <p> + {{ _("And just like that, you\'re ready to analyze!") }} + </p> + <p> + {{ _("In addition to saving time, the VRE Repository Connector promotes repeatable, data-driven research by bridging the gap between interactive research tools and robust repository capabilities.") }} + {{ _("VRE is intended to make your research workflow as integrated and efficient as possible, whether you're exploring new datasets or automating your analysis pipeline — all from within Jupyter.") }} 🚀 + </p> + <h2>{{ _("Additional Resources") }}</h2> + <p> + {%- trans trimmed vre_repo_page = "https://gitlab.tuwien.ac.at/crdm/vre-repository-connector" %} + For further details, please refer to the + <a href="{{ vre_repo_page }}" target="_blank" rel="noopener">VRE Repository Connector page</a>. + {%- endtrans %} + </p> + </section> + + {%- block javascript %} + {{ super() }} + {{ webpack["invenio-theme-tuw-clipboard.js"] }} + {%- endblock javascript %} + +{%- endblock page_body %} diff --git a/invenio_theme_tuw/theme/templates/semantic-ui/invenio_theme_tuw/overrides/footer.html b/invenio_theme_tuw/theme/templates/semantic-ui/invenio_theme_tuw/overrides/footer.html index c2e5969a2e0110ed6cea0b0a4dfec3805eef1dea..65405d8cd10119ed27ebab67d99c8b1daf6d1062 100644 --- a/invenio_theme_tuw/theme/templates/semantic-ui/invenio_theme_tuw/overrides/footer.html +++ b/invenio_theme_tuw/theme/templates/semantic-ui/invenio_theme_tuw/overrides/footer.html @@ -3,7 +3,7 @@ Copyright (C) 2019-2020 CERN. Copyright (C) 2019-2020 Northwestern University. Copyright (C) 2021 Graz University of Technology. - Copyright (C) 2020-2023 TU Wien. + Copyright (C) 2020-2025 TU Wien. Invenio Theme TUW is free software; you can redistribute it and/or modify it under the terms of the MIT License; see LICENSE file for more details. @@ -20,6 +20,7 @@ {%- set fairsharing_url = "https://fairsharing.org/FAIRsharing.88d503" %} {#- urls for footer links #} +{%- set about_url = url_for("invenio_theme_tuw.tuw_about") %} {%- set policies_url = url_for("invenio_theme_tuw.tuw_policies") %} {%- set terms_of_use_url = url_for("invenio_theme_tuw.tuw_terms_of_use") %} {%- set privacy_info_url = "https://www.tuwien.at/index.php?eID=dms&s=4&path=Documents/Data%20Protection%20Declaration%20Other/Data_Protection_Information_Research_Data.pdf" %} @@ -46,6 +47,7 @@ </div> <div class="row-border"></div> <nav id="links-container" class="grid-container"> + <a href="{{ about_url }}">{{ _("About") }}</a> <a href="{{ policies_url }}">{{ _("Policies") }}</a> <a href="{{ terms_of_use_url }}">{{ _("Terms of Use") }}</a> <a href="{{ privacy_info_url }}" target="_blank" rel="noopener">{{ _("Privacy Info") }}</a> diff --git a/invenio_theme_tuw/views.py b/invenio_theme_tuw/views.py index 436744bfc98e3ff2fd619a1f0564e1a91def6a4b..d7ee9bbbf1fb99320a47be1c59f3424051ebc4c9 100644 --- a/invenio_theme_tuw/views.py +++ b/invenio_theme_tuw/views.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright (C) 2020-2024 TU Wien. +# Copyright (C) 2020-2025 TU Wien. # # Invenio-Theme-TUW is free software; you can redistribute it and/or modify # it under the terms of the MIT License; see LICENSE file for more details. @@ -20,6 +20,7 @@ from flask import ( ) from flask_login import current_user, login_required from invenio_accounts.proxies import current_datastore +from invenio_app_rdm.config import _get_package_version from invenio_app_rdm.records_ui.views.deposits import deposit_create, deposit_edit from invenio_communities.proxies import current_communities from invenio_communities.views.communities import communities_new @@ -248,6 +249,28 @@ def create_blueprint(app): ) return response, 200 if not captcha_failed else 428 + @blueprint.route("/tuw/about") + def tuw_about(): + """Page showing general information about TUWRD.""" + return render_template( + "invenio_theme_tuw/about.html", package_version=_get_package_version() + ) + + @blueprint.route("/tuw/about/api") + def tuw_about_api(): + """Page showing information about the TUWRD API.""" + return render_template("invenio_theme_tuw/about_api.html") + + @blueprint.route("/tuw/about/damap") + def tuw_about_damap(): + """Page showing information about the TUWRD API.""" + return render_template("invenio_theme_tuw/about_damap.html") + + @blueprint.route("/tuw/about/vre") + def tuw_about_vre(): + """Page showing information about the TUWRD API.""" + return render_template("invenio_theme_tuw/about_vre.html") + @blueprint.route("/tuw/policies") def tuw_policies(): """Page showing the available repository policies.""" diff --git a/invenio_theme_tuw/webpack.py b/invenio_theme_tuw/webpack.py index 721085c583306e70acb57fb9a58cfea0461245ca..38991ae74a42ea2ddd5f58cc1e969b8f2dd67014 100644 --- a/invenio_theme_tuw/webpack.py +++ b/invenio_theme_tuw/webpack.py @@ -68,10 +68,13 @@ theme = WebpackThemeBundle( themes={ "semantic-ui": { "entry": { - "invenio-theme-tuw-login": "./less/invenio_theme_tuw/login.less", - "invenio-theme-tuw-tracking": "./js/invenio_theme_tuw/tracking/index.js", + # JS + "invenio-theme-tuw-clipboard": "./js/invenio_theme_tuw/clipboard/index.js", "invenio-theme-tuw-mobilemenu": "./js/invenio_theme_tuw/mobilemenu/index.js", "invenio-theme-tuw-snowfall": "./js/invenio_theme_tuw/snowfall/index.js", + "invenio-theme-tuw-tracking": "./js/invenio_theme_tuw/tracking/index.js", + # LESS + "invenio-theme-tuw-login": "./less/invenio_theme_tuw/login.less", "invenio-theme-tuw-tuwstones": "./less/invenio_theme_tuw/tuwstone.less", "invenio-theme-tuw-user-infos": "./less/invenio_theme_tuw/user_infos.less", "invenio-theme-tuw-users-welcome": "./less/invenio_theme_tuw/users_welcome.less",