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": {
"defaultMessage": "Contact Us"
},
"footer.donations": {
"defaultMessage": "PayPal Donations"
},
"footer.faq": {
"defaultMessage": "F.A.Q."
},
"footer.faqandhelp": {
"defaultMessage": "Help & FAQ"
"defaultMessage": "Help & FAQ"
},
"footer.feedback": {
"defaultMessage": "Feedback"
@ -38,6 +35,12 @@
"forgot.register": {
"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": {
"defaultMessage": "Reset your password"
},
@ -48,7 +51,7 @@
"defaultMessage": "Already have an account?"
},
"login.desc": {
"defaultMessage": "Log Into Your Account"
"defaultMessage": "Log into your account"
},
"login.email": {
"defaultMessage": "Email"
@ -102,13 +105,13 @@
"registration.success.desc": {
"defaultMessage": "Click 'Sign In' button below and start creating mind maps."
},
"registration.success.title": {
"defaultMessage": "Your account has been created successfully"
},
"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"
},
"registration.title": {
"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",
"brotli-webpack-plugin": "^1.1.0",
"clean-webpack-plugin": "^3.0.0",
"copy-webpack-plugin": "^7.0.0",
"css-loader": "^5.0.1",
"eslint": "^7.14.0",
"eslint-plugin-react": "^7.21.5",

View File

@ -4,17 +4,17 @@
<head>
<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="theme-color" content="#000000" />
<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
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.
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.
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>
</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);
// Boostrap i18n ...
@ -46,7 +50,8 @@ const App = () => {
}, []);
// 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 ? (
<IntlProvider locale={locale} defaultLocale='en' messages={messages}>

View File

@ -17,12 +17,6 @@
"value": "Contact Us"
}
],
"footer.donations": [
{
"type": 0,
"value": "PayPal Donations"
}
],
"footer.faq": [
{
"type": 0,
@ -32,7 +26,7 @@
"footer.faqandhelp": [
{
"type": 0,
"value": "Help &amp; FAQ"
"value": "Help & FAQ"
}
],
"footer.feedback": [
@ -77,6 +71,18 @@
"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": [
{
"type": 0,
@ -98,7 +104,7 @@
"login.desc": [
{
"type": 0,
"value": "Log Into Your Account"
"value": "Log into your account"
}
],
"login.email": [
@ -203,12 +209,6 @@
"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": [
{
"type": 0,
@ -220,5 +220,11 @@
"type": 0,
"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>
</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/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>
@ -24,9 +24,6 @@ const Footer = () => {
<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>
<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>
)
}

View File

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

View File

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

View File

@ -55,7 +55,7 @@ const LoginPage = () => {
<PageContent>
<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 />

View File

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

View File

@ -2,11 +2,37 @@ import React from 'react';
import ReactDOM from 'react-dom';
import App from './app';
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(
<Router>
<App />
<App baseRestUrl={config.apiBaseUrl} />
</Router>,
document.getElementById('root') as HTMLElement
)

View File

@ -1,8 +1,8 @@
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 CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
@ -38,12 +38,20 @@ module.exports = {
},
plugins: [
new CleanWebpackPlugin(),
// @FixMe: Fatten the dir ...
new CopyWebpackPlugin({
patterns: [{
from: 'public/*'
}]
}),
new HtmlWebpackPlugin({
template: path.join(__dirname, 'public/index.html'),
templateParameters: {
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: {
contentBase: path.join(__dirname, 'dist'),