Skip to content
Draft
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
171 changes: 91 additions & 80 deletions src/account-settings/EditableField.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@ import { connect } from 'react-redux';
import classNames from 'classnames';
import { useIntl } from '@edx/frontend-platform/i18n';
import {
Button, Form, StatefulButton,
ActionRow, Button, Card, Form, StatefulButton,
} from '@openedx/paragon';
import { faPencilAlt } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { EditOutline } from '@openedx/paragon/icons';

import SwitchContent from './SwitchContent';
import messages from './AccountSettingsPage.messages';
Expand Down Expand Up @@ -94,83 +93,95 @@ const EditableField = (props) => {
};

return (
<SwitchContent
expression={isEditing ? 'editing' : 'default'}
cases={{
editing: (
<>
<form onSubmit={handleSubmit} data-testid="editable-field-form">
<Form.Group
controlId={id}
isInvalid={error != null}
>
<Form.Label size="sm" className="h6 d-block" htmlFor={id}>{label}</Form.Label>
<Form.Control
data-hj-suppress
name={name}
id={id}
type={type}
value={value}
onChange={handleChange}
data-testid="editable-field-textbox"
{...others}
/>
{!!helpText && <Form.Text>{helpText}</Form.Text>}
{error != null && <Form.Control.Feedback hasIcon={false} data-testid="editable-field-error">{error}</Form.Control.Feedback>}
{others.children}
</Form.Group>
<p>
<StatefulButton
type="submit"
className="mr-2"
state={saveState}
labels={{
default: intl.formatMessage(messages['account.settings.editable.field.action.save']),
}}
onClick={(e) => {
// Swallow clicks if the state is pending.
// We do this instead of disabling the button to prevent
// it from losing focus (disabled elements cannot have focus).
// Disabling it would causes upstream issues in focus management.
// Swallowing the onSubmit event on the form would be better, but
// we would have to add that logic for every field given our
// current structure of the application.
if (saveState === 'pending') { e.preventDefault(); }
}}
disabledStates={[]}
data-testid="editable-field-save"
/>
<Button
variant="outline-primary"
onClick={handleCancel}
data-testid="editable-field-cancel"
data-clicked="cancel"
>
{intl.formatMessage(messages['account.settings.editable.field.action.cancel'])}
</Button>
</p>
</form>
{['name', 'verified_name'].includes(name) && (
<CertificatePreference fieldName={name} data-testid="editable-field-certificate-preference" />
)}
</>
),
default: (
<div className="form-group">
<div className="d-flex align-items-start">
<h6 aria-level="3">{label}</h6>
{isEditable ? (
<Button variant="link" onClick={handleEdit} className="ml-3" data-testid="editable-field-edit" data-clicked="edit">
<FontAwesomeIcon className="mr-1" icon={faPencilAlt} />{intl.formatMessage(messages['account.settings.editable.field.action.edit'])}
</Button>
) : null}
</div>
<p data-hj-suppress className={classNames('text-truncate', { 'grayed-out': isGrayedOut })}>{renderValue(value)}</p>
<p className="small text-muted mt-n2">{renderConfirmationMessage() || helpText}</p>
</div>
),
}}
/>
<Card className="mb-4">
<SwitchContent
expression={isEditing ? 'editing' : 'default'}
cases={{
editing: (
<Card.Body>
<Card.Section>
<Form onSubmit={handleSubmit} data-testid="editable-field-form">
<Form.Group
controlId={id}
isInvalid={error != null}
>
<Form.Label size="sm" className="h6 d-block" htmlFor={id}>{label}</Form.Label>
<Form.Control
data-hj-suppress
name={name}
id={id}
type={type}
value={value}
onChange={handleChange}
data-testid="editable-field-textbox"
{...others}
/>
{!!helpText && <Form.Text>{helpText}</Form.Text>}
{error != null && <Form.Control.Feedback hasIcon={false} data-testid="editable-field-error">{error}</Form.Control.Feedback>}
{others.children}
</Form.Group>
<p>
<StatefulButton
type="submit"
className="mr-2"
state={saveState}
labels={{
default: intl.formatMessage(messages['account.settings.editable.field.action.save']),
}}
onClick={(e) => {
// Swallow clicks if the state is pending.
// We do this instead of disabling the button to prevent
// it from losing focus (disabled elements cannot have focus).
// Disabling it would causes upstream issues in focus management.
// Swallowing the onSubmit event on the form would be better, but
// we would have to add that logic for every field given our
// current structure of the application.
if (saveState === 'pending') { e.preventDefault(); }
}}
disabledStates={[]}
data-testid="editable-field-save"
/>
<Button
variant="outline-primary"
onClick={handleCancel}
data-testid="editable-field-cancel"
data-clicked="cancel"
>
{intl.formatMessage(messages['account.settings.editable.field.action.cancel'])}
</Button>
</p>
</Form>
{['name', 'verified_name'].includes(name) && (
<CertificatePreference fieldName={name} data-testid="editable-field-certificate-preference" />
)}
</Card.Section>
</Card.Body>
),
default: (
<>
<Card.Header
title={label}
subtitle={<p data-hj-suppress className={classNames('text-truncate', { 'grayed-out': isGrayedOut })}>{renderValue(value)}</p>}
actions={isEditable && (
<ActionRow>
<Button variant="outline-primary" onClick={handleEdit} data-testid="editable-field-edit" data-clicked="edit" iconBefore={EditOutline}>
{intl.formatMessage(messages['account.settings.editable.field.action.edit'])}
</Button>
</ActionRow>
)}
/>
{(renderConfirmationMessage() || helpText) && (
<Card.Body>
<Card.Section>
<p className="small text-muted mt-n2 mb-0">{renderConfirmationMessage() || helpText}</p>
</Card.Section>
</Card.Body>
)}
</>
),
}}
/>
</Card>
);
};

