Add support for external runtime configuration

This commit is contained in:
Paulo Gustavo Veiga 2020-12-12 12:23:38 -08:00
parent 9d80a03018
commit c6947dcb39
13 changed files with 92 additions and 44 deletions

View File

@ -8,14 +8,11 @@
"footer.contactus": { "footer.contactus": {
"defaultMessage": "Contact Us" "defaultMessage": "Contact Us"
}, },
"footer.donations": {
"defaultMessage": "PayPal Donations"
},
"footer.faq": { "footer.faq": {
"defaultMessage": "F.A.Q." "defaultMessage": "F.A.Q."
}, },
"footer.faqandhelp": { "footer.faqandhelp": {
"defaultMessage": "Help & FAQ" "defaultMessage": "Help & FAQ"
}, },
"footer.feedback": { "footer.feedback": {
"defaultMessage": "Feedback" "defaultMessage": "Feedback"
@ -38,6 +35,12 @@
"forgot.register": { "forgot.register": {
"defaultMessage": "Send recovery link" "defaultMessage": "Send recovery link"
}, },
"forgot.success.desc": {
"defaultMessage": "We've sent you an email that will allow you to reset your password. Please check your email now."
},
"forgot.success.title": {
"defaultMessage": "Your temporal password has been sent"
},
"forgot.title": { "forgot.title": {
"defaultMessage": "Reset your password" "defaultMessage": "Reset your password"
}, },
@ -48,7 +51,7 @@
"defaultMessage": "Already have an account?" "defaultMessage": "Already have an account?"
}, },
"login.desc": { "login.desc": {
"defaultMessage": "Log Into Your Account" "defaultMessage": "Log into your account"
}, },
"login.email": { "login.email": {
"defaultMessage": "Email" "defaultMessage": "Email"
@ -102,13 +105,13 @@
"registration.success.desc": { "registration.success.desc": {
"defaultMessage": "Click 'Sign In' button below and start creating mind maps." "defaultMessage": "Click 'Sign In' button below and start creating mind maps."
}, },
"registration.success.title": {
"defaultMessage": "Your account has been created successfully"
},
"registration.termandconditions": { "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" "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"
}, },
"registration.title": { "registration.title": {
"defaultMessage": "Become a member of our comunity" "defaultMessage": "Become a member of our comunity"
},
"resetpassword.success.title": {
"defaultMessage": "Your account has been created successfully"
} }
} }

View File

@ -25,6 +25,7 @@
"babel-loader": "^8.2.2", "babel-loader": "^8.2.2",
"brotli-webpack-plugin": "^1.1.0", "brotli-webpack-plugin": "^1.1.0",
"clean-webpack-plugin": "^3.0.0", "clean-webpack-plugin": "^3.0.0",
"copy-webpack-plugin": "^7.0.0",
"css-loader": "^5.0.1", "css-loader": "^5.0.1",
"eslint": "^7.14.0", "eslint": "^7.14.0",
"eslint-plugin-react": "^7.21.5", "eslint-plugin-react": "^7.21.5",

View File

