Skip to content

Implementation of RFC 0072 - Uppy uploader UI for pluggable transfer types #2994

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

Open
wants to merge 1 commit into
base: master
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
8 changes: 7 additions & 1 deletion invenio_app_rdm/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -924,6 +924,13 @@ def github_link_render(record):

APP_RDM_RECORDS_EXPORT_URL = "/records/<pid_value>/export/<export_format>"

APP_RDM_DEPOSIT_NG_FILES_UI_ENABLED = False
"""
Feature toggle to enable the next-generation (NG) file uploader UI in the deposit form.

When enabled, the deposit form will use the new Uppy.io-based file uploader, replacing the current file upload interface.
"""

APP_RDM_DEPOSIT_FORM_DEFAULTS = {
"publication_date": lambda: datetime.now().strftime("%Y-%m-%d"),
"rights": [
Expand Down Expand Up @@ -1482,7 +1489,6 @@ def github_link_render(record):
APP_RDM_SUBCOMMUNITIES_LABEL = "Subcommunities"
"""Label for the subcommunities in the community browse page."""


RDM_DETAIL_SIDE_BAR_MANAGE_ATTRIBUTES_EXTENSION_TEMPLATE = None
"""Side bar manage attributes extension template."""

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
{%- block css %}
{{ super() }}
<link rel="stylesheet" type="text/css" href="/communities/{{community.slug}}/community-theme-{{ community.revision_id }}.css">
{%- if config.APP_RDM_DEPOSIT_NG_FILES_UI_ENABLED %}
{{ webpack['uppy-file-uploader.css'] }}
{%- endif %}
{%- endblock %}
{%- endif %}

Expand Down Expand Up @@ -49,6 +52,8 @@
value='{{ config.USERS_RESOURCES_GROUPS_ENABLED | tojson }}'>
<input type="hidden" name="records-resources-allow-empty-files"
value='{{ config.RECORDS_RESOURCES_ALLOW_EMPTY_FILES | tojson }}'>
<input type="hidden" name="deposits-use-uppy-ui"
value='{{ config.APP_RDM_DEPOSIT_NG_FILES_UI_ENABLED | tojson }}'>

{%- if forms_config %}
<input type="hidden" name="deposits-config"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@


{% macro preview_file_box(file, pid, is_preview, record, include_deleted) %}
{%- set is_remote_file = file.transfer.type == file_transfer_type.REMOTE %}
<div class="ui accordion panel mb-10 {{record.ui.access_status.id}}" href="#files-preview-accordion-panel">
<h3 class="active title panel-heading {{ record.ui.access_status.id }} m-0">
<div
Expand All @@ -53,9 +54,22 @@ <h3 class="active title panel-heading {{ record.ui.access_status.id }} m-0">
aria-labelledby="files-preview-accordion-trigger"
class="active content preview-container pt-0 {{record.ui.access_status.id}}"
>
{%- if is_remote_file %}
<div class="ui info message">
<div class="header">
{{ _('This file cannot be previewed') }}
</div>
<ul class="list">
<li>{{ _('This file is an external reference and not stored directly in this repository.
To access its content, please download it and open it locally.') }}
</li>
</ul>
</div>
{%- else %}
<div>
{{ preview_file('invenio_app_rdm_records.record_file_preview', pid_value=pid, filename=file.key, is_preview=is_preview, include_deleted=include_deleted) }}
</div>
{%- endif %}
</div>
</div>
{%- endmacro %}
Expand Down Expand Up @@ -93,6 +107,7 @@ <h3 class="active title panel-heading {{ record.ui.access_status.id }} m-0">
{% endif %}
{% for file in files %}
{% if not file.access.hidden %}
{%- set is_remote_file = file.transfer.type == file_transfer_type.REMOTE %}
{% if is_preview %}
{%- set file_url_download = url_for(download_endpoint, pid_value=pid, filename=file.key, download=1, preview=1) %}
{%- set file_url_preview = url_for(preview_endpoint, pid_value=pid, filename=file.key, preview=1, include_deleted=include_deleted_value) %}
Expand All @@ -107,16 +122,18 @@ <h3 class="active title panel-heading {{ record.ui.access_status.id }} m-0">
<div>
<a href="{{ file_url_download }}">{{ file.key }}</a>
</div>
{%- if not is_remote_file %}
<small class="ui text-muted font-tiny">{{ file.checksum }}
<div class="ui icon inline-block" data-tooltip="{{_('This is the file fingerprint (checksum), which can be used to verify the file integrity.')}}">
<i class="question circle checksum icon"></i>
</div>
</small>
{%- endif %}
</td>
<td>{{ file.size|filesizeformat(binary=binary_sizes) }}</td>
<td>{%- if is_remote_file %}{{_("N/A (external)")}}{%- else -%}{{ file.size|filesizeformat(binary=binary_sizes) }}{%- endif %}</td>
<td class="right aligned">
<span>
{% if with_preview and file_type|lower is previewable %}
{% if with_preview and file_type|lower is previewable and not is_remote_file %}
<a role="button" class="ui compact mini button preview-link" href="{{ file_url_preview }}" target="preview-iframe" data-file-key="{{file.key}}">
<i class="eye icon" aria-hidden="true"></i>{{_("Preview")}}
</a>
Expand All @@ -140,7 +157,7 @@ <h3 class="active title panel-heading {{ record.ui.access_status.id }} m-0">
<h3 class="active title panel-heading {{ record.ui.access_status.id }} m-0">
<div role="button" id="files-list-accordion-trigger" aria-controls="files-list-accordion-panel" aria-expanded="true" tabindex="0" class="trigger">
{{ _("Files") }}
<small class="text-muted">{% if files %} ({{files|sum(attribute='size')|filesizeformat(binary=binary_sizes)}}){% endif %}</small>
<small class="text-muted">{% if files %} ({{files|map(attribute='size', default=0)|sum()|filesizeformat(binary=binary_sizes)}}){% endif %}</small>
<i class="angle right icon" aria-hidden="true"></i>
</div>
</h3>
Expand Down
8 changes: 7 additions & 1 deletion invenio_app_rdm/records_ui/views/deposits.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
from invenio_rdm_records.resources.serializers import UIJSONSerializer
from invenio_rdm_records.services.schemas import RDMRecordSchema
from invenio_rdm_records.services.schemas.utils import dump_empty
from invenio_rdm_records.views import file_transfer_type_constants
from invenio_records_resources.proxies import current_transfer_registry
from invenio_records_resources.services.errors import PermissionDeniedError
from invenio_search.engine import dsl
from invenio_vocabularies.proxies import current_service as vocabulary_service
Expand Down Expand Up @@ -361,6 +363,7 @@ def get_form_config(**kwargs):
cf for cf in custom_fields["ui"] if not cf.get("hide_from_upload_form", False)
]
quota = deepcopy(conf.get("APP_RDM_DEPOSIT_FORM_QUOTA", {}))
max_file_size = conf.get("RDM_FILES_DEFAULT_MAX_FILE_SIZE", None)
record_quota = kwargs.pop("quota", None)
if record_quota:
quota["maxStorage"] = record_quota["quota_size"]
Expand All @@ -375,7 +378,7 @@ def get_form_config(**kwargs):
current_locale=str(current_i18n.locale),
default_locale=conf.get("BABEL_DEFAULT_LOCALE", "en"),
pids=get_form_pids_config(record=record),
quota=quota,
quota=dict(**quota, maxFileSize=max_file_size),
decimal_size_display=conf.get("APP_RDM_DISPLAY_DECIMAL_FILE_SIZES", True),
links=dict(
user_dashboard_request=conf["RDM_REQUESTS_ROUTES"][
Expand All @@ -387,6 +390,9 @@ def get_form_config(**kwargs):
publish_modal_extra=current_app.config.get(
"APP_RDM_DEPOSIT_FORM_PUBLISH_MODAL_EXTRA"
),
default_transfer_type=current_transfer_registry.default_transfer_type,
enabled_transfer_types=list(current_transfer_registry.get_transfer_types()),
transfer_types=file_transfer_type_constants,
**kwargs,
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
DeleteButton,
DepositStatusBox,
FileUploader,
UppyUploader,
FormFeedback,
IdentifiersField,
PIDField,
Expand Down Expand Up @@ -114,13 +115,15 @@
allowRecordRestriction,
groupsEnabled,
allowEmptyFiles,
useUppy,
} = this.props;

// Adding section id to custom fields UI, to be used for accordions
const customFieldsUI = this.config.custom_fields.ui.map((section) => ({
...section,
id: section.section.toLowerCase().replace(/\s+/g, "-") + "-section",
}));
const UploaderField = useUppy ? UppyUploader : FileUploader;

return (
<Overridable
Expand Down Expand Up @@ -196,13 +199,14 @@
filesLocked={filesLocked}
allowEmptyFiles={allowEmptyFiles}
>
<FileUploader
<UploaderField
isDraftRecord={!record.is_published}
quota={this.config.quota}
decimalSizeDisplay={this.config.decimal_size_display}
showMetadataOnlyToggle={permissions?.can_manage_files}
allowEmptyFiles={allowEmptyFiles}
filesLocked={filesLocked}
fileUploadConcurrency={config.fileUploadConcurrency}
/>
</Overridable>
</AccordionField>
Expand Down Expand Up @@ -765,6 +769,7 @@
permissions: PropTypes.object,
filesLocked: PropTypes.bool,
allowEmptyFiles: PropTypes.bool,
useUppy: PropTypes.bool,

Check warning on line 772 in invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/deposit/RDMDepositForm.js

View workflow job for this annotation

GitHub Actions / JS / Tests (22.x)

propType "useUppy" is not required, but has no corresponding defaultProps declaration
};

RDMDepositForm.defaultProps = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ ReactDOM.render(
preselectedCommunity={getInputFromDOM("deposits-draft-community")}
files={getInputFromDOM("deposits-record-files")}
config={getInputFromDOM("deposits-config")}
useUppy={getInputFromDOM("deposits-use-uppy-ui")}
permissions={getInputFromDOM("deposits-record-permissions")}
filesLocked={getInputFromDOM("deposits-record-locked-files")}
recordRestrictionGracePeriod={getInputFromDOM(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright (C) 2025 CESNET
*
* Invenio RDM Records is free software; you can redistribute it and/or modify
* it under the terms of the MIT License; see LICENSE file for more details.
*/

@import "@uppy/core/dist/style.min.css";
@import "@uppy/dashboard/dist/style.min.css";
@import "@uppy/image-editor/dist/style.min.css";

.uppy-Dashboard-AddFiles {
padding: 1.2rem;
}
.uppy-Dashboard-AddFiles-info {
display: block;
}

.uppy-Dashboard-note {
padding-top: 3rem;
}

.uppy-Dashboard-inner {
border-radius: 0 0 5px 5px;
}

.uppy-Dashboard-innerWrap {
height: 350px;

&:has(#uppy-DashboardContent-panel--editor) {
height: 500px;
}
}

.uppy-DashboardContent-bar, .uppy-StatusBar {
z-index: 10;
}
1 change: 1 addition & 0 deletions invenio_app_rdm/theme/webpack.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"invenio-domains-administration": "./js/invenio_app_rdm/administration/domains/index.js",
"invenio-audit-logs-administration": "./js/invenio_app_rdm/administration/auditLogs/index.js",
"invenio-communities-browse": "./js/invenio_app_rdm/subcommunity/browse.js",
"uppy-file-uploader": "./less/invenio_app_rdm/file_uploader/uppy.less",
},
dependencies={
"@babel/runtime": "^7.9.0",
Expand Down
Loading