deps: react-bootstrap 0.31 -> 2 (Bootstrap 5 CSS deferred as debt)
Removes the largest batch of React-19-blocking warnings: the 0.31 components (Grid, FormGroup, ControlLabel, Navbar.Header/Brand, Checkbox, SafeAnchor) all leaned on legacy context / defaultProps. 29 files converted: Grid->Container, FormGroup/ControlLabel/FormControl/ HelpBlock -> Form.Group/Label/Control/Text, Checkbox -> Form.Check (label as prop), bsStyle->variant (default->secondary), bsSize->size, pull-right->float-end. Custom Col.js now re-exports v2's Col; custom NavItem.js rewritten self-contained (no SafeAnchor/createChainedFunction); Navigation.js drops react-bootstrap Navbar (raw markup anyway). CSS stays on Bootstrap 4 (alexwine:bootstrap-4) for now: the BS4->5 jump is entangled with the jQuery carousel/swipe + navbar-collapse and is tracked as separate debt in UPGRADE.md. Only .form-label needed a shim (forms.scss). Browser-verified home carousel+navbar, signup form + terms checkbox, login form; REST smoke byte-identical.
This commit is contained in:
parent
12bdbe8fed
commit
a1a1b9a801
30 changed files with 539 additions and 333 deletions
|
|
@ -48,7 +48,7 @@ class CenterInMyPosition extends React.Component {
|
|||
const { onlyIcon, t } = this.props;
|
||||
const msg = t('Centrar en tu ubicación');
|
||||
return (
|
||||
<Button bsStyle="default" title={msg} onClick={() => this.onClick()}>
|
||||
<Button variant="secondary" title={msg} onClick={() => this.onClick()}>
|
||||
<i className="fa fa-crosshairs" />{!onlyIcon ? ` ${msg}` : ''}
|
||||
</Button>);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,111 +1,6 @@
|
|||
import classNames from 'classnames';
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import elementType from 'prop-types-extra/lib/elementType';
|
||||
|
||||
import { bsClass, prefix, splitBsProps } from 'react-bootstrap/lib/utils/bootstrapUtils';
|
||||
import { DEVICE_SIZES } from 'react-bootstrap/lib/utils/StyleConfig';
|
||||
|
||||
const column = PropTypes.oneOfType([
|
||||
PropTypes.oneOf(['auto']),
|
||||
PropTypes.number,
|
||||
]);
|
||||
|
||||
const propTypes = {
|
||||
componentClass: elementType,
|
||||
|
||||
/**
|
||||
* The number of columns you wish to span
|
||||
*
|
||||
* for Extra small devices Phones (<576px)
|
||||
*
|
||||
* class-prefix `col-`
|
||||
*/
|
||||
xs: column,
|
||||
|
||||
/**
|
||||
* The number of columns you wish to span
|
||||
*
|
||||
* for Small devices Tablets (≥576px)
|
||||
*
|
||||
* class-prefix `col-sm-`
|
||||
*/
|
||||
sm: column,
|
||||
|
||||
/**
|
||||
* The number of columns you wish to span
|
||||
*
|
||||
* for Medium devices Desktops (≥768px)
|
||||
*
|
||||
* class-prefix `col-md-`
|
||||
*/
|
||||
md: column,
|
||||
|
||||
/**
|
||||
* The number of columns you wish to span
|
||||
*
|
||||
* for Large devices Desktops (≥992px)
|
||||
*
|
||||
* class-prefix `col-lg-`
|
||||
*/
|
||||
lg: column,
|
||||
|
||||
/**
|
||||
* The number of columns you wish to span
|
||||
*
|
||||
* for Large devices Desktops (≥1200px)
|
||||
*
|
||||
* class-prefix `col-xl-`
|
||||
*/
|
||||
xl: column,
|
||||
};
|
||||
|
||||
const defaultProps = {
|
||||
componentClass: 'div',
|
||||
};
|
||||
|
||||
class Col extends React.Component {
|
||||
render() {
|
||||
const { componentClass: Component, className, ...props } = this.props;
|
||||
const [bsProps, elementProps] = splitBsProps(props);
|
||||
|
||||
const classes = [];
|
||||
|
||||
DEVICE_SIZES.forEach((size) => {
|
||||
const propValue = elementProps[size];
|
||||
|
||||
if (propValue == null) return;
|
||||
|
||||
if (size === 'xs') {
|
||||
// col and col-4
|
||||
classes.push(propValue === true ?
|
||||
bsProps.bsClass :
|
||||
prefix(bsProps, `${propValue}`),
|
||||
);
|
||||
} else {
|
||||
// col-md-3
|
||||
classes.push(
|
||||
prefix(bsProps, `${size}-${propValue}`),
|
||||
);
|
||||
}
|
||||
|
||||
delete elementProps[size];
|
||||
});
|
||||
|
||||
if (!classes.length) {
|
||||
classes.push(bsProps.bsClass); // plain 'col'
|
||||
}
|
||||
|
||||
return (
|
||||
<Component
|
||||
{...elementProps}
|
||||
className={classNames(className, classes)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Col.propTypes = propTypes;
|
||||
Col.defaultProps = defaultProps;
|
||||
|
||||
export default bsClass('col', Col);
|
||||
// The old custom Col hand-rolled Bootstrap-4/5 grid classes on top of
|
||||
// react-bootstrap 0.31 internals (`bootstrapUtils`, `StyleConfig`), which no
|
||||
// longer exist in react-bootstrap v2. v2's own Col produces the exact same
|
||||
// `col`/`col-{size}-{n}` output for the xs/sm/md/lg/xl props we use, so we
|
||||
// simply re-export it and keep every importer unchanged.
|
||||
export { Col as default } from 'react-bootstrap';
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { FormGroup, ControlLabel, Button } from 'react-bootstrap';
|
||||
import { Form, Button } from 'react-bootstrap';
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
import { Bert } from 'meteor/themeteorchef:bert';
|
||||
import validate from '../../../modules/validate';
|
||||
|
|
@ -57,8 +57,8 @@ class DocumentEditor extends React.Component {
|
|||
render() {
|
||||
const { doc } = this.props;
|
||||
return (<form ref={form => (this.form = form)} onSubmit={event => event.preventDefault()}>
|
||||
<FormGroup>
|
||||
<ControlLabel>Title</ControlLabel>
|
||||
<Form.Group>
|
||||
<Form.Label>Title</Form.Label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
|
|
@ -67,9 +67,9 @@ class DocumentEditor extends React.Component {
|
|||
defaultValue={doc && doc.title}
|
||||
placeholder="Oh, The Places You'll Go!"
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup>
|
||||
<ControlLabel>Body</ControlLabel>
|
||||
</Form.Group>
|
||||
<Form.Group>
|
||||
<Form.Label>Body</Form.Label>
|
||||
<textarea
|
||||
className="form-control"
|
||||
name="body"
|
||||
|
|
@ -77,8 +77,8 @@ class DocumentEditor extends React.Component {
|
|||
defaultValue={doc && doc.body}
|
||||
placeholder="Congratulations! Today is your day. You're off to Great Places! You're off and away!"
|
||||
/>
|
||||
</FormGroup>
|
||||
<Button type="submit" bsStyle="success">
|
||||
</Form.Group>
|
||||
<Button type="submit" variant="success">
|
||||
{doc && doc._id ? 'Save Changes' : 'Add Document'}
|
||||
</Button>
|
||||
</form>);
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import React, { Component } from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
import { withTranslation } from 'react-i18next';
|
||||
import { FormGroup, Button, FormControl } from 'react-bootstrap';
|
||||
import { Form, Button } from 'react-bootstrap';
|
||||
import { Bert } from 'meteor/themeteorchef:bert';
|
||||
import { withTracker } from 'meteor/react-meteor-data';
|
||||
import { isHome } from '/imports/ui/components/Utils/location';
|
||||
|
|
@ -82,7 +82,7 @@ class Feedback extends Component {
|
|||
className="form card-body"
|
||||
onSubmit={event => event.preventDefault()}
|
||||
>
|
||||
<FormGroup controlId="formEmail">
|
||||
<Form.Group controlId="formEmail">
|
||||
<input
|
||||
id={testId('emailInput')}
|
||||
onChange={this.handleChange}
|
||||
|
|
@ -95,8 +95,8 @@ class Feedback extends Component {
|
|||
defaultValue={disabled ? this.props.emailAddress : ''}
|
||||
type="email"
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
</Form.Group>
|
||||
<Form.Group
|
||||
controlId="formFeedback"
|
||||
>
|
||||
<textarea
|
||||
|
|
@ -107,9 +107,9 @@ class Feedback extends Component {
|
|||
placeholder={t('Por favor, escribe aquí tu feedback...')}
|
||||
rows="6"
|
||||
/>
|
||||
<FormControl.Feedback />
|
||||
</FormGroup>
|
||||
<Button type="submit" bsStyle="success" className="float-right" id={testId('sendFeedbackBtn')} >
|
||||
<Form.Control.Feedback />
|
||||
</Form.Group>
|
||||
<Button type="submit" variant="success" className="float-right" id={testId('sendFeedbackBtn')} >
|
||||
{t('Enviar')}
|
||||
</Button>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
import React from 'react';
|
||||
import { year } from '@cleverbeagle/dates';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Grid } from 'react-bootstrap';
|
||||
import { Container } from 'react-bootstrap';
|
||||
import { withTranslation } from 'react-i18next';
|
||||
import { testId } from '/imports/ui/components/Utils/TestUtils';
|
||||
|
||||
|
|
@ -19,10 +19,10 @@ const Footer = (props) => {
|
|||
const { t } = props;
|
||||
return (
|
||||
<div className="Footer">
|
||||
<Grid>
|
||||
<Container>
|
||||
<p className="pull-left"><span className="reverse">©</span><span className="d-none d-md-inline"> Copyleft</span> {copyrightYear()} <a href="https://comunes.org/"><span className="d-none d-md-inline">{t('OrgName')}</span><span className="d-inline d-md-none">{t('OrgName')}</span></a></p>
|
||||
|
||||
<ul className="pull-right">
|
||||
<ul className="float-end">
|
||||
<li>
|
||||
<Link id={testId('about')} to="/about">
|
||||
<span className="d-none d-lg-inline">{t('Sobre nosotr@s')}</span>
|
||||
|
|
@ -44,7 +44,7 @@ const Footer = (props) => {
|
|||
<li><span className="d-none d-md-inline"><Link id={testId('license')} to="/license">{t('Licencia')}</Link></span></li>
|
||||
<li><span className="d-none d-md-inline"><Link id={testId('credits')} to="/credits">{t('Créditos')}</Link></span></li>
|
||||
</ul>
|
||||
</Grid>
|
||||
</Container>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import React from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
import { withTranslation } from 'react-i18next';
|
||||
import PlacesAutocomplete, { geocodeByAddress, getLatLng } from 'react-places-autocomplete';
|
||||
import { FormGroup, ControlLabel, HelpBlock } from 'react-bootstrap';
|
||||
import { Form } from 'react-bootstrap';
|
||||
import { Bert } from 'meteor/themeteorchef:bert';
|
||||
|
||||
|
||||
|
|
@ -82,8 +82,8 @@ class LocationAutocomplete extends React.Component {
|
|||
|
||||
return (
|
||||
<form>
|
||||
<FormGroup>
|
||||
{ label.length > 0 && <ControlLabel>{t(label)}</ControlLabel> }
|
||||
<Form.Group>
|
||||
{ label.length > 0 && <Form.Label>{t(label)}</Form.Label> }
|
||||
<PlacesAutocomplete
|
||||
styles={myStyles}
|
||||
autocompleteItem={AutocompleteItem}
|
||||
|
|
@ -114,8 +114,8 @@ class LocationAutocomplete extends React.Component {
|
|||
autoFocus: this.props.focusInput
|
||||
}}
|
||||
/>
|
||||
{ helpText.length > 0 && <HelpBlock>{t(helpText)}</HelpBlock> }
|
||||
</FormGroup>
|
||||
{ helpText.length > 0 && <Form.Text>{t(helpText)}</Form.Text> }
|
||||
</Form.Group>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@ import classNames from 'classnames';
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { SafeAnchor } from 'react-bootstrap';
|
||||
import createChainedFunction from 'react-bootstrap/lib/utils/createChainedFunction';
|
||||
|
||||
// Self-contained NavItem. The old one wrapped react-bootstrap 0.31's
|
||||
// `SafeAnchor` + `createChainedFunction` (both gone in v2); the markup this
|
||||
// navbar needs is just an <li><a> that toggles the collapsed menu on click.
|
||||
const propTypes = {
|
||||
active: PropTypes.bool,
|
||||
disabled: PropTypes.bool,
|
||||
|
|
@ -12,7 +12,11 @@ const propTypes = {
|
|||
href: PropTypes.string,
|
||||
onClick: PropTypes.func,
|
||||
onSelect: PropTypes.func,
|
||||
eventKey: PropTypes.any
|
||||
eventKey: PropTypes.any,
|
||||
className: PropTypes.string,
|
||||
anchorClassName: PropTypes.string,
|
||||
style: PropTypes.object,
|
||||
children: PropTypes.node
|
||||
};
|
||||
|
||||
const defaultProps = {
|
||||
|
|
@ -21,42 +25,35 @@ const defaultProps = {
|
|||
};
|
||||
|
||||
class NavItem extends React.Component {
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.handleClick = this.handleClick.bind(this);
|
||||
}
|
||||
|
||||
handleClick(e) {
|
||||
if (this.props.onSelect) {
|
||||
const { disabled, onClick, onSelect, eventKey } = this.props;
|
||||
if (disabled) {
|
||||
e.preventDefault();
|
||||
|
||||
if (!this.props.disabled) {
|
||||
this.props.onSelect(this.props.eventKey, e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (onClick) onClick(e);
|
||||
if (onSelect) {
|
||||
e.preventDefault();
|
||||
onSelect(eventKey, e);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
active, disabled, onClick, className, anchorClassName, style, ...props
|
||||
} =
|
||||
this.props;
|
||||
active, disabled, role, href, onClick, onSelect, eventKey,
|
||||
className, anchorClassName, style, children, ...props
|
||||
} = this.props;
|
||||
|
||||
delete props.onSelect;
|
||||
delete props.eventKey;
|
||||
const anchorProps = { ...props };
|
||||
if (href) anchorProps.href = href;
|
||||
anchorProps.role = role || (href === '#' ? 'button' : undefined);
|
||||
if (role === 'tab') anchorProps['aria-selected'] = active;
|
||||
|
||||
// These are injected down by `<Nav>` for building `<SubNav>`s.
|
||||
delete props.activeKey;
|
||||
delete props.activeHref;
|
||||
|
||||
if (!props.role) {
|
||||
if (props.href === '#') {
|
||||
props.role = 'button';
|
||||
}
|
||||
} else if (props.role === 'tab') {
|
||||
props['aria-selected'] = active;
|
||||
}
|
||||
return (
|
||||
<li
|
||||
role="presentation"
|
||||
|
|
@ -65,12 +62,14 @@ class NavItem extends React.Component {
|
|||
className={classNames(className, { active, disabled })}
|
||||
style={style}
|
||||
>
|
||||
<SafeAnchor
|
||||
{...props}
|
||||
disabled={disabled}
|
||||
{/* eslint-disable-next-line jsx-a11y/anchor-is-valid */}
|
||||
<a
|
||||
{...anchorProps}
|
||||
className={anchorClassName}
|
||||
onClick={createChainedFunction(onClick, this.handleClick)}
|
||||
/>
|
||||
onClick={this.handleClick}
|
||||
>
|
||||
{children}
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Navbar } from 'react-bootstrap';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { LinkContainer } from 'react-router-bootstrap';
|
||||
import { Trans, withTranslation } from 'react-i18next';
|
||||
|
|
@ -20,19 +19,12 @@ const Navigation = props => (
|
|||
<nav className="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||
<div style={{ overflow: 'hidden' } /* for ribbon */} className="container">
|
||||
{/* <BetaRibbon /> */}
|
||||
{/* <Navbar bsClass="navbar navbar-dark bg-dark"> */}
|
||||
{/* https://github.com/react-bootstrap/react-bootstrap/blob/master/src/Navbar.js */}
|
||||
<Navbar.Header>
|
||||
<Navbar.Brand>
|
||||
<Link to="/" className={window.location.pathname === '/' ? 'hide-brand' : ''} >
|
||||
{props.t('AppNameFull')}
|
||||
</Link>
|
||||
</Navbar.Brand>
|
||||
{/* <Navbar.Toggle/> */}
|
||||
<button className="sr-only navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span className="navbar-toggler-icon" />
|
||||
</button>
|
||||
</Navbar.Header>
|
||||
<Link to="/" className={`navbar-brand ${window.location.pathname === '/' ? 'hide-brand' : ''}`} >
|
||||
{props.t('AppNameFull')}
|
||||
</Link>
|
||||
<button className="sr-only navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span className="navbar-toggler-icon" />
|
||||
</button>
|
||||
<button className="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span className="navbar-toggler-icon" />
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ class Prompt extends Component {
|
|||
<p>{confirmation}</p>
|
||||
</Modal.Body>
|
||||
<Modal.Footer>
|
||||
<Button className="button-l" bsStyle="primary" onClick={proceed}>{okBtn}</Button>
|
||||
<Button className="button-l" variant="primary" onClick={proceed}>{okBtn}</Button>
|
||||
<Button onClick={cancel}>{cancelBtn}</Button>
|
||||
</Modal.Footer>
|
||||
</Modal>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Grid, Alert, Button } from 'react-bootstrap';
|
||||
import { Alert, Button } from 'react-bootstrap';
|
||||
import { Trans, withTranslation } from 'react-i18next';
|
||||
import { T9n } from 'meteor-accounts-t9n';
|
||||
|
||||
|
|
@ -16,7 +16,7 @@ const handleResendVerificationEmail = (emailAddress, t) => {
|
|||
|
||||
const ReSendEmail = props => (
|
||||
<div>
|
||||
{props.userId && !props.emailVerified ? <Alert className="verify-email text-center"><p><Trans i18nKey="verifyEmail" values={{ email: props.emailAddress }} /> <Button bsStyle="link" onClick={() => handleResendVerificationEmail(props.emailAddress, props.t)} href="#"><Trans parent="span">Reenviar email de verificación</Trans></Button></p></Alert> : ''}
|
||||
{props.userId && !props.emailVerified ? <Alert className="verify-email text-center"><p><Trans i18nKey="verifyEmail" values={{ email: props.emailAddress }} /> <Button variant="link" onClick={() => handleResendVerificationEmail(props.emailAddress, props.t)} href="#"><Trans parent="span">Reenviar email de verificación</Trans></Button></p></Alert> : ''}
|
||||
</div>
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -241,7 +241,7 @@ class SelectionMap extends Component {
|
|||
<ButtonGroup>
|
||||
{ this.props.sndBtn && this.props.onSndBtn &&
|
||||
<Button
|
||||
bsStyle="warning"
|
||||
variant="warning"
|
||||
title={this.props.sndBtnTitle}
|
||||
onClick={event => this.onSndBtn(event)}
|
||||
>
|
||||
|
|
@ -249,7 +249,7 @@ class SelectionMap extends Component {
|
|||
</Button>
|
||||
}
|
||||
<Button
|
||||
bsStyle="success"
|
||||
variant="success"
|
||||
disabled={this.props.disableFstBtn}
|
||||
onClick={event => this.onFstBtn(event)}
|
||||
>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue