Move to stateless function mode.

This commit is contained in:
Paulo Gustavo Veiga 2020-12-01 17:01:57 -08:00
parent 78cd809acd
commit 2d9e66f32f
8 changed files with 154 additions and 152 deletions

View File

@ -1 +1 @@
[{"/Users/pveiga/repos/wisemapping-react/src/Footer.js":"1","/Users/pveiga/repos/wisemapping-react/src/Header.js":"2","/Users/pveiga/repos/wisemapping-react/src/index.js":"3","/Users/pveiga/repos/wisemapping-react/src/RegistrationApp.js":"4","/Users/pveiga/repos/wisemapping-react/src/LoginApp.js":"5"},{"size":1601,"mtime":1606716377431,"results":"6","hashOfConfig":"7"},{"size":1572,"mtime":1606670050593,"results":"8","hashOfConfig":"7"},{"size":1882,"mtime":1606786667541,"results":"9","hashOfConfig":"7"},{"size":3839,"mtime":1606786664130,"results":"10","hashOfConfig":"7"},{"size":4089,"mtime":1606780103039,"results":"11","hashOfConfig":"7"},{"filePath":"12","messages":"13","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"1xegajf",{"filePath":"14","messages":"15","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"16","messages":"17","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"18","messages":"19","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"20","messages":"21","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"/Users/pveiga/repos/wisemapping-react/src/Footer.js",[],"/Users/pveiga/repos/wisemapping-react/src/Header.js",[],"/Users/pveiga/repos/wisemapping-react/src/index.js",["22"],"/Users/pveiga/repos/wisemapping-react/src/RegistrationApp.js",[],"/Users/pveiga/repos/wisemapping-react/src/LoginApp.js",[],{"ruleId":"23","severity":1,"message":"24","line":37,"column":57,"nodeType":"25","messageId":"26","endLine":37,"endColumn":59},"eqeqeq","Expected '===' and instead saw '=='.","BinaryExpression","unexpected"]
[{"/Users/pveiga/repos/wisemapping-react/src/Footer.js":"1","/Users/pveiga/repos/wisemapping-react/src/Header.js":"2","/Users/pveiga/repos/wisemapping-react/src/index.js":"3","/Users/pveiga/repos/wisemapping-react/src/RegistrationApp.js":"4","/Users/pveiga/repos/wisemapping-react/src/LoginApp.js":"5"},{"size":1601,"mtime":1606716377431,"results":"6","hashOfConfig":"7"},{"size":1818,"mtime":1606793242108,"results":"8","hashOfConfig":"7"},{"size":1883,"mtime":1606789677736,"results":"9","hashOfConfig":"7"},{"size":3516,"mtime":1606870582803,"results":"10","hashOfConfig":"7"},{"size":3472,"mtime":1606870845676,"results":"11","hashOfConfig":"7"},{"filePath":"12","messages":"13","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"1xegajf",{"filePath":"14","messages":"15","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"16","messages":"17","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"18","messages":"19","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"20","messages":"21","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"/Users/pveiga/repos/wisemapping-react/src/Footer.js",[],"/Users/pveiga/repos/wisemapping-react/src/Header.js",[],"/Users/pveiga/repos/wisemapping-react/src/index.js",[],"/Users/pveiga/repos/wisemapping-react/src/RegistrationApp.js",[],"/Users/pveiga/repos/wisemapping-react/src/LoginApp.js",[]]

43
package-lock.json generated
View File

@ -13,6 +13,7 @@
"@testing-library/user-event": "^12.2.2",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-google-recaptcha": "^2.1.0",
"react-intl": "^5.10.5",
"react-scripts": "4.0.1",
"web-vitals": "^0.2.4"
@ -16112,6 +16113,18 @@
"node": ">=10"
}
},
"node_modules/react-async-script": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/react-async-script/-/react-async-script-1.2.0.tgz",
"integrity": "sha512-bCpkbm9JiAuMGhkqoAiC0lLkb40DJ0HOEJIku+9JDjxX3Rcs+ztEOG13wbrOskt3n2DTrjshhaQ/iay+SnGg5Q==",
"dependencies": {
"hoist-non-react-statics": "^3.3.0",
"prop-types": "^15.5.0"
},
"peerDependencies": {
"react": ">=16.4.1"
}
},
"node_modules/react-dev-utils": {
"version": "11.0.1",
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-11.0.1.tgz",
@ -16193,6 +16206,18 @@
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.8.tgz",
"integrity": "sha512-HvPuUQnLp5H7TouGq3kzBeioJmXms1wHy9EGjz2OURWBp4qZO6AfGEcnxts1D/CbwPLRAgTMPCEgYhA3sEM4vw=="
},
"node_modules/react-google-recaptcha": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/react-google-recaptcha/-/react-google-recaptcha-2.1.0.tgz",
"integrity": "sha512-K9jr7e0CWFigi8KxC3WPvNqZZ47df2RrMAta6KmRoE4RUi7Ys6NmNjytpXpg4HI/svmQJLKR+PncEPaNJ98DqQ==",
"dependencies": {
"prop-types": "^15.5.0",
"react-async-script": "^1.1.1"
},
"peerDependencies": {
"react": ">=16.4.1"
}
},
"node_modules/react-intl": {
"version": "5.10.5",
"resolved": "https://registry.npmjs.org/react-intl/-/react-intl-5.10.5.tgz",
@ -34293,6 +34318,15 @@
"whatwg-fetch": "^3.4.1"
}
},
"react-async-script": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/react-async-script/-/react-async-script-1.2.0.tgz",
"integrity": "sha512-bCpkbm9JiAuMGhkqoAiC0lLkb40DJ0HOEJIku+9JDjxX3Rcs+ztEOG13wbrOskt3n2DTrjshhaQ/iay+SnGg5Q==",
"requires": {
"hoist-non-react-statics": "^3.3.0",
"prop-types": "^15.5.0"
}
},
"react-dev-utils": {
"version": "11.0.1",
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-11.0.1.tgz",
@ -34357,6 +34391,15 @@
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.8.tgz",
"integrity": "sha512-HvPuUQnLp5H7TouGq3kzBeioJmXms1wHy9EGjz2OURWBp4qZO6AfGEcnxts1D/CbwPLRAgTMPCEgYhA3sEM4vw=="
},
"react-google-recaptcha": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/react-google-recaptcha/-/react-google-recaptcha-2.1.0.tgz",
"integrity": "sha512-K9jr7e0CWFigi8KxC3WPvNqZZ47df2RrMAta6KmRoE4RUi7Ys6NmNjytpXpg4HI/svmQJLKR+PncEPaNJ98DqQ==",
"requires": {
"prop-types": "^15.5.0",
"react-async-script": "^1.1.1"
}
},
"react-intl": {
"version": "5.10.5",
"resolved": "https://registry.npmjs.org/react-intl/-/react-intl-5.10.5.tgz",

View File

@ -7,6 +7,7 @@
"@testing-library/user-event": "^12.2.2",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-google-recaptcha": "^2.1.0",
"react-intl": "^5.10.5",
"react-scripts": "4.0.1",
"web-vitals": "^0.2.4"
@ -49,4 +50,4 @@
"devDependencies": {
"@formatjs/cli": "^2.13.14"
}
}
}