Expand Down
165 changes: 88 additions & 77 deletions src/account-settings/EditableSelectField.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { useIntl } from '@edx/frontend-platform/i18n';
import {
Button, Form, StatefulButton,
ActionRow, Button, Card, Form, StatefulButton,
} from '@openedx/paragon';
import { faPencilAlt } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { EditOutline } from '@openedx/paragon/icons';

import SwitchContent from './SwitchContent';
import messages from './AccountSettingsPage.messages';
Expand Down Expand Up @@ -122,80 +121,92 @@ const EditableSelectField = (props) => {
});

return (
<SwitchContent
expression={isEditing ? 'editing' : 'default'}
cases={{
editing: (
<>
<form onSubmit={handleSubmit}>
<Form.Group
controlId={id}
isInvalid={error != null}
>
<Form.Label size="sm" className="h6 d-block" htmlFor={id}>{label}</Form.Label>
<Form.Control
data-hj-suppress
name={name}
id={id}
type={type}
as={type}
value={value}
onChange={handleChange}
{...others}
>
{options.length > 0 && selectOptions}
</Form.Control>
{!!helpText && <Form.Text>{helpText}</Form.Text>}
{error != null && <Form.Control.Feedback>{error}</Form.Control.Feedback>}
{others.children}
</Form.Group>
<p>
<StatefulButton
type="submit"
className="mr-2"
state={saveState}
labels={{
default: intl.formatMessage(messages['account.settings.editable.field.action.save']),
}}
onClick={(e) => {
// Swallow clicks if the state is pending.
// We do this instead of disabling the button to prevent
// it from losing focus (disabled elements cannot have focus).
// Disabling it would causes upstream issues in focus management.
// Swallowing the onSubmit event on the form would be better, but
// we would have to add that logic for every field given our
// current structure of the application.
if (saveState === 'pending') { e.preventDefault(); }
}}
disabledStates={[]}
/>
<Button
variant="outline-primary"
onClick={handleCancel}
>
{intl.formatMessage(messages['account.settings.editable.field.action.cancel'])}
</Button>
</p>
</form>
{['name', 'verified_name'].includes(name) && <CertificatePreference fieldName={name} />}
</>
),
default: (
<div className="form-group">
<div className="d-flex align-items-start">
<h6 aria-level="3">{label}</h6>
{isEditable ? (
<Button variant="link" onClick={handleEdit} className="ml-3">
<FontAwesomeIcon className="mr-1" icon={faPencilAlt} />{intl.formatMessage(messages['account.settings.editable.field.action.edit'])}
</Button>
) : null}
</div>
<p data-hj-suppress className={isGrayedOut ? 'grayed-out' : null}>{renderValue(value)}</p>
<p className="small text-muted mt-n2">{renderConfirmationMessage() || helpText}</p>
</div>
),
}}
/>
<Card className="mb-4">
<SwitchContent
expression={isEditing ? 'editing' : 'default'}
cases={{
editing: (
<Card.Body>
<Card.Section>
<Form onSubmit={handleSubmit}>
<Form.Group
controlId={id}
isInvalid={error != null}
>
<Form.Label size="sm" className="h6 d-block" htmlFor={id}>{label}</Form.Label>
<Form.Control
data-hj-suppress
name={name}
id={id}
type={type}
as={type}
value={value}
onChange={handleChange}
{...others}
>
{options.length > 0 && selectOptions}
</Form.Control>
{!!helpText && <Form.Text>{helpText}</Form.Text>}
{error != null && <Form.Control.Feedback>{error}</Form.Control.Feedback>}
{others.children}
</Form.Group>
<p>
<StatefulButton
type="submit"
className="mr-2"
state={saveState}
labels={{
default: intl.formatMessage(messages['account.settings.editable.field.action.save']),
}}
onClick={(e) => {
// Swallow clicks if the state is pending.
// We do this instead of disabling the button to prevent
// it from losing focus (disabled elements cannot have focus).
// Disabling it would causes upstream issues in focus management.
// Swallowing the onSubmit event on the form would be better, but
// we would have to add that logic for every field given our
// current structure of the application.
if (saveState === 'pending') { e.preventDefault(); }
}}
disabledStates={[]}
/>
<Button
variant="outline-primary"
onClick={handleCancel}
>
{intl.formatMessage(messages['account.settings.editable.field.action.cancel'])}
</Button>
</p>
</Form>
{['name', 'verified_name'].includes(name) && <CertificatePreference fieldName={name} />}
</Card.Section>
</Card.Body>
),
default: (
<>
<Card.Header
title={label}
subtitle={<p data-hj-suppress className={isGrayedOut ? 'grayed-out' : null}>{renderValue(value)}</p>}
actions={isEditable && (
<ActionRow>
<Button variant="outline-primary" onClick={handleEdit} data-testid="editable-field-edit" data-clicked="edit" iconBefore={EditOutline}>
{intl.formatMessage(messages['account.settings.editable.field.action.edit'])}
</Button>
</ActionRow>
)}
/>
{(renderConfirmationMessage() || helpText) && (
<Card.Body>
<Card.Section>
<p className="small text-muted mt-n2 mb-0">{renderConfirmationMessage() || helpText}</p>
</Card.Section>
</Card.Body>
)}
</>
),
}}
/>
</Card>
);
};

Expand Down
Loading
Loading