webpack
This commit is contained in:
parent
8dec4c8262
commit
75323ebc79
|
@ -5,6 +5,6 @@ ADD package.json package-lock.json /opt/obs/frontend/
|
||||||
RUN echo update-notifier=false >> ~/.npmrc
|
RUN echo update-notifier=false >> ~/.npmrc
|
||||||
RUN npm ci
|
RUN npm ci
|
||||||
|
|
||||||
ADD tsconfig.json index.html webpack.config.js /opt/obs/frontend/
|
ADD tsconfig.json webpack.config.js /opt/obs/frontend/
|
||||||
ADD public/ /opt/obs/frontend/public/
|
ADD public/ /opt/obs/frontend/public/
|
||||||
ADD src/ /opt/obs/frontend/src/
|
ADD src/ /opt/obs/frontend/src/
|
||||||
|
|
|
@ -9,7 +9,7 @@ ADD package.json package-lock.json /opt/obs/frontend/
|
||||||
RUN echo update-notifier=false >> ~/.npmrc
|
RUN echo update-notifier=false >> ~/.npmrc
|
||||||
RUN npm ci
|
RUN npm ci
|
||||||
|
|
||||||
ADD tsconfig.json index.html webpack.config.js /opt/obs/frontend/
|
ADD tsconfig.json webpack.config.js /opt/obs/frontend/
|
||||||
ADD public/ /opt/obs/frontend/public/
|
ADD public/ /opt/obs/frontend/public/
|
||||||
ADD src/ /opt/obs/frontend/src/
|
ADD src/ /opt/obs/frontend/src/
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
"loginUrl": "http://localhost:3000/login",
|
"loginUrl": "http://localhost:3000/login",
|
||||||
"imprintUrl": "https://example.com/imprint",
|
"imprintUrl": "https://example.com/imprint",
|
||||||
"privacyPolicyUrl": "https://example.com/privacy",
|
"privacyPolicyUrl": "https://example.com/privacy",
|
||||||
|
"basename": "/",
|
||||||
"mapTileset": {
|
"mapTileset": {
|
||||||
"url": "https://tiles.wmflabs.org/bw-mapnik/{z}/{x}/{y}.png",
|
"url": "https://tiles.wmflabs.org/bw-mapnik/{z}/{x}/{y}.png",
|
||||||
"minZoom": 0,
|
"minZoom": 0,
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
"loginUrl": "https://portal.example.com/login",
|
"loginUrl": "https://portal.example.com/login",
|
||||||
"imprintUrl": "https://example.com/imprint",
|
"imprintUrl": "https://example.com/imprint",
|
||||||
"privacyPolicyUrl": "https://example.com/privacy",
|
"privacyPolicyUrl": "https://example.com/privacy",
|
||||||
|
"basename": "/",
|
||||||
"mapTileset": {
|
"mapTileset": {
|
||||||
"url": "https://tiles.wmflabs.org/bw-mapnik/{z}/{x}/{y}.png",
|
"url": "https://tiles.wmflabs.org/bw-mapnik/{z}/{x}/{y}.png",
|
||||||
"minZoom": 0,
|
"minZoom": 0,
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<base href="%PUBLIC_URL%">
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<link rel="icon" href="public/favicon.ico" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
||||||
<meta name="theme-color" content="#000000" />
|
|
||||||
<meta
|
|
||||||
name="description"
|
|
||||||
content="Upload the tracks recorded with your OpenBikeSensor device to this portal and participate in the accumulation of Open Data."
|
|
||||||
/>
|
|
||||||
<link rel="apple-touch-icon" href="public/apple-touch-icon.png" />
|
|
||||||
<link rel="manifest" href="public/manifest.json" />
|
|
||||||
<title>OpenBikeSensor Portal</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
|
||||||
<div id="root"></div>
|
|
||||||
<script src="./src/index.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
998
frontend/package-lock.json
generated
998
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -4,11 +4,13 @@
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "webpack-dev-server",
|
"start": "webpack-dev-server",
|
||||||
"build": "webpack"
|
"build": "NODE_ENV=production webpack"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.16.3",
|
||||||
"classnames": "^2.3.1",
|
"classnames": "^2.3.1",
|
||||||
"downloadjs": "^1.4.7",
|
"downloadjs": "^1.4.7",
|
||||||
|
"fomantic-ui-less": "^2.8.8",
|
||||||
"luxon": "^1.28.0",
|
"luxon": "^1.28.0",
|
||||||
"maplibre-gl": "^1.15.2",
|
"maplibre-gl": "^1.15.2",
|
||||||
"pkce": "^1.0.0-beta2",
|
"pkce": "^1.0.0-beta2",
|
||||||
|
@ -25,7 +27,6 @@
|
||||||
"rxjs": "^6.6.7",
|
"rxjs": "^6.6.7",
|
||||||
"rxjs-hooks": "^0.6.2",
|
"rxjs-hooks": "^0.6.2",
|
||||||
"sass": "^1.43.5",
|
"sass": "^1.43.5",
|
||||||
"fomantic-ui-less": "^2.8.8",
|
|
||||||
"semantic-ui-react": "^2.0.4",
|
"semantic-ui-react": "^2.0.4",
|
||||||
"ts-loader": "^9.2.6",
|
"ts-loader": "^9.2.6",
|
||||||
"typescript": "^4.5.2"
|
"typescript": "^4.5.2"
|
||||||
|
@ -47,12 +48,13 @@
|
||||||
"last 1 safari version"
|
"last 1 safari version"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"proxy": "http://api:3000",
|
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.16.0",
|
"@babel/core": "^7.16.0",
|
||||||
|
"@babel/plugin-transform-runtime": "^7.16.4",
|
||||||
"@babel/preset-env": "^7.16.4",
|
"@babel/preset-env": "^7.16.4",
|
||||||
"@babel/preset-react": "^7.16.0",
|
"@babel/preset-react": "^7.16.0",
|
||||||
"@babel/preset-typescript": "^7.16.0",
|
"@babel/preset-typescript": "^7.16.0",
|
||||||
|
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.2",
|
||||||
"@types/lodash": "^4.14.177",
|
"@types/lodash": "^4.14.177",
|
||||||
"@types/node": "^14.17.34",
|
"@types/node": "^14.17.34",
|
||||||
"@types/react": "^17.0.37",
|
"@types/react": "^17.0.37",
|
||||||
|
@ -60,8 +62,10 @@
|
||||||
"@types/react-redux": "^7.1.20",
|
"@types/react-redux": "^7.1.20",
|
||||||
"@types/react-router-dom": "^5.3.2",
|
"@types/react-router-dom": "^5.3.2",
|
||||||
"babel-loader": "^8.2.3",
|
"babel-loader": "^8.2.3",
|
||||||
"css-loader": "^6.5.1",
|
"css-loader": "^5.2.7",
|
||||||
|
"html-webpack-plugin": "^5.5.0",
|
||||||
"less-loader": "^10.2.0",
|
"less-loader": "^10.2.0",
|
||||||
|
"react-refresh": "^0.11.0",
|
||||||
"style-loader": "^3.3.1",
|
"style-loader": "^3.3.1",
|
||||||
"webpack": "^5.64.4",
|
"webpack": "^5.64.4",
|
||||||
"webpack-cli": "^4.9.1",
|
"webpack-cli": "^4.9.1",
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
"apiUrl": "https://api.example.com",
|
"apiUrl": "https://api.example.com",
|
||||||
"imprintUrl": "https://portal.example.com/imprint",
|
"imprintUrl": "https://portal.example.com/imprint",
|
||||||
"privacyPolicyUrl": "https://portal.example.com/privacy",
|
"privacyPolicyUrl": "https://portal.example.com/privacy",
|
||||||
|
"basename": "/",
|
||||||
"mapTileset": {
|
"mapTileset": {
|
||||||
"url": "https://tiles.wmflabs.org/bw-mapnik/{z}/{x}/{y}.png",
|
"url": "https://tiles.wmflabs.org/bw-mapnik/{z}/{x}/{y}.png",
|
||||||
"minZoom": 0,
|
"minZoom": 0,
|
||||||
|
|
|
@ -42,9 +42,9 @@ const App = connect((state) => ({login: state.login}))(function App({login}) {
|
||||||
api.loadUser()
|
api.loadUser()
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return (
|
return config ? (
|
||||||
<Router basename={process.env.PUBLIC_URL || '/'}>
|
<Router basename={config.basename}>
|
||||||
<Menu fixed="top">
|
<Menu fixed="top" className={styles.menu}>
|
||||||
<Container>
|
<Container>
|
||||||
<Link to="/" component={MenuItemForLink} header className={styles.pageTitle}>
|
<Link to="/" component={MenuItemForLink} header className={styles.pageTitle}>
|
||||||
OpenBikeSensor
|
OpenBikeSensor
|
||||||
|
@ -184,7 +184,7 @@ const App = connect((state) => ({login: state.login}))(function App({login}) {
|
||||||
</Container>
|
</Container>
|
||||||
</div>
|
</div>
|
||||||
</Router>
|
</Router>
|
||||||
)
|
) : null
|
||||||
})
|
})
|
||||||
|
|
||||||
export default App
|
export default App
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
@import 'styles.less';
|
@import 'styles.less';
|
||||||
|
|
||||||
:global(#root) {
|
:global(#root) {
|
||||||
padding-top: 60px;
|
padding-top: @menuHeight;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
@ -12,6 +12,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.menu {
|
||||||
|
> :global(.ui.container) {
|
||||||
|
height: @menuHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.footer {
|
.footer {
|
||||||
margin-top: auto;
|
margin-top: auto;
|
||||||
min-height: 12rem;
|
min-height: 12rem;
|
||||||
|
|
|
@ -73,7 +73,7 @@ export default function Stats({user = null}: {user?: null | string}) {
|
||||||
<Statistic.Group widths={2} size="tiny">
|
<Statistic.Group widths={2} size="tiny">
|
||||||
<Statistic>
|
<Statistic>
|
||||||
<Statistic.Value>{stats ? `${Number(stats?.trackLength / 1000).toFixed(1)} km` : '...'}</Statistic.Value>
|
<Statistic.Value>{stats ? `${Number(stats?.trackLength / 1000).toFixed(1)} km` : '...'}</Statistic.Value>
|
||||||
<Statistic.Label>Total track length</Statistic.Label>
|
<Statistic.Label>Total xtrack length</Statistic.Label>
|
||||||
</Statistic>
|
</Statistic>
|
||||||
<Statistic>
|
<Statistic>
|
||||||
<Statistic.Value>{stats ? formatDuration(stats?.trackDuration) : '...'}</Statistic.Value>
|
<Statistic.Value>{stats ? formatDuration(stats?.trackDuration) : '...'}</Statistic.Value>
|
||||||
|
|
8
frontend/src/index.ejs
Normal file
8
frontend/src/index.ejs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head></head>
|
||||||
|
<body>
|
||||||
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
|
<div id="root"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -1,5 +1,7 @@
|
||||||
|
@import 'styles.less';
|
||||||
|
|
||||||
.mapContainer {
|
.mapContainer {
|
||||||
height: calc(100vh - 60px);
|
height: calc(100vh - @menuHeight);
|
||||||
background: red;
|
background: red;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,3 +8,4 @@
|
||||||
@primaryColor: @obsColorB4;
|
@primaryColor: @obsColorB4;
|
||||||
@secondaryColor: @obsColorG1;
|
@secondaryColor: @obsColorG1;
|
||||||
|
|
||||||
|
@menuHeight: 50px;
|
||||||
|
|
|
@ -1,84 +1,161 @@
|
||||||
const path = require('path');
|
var HtmlWebpackPlugin = require('html-webpack-plugin')
|
||||||
|
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin')
|
||||||
|
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
const isDevelopment = process.env.NODE_ENV !== 'production'
|
||||||
|
|
||||||
|
const API_URL = process.env.API_URL || 'http://localhost:3000'
|
||||||
|
const BASE_URL = process.env.BASE_URL || isDevelopment ? 'http://localhost:3001' : '__BASE_HREF__'
|
||||||
|
const PORT = process.env.PORT || 3001
|
||||||
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
entry: './src/index.js',
|
entry: './src/index.js',
|
||||||
mode: 'development',
|
mode: isDevelopment ? 'development' : 'production',
|
||||||
|
cache: isDevelopment && {type: 'filesystem'},
|
||||||
|
devtool: 'eval-cheap-module-source-map',
|
||||||
output: {
|
output: {
|
||||||
path: path.resolve(__dirname, 'dist'),
|
path: path.resolve(__dirname, 'build'),
|
||||||
filename: 'bundle.js',
|
filename: 'bundle.js',
|
||||||
},
|
},
|
||||||
|
cache: false,
|
||||||
resolve: {
|
resolve: {
|
||||||
extensions: ['.tsx', '.ts', '.js'],
|
extensions: ['.tsx', '.ts', '.js'],
|
||||||
alias: {
|
alias: {
|
||||||
'mapbox-gl': 'maplibre-gl',
|
'mapbox-gl': 'maplibre-gl',
|
||||||
'../../theme.config': path.resolve('./src/semantic-ui/theme.config')
|
'../../theme.config': path.resolve('./src/semantic-ui/theme.config'),
|
||||||
},
|
},
|
||||||
modules: ['node_modules', 'src'],
|
modules: ['node_modules', 'src'],
|
||||||
},
|
},
|
||||||
|
plugins: [
|
||||||
|
new HtmlWebpackPlugin({
|
||||||
|
base: BASE_URL,
|
||||||
|
meta: {
|
||||||
|
charset: 'utf-8',
|
||||||
|
viewport: 'width=device-width, initial-scale=1',
|
||||||
|
'theme-color': '#000000',
|
||||||
|
description:
|
||||||
|
'Upload the tracks recorded with your OpenBikeSensor device to this portal and participate in the accumulation of Open Data.',
|
||||||
|
},
|
||||||
|
favicon: 'public/favicon.ico',
|
||||||
|
manifest: 'public/manifest.json',
|
||||||
|
}),
|
||||||
|
|
||||||
|
isDevelopment && new ReactRefreshWebpackPlugin(),
|
||||||
|
].filter(Boolean),
|
||||||
|
devServer: {
|
||||||
|
port: PORT,
|
||||||
|
hot: true,
|
||||||
|
compress: true,
|
||||||
|
historyApiFallback: true,
|
||||||
|
static: {
|
||||||
|
directory: path.join(__dirname, 'public'),
|
||||||
|
serveIndex: true,
|
||||||
|
},
|
||||||
|
client: {
|
||||||
|
webSocketURL: `ws://0.0.0.0:${PORT}/ws`,
|
||||||
|
},
|
||||||
|
proxy: {
|
||||||
|
'/api': API_URL,
|
||||||
|
'/login': API_URL,
|
||||||
|
},
|
||||||
|
},
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
test: /\.(m?j|t)sx?$/,
|
test: /\.(mjs|js|jsx|ts|tsx)$/,
|
||||||
exclude: /(node_modules|bower_components)/,
|
include: path.resolve('./src'),
|
||||||
use: {
|
use: {
|
||||||
loader: 'babel-loader',
|
loader: 'babel-loader',
|
||||||
options: {
|
options: {
|
||||||
|
babelrc: false,
|
||||||
|
configFile: false,
|
||||||
|
cacheDirectory: true,
|
||||||
|
cacheCompression: false,
|
||||||
|
sourceMaps: true,
|
||||||
|
inputSourceMap: true,
|
||||||
|
|
||||||
|
plugins: [
|
||||||
|
isDevelopment && 'react-refresh/babel',
|
||||||
|
[
|
||||||
|
'@babel/plugin-transform-runtime',
|
||||||
|
{
|
||||||
|
corejs: false,
|
||||||
|
regenerator: true,
|
||||||
|
useESModules: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
].filter(Boolean),
|
||||||
presets: [
|
presets: [
|
||||||
|
[
|
||||||
'@babel/preset-react',
|
'@babel/preset-react',
|
||||||
|
{
|
||||||
|
development: isDevelopment,
|
||||||
|
runtime: 'automatic',
|
||||||
|
},
|
||||||
|
],
|
||||||
'@babel/preset-typescript',
|
'@babel/preset-typescript',
|
||||||
'@babel/preset-env']
|
'@babel/preset-env',
|
||||||
}
|
],
|
||||||
}
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.css$/i,
|
test: /\.css$/i,
|
||||||
use: [
|
use: ['style-loader', 'css-loader'],
|
||||||
"style-loader",
|
sideEffects: true,
|
||||||
"css-loader"
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.module\.less$/i,
|
test: /\.module\.less$/i,
|
||||||
use: [
|
use: [
|
||||||
// compiles Less to CSS
|
// compiles Less to CSS
|
||||||
"style-loader",
|
'style-loader',
|
||||||
{loader: "css-loader", options: { modules: true,}},
|
{loader: 'css-loader', options: {modules: true}},
|
||||||
{loader: "less-loader", options: {
|
{
|
||||||
|
loader: 'less-loader',
|
||||||
|
options: {
|
||||||
lessOptions: {
|
lessOptions: {
|
||||||
math: 'always',
|
math: 'always',
|
||||||
}
|
},
|
||||||
}},
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
|
sideEffects: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.less$/i,
|
test: /\.less$/i,
|
||||||
exclude: /\.module\.less$/i,
|
exclude: /\.module\.less$/i,
|
||||||
use: [
|
use: [
|
||||||
// compiles Less to CSS
|
// compiles Less to CSS
|
||||||
"style-loader",
|
'style-loader',
|
||||||
"css-loader",
|
'css-loader',
|
||||||
{loader: "less-loader", options: {
|
{
|
||||||
|
loader: 'less-loader',
|
||||||
|
options: {
|
||||||
lessOptions: {
|
lessOptions: {
|
||||||
math: 'always',
|
math: 'always',
|
||||||
}
|
},
|
||||||
}},
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
|
sideEffects: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
test: /\.(png|svg|jpg|jpeg|gif)$/i,
|
test: /\.(png|svg|jpg|jpeg|gif)$/i,
|
||||||
|
|
||||||
type: 'asset/resource',
|
type: 'asset/resource',
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
test: /\.(woff|woff2|eot|ttf|otf)$/i,
|
test: /\.(woff|woff2|eot|ttf|otf)$/i,
|
||||||
|
|
||||||
type: 'asset/resource',
|
type: 'asset/resource',
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
scheme: 'data',
|
||||||
|
type: 'asset/resource',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
|
|
Loading…
Reference in a new issue