commas
This commit is contained in:
@@ -3,8 +3,10 @@ root = true
|
|||||||
[*]
|
[*]
|
||||||
end_of_line = lf
|
end_of_line = lf
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
[*.js]
|
|
||||||
charset = utf-8
|
|
||||||
indent_style = space
|
indent_style = space
|
||||||
|
charset = utf-8
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
trim_trailing_whitespace = false
|
||||||
|
|||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,4 +1,2 @@
|
|||||||
node_modules/
|
node_modules/
|
||||||
.vscode/
|
|
||||||
tmp/
|
|
||||||
.env
|
.env
|
||||||
|
|||||||
20
.vscode/settings.json
vendored
Normal file
20
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"workbench.colorCustomizations": {
|
||||||
|
"activityBar.activeBackground": "#d04649",
|
||||||
|
"activityBar.activeBorder": "#37cb34",
|
||||||
|
"activityBar.background": "#d04649",
|
||||||
|
"activityBar.foreground": "#e7e7e7",
|
||||||
|
"activityBar.inactiveForeground": "#e7e7e799",
|
||||||
|
"activityBarBadge.background": "#37cb34",
|
||||||
|
"activityBarBadge.foreground": "#15202b",
|
||||||
|
"statusBar.background": "#b52e31",
|
||||||
|
"statusBar.border": "#b52e31",
|
||||||
|
"statusBar.foreground": "#e7e7e7",
|
||||||
|
"statusBarItem.hoverBackground": "#d04649",
|
||||||
|
"titleBar.activeBackground": "#b52e31",
|
||||||
|
"titleBar.activeForeground": "#e7e7e7",
|
||||||
|
"titleBar.border": "#b52e31",
|
||||||
|
"titleBar.inactiveBackground": "#b52e3199",
|
||||||
|
"titleBar.inactiveForeground": "#e7e7e799"
|
||||||
|
}
|
||||||
|
}
|
||||||
4
api/.gitignore
vendored
Normal file
4
api/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
node_modules/
|
||||||
|
.vscode/
|
||||||
|
tmp/
|
||||||
|
.env
|
||||||
7118
api/package-lock.json
generated
Normal file
7118
api/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
39
api/package.json
Normal file
39
api/package.json
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
{
|
||||||
|
"name": "maanteeamet-fetch",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"main": "index.js",
|
||||||
|
"engines": {
|
||||||
|
"node": "14.3.0"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"start": "babel-node src/index.js",
|
||||||
|
"dev": "nodemon -r dotenv/config --watch src --exec babel-node src/index.js"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"cacheman": "2.2.1",
|
||||||
|
"cacheman-file": "0.2.1",
|
||||||
|
"compression": "1.7.4",
|
||||||
|
"dotenv": "8.2.0",
|
||||||
|
"express": "4.17.1",
|
||||||
|
"form-data": "3.0.0",
|
||||||
|
"helmet": "^3.22.0",
|
||||||
|
"jsdom": "16.2.2",
|
||||||
|
"node-fetch": "2.6.0",
|
||||||
|
"puppeteer": "3.1.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/cli": "7.8.4",
|
||||||
|
"@babel/core": "7.9.6",
|
||||||
|
"@babel/node": "7.8.7",
|
||||||
|
"@babel/plugin-proposal-class-properties": "7.8.3",
|
||||||
|
"@babel/preset-env": "7.9.6",
|
||||||
|
"babel-eslint": "10.1.0",
|
||||||
|
"eslint": "^6.8.0",
|
||||||
|
"eslint-config-airbnb": "18.1.0",
|
||||||
|
"eslint-plugin-import": "2.20.2",
|
||||||
|
"eslint-plugin-jsx-a11y": "6.2.3",
|
||||||
|
"eslint-plugin-react": "7.20.0",
|
||||||
|
"eslint-plugin-react-hooks": "2.5.0",
|
||||||
|
"nodemon": "2.0.4"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
import express from 'express';
|
import express from 'express';
|
||||||
import http from 'http';
|
import http from 'http';
|
||||||
|
import compression from 'compression';
|
||||||
|
import helmet from 'helmet';
|
||||||
import Hack from '../components/Hack';
|
import Hack from '../components/Hack';
|
||||||
|
|
||||||
const PORT = 3000;
|
const PORT = process.env.PORT || "8000";
|
||||||
|
|
||||||
class BasicApi {
|
class BasicApi {
|
||||||
app;
|
app;
|
||||||
@@ -11,6 +13,8 @@ class BasicApi {
|
|||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.app = express();
|
this.app = express();
|
||||||
|
this.app.use(compression());
|
||||||
|
this.app.use(helmet());
|
||||||
this.server = http.createServer(this.app);
|
this.server = http.createServer(this.app);
|
||||||
this.hack = new Hack();
|
this.hack = new Hack();
|
||||||
}
|
}
|
||||||
|
Before Width: | Height: | Size: 469 KiB After Width: | Height: | Size: 469 KiB |
29
deploy/ftp.js
Normal file
29
deploy/ftp.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
const FtpDeploy = require("ftp-deploy");
|
||||||
|
const ftpDeploy = new FtpDeploy();
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
user: process.env.FTP_USER,
|
||||||
|
password: process.env.FTP_PASSWORD,
|
||||||
|
host: process.env.FTP_HOST,
|
||||||
|
port: process.env.FTP_PORT,
|
||||||
|
localRoot: __dirname + "/../frontend",
|
||||||
|
remoteRoot: "/public_html/car/",
|
||||||
|
// include: ["*", "**/*"], // this would upload everything except dot files
|
||||||
|
include: ["build/**"],
|
||||||
|
// e.g. exclude sourcemaps, and ALL files in node_modules (including dot files)
|
||||||
|
exclude: ["build/**/*.map", "node_modules/**", "node_modules/**/.*", ".git/**"],
|
||||||
|
// delete ALL existing files at destination before uploading, if true
|
||||||
|
deleteRemote: false,
|
||||||
|
// Passive mode is forced (EPSV command is not sent)
|
||||||
|
forcePasv: true
|
||||||
|
};
|
||||||
|
|
||||||
|
ftpDeploy
|
||||||
|
.deploy(config)
|
||||||
|
.then(res => {
|
||||||
|
console.log("Deployment to FTP finished");
|
||||||
|
return;
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err);
|
||||||
|
});
|
||||||
61
frontend/.babelrc.js
Normal file
61
frontend/.babelrc.js
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
module.exports = (api) => {
|
||||||
|
api.cache(true);
|
||||||
|
return {
|
||||||
|
sourceType: 'module',
|
||||||
|
presets: [
|
||||||
|
[
|
||||||
|
'@babel/preset-env',
|
||||||
|
{
|
||||||
|
useBuiltIns: 'usage',
|
||||||
|
corejs: 3,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'@babel/preset-react',
|
||||||
|
{
|
||||||
|
development: process.env.NODE_ENV === 'development',
|
||||||
|
}
|
||||||
|
]
|
||||||
|
],
|
||||||
|
plugins: [
|
||||||
|
'@babel/plugin-proposal-optional-chaining',
|
||||||
|
[
|
||||||
|
'@babel/plugin-proposal-decorators',
|
||||||
|
{
|
||||||
|
legacy: true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'@babel/plugin-proposal-function-sent',
|
||||||
|
'@babel/plugin-proposal-export-namespace-from',
|
||||||
|
'@babel/plugin-proposal-numeric-separator',
|
||||||
|
'@babel/plugin-proposal-throw-expressions',
|
||||||
|
// Stage 3
|
||||||
|
'@babel/plugin-syntax-dynamic-import',
|
||||||
|
'@babel/plugin-syntax-import-meta',
|
||||||
|
[
|
||||||
|
'@babel/plugin-proposal-class-properties',
|
||||||
|
{
|
||||||
|
loose: true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'@babel/plugin-proposal-json-strings',
|
||||||
|
[
|
||||||
|
'module-resolver', {
|
||||||
|
root: [
|
||||||
|
'./src'
|
||||||
|
],
|
||||||
|
alias: {
|
||||||
|
'@slice': './src/slice',
|
||||||
|
'@util': './src/util',
|
||||||
|
'@container': './src/container',
|
||||||
|
'@style': './src/style',
|
||||||
|
'@constant': './src/constant',
|
||||||
|
'@context': './src/context',
|
||||||
|
'@components': './src/components',
|
||||||
|
'@hook': './src/hook',
|
||||||
|
'@assets': './assets',
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
4
frontend/.browserslistrc
Normal file
4
frontend/.browserslistrc
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
> 1%
|
||||||
|
not dead
|
||||||
|
not ie <12
|
||||||
|
Firefox ESR
|
||||||
1
frontend/.eslintignore
Normal file
1
frontend/.eslintignore
Normal file
@@ -0,0 +1 @@
|
|||||||
|
webpack/**
|
||||||
129
frontend/.eslintrc.js
Normal file
129
frontend/.eslintrc.js
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
module.exports = {
|
||||||
|
root: true,
|
||||||
|
parser: 'babel-eslint',
|
||||||
|
parserOptions: {
|
||||||
|
ecmaVersion: 2019,
|
||||||
|
sourceType: 'module',
|
||||||
|
ecmaFeatures: {
|
||||||
|
jsx: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
settings: {
|
||||||
|
react: {
|
||||||
|
version: 'detect',
|
||||||
|
},
|
||||||
|
'import/resolver': {
|
||||||
|
// resolves aliases from .babelrc automatically
|
||||||
|
'babel-module': {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
env: {
|
||||||
|
es6: true,
|
||||||
|
browser: true,
|
||||||
|
node: true,
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
'react',
|
||||||
|
'jsx-a11y',
|
||||||
|
],
|
||||||
|
extends: [
|
||||||
|
'airbnb',
|
||||||
|
'airbnb/hooks',
|
||||||
|
'plugin:react/recommended',
|
||||||
|
],
|
||||||
|
globals: {
|
||||||
|
React: true,
|
||||||
|
document: true,
|
||||||
|
window: true,
|
||||||
|
localStorage: true,
|
||||||
|
fetch: true,
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
'babel/object-curly-spacing': 0,
|
||||||
|
'class-methods-use-this': 0,
|
||||||
|
indent: [
|
||||||
|
'error',
|
||||||
|
2,
|
||||||
|
],
|
||||||
|
'jsx-a11y/anchor-is-valid': [
|
||||||
|
'warn',
|
||||||
|
{
|
||||||
|
aspects: [
|
||||||
|
'invalidHref',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'jsx-a11y/href-no-hash': 'off',
|
||||||
|
'no-trailing-spaces': [
|
||||||
|
2,
|
||||||
|
{
|
||||||
|
skipBlankLines: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'prefer-template': 0,
|
||||||
|
'react/jsx-boolean-value': [
|
||||||
|
'warn',
|
||||||
|
'never',
|
||||||
|
],
|
||||||
|
'react/jsx-closing-bracket-location': [
|
||||||
|
'warn',
|
||||||
|
'after-props',
|
||||||
|
],
|
||||||
|
'react/jsx-curly-spacing': [
|
||||||
|
'warn',
|
||||||
|
'never',
|
||||||
|
],
|
||||||
|
'react/jsx-filename-extension': [
|
||||||
|
'warn',
|
||||||
|
{
|
||||||
|
extensions: [
|
||||||
|
'.jsx',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'react/jsx-first-prop-new-line': [
|
||||||
|
'warn',
|
||||||
|
'multiline',
|
||||||
|
],
|
||||||
|
'react/jsx-handler-names': [
|
||||||
|
'warn',
|
||||||
|
{
|
||||||
|
eventHandlerPrefix: 'handle',
|
||||||
|
eventHandlerPropPrefix: 'on',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'react/jsx-indent': [
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
],
|
||||||
|
'react/jsx-key': 'error',
|
||||||
|
'react/jsx-wrap-multilines': [
|
||||||
|
'warn',
|
||||||
|
],
|
||||||
|
'react/prop-types': 0,
|
||||||
|
'react/self-closing-comp': [
|
||||||
|
'warn',
|
||||||
|
{
|
||||||
|
component: true,
|
||||||
|
html: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'react/sort-comp': [
|
||||||
|
1,
|
||||||
|
{
|
||||||
|
groups: {
|
||||||
|
rendering: [
|
||||||
|
'/^render.+$/',
|
||||||
|
'render',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
order: [
|
||||||
|
'everything-else',
|
||||||
|
'lifecycle',
|
||||||
|
'rendering',
|
||||||
|
'static-methods',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
2
frontend/.gitattributes
vendored
Normal file
2
frontend/.gitattributes
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
package-lock.json -diff
|
||||||
|
yarn.lock -diff
|
||||||
23
frontend/.gitignore
vendored
Normal file
23
frontend/.gitignore
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# Cruft
|
||||||
|
*~
|
||||||
|
*#
|
||||||
|
.#*
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Test
|
||||||
|
coverage
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# npm & yarn
|
||||||
|
node_modules/
|
||||||
|
.npm
|
||||||
|
.yarn-integrity
|
||||||
|
build/*
|
||||||
|
|
||||||
|
# Editor/IDE
|
||||||
|
.idea
|
||||||
|
.vscode
|
||||||
|
packages/api/etc/
|
||||||
5
frontend/README.md
Normal file
5
frontend/README.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# React Base
|
||||||
|
|
||||||
|
[](https://github.com/k4rli/react-base/releases)
|
||||||
|
[](https://github.com/k4rli/react-base/commit/)
|
||||||
|
[](https://github.com/k4rli/react-base/graphs/contributors/)
|
||||||
0
frontend/assets/fonts/.gitkeep
Normal file
0
frontend/assets/fonts/.gitkeep
Normal file
10
frontend/jsconfig.json
Normal file
10
frontend/jsconfig.json
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": "./",
|
||||||
|
"paths": {
|
||||||
|
"@*":[
|
||||||
|
"src/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
8
frontend/nodemon.json
Normal file
8
frontend/nodemon.json
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"watch": [
|
||||||
|
"webpack/webpack.common.js",
|
||||||
|
"webpack/webpack.dev.js",
|
||||||
|
".babelrc.js",
|
||||||
|
"package-lock.json"
|
||||||
|
]
|
||||||
|
}
|
||||||
14628
frontend/package-lock.json
generated
Normal file
14628
frontend/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
95
frontend/package.json
Normal file
95
frontend/package.json
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
{
|
||||||
|
"name": "react-base",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "Base React template",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"start": "nodemon --exec \"cross-env NODE_ENV=development webpack-dev-server\"",
|
||||||
|
"prebundle": "rimraf build/*",
|
||||||
|
"bundle": "cross-env NODE_ENV=production webpack",
|
||||||
|
"cacheclean": "rimraf node_modules/.cache/hard-source",
|
||||||
|
"precommit": "lint-staged",
|
||||||
|
"lint": "eslint --fix src --ext .jsx"
|
||||||
|
},
|
||||||
|
"author": "k4rli",
|
||||||
|
"contributors": [],
|
||||||
|
"keywords": [
|
||||||
|
"react",
|
||||||
|
"reactjs",
|
||||||
|
"react-boilerplate"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=11",
|
||||||
|
"npm": ">=6"
|
||||||
|
},
|
||||||
|
"lint-staged": {
|
||||||
|
"*.{js,jsx,css,md}": [
|
||||||
|
"eslint --fix",
|
||||||
|
"git add"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@reduxjs/toolkit": "1.3.6",
|
||||||
|
"core-js": "3.6.5",
|
||||||
|
"react": "16.13.1",
|
||||||
|
"react-dom": "16.13.1",
|
||||||
|
"react-hot-loader": "4.12.21",
|
||||||
|
"react-webcam": "5.0.2",
|
||||||
|
"regenerator-runtime": "0.13.5",
|
||||||
|
"use-dark-mode": "2.3.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "7.9.6",
|
||||||
|
"@babel/plugin-proposal-class-properties": "7.8.3",
|
||||||
|
"@babel/plugin-proposal-decorators": "7.8.3",
|
||||||
|
"@babel/plugin-proposal-export-namespace-from": "7.8.3",
|
||||||
|
"@babel/plugin-proposal-function-sent": "7.8.3",
|
||||||
|
"@babel/plugin-proposal-json-strings": "7.8.3",
|
||||||
|
"@babel/plugin-proposal-numeric-separator": "7.8.3",
|
||||||
|
"@babel/plugin-proposal-optional-chaining": "7.9.0",
|
||||||
|
"@babel/plugin-proposal-throw-expressions": "7.8.3",
|
||||||
|
"@babel/plugin-syntax-dynamic-import": "7.8.3",
|
||||||
|
"@babel/plugin-syntax-import-meta": "7.8.3",
|
||||||
|
"@babel/plugin-transform-runtime": "7.9.6",
|
||||||
|
"@babel/preset-env": "7.9.6",
|
||||||
|
"@babel/preset-react": "7.9.4",
|
||||||
|
"@babel/register": "7.9.0",
|
||||||
|
"@babel/runtime-corejs3": "7.9.6",
|
||||||
|
"babel-eslint": "10.1.0",
|
||||||
|
"babel-loader": "8.1.0",
|
||||||
|
"babel-plugin-module-resolver": "4.0.0",
|
||||||
|
"browserslist": "4.12.0",
|
||||||
|
"connect-history-api-fallback": "1.6.0",
|
||||||
|
"copy-webpack-plugin": "6.0.1",
|
||||||
|
"cross-env": "7.0.2",
|
||||||
|
"css-loader": "3.5.3",
|
||||||
|
"eslint": "7.0.0",
|
||||||
|
"eslint-config-airbnb": "18.1.0",
|
||||||
|
"eslint-import-resolver-babel-module": "5.1.2",
|
||||||
|
"eslint-loader": "4.0.2",
|
||||||
|
"eslint-plugin-import": "2.20.2",
|
||||||
|
"eslint-plugin-jsx-a11y": "6.2.3",
|
||||||
|
"eslint-plugin-react": "7.20.0",
|
||||||
|
"eslint-plugin-react-hooks": "4.0.2",
|
||||||
|
"file-loader": "6.0.0",
|
||||||
|
"hard-source-webpack-plugin": "0.13.1",
|
||||||
|
"html-webpack-plugin": "4.3.0",
|
||||||
|
"koa-connect": "2.0.1",
|
||||||
|
"lint-staged": "10.2.2",
|
||||||
|
"mini-css-extract-plugin": "0.9.0",
|
||||||
|
"node-sass": "4.14.1",
|
||||||
|
"nodemon": "2.0.4",
|
||||||
|
"optimize-css-assets-webpack-plugin": "5.0.3",
|
||||||
|
"rimraf": "3.0.2",
|
||||||
|
"sass-loader": "8.0.2",
|
||||||
|
"script-ext-html-webpack-plugin": "2.1.4",
|
||||||
|
"style-loader": "1.2.1",
|
||||||
|
"terser-webpack-plugin": "3.0.1",
|
||||||
|
"webpack": "4.43.0",
|
||||||
|
"webpack-bundle-analyzer": "3.7.0",
|
||||||
|
"webpack-cli": "3.3.11",
|
||||||
|
"webpack-dev-server": "3.11.0",
|
||||||
|
"webpack-merge": "4.2.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
1
frontend/public/assets/css/skeleton.min.css
vendored
Normal file
1
frontend/public/assets/css/skeleton.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
frontend/public/assets/images/icon.png
Normal file
BIN
frontend/public/assets/images/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.5 KiB |
15
frontend/public/template.html
Normal file
15
frontend/public/template.html
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<title>😕</title>
|
||||||
|
<link type="text/css" rel="stylesheet" href="./assets/css/skeleton.min.css" />
|
||||||
|
<link type="text/css" rel="stylesheet" href="https://fonts.googleapis.com/css?family=Inconsolata&display=swap">
|
||||||
|
<link rel="apple-touch-icon" sizes="180x180" href="./assets/images/icon.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="64x64" href="./assets/images/icon.png">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
12
frontend/src/constant/Properties.js
Normal file
12
frontend/src/constant/Properties.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
export default {
|
||||||
|
STORE_KEY: 'data',
|
||||||
|
DARK_MODE: {
|
||||||
|
CLASSNAME: {
|
||||||
|
Dark: 'dark',
|
||||||
|
Light: 'light',
|
||||||
|
},
|
||||||
|
STORE: {
|
||||||
|
Key: 'theme',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
27
frontend/src/container/App.jsx
Normal file
27
frontend/src/container/App.jsx
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import React, { useReducer, useContext } from 'react';
|
||||||
|
import { usePersistedContext, usePersistedReducer } from '@hook/usePersist';
|
||||||
|
|
||||||
|
import RootContainer from '@container/RootContainer';
|
||||||
|
import RootContext from '@context/RootContext';
|
||||||
|
import RootReducer from '@slice/RootSlice';
|
||||||
|
import Properties from '@constant/Properties';
|
||||||
|
|
||||||
|
const App = () => {
|
||||||
|
const globalStore = usePersistedContext(
|
||||||
|
useContext(RootContext),
|
||||||
|
Properties.STORE_KEY,
|
||||||
|
);
|
||||||
|
|
||||||
|
const [state, dispatch] = usePersistedReducer(
|
||||||
|
useReducer(RootReducer, globalStore),
|
||||||
|
Properties.STORE_KEY,
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<RootContext.Provider value={{ state, dispatch }}>
|
||||||
|
<RootContainer />
|
||||||
|
</RootContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default App;
|
||||||
91
frontend/src/container/RootContainer.jsx
Normal file
91
frontend/src/container/RootContainer.jsx
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
import React, {
|
||||||
|
useState, useRef, useEffect, useCallback,
|
||||||
|
} from 'react';
|
||||||
|
import Webcam from 'react-webcam';
|
||||||
|
|
||||||
|
import '@style/RootContainer';
|
||||||
|
|
||||||
|
const RootContainer = () => {
|
||||||
|
const webcamRef = useRef(null);
|
||||||
|
const [videoInputs, setVideoInputs] = useState([]);
|
||||||
|
const [resetCameraView, setResetCameraView] = useState(false);
|
||||||
|
const [videoConstraints, setVideoConstraints] = useState({
|
||||||
|
facingMode: { exact: 'environment' },
|
||||||
|
});
|
||||||
|
|
||||||
|
const [imgSrc, setImgSrc] = useState(null);
|
||||||
|
|
||||||
|
const capture = useCallback(() => {
|
||||||
|
const imageSrc = webcamRef.current.getScreenshot();
|
||||||
|
setImgSrc(imageSrc);
|
||||||
|
}, [webcamRef, setImgSrc]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const gotDevices = (mediaDevices) => new Promise((resolve, reject) => {
|
||||||
|
const availableVideoInputs = [];
|
||||||
|
mediaDevices.forEach((mediaDevice) => {
|
||||||
|
if (mediaDevice.kind === 'videoinput') {
|
||||||
|
availableVideoInputs.push({
|
||||||
|
deviceId: mediaDevice.deviceId,
|
||||||
|
label: mediaDevice.label,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (availableVideoInputs.length > 0) {
|
||||||
|
resolve(availableVideoInputs);
|
||||||
|
} else {
|
||||||
|
reject(new Error('ERR::NO_MEDIA_TO_STREAM'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
navigator.mediaDevices
|
||||||
|
.enumerateDevices()
|
||||||
|
.then(gotDevices)
|
||||||
|
.then((availableVideoInputs) => setVideoInputs({ availableVideoInputs }))
|
||||||
|
.catch((err) => console.error(err));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const changeCameraView = () => {
|
||||||
|
if (videoInputs.length === 1) {
|
||||||
|
return console.error('ERR::AVAILABLE_MEDIA_STREAMS_IS_1');
|
||||||
|
}
|
||||||
|
|
||||||
|
setResetCameraView(true);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
const { facingMode } = videoConstraints;
|
||||||
|
const newFacingMode = facingMode === 'user' ? { exact: 'environment' } : 'user';
|
||||||
|
setResetCameraView(false);
|
||||||
|
setVideoConstraints({ ...videoConstraints, facingMode: newFacingMode });
|
||||||
|
}, 100);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{resetCameraView ? (
|
||||||
|
'Loading...'
|
||||||
|
) : (
|
||||||
|
<Webcam
|
||||||
|
audio={false}
|
||||||
|
height="100%"
|
||||||
|
ref={webcamRef}
|
||||||
|
screenshotFormat="image/png"
|
||||||
|
minScreenshotWidth={1080}
|
||||||
|
minScreenshotHeight={1920}
|
||||||
|
screenshotQuality={1}
|
||||||
|
width="100%"
|
||||||
|
videoConstraints={videoConstraints} />
|
||||||
|
)}
|
||||||
|
<button type="button" onClick={changeCameraView}>
|
||||||
|
Switch camera
|
||||||
|
</button>
|
||||||
|
<button type="button" onClick={capture}>
|
||||||
|
Take image
|
||||||
|
</button>
|
||||||
|
{imgSrc && (<img src={imgSrc} />)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default RootContainer;
|
||||||
3
frontend/src/context/RootContext.js
Normal file
3
frontend/src/context/RootContext.js
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import { createContext } from 'react';
|
||||||
|
|
||||||
|
export default createContext({}); // include initialStates here
|
||||||
23
frontend/src/hook/useInterval.js
Normal file
23
frontend/src/hook/useInterval.js
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import { useEffect, useRef } from 'react';
|
||||||
|
|
||||||
|
// https://overreacted.io/making-setinterval-declarative-with-react-hooks/
|
||||||
|
const useInterval = (callback, delay) => {
|
||||||
|
const savedCallback = useRef();
|
||||||
|
|
||||||
|
// Remember the latest callback.
|
||||||
|
useEffect(() => {
|
||||||
|
savedCallback.current = callback;
|
||||||
|
}, [callback]);
|
||||||
|
|
||||||
|
// Set up the interval.
|
||||||
|
useEffect(() => {
|
||||||
|
const tick = () => savedCallback.current();
|
||||||
|
if (delay !== null) {
|
||||||
|
const id = setInterval(tick, delay);
|
||||||
|
return () => clearInterval(id);
|
||||||
|
}
|
||||||
|
return () => {};
|
||||||
|
}, [delay]);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useInterval;
|
||||||
16
frontend/src/hook/usePersist.js
Normal file
16
frontend/src/hook/usePersist.js
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { useEffect } from 'react';
|
||||||
|
|
||||||
|
const DEFAULT_STATE_KEY = 'state';
|
||||||
|
|
||||||
|
export const usePersistedContext = (context, key = DEFAULT_STATE_KEY) => {
|
||||||
|
const persistedContext = localStorage.getItem(key);
|
||||||
|
return persistedContext ? JSON.parse(persistedContext) : context;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const usePersistedReducer = ([state, dispatch], key = DEFAULT_STATE_KEY) => {
|
||||||
|
useEffect(
|
||||||
|
() => localStorage.setItem(key, JSON.stringify(state)),
|
||||||
|
[key, state],
|
||||||
|
);
|
||||||
|
return [state, dispatch];
|
||||||
|
};
|
||||||
6
frontend/src/index.jsx
Normal file
6
frontend/src/index.jsx
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { render } from 'react-dom';
|
||||||
|
|
||||||
|
import App from '@container/App';
|
||||||
|
|
||||||
|
render(<App />, document.getElementById('root'));
|
||||||
3
frontend/src/slice/RootSlice.js
Normal file
3
frontend/src/slice/RootSlice.js
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import { combineReducers } from '@reduxjs/toolkit';
|
||||||
|
|
||||||
|
export default combineReducers({}); // include slices here
|
||||||
10
frontend/src/style/RootContainer.scss
Normal file
10
frontend/src/style/RootContainer.scss
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
@import 'palette.scss';
|
||||||
|
@import 'constants.scss';
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
font-family: 'Roboto';
|
||||||
|
overflow-x: hidden;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
2
frontend/src/style/constants.scss
Normal file
2
frontend/src/style/constants.scss
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
$asset_dir: '../../assets';
|
||||||
|
$fonts_dir: '../../assets/fonts';
|
||||||
0
frontend/src/style/palette.scss
Normal file
0
frontend/src/style/palette.scss
Normal file
14
frontend/webpack.config.js
Normal file
14
frontend/webpack.config.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
const webpackMerge = require('webpack-merge');
|
||||||
|
const common = require('./webpack/webpack.common');
|
||||||
|
const Environment = require('./webpack/webpack.common');
|
||||||
|
|
||||||
|
const envs = {
|
||||||
|
development: 'dev',
|
||||||
|
production: 'prod',
|
||||||
|
};
|
||||||
|
|
||||||
|
/* eslint-disable global-require,import/no-dynamic-require */
|
||||||
|
const env = envs[process.env.NODE_ENV || Environment.development];
|
||||||
|
const envConfig = require(`./webpack/webpack.${env}.js`);
|
||||||
|
|
||||||
|
module.exports = webpackMerge(common, envConfig);
|
||||||
4
frontend/webpack/Environment.js
Normal file
4
frontend/webpack/Environment.js
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
module.exports = {
|
||||||
|
development: 'development',
|
||||||
|
production: 'production',
|
||||||
|
};
|
||||||
20
frontend/webpack/paths.js
Normal file
20
frontend/webpack/paths.js
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
const root = '../';
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
root: path.resolve(__dirname, root),
|
||||||
|
outputPath: path.resolve(__dirname, root, 'build'),
|
||||||
|
entryPath: path.resolve(__dirname, root, 'src/index.jsx'),
|
||||||
|
source: path.resolve(__dirname, root, 'src/'),
|
||||||
|
templatePath: path.resolve(__dirname, root, 'public/template.html'),
|
||||||
|
cachePath: path.join(process.cwd(), 'node_modules/.cache/hard-source/', '[confighash]'),
|
||||||
|
publicPath: './',
|
||||||
|
assetPath: 'assets',
|
||||||
|
assetOriginPath: 'public/assets/',
|
||||||
|
scriptsPath: 'scripts',
|
||||||
|
imagesFolder: 'images',
|
||||||
|
fontsFolder: 'fonts',
|
||||||
|
cssFolder: 'css',
|
||||||
|
jsFolder: 'js',
|
||||||
|
};
|
||||||
88
frontend/webpack/webpack.common.js
Normal file
88
frontend/webpack/webpack.common.js
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
/* eslint-disable import/no-extraneous-dependencies */
|
||||||
|
|
||||||
|
const { ProgressPlugin } = require('webpack');
|
||||||
|
const convert = require('koa-connect');
|
||||||
|
const history = require('connect-history-api-fallback');
|
||||||
|
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||||
|
const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin');
|
||||||
|
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||||
|
const commonPaths = require('./paths');
|
||||||
|
const Environment = require('./Environment');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
mode: Environment[process.env.NODE_ENV],
|
||||||
|
entry: commonPaths.entryPath,
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.(js|jsx)$/,
|
||||||
|
loader: 'babel-loader',
|
||||||
|
exclude: /(node_modules)/,
|
||||||
|
options: {
|
||||||
|
presets: ['@babel/preset-env'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
enforce: 'pre',
|
||||||
|
test: /\.(js|jsx)$/,
|
||||||
|
loader: 'eslint-loader',
|
||||||
|
exclude: /(node_modules)/,
|
||||||
|
options: {
|
||||||
|
// emitWarning: process.env.NODE_ENV !== Environment.production,
|
||||||
|
emitWarning: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.(png|jpg|gif|svg)$/,
|
||||||
|
use: [
|
||||||
|
{
|
||||||
|
loader: 'file-loader',
|
||||||
|
options: {
|
||||||
|
outputPath: commonPaths.imagesFolder,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.(woff2|ttf|woff|eot)$/,
|
||||||
|
use: [
|
||||||
|
{
|
||||||
|
loader: 'file-loader',
|
||||||
|
options: {
|
||||||
|
outputPath: commonPaths.fontsFolder,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
serve: {
|
||||||
|
add: (app) => {
|
||||||
|
app.use(convert(history()));
|
||||||
|
},
|
||||||
|
content: commonPaths.entryPath,
|
||||||
|
dev: {
|
||||||
|
publicPath: commonPaths.outputPath,
|
||||||
|
},
|
||||||
|
open: false,
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
modules: ['src', 'node_modules'],
|
||||||
|
extensions: ['*', '.js', '.jsx', '.css', '.scss'],
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new ProgressPlugin(),
|
||||||
|
new HtmlWebpackPlugin({
|
||||||
|
template: commonPaths.templatePath,
|
||||||
|
}),
|
||||||
|
new ScriptExtHtmlWebpackPlugin({
|
||||||
|
defaultAttribute: 'async',
|
||||||
|
}),
|
||||||
|
new CopyWebpackPlugin({
|
||||||
|
patterns: [{
|
||||||
|
from: commonPaths.assetOriginPath,
|
||||||
|
to: commonPaths.assetPath,
|
||||||
|
}],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
};
|
||||||
92
frontend/webpack/webpack.dev.js
Normal file
92
frontend/webpack/webpack.dev.js
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
/* eslint-disable import/no-extraneous-dependencies */
|
||||||
|
|
||||||
|
const { HotModuleReplacementPlugin } = require('webpack');
|
||||||
|
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
|
||||||
|
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
|
||||||
|
const commonPaths = require('./paths');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
devtool: 'cheap-eval-source-map',
|
||||||
|
output: {
|
||||||
|
filename: '[name].js',
|
||||||
|
path: commonPaths.outputPath,
|
||||||
|
chunkFilename: '[name].js',
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.(js|jsx)$/, // allows both .jsx and .js
|
||||||
|
exclude: /node_modules/,
|
||||||
|
include: commonPaths.source,
|
||||||
|
loader: 'babel-loader',
|
||||||
|
options: {
|
||||||
|
cacheDirectory: true,
|
||||||
|
plugins: ['react-hot-loader/babel'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.(sa|sc|c)ss$/,
|
||||||
|
use: [{
|
||||||
|
loader: 'style-loader',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
loader: 'css-loader',
|
||||||
|
options: {
|
||||||
|
modules: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
loader: 'sass-loader',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
devServer: {
|
||||||
|
contentBase: commonPaths.outputPath,
|
||||||
|
compress: true,
|
||||||
|
hot: true,
|
||||||
|
port: 3001,
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new HotModuleReplacementPlugin(),
|
||||||
|
new HardSourceWebpackPlugin({
|
||||||
|
// Either an absolute path or relative to webpack's options.context.
|
||||||
|
cacheDirectory: commonPaths.cachePath,
|
||||||
|
// Either a string of object hash function given a webpack config.
|
||||||
|
// node-object-hash on npm can be used to build this.
|
||||||
|
configHash: (webpackConfig) => require('node-object-hash')({ // eslint-disable-line
|
||||||
|
sort: false,
|
||||||
|
}).hash(webpackConfig),
|
||||||
|
// Either false, a string, an object, or a project hashing function.
|
||||||
|
environmentHash: {
|
||||||
|
root: process.cwd(),
|
||||||
|
directories: [],
|
||||||
|
files: [
|
||||||
|
// Cache will get an unique hash based on those files
|
||||||
|
// if either of them changes, new cache must be generated
|
||||||
|
'package-lock.json',
|
||||||
|
'.babelrc.js',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
info: {
|
||||||
|
mode: 'none',
|
||||||
|
level: 'debug',
|
||||||
|
},
|
||||||
|
// Clean up large, old caches automatically.
|
||||||
|
cachePrune: {
|
||||||
|
// Caches younger than `maxAge` are not considered for deletion.
|
||||||
|
// They must be at least this old in milliseconds.
|
||||||
|
maxAge: 3 * 60 * 60 * 1000, // 3 hours
|
||||||
|
// All caches together must be larger than `sizeThreshold` before any
|
||||||
|
// caches will be deleted.
|
||||||
|
// Together they must be at least this big in bytes.
|
||||||
|
sizeThreshold: 50 * 1024 * 1024, // 50 MB
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
new BundleAnalyzerPlugin({
|
||||||
|
analyzerPort: 8888,
|
||||||
|
openAnalyzer: false,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
};
|
||||||
98
frontend/webpack/webpack.prod.js
Normal file
98
frontend/webpack/webpack.prod.js
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
/* eslint-disable import/no-extraneous-dependencies */
|
||||||
|
|
||||||
|
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||||
|
const TerserPlugin = require('terser-webpack-plugin');
|
||||||
|
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
|
||||||
|
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
|
||||||
|
|
||||||
|
const commonPaths = require('./paths');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
output: {
|
||||||
|
publicPath: commonPaths.publicPath,
|
||||||
|
filename: `${commonPaths.scriptsPath}/${commonPaths.jsFolder}/[name].[hash].js`,
|
||||||
|
path: commonPaths.outputPath,
|
||||||
|
chunkFilename: `${commonPaths.scriptsPath}/${commonPaths.jsFolder}/[name].[chunkHash].js`,
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.(js|jsx)$/, // allows both .jsx and .js
|
||||||
|
exclude: /node_modules/,
|
||||||
|
include: commonPaths.source,
|
||||||
|
use: [
|
||||||
|
{
|
||||||
|
loader: 'babel-loader',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.(sa|sc|c)ss$/,
|
||||||
|
enforce: 'pre',
|
||||||
|
use: [{
|
||||||
|
loader: MiniCssExtractPlugin.loader,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
loader: 'css-loader',
|
||||||
|
options: {
|
||||||
|
modules: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
loader: 'sass-loader',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
optimization: {
|
||||||
|
usedExports: true, // to remove unused exports
|
||||||
|
splitChunks: {
|
||||||
|
chunks: 'all',
|
||||||
|
automaticNameDelimiter: '.',
|
||||||
|
minSize: 30000,
|
||||||
|
},
|
||||||
|
noEmitOnErrors: true,
|
||||||
|
minimize: true,
|
||||||
|
minimizer: [
|
||||||
|
new TerserPlugin({
|
||||||
|
parallel: true, // use multi-process parallel running to improve the build speed
|
||||||
|
sourceMap: false, // set to true if you want JS source maps
|
||||||
|
terserOptions: {
|
||||||
|
mangle: true, // pass false to skip mangling names
|
||||||
|
toplevel: false, // set to true if you wish to enable top level variable and function name mangling and to drop unused variables and functions
|
||||||
|
ie8: false, // set to true to support IE8.
|
||||||
|
keep_fnames: false, // pass true to prevent discarding or mangling of function names
|
||||||
|
output: {
|
||||||
|
comments: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
new OptimizeCSSAssetsPlugin({
|
||||||
|
assetNameRegExp: /\.css$/g,
|
||||||
|
cssProcessorPluginOptions: {
|
||||||
|
preset: [
|
||||||
|
'default',
|
||||||
|
{
|
||||||
|
discardComments: {
|
||||||
|
removeAll: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
canPrint: true,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new MiniCssExtractPlugin({
|
||||||
|
filename: `${commonPaths.assetPath}/${commonPaths.cssFolder}/[name].css`,
|
||||||
|
chunkFilename: '[id].css',
|
||||||
|
}),
|
||||||
|
new BundleAnalyzerPlugin({
|
||||||
|
generateStatsFile: true,
|
||||||
|
reportFilename: 'bundleReport.html',
|
||||||
|
analyzerMode: 'static',
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
};
|
||||||
9399
frontend/yarn.lock
Normal file
9399
frontend/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
6895
package-lock.json
generated
6895
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
28
package.json
28
package.json
@@ -1,33 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name": "maanteeamet-fetch",
|
"name": "maanteeamet-fetch",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "nodemon -r dotenv/config --watch src --exec babel-node src/index.js"
|
"deploy": "node -r dotenv/config deploy/ftp.js"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"cacheman": "2.2.1",
|
|
||||||
"cacheman-file": "0.2.1",
|
|
||||||
"dotenv": "8.2.0",
|
|
||||||
"express": "4.17.1",
|
|
||||||
"form-data": "3.0.0",
|
|
||||||
"jsdom": "16.2.2",
|
|
||||||
"node-fetch": "2.6.0",
|
|
||||||
"puppeteer": "3.1.0"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "7.8.4",
|
"dotenv": "8.2.0",
|
||||||
"@babel/core": "7.9.6",
|
"ftp-deploy": "2.3.7"
|
||||||
"@babel/node": "7.8.7",
|
|
||||||
"@babel/plugin-proposal-class-properties": "7.8.3",
|
|
||||||
"@babel/preset-env": "7.9.6",
|
|
||||||
"babel-eslint": "10.1.0",
|
|
||||||
"eslint": "^6.8.0",
|
|
||||||
"eslint-config-airbnb": "18.1.0",
|
|
||||||
"eslint-plugin-import": "2.20.2",
|
|
||||||
"eslint-plugin-jsx-a11y": "6.2.3",
|
|
||||||
"eslint-plugin-react": "7.20.0",
|
|
||||||
"eslint-plugin-react-hooks": "2.5.0",
|
|
||||||
"nodemon": "2.0.4"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user