From e47b2b169a292c40ef3d3b00d174174f6a902094 Mon Sep 17 00:00:00 2001 From: mb-wali Date: Sat, 1 May 2021 11:27:43 +0200 Subject: [PATCH] feature: override deposit & deposit edit --- .../deposit/RDMDepositForm.js | 528 ++++++++++++++++++ .../js/invenio_theme_tugraz/deposit/index.js | 23 + invenio_theme_tugraz/config.py | 1 - invenio_theme_tugraz/deposits.py | 55 ++ invenio_theme_tugraz/ext.py | 3 + .../invenio_theme_tugraz/deposit/deposit.html | 37 ++ invenio_theme_tugraz/views.py | 1 - invenio_theme_tugraz/webpack.py | 19 +- 8 files changed, 663 insertions(+), 4 deletions(-) create mode 100644 invenio_theme_tugraz/assets/semantic-ui/js/invenio_theme_tugraz/deposit/RDMDepositForm.js create mode 100644 invenio_theme_tugraz/assets/semantic-ui/js/invenio_theme_tugraz/deposit/index.js create mode 100644 invenio_theme_tugraz/deposits.py create mode 100644 invenio_theme_tugraz/templates/invenio_theme_tugraz/deposit/deposit.html diff --git a/invenio_theme_tugraz/assets/semantic-ui/js/invenio_theme_tugraz/deposit/RDMDepositForm.js b/invenio_theme_tugraz/assets/semantic-ui/js/invenio_theme_tugraz/deposit/RDMDepositForm.js new file mode 100644 index 0000000..f79cb81 --- /dev/null +++ b/invenio_theme_tugraz/assets/semantic-ui/js/invenio_theme_tugraz/deposit/RDMDepositForm.js @@ -0,0 +1,528 @@ +// This file is part of InvenioRDM +// Copyright (C) 2020 CERN. +// Copyright (C) 2020 Northwestern University. +// Copyright (C) 2021 Graz University of Technology. +// +// 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. + +import _get from "lodash/get"; +import React, { Component, createRef, Fragment } from "react"; +import { + AccessRightField, + CreatibutorsField, + DatesField, + DeleteButton, + DepositFormApp, + DepositFormTitle, + DescriptionsField, + FileUploader, + FormFeedback, + IdentifiersField, + LanguagesField, + LicenseField, + PIDField, + PreviewButton, + PublicationDateField, + PublishButton, + PublisherField, + RelatedWorksField, + ResourceTypeField, + SaveButton, + TitlesField, + VersionField, +} from "react-invenio-deposit"; +import { AccordionField } from "react-invenio-forms"; +import { Card, Container, Divider, Grid, Ref, Sticky } from "semantic-ui-react"; + +export class RDMDepositForm extends Component { + constructor(props) { + super(props); + this.config = props.config || {}; + // TODO: retrieve from backend + this.config["canHaveMetadataOnlyRecords"] = true; + + // TODO: Make ALL vocabulary be generated by backend. + // Currently, some vocabulary is generated by backend and some is + // generated by frontend here. Iteration is faster and abstractions can be + // discovered by generating vocabulary here. Once happy with vocabularies, + // then we can generate it in the backend. + this.vocabularies = { + metadata: { + ...this.config.vocabularies, + + titles: { + ...this.config.vocabularies.titles, + }, + + descriptions: { + type: [ + { text: "Abstract", value: "abstract" }, + { text: "Methods", value: "methods" }, + { text: "Series Information", value: "seriesinformation" }, + { text: "Table of Contents", value: "tableofcontents" }, + { text: "Technical Info", value: "technicalinfo" }, + { text: "Other", value: "other" }, + ], + }, + + creators: { + type: [ + { text: "Person", value: "personal" }, + { text: "Organization", value: "organizational" }, + ], + role: [ + { text: "Editor", value: "editor" }, + { text: "Data Curator", value: "datacurator" }, + { text: "Data Manager", value: "datamanager" }, + { text: "Project Manager", value: "projectmanager" }, + ], + }, + + contributors: { + type: [ + { text: "Person", value: "personal" }, + { text: "Organization", value: "organizational" }, + ], + role: [ + { text: "Editor", value: "editor" }, + { text: "Data Curator", value: "datacurator" }, + { text: "Data Manager", value: "datamanager" }, + { text: "Project Manager", value: "projectmanager" }, + ], + }, + + dates: { + type: [ + { text: "Accepted", value: "accepted" }, + { text: "Available", value: "available" }, + { text: "Copyrighted", value: "copyrighted" }, + { text: "Collected", value: "collected" }, + { text: "Created", value: "created" }, + { text: "Issued", value: "issued" }, + { text: "Submitted", value: "submitted" }, + { text: "Updated", value: "updated" }, + { text: "Valid", value: "valid" }, + { text: "Withdrawn", value: "withdrawn" }, + { text: "Other", value: "other" }, + ], + }, + + // TODO: Replace with an API backend + funding: { + funder: [ + { + name: "National Institutes of Health (US)", + identifier: "funder1", + scheme: "funderScheme1", + }, + { + name: "European Commission (EU)", + identifier: "funder2", + scheme: "funderScheme2", + }, + ], + award: [ + { + title: "CANCER &AIDS DRUGS--PRECLIN PHARMACOL/TOXICOLOGY", + number: "N01CM037835-016", + identifier: "awardA", + scheme: "awardSchemeA", + parentScheme: "funderScheme1", + parentIdentifier: "funder1", + }, + { + title: + "Beyond the Standard Model at the LHC and with Atom Interferometers.", + number: "228169", + identifier: "awardB1", + scheme: "awardSchemeB", + parentScheme: "funderScheme2", + parentIdentifier: "funder2", + }, + { + title: "ENvironmental COnditions in GLAucoma Patients", + number: "747441", + identifier: "awardB2", + scheme: "awardSchemeB", + parentScheme: "funderScheme2", + parentIdentifier: "funder2", + }, + ], + }, + + identifiers: { + resource_type: this.config.vocabularies.resource_type, + scheme: [ + { text: "ARK", value: "ark" }, + { text: "ARXIV", value: "arxiv" }, + { text: "BIBCODE", value: "bibcode" }, + { text: "DOI", value: "doi" }, + { text: "EAN13", value: "ean13" }, + { text: "EISSN", value: "eissn" }, + { text: "HANDLE", value: "handle" }, + { text: "IGSN", value: "igsn" }, + { text: "ISBN", value: "isbn" }, + { text: "ISSN", value: "issn" }, + { text: "ISTC", value: "istc" }, + { text: "LISSN", value: "lissn" }, + { text: "LSID", value: "lsid" }, + { text: "PMID", value: "pmid" }, + { text: "PURL", value: "purl" }, + { text: "UPC", value: "upc" }, + { text: "URL", value: "url" }, + { text: "URN", value: "urn" }, + { text: "W3ID", value: "w3id" }, + ], + relations: [ + { text: "Is cited by", value: "iscitedby" }, + { text: "Cites", value: "cites" }, + { text: "Is supplement to", value: "issupplementto" }, + { text: "Is supplemented by", value: "issupplementedby" }, + { text: "Is continued by", value: "iscontinuedby" }, + { text: "Continues", value: "continues" }, + { text: "Is described by", value: "isdescribedby" }, + { text: "Describes", value: "describes" }, + { text: "Has metadata", value: "hasmetadata" }, + { text: "Is metadata for", value: "ismetadatafor" }, + { text: "Has version", value: "hasversion" }, + { text: "Is version of", value: "isversionof" }, + { text: "Is new version of", value: "isnewversionof" }, + { text: "Is previous version of", value: "ispreviousversionof" }, + { text: "Is part of", value: "ispartof" }, + { text: "Has part", value: "haspart" }, + { text: "Is referenced by", value: "isreferencedby" }, + { text: "References", value: "references" }, + { text: "Is documented by", value: "isdocumentedby" }, + { text: "Documents", value: "documents" }, + { text: "Is compiled by", value: "iscompiledby" }, + { text: "Compiles", value: "compiles" }, + { text: "Is variant form of", value: "isvariantformof" }, + { text: "Is original form of", value: "isoriginalformof" }, + { text: "Is identical to", value: "isidenticalto" }, + { text: "Is reviewed by", value: "isreviewedby" }, + { text: "Reviews", value: "reviews" }, + { text: "Is derived from", value: "isderivedfrom" }, + { text: "Is source of", value: "issourceof" }, + { text: "Is required by", value: "isrequiredby" }, + { text: "Requires", value: "requires" }, + { text: "Is obsoleted by", value: "isobsoletedby" }, + { text: "Obsoletes", value: "obsoletes" }, + ], + }, + subjects: { + options: [ + { + text: "Deep Learning", + value: { + subject: "Deep Learning", + scheme: "user", + identifier: "U1", + }, + }, + { + text: "MeSH: Cognitive Neuroscience", + value: { + subject: "Cognitive Neuroscience", + scheme: "mesh", + identifier: "D000066494", + }, + }, + { + text: "FAST: Glucagonoma", + value: { + subject: "Glucagonoma", + scheme: "fast", + identifier: "943672", + }, + }, + ], + limitToOptions: [ + { text: "All", value: "all" }, + { text: "MeSH", value: "mesh" }, + { text: "FAST", value: "fast" }, + ], + }, + }, + }; + + // check if files are present + this.noFiles = false; + if ( + !Array.isArray(this.props.files.entries) || + (!this.props.files.entries.length && this.props.record.is_published) + ) { + this.noFiles = true; + } + } + + formFeedbackRef = createRef(); + sidebarRef = createRef(); + + accordionStyle = { + header: { className: "inverted brand", style: { cursor: "pointer" } }, + }; + + render() { + return ( + + + + + + + + + {this.noFiles && this.props.record.is_published && ( +

