Skip to content

Commit

Permalink
WIP: start moving the access button to a react component
Browse files Browse the repository at this point in the history
  • Loading branch information
max-moser committed Jun 29, 2023
1 parent ab7a5be commit 3160f3b
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 86 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{#
Copyright (C) 2020-2021 CERN.
Copyright (C) 2020-2021 Northwestern University.
Copyright (C) 2021 TU Wien.
Copyright (C) 2021-2023 TU Wien.
Copyright (C) 2021 Graz University of Technology.
Copyright (C) 2021 New York University.

Expand All @@ -24,9 +24,9 @@
{%- set is_preview_submission_request = preview_submission_request or false %}
{%- set show_record_management_menu = can_manage_record and (not is_preview or is_preview_submission_request) %}

{#- TODO check if the record allows requests for users/guests #}
{%- set user_request_enabled = not current_user.is_anonymous %}
{%- set guest_request_enabled = current_user.is_anonymous %}
{%- set access_endpoint = "user" if user_request_enabled else "guest" %}

{%- block page_body %}
<section id="banners" class="banners" aria-label="{{ _('Information banner') }}">
Expand Down Expand Up @@ -256,7 +256,7 @@ <h2 id="files-heading">{{ _('Files') }}</h2>
<p>{{ _("Reason") }}: {{ record.access.embargo.reason }}</p>
{% endif %}

{%- if user_request_enabled or guest_request_enabled %}
{%- if user_request_enabled or guest_request_enabled %}
<hr style="border-color: darkred;">
<p>
<p>
Expand All @@ -266,42 +266,7 @@ <h2 id="files-heading">{{ _('Files') }}</h2>
Here we would like to display the customized text from the record parent's access settings, if there is one.
Otherwise, we just display a boring old default text.
</p>

{#- Access requests for (authenticated) users and (unauthenticated) guests -#}
{%- if user_request_enabled %}
<p>
Logged in as <strong>{{ current_user.email }}</strong>
<br/>
Not you? <a href="{{ url_for('security.logout') }}">Log out</a>
</p>
<form>
<label for="access-request-message">Message</label>
<textarea name="access-request-message" id="access-request-message">Describe why you need access here</textarea>
</form>

{%- elif guest_request_enabled %}
<p>
You are currently <em>not logged in</em>.
<br/>
Do you have an account? <a href="{{ url_for('security.login') }}">Log in</a>
</p>
<form>
<p>
<label for="email">Your e-mail address</label>
<input name="email" id="email" type="email">
</p>
<p>
<label for="full_name">Your full name</label>
<input name="full_name" id="full_name" type="text">
</p>
<p>
<label for="access-request-message">Message</label>
<textarea name="access-request-message" id="access-request-message">Describe why you need access here</textarea>
</p>
</form>
{%- endif %}

<a class="ui button" id="request-access-button" data-recid="{{ record.id }}" data-endpoint="{{ access_endpoint }}">Request access</a>
<div id="accessRequestForm" data-user-email="{{ current_user.email if not current_user.is_anonymous else 'guest' }}" data-recid="{{ record.id }}" data-login-url="{{ url_for('security.login') }}" data-logout-url="{{ url_for('security.logout') }}" />
</p>
{%- endif %}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
// This file is part of InvenioRDM
// Copyright (C) 2023 TU Wien.
//
// 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 React from "react";
import { http } from "react-invenio-forms";
import PropTypes from "prop-types";
import { Form, Icon, Segment } from "semantic-ui-react";

export class AccessRequestForm extends React.Component {
constructor(props) {
super(props);
this.state = {
email: null,
fullName: null,
message: "",
submitEnabled: true,
};
}

submitRequest = () => {
const { userEmail, recid } = this.props;
const { message, email, fullName } = this.state;
const isGuest = userEmail === "guest";
const requestData = isGuest ? { message, email, full_name: fullName } : { message };
const endpoint = isGuest ? "request/guest" : "request";

// don't reject the promise because of a status code other than 2XX
const extraConfig = {
validateStatus: null,
};

http
.post(`/api/records/${recid}/access/${endpoint}`, requestData, extraConfig)
.then((result) => {
if (result.status === 200) {
this.setState({ submitEnabled: false });

if (!isGuest) {
// TODO it would be nicer to have the backend report the proper
// `links.self_html` instead of constructing the URL here
const url = `/me/requests/${result.data.id}`;

// redirection here because opening in new tab might be blocked as popup
window.location.href = url;
} else {
// for the guest-based workflow, just display the message
alert(result.data.message); // TODO something nicer than an `alert`?
}
} else {
alert(`Could not create the access request: ${result.data.message}`); // TODO something nicer than an `alert`?
}
})
.catch((error) => {
alert(error); // TODO something nicer than an `alert`?
});
};

render = () => {
const { userEmail, loginUrl, logoutUrl } = this.props;
const { submitEnabled } = this.state;
const isGuest = userEmail === "guest";

const authNote = isGuest ? (
<Segment>
<Icon name="user secret" />
You are currently <strong>not logged in</strong>. Do you have an account?{" "}
<a href={loginUrl}>Log in</a>
</Segment>
) : (
<Segment>
<Icon name="user" />
You are logged in as <strong>{userEmail}</strong>. Not you?{" "}
<a href={logoutUrl}>Log out</a>
</Segment>
);

const guestFields = (
<Form.Group widths="equal">
<Form.Field>
<Form.Input
id="access-request-email-address"
label="Your email address"
icon="at"
iconPosition="left"
placeholder="Email address"
onChange={(_event, { value }) => this.setState({ email: value })}
required
/>
</Form.Field>
<Form.Field>
<Form.Input
id="access-request-full-name"
label="Your full name"
icon="address card"
iconPosition="left"
placeholder="Full name"
onChange={(_event, { value }) => this.setState({ fullName: value })}
required
/>
</Form.Field>
</Form.Group>
);

return (
<Form onSubmit={this.submitRequest}>
{authNote}
{isGuest && guestFields}
<Form.Field>
<Form.TextArea
id="access-request-message"
label="Request message"
placeholder="Please describe why you need access here"
onChange={(_event, { value }) => this.setState({ message: value })}
required
/>
</Form.Field>
<Form.Button type="submit" disabled={!submitEnabled}>
Request access
</Form.Button>
</Form>
);
};
}

AccessRequestForm.propTypes = {
loginUrl: PropTypes.string.isRequired,
logoutUrl: PropTypes.string.isRequired,
userEmail: PropTypes.string.isRequired,
recid: PropTypes.string.isRequired,
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,20 @@
// Copyright (C) 2020-2021 CERN.
// Copyright (C) 2020-2021 Northwestern University.
// Copyright (C) 2021 Graz University of Technology.
// Copyright (C) 2023 TU Wien.
//
// 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 React from "react";
import ReactDOM from "react-dom";
import { AccessRequestForm } from "./AccessRequestForm";
import { RecordManagement } from "./RecordManagement";
import { RecordVersionsList } from "./RecordVersionsList";
import { RecordCitationField } from "./RecordCitationField";
import { ExportDropdown } from "./ExportDropdown";
import { CommunitiesManagement } from "./CommunitiesManagement";
import { OverridableContext, overrideStore } from "react-overridable";
import { http } from "react-invenio-forms";

const recordManagementAppDiv = document.getElementById("recordManagement");
const recordManagementMobile = document.getElementById("recordManagementMobile");
Expand All @@ -25,6 +26,7 @@ const recordExportDownloadDiv = document.getElementById("recordExportDownload");
const sidebarCommunitiesManageDiv = document.getElementById(
"sidebar-communities-manage"
);
const accessRequestDiv = document.getElementById("accessRequestForm");

if (recordManagementAppDiv) {
renderRecordManagement(recordManagementAppDiv);
Expand Down Expand Up @@ -102,50 +104,14 @@ if (sidebarCommunitiesManageDiv) {
);
}

const requestAccessButton = document.getElementById("request-access-button");
const handler = async () => {
const messageInput = document.getElementById("access-request-message");
const recid = requestAccessButton.dataset.recid;
let endpoint = "request";
let data = { message: messageInput.value };

if (requestAccessButton.dataset.endpoint === "guest") {
const nameInput = document.getElementById("full_name");
const emailInput = document.getElementById("email");

endpoint = "request/guest";
data = { ...data, full_name: nameInput.value, email: emailInput.value };
}

// don't reject the promise because of a status code other than 2XX
const extraConfig = {
validateStatus: null,
};

http
.post(`/api/records/${recid}/access/${endpoint}`, data, extraConfig)
.then((result) => {
if (result.status === 200) {
if (requestAccessButton.dataset.endpoint === "user") {
// TODO it would be nicer to have the backend report the proper
// `links.self_html` instead of constructing the URL here
const url = `/me/requests/${result.data.id}`;

// redirection here because opening in new tab might be blocked as popup
window.location.href = url;
} else {
// for the guest-based workflow, just display the message
alert(result.data.message);
}
} else {
alert(`Could not create the access request: ${result.data.message}`);
}
})
.catch((error) => {
alert(error);
});
};

if (requestAccessButton) {
requestAccessButton.addEventListener("click", handler);
if (accessRequestDiv) {
ReactDOM.render(
<AccessRequestForm
userEmail={accessRequestDiv.dataset.userEmail}
recid={accessRequestDiv.dataset.recid}
loginUrl={accessRequestDiv.dataset.loginUrl}
logoutUrl={accessRequestDiv.dataset.logoutUrl}
/>,
accessRequestDiv
);
}

0 comments on commit 3160f3b

Please sign in to comment.