@ -4,17 +4,17 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<link rel="icon" href="<%=PUBLIC_URL %>/favicon.ico" /> <link rel="icon" href="<%=PUBLIC_URL%>/public/favicon.ico" />
<meta name="viewport" content="width=device-width" /> <meta name="viewport" content="width=device-width" />
<meta name="theme-color" content="#000000" /> <meta name="theme-color" content="#000000" />
<meta name="description" content="WiseMappping" /> <meta name="description" content="WiseMappping" />
<link rel="apple-touch-icon" href="<%=PUBLIC_URL %>/favicon.png" /> <link rel="apple-touch-icon" href="<%=PUBLIC_URL%>/favicon.png" />
<!-- <!--
manifest.json provides metadata used when your web app is installed on a manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/ user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
--> -->
<link rel="manifest" href="<%=PUBLIC_URL %>/manifest.json" /> <link rel="manifest" href="<%=PUBLIC_URL%>/public/manifest.json" />
<!-- <!--
Notice the use of %PUBLIC_URL% in the tags above. Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build. It will be replaced with the URL of the `public` folder during the build.
@ -24,8 +24,9 @@
work correctly both with client-side routing and a non-root public URL. work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`. Learn how to configure a non-root public URL by running `npm run build`.
--> -->
<!--
<base href="<%=PUBLIC_URL%>" /> Dynamic runtime configuration properties (https://dev.to/matt_catalfamo/runtime-configurations-with-react-22dl)
-->
<title>Loading | WiseMapping</title> <title>Loading | WiseMapping</title>
</head> </head>

View File

@ -0,0 +1,3 @@
{
"apiBaseUrl": "http://localhost:8080"
}

View File

@ -26,7 +26,11 @@ function loadLocaleData(language: string) {
} }
} }
const App = () => { type AppProps = {
baseRestUrl: string;
}
const App = (props: AppProps) => {
const [messages, setMessages] = useState(undefined); const [messages, setMessages] = useState(undefined);
// Boostrap i18n ... // Boostrap i18n ...
@ -46,7 +50,8 @@ const App = () => {
}, []); }, []);
// Create Service object... // Create Service object...
const service: Service = new RestService('http://localhost:8080', () => { console.log("401 error") });
const service: Service = new RestService(props.baseRestUrl, () => { console.log("401 error") });
return messages ? ( return messages ? (
<IntlProvider locale={locale} defaultLocale='en' messages={messages}> <IntlProvider locale={locale} defaultLocale='en' messages={messages}>

View File

@ -17,12 +17,6 @@
"value": "Contact Us" "value": "Contact Us"
} }
], ],
"footer.donations": [
{
"type": 0,
"value": "PayPal Donations"
}
],
"footer.faq": [ "footer.faq": [
{ {
"type": 0, "type": 0,
@ -32,7 +26,7 @@
"footer.faqandhelp": [ "footer.faqandhelp": [
{ {
"type": 0, "type": 0,
"value": "Help &amp; FAQ" "value": "Help & FAQ"
} }
], ],
"footer.feedback": [ "footer.feedback": [
@ -77,6 +71,18 @@
"value": "Send recovery link" "value": "Send recovery link"
} }
], ],
"forgot.success.desc": [
{
"type": 0,
"value": "We've sent you an email that will allow you to reset your password. Please check your email now."
}
],
"forgot.success.title": [
{
"type": 0,
"value": "Your temporal password has been sent"
}
],
"forgot.title": [ "forgot.title": [
{ {
"type": 0, "type": 0,
@ -98,7 +104,7 @@
"login.desc": [ "login.desc": [
{ {
"type": 0, "type": 0,
"value": "Log Into Your Account" "value": "Log into your account"
} }
], ],
"login.email": [ "login.email": [
@ -203,12 +209,6 @@
"value": "Click 'Sign In' button below and start creating mind maps." "value": "Click 'Sign In' button below and start creating mind maps."
} }
], ],
"registration.success.title": [
{
"type": 0,
"value": "Your account has been created successfully"
}
],
"registration.termandconditions": [ "registration.termandconditions": [
{ {
"type": 0, "type": 0,
@ -220,5 +220,11 @@
"type": 0, "type": 0,
"value": "Become a member of our comunity" "value": "Become a member of our comunity"
} }
],
"resetpassword.success.title": [
{
"type": 0,
"value": "Your account has been created successfully"
}
] ]
} }

View File

@ -13,7 +13,7 @@ const Footer = () => {
</a> </a>
</div> </div>
<div > <div >
<h4><FormattedMessage id="footer.faqandhelp" defaultMessage="Help &amp; FAQ" /></h4> <h4><FormattedMessage id="footer.faqandhelp" defaultMessage="Help & FAQ" /></h4>
<div><a href="https://www.wisemapping.com/faq.html"> <FormattedMessage id="footer.faq" defaultMessage="F.A.Q." /> </a></div > <div><a href="https://www.wisemapping.com/faq.html"> <FormattedMessage id="footer.faq" defaultMessage="F.A.Q." /> </a></div >
<div><a href="https://www.wisemapping.com/termsofuse.html"> <FormattedMessage id="footer.termsandconditions" defaultMessage="Term And Conditions" /> </a></div> <div><a href="https://www.wisemapping.com/termsofuse.html"> <FormattedMessage id="footer.termsandconditions" defaultMessage="Term And Conditions" /> </a></div>
<div><a href="mailto:team@wisemapping.com"> <FormattedMessage id="footer.contactus" defaultMessage="Contact Us" /> </a></div> <div><a href="mailto:team@wisemapping.com"> <FormattedMessage id="footer.contactus" defaultMessage="Contact Us" /> </a></div>
@ -24,9 +24,6 @@ const Footer = () => {
<div><a href="mailto:feedback@wisemapping.com" > <FormattedMessage id="footer.feedback" defaultMessage="Feedback" /> </a></div> <div><a href="mailto:feedback@wisemapping.com" > <FormattedMessage id="footer.feedback" defaultMessage="Feedback" /> </a></div>
<div><a href="http://www.wisemapping.org/"> <FormattedMessage id="footer.opensource" defaultMessage="Open Source" /> </a></div> <div><a href="http://www.wisemapping.org/"> <FormattedMessage id="footer.opensource" defaultMessage="Open Source" /> </a></div>
</div> </div>
<div>
<div><span className="button-style2" >< a href="https://www.paypal.com/webapps/shoppingcart?flowlogging_id=c7ac923b53025&mfid=1606520600355_c7ac923b53025#/checkout/openButton">< FormattedMessage id="footer.donations" defaultMessage="PayPal Donations" /> </a></span ></div>
</div>
</StyledFooter> </StyledFooter>
) )
} }

View File

@ -32,7 +32,7 @@ const ForgotPassword = (props: ServiceProps) => {
// Call Service ... // Call Service ...
props.service.resetPassword( props.service.resetPassword(
email, email,
() => history.push("/c/view/forgot-password-success"), () => history.push("/c/forgot-password-success"),
(msg) => { (msg) => {
setErrorMsg(msg); setErrorMsg(msg);
setDisableButton(false); setDisableButton(false);

View File

@ -1,7 +1,7 @@
import React, { useEffect } from 'react' import React, { useEffect } from 'react'
import { FormattedMessage } from 'react-intl' import { FormattedMessage } from 'react-intl'
import {PageContent} from '../../theme/global-style'; import { PageContent } from '../../theme/global-style';
import Header, { SignInButton } from '../header' import Header, { SignInButton } from '../header'
import Footer from '../footer' import Footer from '../footer'
@ -14,7 +14,6 @@ const ForgotPasswordSuccessPage = () => {
return ( return (
<div> <div>
<Header type='none' /> <Header type='none' />
<div>
<PageContent> <PageContent>
<h1> <h1>
<FormattedMessage id="forgot.success.title" defaultMessage="Your temporal password has been sent" /> <FormattedMessage id="forgot.success.title" defaultMessage="Your temporal password has been sent" />
@ -25,12 +24,11 @@ const ForgotPasswordSuccessPage = () => {
<SignInButton style='style1' /> <SignInButton style='style1' />
</PageContent> </PageContent>
</div>
<Footer /> <Footer />
</div> </div>
); );
} }
export default ForgotPasswordSuccessPage export default ForgotPasswordSuccessPage

View File

@ -55,7 +55,7 @@ const LoginPage = () => {
<PageContent> <PageContent>
<h1><FormattedMessage id="login.title" defaultMessage="Welcome" /></h1> <h1><FormattedMessage id="login.title" defaultMessage="Welcome" /></h1>
<p><FormattedMessage id="login.desc" defaultMessage="Log Into Your Account" /></p> <p><FormattedMessage id="login.desc" defaultMessage="Log into your account" /></p>
<LoginError /> <LoginError />

View File

@ -1,4 +1,4 @@
import React, { useState, useEffect} from 'react' import React, { useState, useEffect } from 'react'
import { useIntl } from 'react-intl' import { useIntl } from 'react-intl'
type SubmitButton = { type SubmitButton = {

View File

@ -2,11 +2,37 @@ import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import App from './app'; import App from './app';
import { BrowserRouter as Router } from 'react-router-dom'; import { BrowserRouter as Router } from 'react-router-dom';
import axios from 'axios'
function bootstrapApplication() { type RutimeConfig = {
apiBaseUrl: string;
}
async function loadRuntimeConfig() {
let result: RutimeConfig | undefined;
await axios.get("public/runtime-config.json"
).then(response => {
// All was ok, let's sent to success page ...
result = response.data as RutimeConfig;
console.log("Dynamic configuration->" + response.data);
}).catch(e => {
console.log(e)
});
// Was is loaded ?
if (!result) {
throw "Please, review runtime config"
}
return result;
}
async function bootstrapApplication() {
const config: RutimeConfig = await loadRuntimeConfig();
ReactDOM.render( ReactDOM.render(
<Router> <Router>
<App /> <App baseRestUrl={config.apiBaseUrl} />
</Router>, </Router>,
document.getElementById('root') as HTMLElement document.getElementById('root') as HTMLElement
) )

View File

@ -1,8 +1,8 @@
const path = require('path'); const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack'); const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin'); const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = { module.exports = {
@ -38,12 +38,20 @@ module.exports = {
}, },
plugins: [ plugins: [
new CleanWebpackPlugin(), new CleanWebpackPlugin(),
// @FixMe: Fatten the dir ...
new CopyWebpackPlugin({
patterns: [{
from: 'public/*'
}]
}),
new HtmlWebpackPlugin({ new HtmlWebpackPlugin({
template: path.join(__dirname, 'public/index.html'), template: path.join(__dirname, 'public/index.html'),
templateParameters: { templateParameters: {
PUBLIC_URL: process.env.PUBLIC_URL ? process.env.PUBLIC_URL : 'http://localhost:3000' PUBLIC_URL: process.env.PUBLIC_URL ? process.env.PUBLIC_URL : 'http://localhost:3000'
}, },
base: process.env.PUBLIC_URL ? process.env.PUBLIC_URL : 'http://localhost:3000'
}) })
], ],
devServer: { devServer: {
contentBase: path.join(__dirname, 'dist'), contentBase: path.join(__dirname, 'dist'),