+ The record has no files. +

+ )} + +
+ + + {this.config.pids.map((pid) => ( + + + + + ))} + + + + + + + ({ + title: result.title_l10n, + description: result.description_l10n, + id: result.id, + link: result.props.url, + })} + /> +
+
+ + + + {/**TODO: uncomment to use Subjects*/} + {/* + */} + + lang !== null)} // needed because dumped empty record from backend gives [null] + serializeSuggestions={(suggestions) => + suggestions.map((item) => ({ + text: item.title_l10n, + value: item.id, + key: item.id, + })) + } + /> + + + +
+
+ {/**TODO: uncomment to use FundingField*/} + {/* + + + +
+
*/} + + + + + + + +
+
+
+ + + + + +
+ + +
+ +
+
+ + + + + + + + +
+
+
+
+
+
+
+ ); + } +} diff --git a/invenio_theme_tugraz/assets/semantic-ui/js/invenio_theme_tugraz/deposit/index.js b/invenio_theme_tugraz/assets/semantic-ui/js/invenio_theme_tugraz/deposit/index.js new file mode 100644 index 0000000..869d72b --- /dev/null +++ b/invenio_theme_tugraz/assets/semantic-ui/js/invenio_theme_tugraz/deposit/index.js @@ -0,0 +1,23 @@ +// This file is part of InvenioRDM +// Copyright (C) 2020 CERN. +// Copyright (C) 2020 Northwestern University. +// +// 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. + +import React from "react"; +import ReactDOM from "react-dom"; +import "semantic-ui-css/semantic.min.css"; + +import { getInputFromDOM } from "react-invenio-deposit"; +import { RDMDepositForm } from "./RDMDepositForm"; + +ReactDOM.render( + , + document.getElementById("deposit-form") +); diff --git a/invenio_theme_tugraz/config.py b/invenio_theme_tugraz/config.py index 9a9b34f..2e998a4 100644 --- a/invenio_theme_tugraz/config.py +++ b/invenio_theme_tugraz/config.py @@ -122,5 +122,4 @@ TUG_ROUTES = { "guide": "/guide", "terms": "/terms", "gdpr": "/gdpr", - "record_detail": "/records/", } diff --git a/invenio_theme_tugraz/deposits.py b/invenio_theme_tugraz/deposits.py new file mode 100644 index 0000000..6a2d27b --- /dev/null +++ b/invenio_theme_tugraz/deposits.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2019-2021 CERN. +# Copyright (C) 2019-2021 Northwestern University. +# Copyright (C) 2021 TU Wien. +# Copyright (C) 2021 Graz University of Technology. +# +# Invenio_theme_tugraz is free software; you can redistribute it and/or modify it +# under the terms of the MIT License; see LICENSE file for more details. +# https://github.com/inveniosoftware/invenio-app-rdm/blob/master/invenio_app_rdm/records_ui/views/deposits.py +"""Routes for record-related pages provided by Invenio-App-RDM.""" + + +from flask import render_template +from flask_login import login_required +from invenio_app_rdm.records_ui.utils import set_default_value +from invenio_app_rdm.records_ui.views.decorators import pass_draft, pass_draft_files +from invenio_app_rdm.records_ui.views.deposits import ( + get_form_config, + get_search_url, + new_record, +) +from invenio_rdm_records.resources.serializers import UIJSONSerializer + + +@login_required +def deposit_create(): + """Create a new deposit.""" + return render_template( + "invenio_theme_tugraz/deposit/deposit.html", + forms_config=get_form_config(createUrl=("/api/records")), + searchbar_config=dict(searchUrl=get_search_url()), + record=new_record(), + files=dict( + default_preview=None, entries=[], links={} + ), + ) + + +@login_required +@pass_draft +@pass_draft_files +def deposit_edit(draft=None, draft_files=None, pid_value=None): + """Edit an existing deposit.""" + serializer = UIJSONSerializer() + record = serializer.serialize_object_to_dict(draft.to_dict()) + + return render_template( + "invenio_theme_tugraz/deposit/deposit.html", + forms_config=get_form_config(apiUrl=f"/api/records/{pid_value}/draft"), + record=record, + files=draft_files.to_dict(), + searchbar_config=dict(searchUrl=get_search_url()), + permissions=draft.has_permissions_to(['new_version']) + ) diff --git a/invenio_theme_tugraz/ext.py b/invenio_theme_tugraz/ext.py index c9a9de5..46cbd83 100644 --- a/invenio_theme_tugraz/ext.py +++ b/invenio_theme_tugraz/ext.py @@ -9,6 +9,7 @@ """invenio module for TUGRAZ theme.""" from . import config +from .deposits import deposit_create, deposit_edit from .views import index, record_detail @@ -26,6 +27,8 @@ class InvenioThemeTugraz(object): # https://flask.palletsprojects.com/en/1.1.x/api/#flask.Flask.add_url_rule app.add_url_rule("/", "index", index) app.add_url_rule("/records/", "record_detail", record_detail) + app.add_url_rule("/uploads/new", "deposit_create", deposit_create) + app.add_url_rule("/uploads/", "deposit_edit", deposit_edit) self.init_config(app) app.extensions["invenio-theme-tugraz"] = self diff --git a/invenio_theme_tugraz/templates/invenio_theme_tugraz/deposit/deposit.html b/invenio_theme_tugraz/templates/invenio_theme_tugraz/deposit/deposit.html new file mode 100644 index 0000000..00831d4 --- /dev/null +++ b/invenio_theme_tugraz/templates/invenio_theme_tugraz/deposit/deposit.html @@ -0,0 +1,37 @@ +{# + Copyright (C) 2020 CERN. + Copyright (C) 2020 Northwestern University. + Copyright (C) 2021 Graz University of Technology. + + 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. + #} + {%- if not record.is_published and record.versions.index and record.versions.index > 1%} + {%- set title = _("New version") %} + {%- elif not record.is_published %} + {%- set title = _("New upload") %} + {% else %} + {%- set title = _("Edit upload") %} + {%- endif %} + {%- extends config.BASE_TEMPLATE %} + + {%- block page_body %} + {%- if record %} + + {%- endif %} + {%- if files %} + + {%- endif %} + {%- if forms_config %} + + {%- endif %} + {%- if permissions %} + + {%- endif %} +
+ {%- endblock page_body %} + + {%- block javascript %} + {{ super() }} + {{ webpack['invenio-theme-tugraz-rdm-deposit.js'] }} + {%- endblock %} diff --git a/invenio_theme_tugraz/views.py b/invenio_theme_tugraz/views.py index 94fef7a..38aa4f8 100644 --- a/invenio_theme_tugraz/views.py +++ b/invenio_theme_tugraz/views.py @@ -44,7 +44,6 @@ def ui_blueprint(app): blueprint.add_url_rule(routes["guide"], view_func=guide) blueprint.add_url_rule(routes["terms"], view_func=terms) blueprint.add_url_rule(routes["gdpr"], view_func=gdpr) - blueprint.add_url_rule(routes["record_detail"], view_func=record_detail) @blueprint.app_template_filter("make_dict_like") def make_dict_like(value: str, key: str) -> Dict[str, str]: diff --git a/invenio_theme_tugraz/webpack.py b/invenio_theme_tugraz/webpack.py index 4cc5fe9..4fb8f5c 100644 --- a/invenio_theme_tugraz/webpack.py +++ b/invenio_theme_tugraz/webpack.py @@ -17,10 +17,25 @@ theme = WebpackThemeBundle( entry={ "invenio-theme-tugraz-theme": "./less/invenio_theme_tugraz/theme.less", "invenio-theme-tugraz-js": "./js/invenio_theme_tugraz/theme.js", - # "invenio-theme-tugraz-search-app": "./js/invenio_theme_tugraz/search/index.js", + # overrides RDM deposit form + 'invenio-theme-tugraz-rdm-deposit': './js/invenio_theme_tugraz/deposit/index.js', }, dependencies={ - # Add your dependencies + # add any additional npm dependencies here... + # Keep these dep: in sync with releases + "@babel/runtime": "^7.9.0", + 'formik': '^2.1.4', + 'luxon': '^1.23.0', + 'path': '^0.12.7', + 'prop-types': '^15.7.2', + 'react-dnd': '^11.1.3', + 'react-dnd-html5-backend': '^11.1.3', + 'react-invenio-deposit': '^0.13.5', + 'react-invenio-forms': '^0.7.0', + 'react-dropzone': "^11.0.3", + 'yup': '^0.27.0', + '@ckeditor/ckeditor5-build-classic': '^16.0.0', + '@ckeditor/ckeditor5-react': '^2.1.0', }, ) },