View File

@ -2,7 +2,6 @@ import React from 'react';
import { FormattedMessage } from 'react-intl'
import logo from './images/header-logo.png'
class Header extends React.Component {
constructor(props) {
super(props);
@ -17,9 +16,12 @@ class Header extends React.Component {
let text;
const pageType = this.state.type;
if (pageType === 'login') {
if (pageType === 'only-signup') {
text = <span class="nav-center"><FormattedMessage id="header.donthaveaccount" defaultMessage="Don't have an account ?" /></span>;
signUpButton = <SignUpButton/>;
} if (pageType === 'only-signin') {
text = <span class="nav-center"><FormattedMessage id="header.haveaccount" defaultMessage="Already have an account?" /></span>;
signUpButton = <SignInButton/>;
} else {
signUpButton = <SignUpButton/>
signInButton = <SignInButton/>;
@ -40,7 +42,7 @@ class Header extends React.Component {
class SignInButton extends React.Component {
render() {
return <span class="nav-signin"><a href="/c/login"><FormattedMessage id="login.signin" defaultMessage="Sign In" /></a></span>;
return <span class="nav-signin button-style1"><a href="/c/login"><FormattedMessage id="login.signin" defaultMessage="Sign In" /></a></span>;
}
}
class SignUpButton extends React.Component {

View File

@ -6,71 +6,47 @@ import { FormattedMessage, IntlProvider, injectIntl } from 'react-intl'
import Header from './Header.js';
import Footer from './Footer.js';
class ConfigStatusMessage extends React.Component {
constructor(props) {
super(props)
this.state = {
enabled: props.enabled
}
const ConfigStatusMessage = (props) => {
const enabled = props.enabled
let result;
if (enabled === true) {
result = (<div class="db-warn-msg">
<p>
<FormattedMessage id="login.hsqldbcofig" defaultMessage="Although HSQLDB is bundled with WiseMapping by default during the installation, we do not recommend this database for production use. Please consider using MySQL 5.7 instead. You can find more information how to configure MySQL" description="Missing production database configured" /><a href="https://wisemapping.atlassian.net/wiki/display/WS/Database+Configuration"> here</a>
</p>
</div>);
} else {
result = <span></span>;
}
render() {
let result;
if (this.state.enabled===true) {
result = (<div class="db-warn-msg">
<p>
<FormattedMessage id="login.hsqldbcofig" defaultMessage="Although HSQLDB is bundled with WiseMapping by default during the installation, we do not recommend this database for production use. Please consider using MySQL 5.7 instead. You can find more information how to configure MySQL" description="Missing production database configured" /><a href="https://wisemapping.atlassian.net/wiki/display/WS/Database+Configuration"> here</a>
</p>
</div>);
} else {
result = <span></span>;
}
return result;
}
return result;
}
class LoginError extends React.Component {
constructor(props) {
super(props)
// @Todo: This must be reviewed to be based on navigation state.
// Login error example: http://localhost:8080/c/login?login.error=2
const errorCode = new URLSearchParams(window.location.search).get('login_error');
this.state = {
errorCode: errorCode
const LoginError = (props) => {
// @Todo: This must be reviewed to be based on navigation state.
// Login error example: http://localhost:8080/c/login?login.error=2
const errorCode = new URLSearchParams(window.location.search).get('login_error');
let result;
if (errorCode) {
if (errorCode === 3) {
result = (
<div class='error'>
<FormattedMessage id="login.userinactive" defaultMessage="Sorry, your account has not been activated yet. You'll receive a notification login.email when it becomes active. Stay tuned!." />
</div>)
} else {
result = (
<div class='error'>
<FormattedMessage id="login.error" defaultMessage="The login.email address or login.password you entered is not valid." />
</div>)
}
}
return (<span>{result}</span>);
render() {
let result;
const errorCode = this.state.errorCode;
if (errorCode) {
if (errorCode === 3) {
result = (
<div class='error'>
<FormattedMessage id="login.userinactive" defaultMessage="Sorry, your account has not been activated yet. You'll receive a notification login.email when it becomes active. Stay tuned!." />
</div>)
} else {
result = (
<div class='error'>
<FormattedMessage id="login.error" defaultMessage="The login.email address or login.password you entered is not valid." />
</div>)
}
}
return (<span>{result}</span>);
}
}
class LoginForm extends React.Component {
constructor(props) {
super(props);
this.state = {
intl: props.intl
}
}
render() {
const intl = this.props.intl;
@ -99,32 +75,22 @@ class LoginForm extends React.Component {
}
}
class LoginApp extends React.Component {
constructor(props) {
super(props);
const LoginApp = (props) => {
const messages = props.messages;
const locale = props.locale;
const messages = props.messages;
const locale = props.locale;
this.state = {
locale: locale,
messages: messages
};
}
render() {
return (
<IntlProvider locale={this.state.locale} defaultLocale='en' messages={this.state.messages}>
<div>
<Header type='login' />
<LoginForm />
<ConfigStatusMessage enabled='false' />
<Footer />
</div>
</IntlProvider>
);
}
return (
<IntlProvider locale={locale} defaultLocale='en' messages={messages}>
<div>
<Header type='only-signup' />
<LoginForm />
<ConfigStatusMessage enabled='false' />
<Footer />
</div>
</IntlProvider>
);
}
LoginForm = injectIntl(LoginForm)
export default LoginApp;

View File

@ -2,70 +2,64 @@ import './css/registration.css';
import React from 'react';
import { FormattedMessage, IntlProvider, injectIntl } from 'react-intl'
import ReCAPTCHA from "react-google-recaptcha";
import Header from './Header.js';
import Footer from './Footer.js';
class RegistrationError extends React.Component {
constructor(props) {
super(props)
// @Todo: This must be reviewed to be based on navigation state.
// Login error example: http://localhost:8080/c/login?login.error=2
const errorCode = new URLSearchParams(window.location.search).get('login_error');
this.state = {
errorCode: errorCode
}
}
render() {
let result;
const errorCode = this.state.errorCode;
if (errorCode) {
if (errorCode === 3) {
result = (
<div class='error'>
<FormattedMessage id="login.userinactive" defaultMessage="Sorry, your account has not been activated yet. You'll receive a notification login.email when it becomes active. Stay tuned!." />
</div>)
} else {
result = (
<div class='error'>
<FormattedMessage id="login.error" defaultMessage="The login.email address or login.password you entered is not valid." />
</div>)
}
}
return (<span>{result}</span>);
}
const RegistrationError = (props) => {
return (<span></span>);
}
class RegistrationForm extends React.Component {
constructor(props) {
super(props);
this.state = {
intl: props.intl
}
super(props)
this.handleChange = this.handleChange.bind(this);
this.handleRecaptchaChange = this.handleRecaptchaChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({ value: event.target.value });
}
handleRecaptchaChange(value) {
this.setState({ "recaptcha": value });
}
handleSubmit(event) {
event.preventDefault();
}
render() {
const intl = this.props.intl;
return (
<div class="wrapper">
<div class="content">
<h1><FormattedMessage id="registration.welcome" defaultMessage="Become a member of our comunity" /></h1>
<h1><FormattedMessage id="registration.become" defaultMessage="Become a member of our comunity" /></h1>
<p><FormattedMessage id="registration.signup" defaultMessage="Signing up is free and just take a moment " /></p>
<RegistrationError />
<form action="/c/perform-login" method="POST">
<input type="email" name="username" placeholder={intl.formatMessage({ id: "registration.email", defaultMessage: "Email" })} required="true" autocomplete="email" />
<input type="text" name="firstname" placeholder={intl.formatMessage({ id: "registration.firstname", defaultMessage: "First Name" })} required="true" autocomplete="given-name" />
<input type="text" name="lastname" placeholder={intl.formatMessage({ id: "registration.lastname", defaultMessage: "Last Name" })} required="true" autocomplete="family-name" />
<input type="password" name="password" placeholder={intl.formatMessage({ id: "registration.password", defaultMessage: "Password" })} required="true" autocomplete="new-password" />
<input type="password" name="retypePassword" placeholder={intl.formatMessage({ id: "registration.retypepassword", defaultMessage: "Retype Password" })} required="true" autocomplete="new-password" />
<form action="/" method="POST" onSubmit={this.handleSubmit}>
<input type="email" name="username" onChange={this.handleChange} placeholder={intl.formatMessage({ id: "registration.email", defaultMessage: "Email" })} required="true" autoComplete="email" />
<input type="text" name="firstname" onChange={this.handleChange} placeholder={intl.formatMessage({ id: "registration.firstname", defaultMessage: "First Name" })} required="true" autoComplete="given-name" />
<input type="text" name="lastname" onChange={this.handleChange} placeholder={intl.formatMessage({ id: "registration.lastname", defaultMessage: "Last Name" })} required="true" autoComplete="family-name" />
<input type="password" name="password" onChange={this.handleChange} placeholder={intl.formatMessage({ id: "registration.password", defaultMessage: "Password" })} required="true" autoComplete="new-password" />
<input type="password" name="retypePassword" onChange={this.handleChange} placeholder={intl.formatMessage({ id: "registration.retypepassword", defaultMessage: "Retype Password" })} required="true" autoComplete="new-password" />
<div>
<FormattedMessage id="registration.termandconditions" defaultMessage="By clicking Sign Up, you agree to our Terms, Data Policy and Cookies Policy. You may receive SMS Notifications from us and can opt out any time." />
<ReCAPTCHA
sitekey="6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI"
onChange={this.handleRecaptchaChange}
/>
</div>
<p>
<FormattedMessage id="registration.termandconditions" defaultMessage="Terms of Service: Please check the WiseMapping Account information you've entered above, and review the Terms of Service here. By clicking on 'Register' below you are agreeing to the Terms of Service above and the Privacy Policy" />
</p>
<input type="submit" value={intl.formatMessage({ id: "registration.register", defaultMessage: "Register" })} />
</form>
@ -75,31 +69,20 @@ class RegistrationForm extends React.Component {
}
}
class RegistationApp extends React.Component {
constructor(props) {
super(props);
const messages = props.messages;
const locale = props.locale;
this.state = {
locale: locale,
messages: messages
};
}
render() {
return (
<IntlProvider locale={this.state.locale} defaultLocale='en' messages={this.state.messages}>
<div>
<Header type='none' />
<RegistrationForm />
<Footer />
</div>
</IntlProvider>
);
}
const RegistationApp = props => {
const messages = props.messages;
const locale = props.locale;
return (
<IntlProvider locale={locale} defaultLocale='en' messages={messages}>
<div>
<Header type='only-signin' />
<RegistrationForm />
<Footer />
</div>
</IntlProvider>
);
}
RegistrationForm = injectIntl(RegistrationForm)
export default RegistationApp;

View File

@ -37,6 +37,13 @@
color: white;
}
form>p,
form>div {
font-size: 13px;
width: 300px;
margin: auto;
}
input[type=submit]:hover {
background-color: #f9a826;
}

View File

@ -34,7 +34,7 @@ function router() {
} else {
// It's loaded from the npm start
const pageId = new URLSearchParams(location.search).get('app');
result = Object.values(Apps).find(value => value.id == pageId);
result = Object.values(Apps).find(value => value.id === pageId);
}
if (result === null) {
result = Apps.LOGIN;