invenio-app-rdm 13.0.0rc3__py2.py3-none-any.whl → 13.0.0rc6__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- invenio_app_rdm/__init__.py +1 -1
- invenio_app_rdm/config.py +7 -0
- invenio_app_rdm/ext.py +2 -2
- invenio_app_rdm/records_ui/templates/semantic-ui/invenio_app_rdm/records/macros/doi.html +7 -5
- invenio_app_rdm/records_ui/views/deposits.py +4 -4
- invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/components/CopyButton.js +38 -19
- invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/landing_page/ExportDropdown.js +7 -2
- invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/landing_page/theme.js +4 -0
- invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/theme.js +9 -0
- invenio_app_rdm/theme/assets/semantic-ui/less/invenio_app_rdm/theme/globals/site.overrides +6 -1
- invenio_app_rdm/theme/assets/semantic-ui/less/invenio_app_rdm/theme/modules/accordion.overrides +9 -0
- invenio_app_rdm/theme/templates/semantic-ui/invenio_app_rdm/intro_section.html +7 -6
- invenio_app_rdm/theme/webpack.py +0 -1
- invenio_app_rdm/upgrade_scripts/migrate_12_0_to_13_0.py +94 -65
- {invenio_app_rdm-13.0.0rc3.dist-info → invenio_app_rdm-13.0.0rc6.dist-info}/METADATA +28 -2
- {invenio_app_rdm-13.0.0rc3.dist-info → invenio_app_rdm-13.0.0rc6.dist-info}/RECORD +20 -60
- {invenio_app_rdm-13.0.0rc3.dist-info → invenio_app_rdm-13.0.0rc6.dist-info}/top_level.txt +0 -1
- invenio_app_rdm/theme/assets/semantic-ui/translations/invenio_app_rdm/i18next-scanner.config.js +0 -64
- invenio_app_rdm/theme/assets/semantic-ui/translations/invenio_app_rdm/package-lock.json +0 -2129
- invenio_app_rdm/theme/assets/semantic-ui/translations/invenio_app_rdm/scripts/compileCatalog.js +0 -118
- invenio_app_rdm/theme/assets/semantic-ui/translations/invenio_app_rdm/scripts/fixTrailingNewlines.js +0 -23
- invenio_app_rdm/theme/assets/semantic-ui/translations/invenio_app_rdm/scripts/initCatalog.js +0 -20
- invenio_app_rdm/theme/assets/semantic-ui/translations/invenio_app_rdm/scripts/postExtractMessages.js +0 -36
- tests/__init__.py +0 -8
- tests/api/__init__.py +0 -8
- tests/api/conftest.py +0 -24
- tests/api/test_protect_files_rest.py +0 -73
- tests/api/test_record_api.py +0 -175
- tests/api/test_stats_api.py +0 -26
- tests/conftest.py +0 -390
- tests/fixtures/__init__.py +0 -8
- tests/fixtures/app_data/oai_sets.yaml +0 -3
- tests/fixtures/app_data/pages/about.html +0 -1
- tests/fixtures/app_data/pages.yaml +0 -4
- tests/fixtures/conftest.py +0 -27
- tests/fixtures/test_cli.py +0 -25
- tests/fixtures/test_fixtures.py +0 -46
- tests/mock_module/__init__.py +0 -7
- tests/mock_module/templates/mock_mail.html +0 -27
- tests/mock_module/views.py +0 -32
- tests/redirector/__init__.py +0 -8
- tests/redirector/conftest.py +0 -54
- tests/redirector/test_redirector.py +0 -28
- tests/test_tasks.py +0 -209
- tests/test_utils.py +0 -67
- tests/test_version.py +0 -16
- tests/test_views.py +0 -43
- tests/ui/__init__.py +0 -8
- tests/ui/conftest.py +0 -115
- tests/ui/test_deposits.py +0 -115
- tests/ui/test_export_formats.py +0 -37
- tests/ui/test_file_download.py +0 -73
- tests/ui/test_filters.py +0 -10
- tests/ui/test_robotstxt.py +0 -35
- tests/ui/test_signposting_ui.py +0 -95
- tests/ui/test_sitemaps.py +0 -85
- tests/ui/test_stats_ui.py +0 -92
- {invenio_app_rdm-13.0.0rc3.dist-info → invenio_app_rdm-13.0.0rc6.dist-info}/WHEEL +0 -0
- {invenio_app_rdm-13.0.0rc3.dist-info → invenio_app_rdm-13.0.0rc6.dist-info}/entry_points.txt +0 -0
- {invenio_app_rdm-13.0.0rc3.dist-info → invenio_app_rdm-13.0.0rc6.dist-info}/licenses/LICENSE +0 -0
invenio_app_rdm/__init__.py
CHANGED
invenio_app_rdm/config.py
CHANGED
|
@@ -903,6 +903,13 @@ APP_RDM_RECORD_EXPORTERS = {
|
|
|
903
903
|
"content-type": "application/x-yaml",
|
|
904
904
|
"filename": "{id}.yaml",
|
|
905
905
|
},
|
|
906
|
+
"datapackage": {
|
|
907
|
+
"name": _("Data Package JSON"),
|
|
908
|
+
"serializer": "invenio_rdm_records.resources.serializers:DataPackageSerializer",
|
|
909
|
+
"params": {},
|
|
910
|
+
"content-type": "application/ld+json",
|
|
911
|
+
"filename": "{id}.json",
|
|
912
|
+
},
|
|
906
913
|
}
|
|
907
914
|
|
|
908
915
|
APP_RDM_RECORD_LANDING_PAGE_EXTERNAL_LINKS = []
|
invenio_app_rdm/ext.py
CHANGED
|
@@ -33,10 +33,10 @@ def finalize_app(app):
|
|
|
33
33
|
|
|
34
34
|
def init_config(app):
|
|
35
35
|
"""Initialize configuration."""
|
|
36
|
-
record_doi_required = (
|
|
36
|
+
record_doi_required = bool(
|
|
37
37
|
app.config["RDM_PERSISTENT_IDENTIFIERS"].get("doi", {}).get("required")
|
|
38
38
|
)
|
|
39
|
-
parent_doi_required = (
|
|
39
|
+
parent_doi_required = bool(
|
|
40
40
|
app.config["RDM_PARENT_PERSISTENT_IDENTIFIERS"].get("doi", {}).get("required")
|
|
41
41
|
)
|
|
42
42
|
|
|
@@ -6,15 +6,17 @@
|
|
|
6
6
|
#}
|
|
7
7
|
|
|
8
8
|
{% macro show_doi(doi_value, record_ui, badge_id="record-doi-badge", modal_id="doi-modal", subheader=None, parent_doi=false) %}
|
|
9
|
+
{%- set doi_link = record_ui["links"]["doi"] if not parent_doi else record_ui["links"]["parent_doi"] %}
|
|
9
10
|
<dt class="ui tiny header">{{_('DOI')}}
|
|
10
11
|
{% if subheader %}
|
|
11
|
-
<i><span class="doi sub header">{{subheader}}</span></i
|
|
12
|
+
<i><span class="doi sub header">{{subheader}}</span></i>
|
|
12
13
|
{% endif %}
|
|
14
|
+
</dt>
|
|
13
15
|
<dd>
|
|
14
|
-
<span class="get-badge" data-toggle="tooltip" data-placement="bottom"
|
|
15
|
-
title="{{ _('Get the DOI badge!') }}"
|
|
16
|
-
<img id='{{badge_id}}' data-target="[data-modal='{{ doi_value }}']"
|
|
16
|
+
<span class="get-badge details-doi-section" data-toggle="tooltip" data-placement="bottom">
|
|
17
|
+
<img id='{{badge_id}}' data-target="[data-modal='{{ doi_value }}']" title="{{ _('Get the DOI badge!') }}"
|
|
17
18
|
src="{{ url_for('invenio_formatter_badges.badge', title='DOI', value=doi_value, ext='svg') }}" alt="{{ doi_value }}" />
|
|
19
|
+
<div id="copy-button-{{ badge_id }}" class="copy-doi-button" data-value={{ doi_link }} data-size="mini"></div>
|
|
18
20
|
</span>
|
|
19
21
|
|
|
20
22
|
<div id="{{modal_id}}" class="ui modal fade badge-modal" data-modal="{{ doi_value }}">
|
|
@@ -27,7 +29,7 @@
|
|
|
27
29
|
<pre>{{ doi_value }}</pre>
|
|
28
30
|
</h4>
|
|
29
31
|
{% from "semantic-ui/invenio_formatter/macros/badges.html" import badges_formats_list %}
|
|
30
|
-
{{ badges_formats_list(url_for('invenio_formatter_badges.badge', title='DOI', value=doi_value, ext='svg', _external=True, _scheme='https'),
|
|
32
|
+
{{ badges_formats_list(url_for('invenio_formatter_badges.badge', title='DOI', value=doi_value, ext='svg', _external=True, _scheme='https'), doi_link) }}
|
|
31
33
|
</div>
|
|
32
34
|
</div>
|
|
33
35
|
</dd>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# Copyright (C) 2019-2025 CERN.
|
|
4
4
|
# Copyright (C) 2019-2021 Northwestern University.
|
|
5
5
|
# Copyright (C) 2021 TU Wien.
|
|
6
|
-
# Copyright (C) 2022-
|
|
6
|
+
# Copyright (C) 2022-2025 KTH Royal Institute of Technology
|
|
7
7
|
# Copyright (C) 2023-2024 Graz University of Technology.
|
|
8
8
|
#
|
|
9
9
|
# Invenio App RDM is free software; you can redistribute it and/or modify it
|
|
@@ -100,9 +100,9 @@ def get_form_pids_config(record=None):
|
|
|
100
100
|
|
|
101
101
|
pids_provider = {
|
|
102
102
|
"scheme": scheme,
|
|
103
|
-
"field_label": "Digital Object Identifier",
|
|
104
|
-
"pid_label": "DOI",
|
|
105
|
-
"pid_placeholder": "Copy/paste your existing DOI here...",
|
|
103
|
+
"field_label": _("Digital Object Identifier"),
|
|
104
|
+
"pid_label": _("DOI"),
|
|
105
|
+
"pid_placeholder": _("Copy/paste your existing DOI here..."),
|
|
106
106
|
"can_be_managed": can_be_managed,
|
|
107
107
|
"can_be_unmanaged": can_be_unmanaged,
|
|
108
108
|
"btn_label_discard_pid": _(
|
|
@@ -7,29 +7,38 @@
|
|
|
7
7
|
import React, { Component } from "react";
|
|
8
8
|
import PropTypes from "prop-types";
|
|
9
9
|
import { Button, Popup } from "semantic-ui-react";
|
|
10
|
-
import { CopyToClipboard } from "react-copy-to-clipboard";
|
|
11
10
|
import { i18next } from "@translations/invenio_app_rdm/i18next";
|
|
12
11
|
|
|
13
12
|
class SimpleCopyButton extends React.Component {
|
|
13
|
+
fetchUrl = async (url) => {
|
|
14
|
+
return await (await fetch(url)).text();
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
handleClick = async () => {
|
|
18
|
+
const { url, text, onCopy } = this.props;
|
|
19
|
+
let textToCopy = text;
|
|
20
|
+
if (url) {
|
|
21
|
+
textToCopy = await this.fetchUrl(url);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
await navigator.clipboard.writeText(textToCopy);
|
|
25
|
+
onCopy(text);
|
|
26
|
+
};
|
|
27
|
+
|
|
14
28
|
render() {
|
|
15
|
-
const {
|
|
29
|
+
const { hoverState, size } = this.props;
|
|
16
30
|
|
|
17
31
|
return (
|
|
18
|
-
<
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
aria-label={i18next.t("Copy to clipboard")}
|
|
29
|
-
onMouseEnter={hoverState}
|
|
30
|
-
onMouseLeave={hoverState}
|
|
31
|
-
/>
|
|
32
|
-
</CopyToClipboard>
|
|
32
|
+
<Button
|
|
33
|
+
className="copy"
|
|
34
|
+
basic
|
|
35
|
+
size={size}
|
|
36
|
+
icon="copy"
|
|
37
|
+
aria-label={i18next.t("Copy to clipboard")}
|
|
38
|
+
onClick={this.handleClick} // Handle click to fetch from url if url passed, otherwise use text from props
|
|
39
|
+
onMouseEnter={hoverState}
|
|
40
|
+
onMouseLeave={hoverState}
|
|
41
|
+
/>
|
|
33
42
|
);
|
|
34
43
|
}
|
|
35
44
|
}
|
|
@@ -37,11 +46,15 @@ class SimpleCopyButton extends React.Component {
|
|
|
37
46
|
SimpleCopyButton.propTypes = {
|
|
38
47
|
text: PropTypes.string.isRequired,
|
|
39
48
|
onCopy: PropTypes.func.isRequired,
|
|
49
|
+
url: PropTypes.func,
|
|
40
50
|
hoverState: PropTypes.func,
|
|
51
|
+
size: PropTypes.string,
|
|
41
52
|
};
|
|
42
53
|
|
|
43
54
|
SimpleCopyButton.defaultProps = {
|
|
44
55
|
hoverState: null,
|
|
56
|
+
url: null,
|
|
57
|
+
size: "medium",
|
|
45
58
|
};
|
|
46
59
|
|
|
47
60
|
export class CopyButton extends Component {
|
|
@@ -86,12 +99,12 @@ export class CopyButton extends Component {
|
|
|
86
99
|
};
|
|
87
100
|
|
|
88
101
|
render() {
|
|
89
|
-
const { text,
|
|
102
|
+
const { popUpPosition, text, url, size } = this.props;
|
|
90
103
|
const { confirmationPopupMsg, confirmationPopupIsOpen, hoverPopupIsOpen } =
|
|
91
104
|
this.state;
|
|
92
105
|
|
|
93
106
|
return (
|
|
94
|
-
text && (
|
|
107
|
+
(text || url) && ( // Ensure text or url is provided
|
|
95
108
|
<Popup
|
|
96
109
|
role="alert"
|
|
97
110
|
open={hoverPopupIsOpen || confirmationPopupIsOpen}
|
|
@@ -103,7 +116,9 @@ export class CopyButton extends Component {
|
|
|
103
116
|
<SimpleCopyButton
|
|
104
117
|
text={text}
|
|
105
118
|
onCopy={this.onCopy}
|
|
119
|
+
url={url}
|
|
106
120
|
hoverState={this.hoverStateHandler}
|
|
121
|
+
size={size}
|
|
107
122
|
/>
|
|
108
123
|
}
|
|
109
124
|
/>
|
|
@@ -115,9 +130,13 @@ export class CopyButton extends Component {
|
|
|
115
130
|
CopyButton.propTypes = {
|
|
116
131
|
popUpPosition: PropTypes.string,
|
|
117
132
|
text: PropTypes.string,
|
|
133
|
+
url: PropTypes.func,
|
|
134
|
+
size: PropTypes.string,
|
|
118
135
|
};
|
|
119
136
|
|
|
120
137
|
CopyButton.defaultProps = {
|
|
121
138
|
popUpPosition: "right center",
|
|
122
139
|
text: "",
|
|
140
|
+
url: "",
|
|
141
|
+
size: "medium",
|
|
123
142
|
};
|
|
@@ -9,6 +9,7 @@ import React, { Component } from "react";
|
|
|
9
9
|
import PropTypes from "prop-types";
|
|
10
10
|
import { Grid, Dropdown, Button } from "semantic-ui-react";
|
|
11
11
|
import { i18next } from "@translations/invenio_app_rdm/i18next";
|
|
12
|
+
import { CopyButton } from "@js/invenio_app_rdm/components/CopyButton";
|
|
12
13
|
|
|
13
14
|
export class ExportDropdown extends Component {
|
|
14
15
|
constructor(props) {
|
|
@@ -18,6 +19,7 @@ export class ExportDropdown extends Component {
|
|
|
18
19
|
selectedFormatUrl: formats[0]?.export_url,
|
|
19
20
|
};
|
|
20
21
|
}
|
|
22
|
+
|
|
21
23
|
render() {
|
|
22
24
|
const { formats } = this.props;
|
|
23
25
|
const { selectedFormatUrl } = this.state;
|
|
@@ -31,7 +33,7 @@ export class ExportDropdown extends Component {
|
|
|
31
33
|
|
|
32
34
|
return (
|
|
33
35
|
<Grid>
|
|
34
|
-
<Grid.Column width={
|
|
36
|
+
<Grid.Column width={10}>
|
|
35
37
|
<Dropdown
|
|
36
38
|
aria-label={i18next.t("Export selection")}
|
|
37
39
|
selection
|
|
@@ -42,7 +44,7 @@ export class ExportDropdown extends Component {
|
|
|
42
44
|
defaultValue={selectedFormatUrl}
|
|
43
45
|
/>
|
|
44
46
|
</Grid.Column>
|
|
45
|
-
<Grid.Column width={
|
|
47
|
+
<Grid.Column width={4} className="pl-0">
|
|
46
48
|
<Button
|
|
47
49
|
as="a"
|
|
48
50
|
role="button"
|
|
@@ -53,6 +55,9 @@ export class ExportDropdown extends Component {
|
|
|
53
55
|
{i18next.t("Export")}
|
|
54
56
|
</Button>
|
|
55
57
|
</Grid.Column>
|
|
58
|
+
<Grid.Column width={2} className="pl-0">
|
|
59
|
+
<CopyButton url={selectedFormatUrl} />
|
|
60
|
+
</Grid.Column>
|
|
56
61
|
</Grid>
|
|
57
62
|
);
|
|
58
63
|
}
|
|
@@ -12,6 +12,10 @@ $("#record-doi-badge").on("click", function () {
|
|
|
12
12
|
$("#doi-modal").modal("show");
|
|
13
13
|
});
|
|
14
14
|
|
|
15
|
+
$("#record-conceptdoi-badge").on("click", function () {
|
|
16
|
+
$("#conceptdoi-modal").modal("show");
|
|
17
|
+
});
|
|
18
|
+
|
|
15
19
|
$(".preview-link").on("click", function (event) {
|
|
16
20
|
$("#preview-file-title").html(event.target.dataset.fileKey);
|
|
17
21
|
});
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import $ from "jquery";
|
|
9
9
|
import { MultipleOptionsSearchBar } from "@js/invenio_search_ui/components";
|
|
10
|
+
import { CopyButton } from "@js/invenio_app_rdm/components/CopyButton";
|
|
10
11
|
import { i18next } from "@translations/invenio_app_rdm/i18next";
|
|
11
12
|
import ReactDOM from "react-dom";
|
|
12
13
|
import React from "react";
|
|
@@ -153,3 +154,11 @@ if (window.invenio) {
|
|
|
153
154
|
}
|
|
154
155
|
};
|
|
155
156
|
}
|
|
157
|
+
|
|
158
|
+
// Copy Buttons for DOI
|
|
159
|
+
document.querySelectorAll(".copy-doi-button").forEach((element) => {
|
|
160
|
+
ReactDOM.render(
|
|
161
|
+
<CopyButton text={element.dataset.value} size={element.dataset.size} />,
|
|
162
|
+
element
|
|
163
|
+
);
|
|
164
|
+
});
|
invenio_app_rdm/theme/assets/semantic-ui/less/invenio_app_rdm/theme/modules/accordion.overrides
CHANGED
|
@@ -3,6 +3,15 @@
|
|
|
3
3
|
&.tab-menu-accordion {
|
|
4
4
|
transform: none;
|
|
5
5
|
}
|
|
6
|
+
|
|
7
|
+
transform: @activeIconTransform;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.ui.accordion .title .icon,
|
|
11
|
+
.ui.accordion .accordion .title .icon {
|
|
12
|
+
transition: @iconTransition;
|
|
13
|
+
width: auto;
|
|
14
|
+
height: auto;
|
|
6
15
|
}
|
|
7
16
|
|
|
8
17
|
/* use these classes to change accordion title when up/down */
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{#
|
|
2
2
|
Copyright (C) 2019-2022 CERN.
|
|
3
3
|
Copyright (C) 2014 KTH Royal Institute of Technology.
|
|
4
|
+
Copyright (C) 2025 Northwestern University.
|
|
4
5
|
|
|
5
6
|
Invenio App RDM is free software; you can redistribute it and/or modify it
|
|
6
7
|
under the terms of the MIT License; see LICENSE file for more details.
|
|
@@ -25,7 +26,7 @@
|
|
|
25
26
|
</div>
|
|
26
27
|
<div class="description">
|
|
27
28
|
{{ _("Configure the datamodel, resource types, permissions and much more to make it suit your needs! For more information on how to do it visit the") }}
|
|
28
|
-
<a href="https://inveniordm.docs.cern.ch/
|
|
29
|
+
<a href="https://inveniordm.docs.cern.ch/operate/customize/configuration/" target="_blank">
|
|
29
30
|
{{ _("configuration section in the docs") }}
|
|
30
31
|
</a>.
|
|
31
32
|
</div>
|
|
@@ -42,7 +43,7 @@
|
|
|
42
43
|
</div>
|
|
43
44
|
<div class="description">
|
|
44
45
|
{{ _("Customize the layout and adapt the styling to match your institution's. See how to do so") }}
|
|
45
|
-
<a href="https://inveniordm.docs.cern.ch/customize/" target="_blank">
|
|
46
|
+
<a href="https://inveniordm.docs.cern.ch/operate/customize/look-and-feel/" target="_blank">
|
|
46
47
|
{{ _("here") }}
|
|
47
48
|
</a>.
|
|
48
49
|
</div>
|
|
@@ -54,11 +55,11 @@
|
|
|
54
55
|
<div class="intro-step-list-image">3</div>
|
|
55
56
|
</div>
|
|
56
57
|
<div class="content">
|
|
57
|
-
<div class="header">{{ _("
|
|
58
|
+
<div class="header">{{ _("Use it!") }}</div>
|
|
58
59
|
<div class="description">
|
|
59
|
-
{{ _("
|
|
60
|
-
<a href="https://inveniordm.docs.cern.ch/
|
|
61
|
-
{{ _("
|
|
60
|
+
{{ _("Use and explore your InvenioRDM instance.") }}
|
|
61
|
+
<a href="https://inveniordm.docs.cern.ch/use/" target="_blank">
|
|
62
|
+
{{ _("Use") }}
|
|
62
63
|
</a>.
|
|
63
64
|
</div>
|
|
64
65
|
</div>
|
invenio_app_rdm/theme/webpack.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
#
|
|
3
3
|
# Copyright (C) 2023-2024 CERN.
|
|
4
|
-
# Copyright (C) 2024 Graz University of Technology.
|
|
4
|
+
# Copyright (C) 2024-2025 Graz University of Technology.
|
|
5
5
|
#
|
|
6
6
|
# Invenio-App-RDM is free software; you can redistribute it and/or modify
|
|
7
7
|
# it under the terms of the MIT License; see LICENSE file for more details.
|
|
@@ -20,86 +20,115 @@ This script has been tested with following data:
|
|
|
20
20
|
- internal_notes
|
|
21
21
|
"""
|
|
22
22
|
|
|
23
|
-
import sys
|
|
24
|
-
|
|
25
23
|
from click import secho
|
|
24
|
+
from invenio_access.permissions import system_identity
|
|
26
25
|
from invenio_db import db
|
|
27
|
-
from invenio_rdm_records.
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
26
|
+
from invenio_rdm_records.proxies import current_rdm_records_service as records_service
|
|
27
|
+
from invenio_search.engine import dsl
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def run_upgrade(has, migrate):
|
|
31
|
+
"""Run upgrade."""
|
|
32
|
+
record_success_counter = 0
|
|
33
|
+
record_error_counter = 0
|
|
34
|
+
draft_success_counter = 0
|
|
35
|
+
draft_error_counter = 0
|
|
36
|
+
|
|
37
|
+
# Handle published records
|
|
38
|
+
published_records = records_service.search(
|
|
39
|
+
system_identity,
|
|
40
|
+
params={"allversions": True, "include_deleted": True},
|
|
41
|
+
extra_filter=has,
|
|
42
|
+
)
|
|
43
|
+
for result in published_records.hits:
|
|
44
|
+
record = records_service.record_cls.pid.resolve(result["id"])
|
|
45
|
+
try:
|
|
46
|
+
migrate(record)
|
|
47
|
+
record_success_counter += 1
|
|
48
|
+
except Exception as error:
|
|
49
|
+
secho(f"> Error {repr(error)}", fg="red")
|
|
50
|
+
error = f"Record {record.pid.pid_value} failed to update"
|
|
51
|
+
record_error_counter += 1
|
|
52
|
+
|
|
53
|
+
# Handle draft records
|
|
54
|
+
draft_records = records_service.search_drafts(
|
|
55
|
+
system_identity,
|
|
56
|
+
params={"allversions": True},
|
|
57
|
+
extra_filter=has,
|
|
58
|
+
)
|
|
59
|
+
for result in draft_records.hits:
|
|
60
|
+
draft = records_service.draft_cls.pid.resolve(
|
|
61
|
+
result["id"],
|
|
62
|
+
registered_only=False,
|
|
63
|
+
)
|
|
64
|
+
try:
|
|
65
|
+
migrate(draft)
|
|
66
|
+
draft_success_counter += 1
|
|
67
|
+
except Exception as error:
|
|
68
|
+
secho(f"> Error {repr(error)}", fg="red")
|
|
69
|
+
error = f"Draft {draft.pid.pid_value} failed to update"
|
|
70
|
+
draft_error_counter += 1
|
|
71
|
+
|
|
72
|
+
if draft_error_counter > 0 or record_error_counter > 0:
|
|
73
|
+
db.session.rollback()
|
|
74
|
+
secho(
|
|
75
|
+
f"{record_error_counter} records had failures and {draft_error_counter} drafts had failures",
|
|
76
|
+
fg="red",
|
|
77
|
+
)
|
|
78
|
+
secho(
|
|
79
|
+
"The changes have been rolled back. Please fix the above listed errors and try the upgrade again",
|
|
80
|
+
fg="yellow",
|
|
81
|
+
err=True,
|
|
82
|
+
)
|
|
83
|
+
elif draft_success_counter > 0 or record_success_counter > 0:
|
|
84
|
+
db.session.commit()
|
|
85
|
+
secho(
|
|
86
|
+
f"{record_success_counter} records have been updated and {draft_error_counter} drafts have been updated",
|
|
87
|
+
fg="green",
|
|
88
|
+
)
|
|
89
|
+
else:
|
|
90
|
+
secho("nothing has been updated")
|
|
37
91
|
|
|
38
|
-
def update_record(record):
|
|
39
|
-
# skipping deleted records because can't be committed
|
|
40
|
-
if record.is_deleted:
|
|
41
|
-
return
|
|
42
92
|
|
|
43
|
-
|
|
44
|
-
|
|
93
|
+
def run_upgrade_for_thesis():
|
|
94
|
+
"""Run upgrade for thesis."""
|
|
45
95
|
|
|
46
|
-
|
|
47
|
-
|
|
96
|
+
def migrate_thesis_university(record_or_draft):
|
|
97
|
+
custom_fields = record_or_draft.get("custom_fields", {})
|
|
98
|
+
university = custom_fields.get("thesis:university")
|
|
99
|
+
if university and "thesis:thesis" not in custom_fields:
|
|
100
|
+
custom_fields["thesis:thesis"] = {"university": university}
|
|
48
101
|
|
|
49
|
-
|
|
50
|
-
secho(f"> Updated record: {record.pid.pid_value}\n", fg="green")
|
|
51
|
-
return None
|
|
52
|
-
except Exception as e:
|
|
53
|
-
secho(f"> Error {repr(e)}", fg="red")
|
|
54
|
-
error = f"Record {record.pid.pid_value} failed to update"
|
|
55
|
-
return error
|
|
102
|
+
record_or_draft.commit()
|
|
56
103
|
|
|
57
|
-
|
|
104
|
+
# Common query filter
|
|
105
|
+
has_thesis = dsl.Q("exists", field="custom_fields.thesis:university")
|
|
58
106
|
|
|
59
|
-
|
|
60
|
-
errors = []
|
|
61
|
-
for record_metadata in RDMRecord.model_cls.query.all():
|
|
62
|
-
record = RDMRecord(record_metadata.data, model=record_metadata)
|
|
63
|
-
error = update_record(record)
|
|
107
|
+
secho("run upgrade for thesis has been started", fg="green")
|
|
64
108
|
|
|
65
|
-
|
|
66
|
-
errors.append(error)
|
|
109
|
+
run_upgrade(has_thesis, migrate_thesis_university)
|
|
67
110
|
|
|
68
|
-
for
|
|
69
|
-
draft = RDMDraft(draft_metadata.data, model=draft_metadata)
|
|
70
|
-
error = update_record(draft)
|
|
71
|
-
if error:
|
|
72
|
-
errors.append(error)
|
|
111
|
+
secho("run upgrade for thesis has been finished", fg="green")
|
|
73
112
|
|
|
74
|
-
success = not errors
|
|
75
113
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
db.session.commit()
|
|
79
|
-
secho(
|
|
80
|
-
"Data migration completed, please rebuild the search indices now.",
|
|
81
|
-
fg="green",
|
|
82
|
-
)
|
|
114
|
+
def execute_upgrade():
|
|
115
|
+
"""Execute the upgrade from InvenioRDM 12.0 to 13.0.0.
|
|
83
116
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
secho(
|
|
88
|
-
"Upgrade aborted due to the following errors:",
|
|
89
|
-
fg="red",
|
|
90
|
-
err=True,
|
|
91
|
-
)
|
|
117
|
+
Please read the disclaimer on this module before thinking about executing
|
|
118
|
+
this function!
|
|
119
|
+
THIS MODULE IS WORK IN PROGRESS, UNTIL official v13 release
|
|
92
120
|
|
|
93
|
-
|
|
94
|
-
|
|
121
|
+
NOTE:
|
|
122
|
+
since the data upgrade steps are more selective now, the approach how to do
|
|
123
|
+
it has been changed. now the records/drafts which should be updated are
|
|
124
|
+
searched by a filter and then the updates are applied to those
|
|
125
|
+
records/drafts explicitly. this should improve speed and should make it
|
|
126
|
+
easier to upgrade large instances
|
|
95
127
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
"Please fix the above listed errors and try the upgrade again",
|
|
99
|
-
)
|
|
100
|
-
secho(msg, fg="yellow", err=True)
|
|
128
|
+
"""
|
|
129
|
+
secho("Starting data migration...", fg="green")
|
|
101
130
|
|
|
102
|
-
|
|
131
|
+
run_upgrade_for_thesis()
|
|
103
132
|
|
|
104
133
|
|
|
105
134
|
# if the script is executed on its own, perform the upgrade
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: invenio-app-rdm
|
|
3
|
-
Version: 13.0.
|
|
3
|
+
Version: 13.0.0rc6
|
|
4
4
|
Summary: Invenio Research Data Management.
|
|
5
5
|
Home-page: https://github.com/inveniosoftware/invenio-app-rdm
|
|
6
6
|
Author: CERN
|
|
@@ -60,7 +60,7 @@ Requires-Dist: invenio-search[opensearch1]<4.0.0,>=3.0.0; extra == "opensearch1"
|
|
|
60
60
|
Provides-Extra: opensearch2
|
|
61
61
|
Requires-Dist: invenio-search[opensearch2]<4.0.0,>=3.0.0; extra == "opensearch2"
|
|
62
62
|
Provides-Extra: s3
|
|
63
|
-
Requires-Dist: invenio-s3<
|
|
63
|
+
Requires-Dist: invenio-s3<4.0.0,>=3.0.0; extra == "s3"
|
|
64
64
|
Dynamic: license-file
|
|
65
65
|
|
|
66
66
|
..
|
|
@@ -101,6 +101,32 @@ https://inveniordm.docs.cern.ch
|
|
|
101
101
|
Changes
|
|
102
102
|
=======
|
|
103
103
|
|
|
104
|
+
Version v13.0.0rc6 (released 2025-07-21)
|
|
105
|
+
|
|
106
|
+
- fix: package.json and package-lock mismatch
|
|
107
|
+
|
|
108
|
+
Version v13.0.0rc5 (released 2025-07-17)
|
|
109
|
+
|
|
110
|
+
- migration: optimize script
|
|
111
|
+
- upgrade_scripts: handle thesis custom field migration
|
|
112
|
+
- version: bumped invenio-s3 version to include multipart upload
|
|
113
|
+
- templates: macros: doi: Add copy button for DOIs
|
|
114
|
+
- semantic-ui: components: CopyButton: add size prop
|
|
115
|
+
- semantic-ui: landing_page: ExportButton: Add copy button
|
|
116
|
+
- semantic-ui: componenets: add url fetching in copy button
|
|
117
|
+
- semantic-ui: landing_page: add click event for cite all versions
|
|
118
|
+
|
|
119
|
+
Version v13.0.0rc4 (released 2025-07-10)
|
|
120
|
+
|
|
121
|
+
- pid-config: cast to bool RDM_(PARENT)_PERSISTENT_IDENTIFIERS required check
|
|
122
|
+
- fix: default parent_doi_required to False
|
|
123
|
+
- links: update doc links to updated ones
|
|
124
|
+
- i18n: localize DOI labels
|
|
125
|
+
- css: remove .invenio-accordion-field qualifier
|
|
126
|
+
- css: use SemanticUI variables and fix class names
|
|
127
|
+
- ui: ensure accordion caret icons rotate when opened/closed
|
|
128
|
+
- config: add Data Package export format
|
|
129
|
+
|
|
104
130
|
Version v13.0.0rc3 (released 2025-07-02)
|
|
105
131
|
|
|
106
132
|
- deposit-ui: uppy uploader ui feature
|