initial commit
Signed-off-by: Jyri Genral <jyri.eerola@jrd.fi>
This commit is contained in:
commit
a9e1501e48
12 changed files with 6006 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
fe/node_modules
|
||||||
|
fe/dist
|
||||||
|
fe/dist.*
|
||||||
192
WebServer/WebServer.ino
Normal file
192
WebServer/WebServer.ino
Normal file
|
|
@ -0,0 +1,192 @@
|
||||||
|
// FukkenRF Web Server
|
||||||
|
// inspired by a Web Server example from year 2009 by David A. Mellis.
|
||||||
|
|
||||||
|
#include <SPI.h>
|
||||||
|
#include <Ethernet.h>
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
#include <HardwareSerial.h>
|
||||||
|
HardwareSerial Serial;
|
||||||
|
|
||||||
|
// Set your desired MAC and IP addresses, you might want to change these below
|
||||||
|
byte mac[] = { 0xCA, 0xFE, 0x01, 0x02, 0x03, 0x04 };
|
||||||
|
IPAddress ip(10, 10, 10, 10);
|
||||||
|
|
||||||
|
// Set port
|
||||||
|
EthernetServer server(80);
|
||||||
|
|
||||||
|
// REMEMBER TO CHECK THE RIGHT CHIP SELECT PIN!
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
#define HFENABLE 3
|
||||||
|
|
||||||
|
#define LOVHF1 54
|
||||||
|
#define LOVHF2 2
|
||||||
|
#define HF1 5
|
||||||
|
#define HF2 6
|
||||||
|
#define HF3 7
|
||||||
|
#define HF4 8
|
||||||
|
#define HF5 9
|
||||||
|
#define HF6 11
|
||||||
|
#define VHF1 12
|
||||||
|
#define VHF2 13
|
||||||
|
#define VHF3 14
|
||||||
|
#define VHF4 15
|
||||||
|
#define VHF5 16
|
||||||
|
#define VHF6 17
|
||||||
|
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
pinMode(LOVHF1, OUTPUT);
|
||||||
|
pinMode(LOVHF2, OUTPUT);
|
||||||
|
pinMode(HF1, OUTPUT);
|
||||||
|
pinMode(HF2, OUTPUT);
|
||||||
|
pinMode(HF3, OUTPUT);
|
||||||
|
pinMode(HF4, OUTPUT);
|
||||||
|
pinMode(HF5, OUTPUT);
|
||||||
|
pinMode(HF6, OUTPUT);
|
||||||
|
pinMode(VHF1, OUTPUT);
|
||||||
|
pinMode(VHF2, OUTPUT);
|
||||||
|
pinMode(VHF3, OUTPUT);
|
||||||
|
pinMode(VHF4, OUTPUT);
|
||||||
|
pinMode(VHF5, OUTPUT);
|
||||||
|
pinMode(VHF6, OUTPUT);
|
||||||
|
|
||||||
|
// REMEMBER TO CHECK THE RIGHT CHIP SELECT PIN!
|
||||||
|
Ethernet.init(ETHERNET_CS_PIN);
|
||||||
|
|
||||||
|
Serial.begin(9600);
|
||||||
|
while (!Serial) {} // wait for it
|
||||||
|
|
||||||
|
// start the Ethernet connection and the server:
|
||||||
|
Ethernet.begin(mac, ip);
|
||||||
|
|
||||||
|
// Check for Ethernet shield's presense
|
||||||
|
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
|
||||||
|
Serial.println("Ethernet: not found");
|
||||||
|
while (true) {
|
||||||
|
delay(1); // do nothing, no point running without Ethernet hardware
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Ethernet.linkStatus() == LinkOFF) {
|
||||||
|
Serial.println("Ethernet: link down");
|
||||||
|
}
|
||||||
|
|
||||||
|
// start the server
|
||||||
|
server.begin();
|
||||||
|
Serial.print("listening at ");
|
||||||
|
Serial.println(Ethernet.localIP());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int newPin = 0;
|
||||||
|
unsigned int currentPin = 0;
|
||||||
|
|
||||||
|
|
||||||
|
void setPin() {
|
||||||
|
if (newPin != currentPin) {
|
||||||
|
digitalWrite(HFENABLE, LOW);
|
||||||
|
digitalWrite(LOVHF1, LOW);
|
||||||
|
digitalWrite(LOVHF2, LOW);
|
||||||
|
digitalWrite(HF1, LOW);
|
||||||
|
digitalWrite(HF2, LOW);
|
||||||
|
digitalWrite(HF3, LOW);
|
||||||
|
digitalWrite(HF4, LOW);
|
||||||
|
digitalWrite(HF5, LOW);
|
||||||
|
digitalWrite(HF6, LOW);
|
||||||
|
digitalWrite(VHF1, LOW);
|
||||||
|
digitalWrite(VHF2, LOW);
|
||||||
|
digitalWrite(VHF3, LOW);
|
||||||
|
digitalWrite(VHF4, LOW);
|
||||||
|
digitalWrite(VHF5, LOW);
|
||||||
|
digitalWrite(VHF6, LOW);
|
||||||
|
|
||||||
|
delay(100);
|
||||||
|
|
||||||
|
if ((HF1==newPin) ||
|
||||||
|
(HF2==newPin) ||
|
||||||
|
(HF3==newPin) ||
|
||||||
|
(HF4==newPin) ||
|
||||||
|
(HF5==newPin) ||
|
||||||
|
(HF6==newPin)) {
|
||||||
|
digitalWrite(HFENABLE, HIGH);
|
||||||
|
}
|
||||||
|
|
||||||
|
digitalWrite(newPin, HIGH);
|
||||||
|
}
|
||||||
|
currentPin = newPin;
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// listen for incoming clients
|
||||||
|
EthernetClient client = server.available();
|
||||||
|
if (client) {
|
||||||
|
Serial.println("new client");
|
||||||
|
|
||||||
|
// an http request ends with a blank line
|
||||||
|
boolean currentLineIsBlank = true;
|
||||||
|
|
||||||
|
boolean firstLine = true;
|
||||||
|
unsigned int firstCharN = 0;
|
||||||
|
char firstLineBuf[5] = "";
|
||||||
|
char postCompare[5] = "POST";
|
||||||
|
boolean wasPostReq = false;
|
||||||
|
|
||||||
|
while (client.connected()) {
|
||||||
|
if (client.available()) {
|
||||||
|
char c = client.read();
|
||||||
|
Serial.write(c);
|
||||||
|
// if you've gotten to the end of the line (received a newline
|
||||||
|
// character) and the line is blank, the http request has ended,
|
||||||
|
// so you can send a reply
|
||||||
|
if (c == '\n' && currentLineIsBlank) {
|
||||||
|
if (wasPostReq) {
|
||||||
|
//pin = client.read() - 65;
|
||||||
|
newPin = c - 65;
|
||||||
|
}
|
||||||
|
// send a standard http response header
|
||||||
|
client.println("HTTP/1.1 200 OK");
|
||||||
|
client.println("Content-Type: text/html");
|
||||||
|
client.println("Access-Control-Allow-Origin: *");
|
||||||
|
client.println("Connection: close"); // the connection will be closed after completion of the response
|
||||||
|
client.println();
|
||||||
|
client.println("<!DOCTYPE HTML>");
|
||||||
|
client.println("<html>");
|
||||||
|
if (wasPostReq) {
|
||||||
|
client.println("Got POST!!");
|
||||||
|
newPin = client.read() - 65;
|
||||||
|
client.print("New pin: ");
|
||||||
|
client.println(newPin);
|
||||||
|
} else {
|
||||||
|
client.println("Didn't get POST :(");
|
||||||
|
}
|
||||||
|
client.println("</html>");
|
||||||
|
setPin();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (c == '\n') {
|
||||||
|
firstLine = false;
|
||||||
|
// you're starting a new line
|
||||||
|
currentLineIsBlank = true;
|
||||||
|
} else if (c != '\r') {
|
||||||
|
// you've gotten a character on the current line
|
||||||
|
currentLineIsBlank = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstLine && firstCharN < sizeof(firstLineBuf)) {
|
||||||
|
firstLineBuf[firstCharN] = c;
|
||||||
|
if (0 == memcmp(firstLineBuf, postCompare, sizeof(postCompare))) {
|
||||||
|
wasPostReq = true;
|
||||||
|
}
|
||||||
|
firstCharN++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// give the web browser time to receive the data
|
||||||
|
delay(1);
|
||||||
|
// close the connection:
|
||||||
|
client.stop();
|
||||||
|
Serial.println("client disconnected");
|
||||||
|
}
|
||||||
|
}
|
||||||
23
fe/LICENSE
Normal file
23
fe/LICENSE
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2015 Michel Weststrate
|
||||||
|
Forked from: https://github.com/bvanreeven/react-typescript
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
||||||
13
fe/README.md
Normal file
13
fe/README.md
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
_Fork of https://github.com/mobxjs/mobx-react-typescript-boilerplate.git_
|
||||||
|
|
||||||
|
# React-TypeScript
|
||||||
|
|
||||||
|
Minimal boilerplate for a single-page app using MobX, React and TypeScript with TSX.
|
||||||
|
|
||||||
|
Initial run:
|
||||||
|
|
||||||
|
* Install Node.js
|
||||||
|
* `yarn install`
|
||||||
|
* `yarn start`
|
||||||
|
|
||||||
|
For simplicity sake Webpack Hot Module Reloading is disabled. If you want to use HMR, see the [Reactive2015 demo](https://github.com/mobxjs/mobx-reactive2015-demo) to see a valid setup.
|
||||||
10
fe/index.html
Normal file
10
fe/index.html
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>FukkenRF</title>
|
||||||
|
<link rel="stylesheet" href="/static/main.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
|
<script src="/static/bundle.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
42
fe/package.json
Normal file
42
fe/package.json
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
{
|
||||||
|
"name": "mobx-react-typescript-boilerplate",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Boilerplate for MobX + React project with Typescript, ES6 compilation and hot code reloading",
|
||||||
|
"scripts": {
|
||||||
|
"start": "node server.js"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"react",
|
||||||
|
"reactjs",
|
||||||
|
"boilerplate",
|
||||||
|
"mobx",
|
||||||
|
"starter-kit"
|
||||||
|
],
|
||||||
|
"author": "Michel Weststrate <mweststrate@gmail.com> (http://github.com/mweststrate)",
|
||||||
|
"license": "MIT",
|
||||||
|
"homepage": "http://mobxjs.github.com/mobx",
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/react-dom": "^16.9.6",
|
||||||
|
"@types/react-router-dom": "^5.1.4",
|
||||||
|
"@types/webpack": "^4.41.10",
|
||||||
|
"css-loader": "^3.5.2",
|
||||||
|
"extract-css-chunks-webpack-plugin": "^4.7.4",
|
||||||
|
"less": "^3.11.1",
|
||||||
|
"less-loader": "^5.0.0",
|
||||||
|
"mini-css-extract-plugin": "^0.9.0",
|
||||||
|
"ts-loader": "6.2.2",
|
||||||
|
"typescript": "^3.8.3",
|
||||||
|
"webpack": "^4.42.1",
|
||||||
|
"webpack-bundle-analyzer": "^3.6.1",
|
||||||
|
"webpack-cli": "^3.3.11",
|
||||||
|
"webpack-dev-server": "^3.10.3"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"antd": "^4.1.2",
|
||||||
|
"mobx": "^5.15.4",
|
||||||
|
"mobx-react": "^6.2.2",
|
||||||
|
"react": "^16.13.1",
|
||||||
|
"react-dom": "^16.13.1",
|
||||||
|
"react-router-dom": "5.1.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
15
fe/server.js
Normal file
15
fe/server.js
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
var webpack = require('webpack');
|
||||||
|
var WebpackDevServer = require('webpack-dev-server');
|
||||||
|
var config = require('./webpack.config');
|
||||||
|
|
||||||
|
new WebpackDevServer(webpack(config), {
|
||||||
|
publicPath: config.output.publicPath,
|
||||||
|
hot: false,
|
||||||
|
historyApiFallback: true
|
||||||
|
}).listen(3000, 'localhost', function (err, result) {
|
||||||
|
if (err) {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Listening at localhost:3000');
|
||||||
|
});
|
||||||
16
fe/src/CRE.tsx
Normal file
16
fe/src/CRE.tsx
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
// Re-exporting components
|
||||||
|
|
||||||
|
import "antd/es/radio/style";
|
||||||
|
export { default as Radio, RadioChangeEvent } from "antd/es/radio";
|
||||||
|
|
||||||
|
// import "antd/es/row/style";
|
||||||
|
// export { default as Row } from "antd/es/row";
|
||||||
|
|
||||||
|
// import "antd/es/col/style";
|
||||||
|
// export { default as Col } from "antd/es/col";
|
||||||
|
|
||||||
|
import "antd/es/divider/style";
|
||||||
|
export { default as Divider } from "antd/es/divider";
|
||||||
|
|
||||||
|
import "antd/es/message/style";
|
||||||
|
export { default as message } from "antd/es/message";
|
||||||
116
fe/src/index.tsx
Normal file
116
fe/src/index.tsx
Normal file
|
|
@ -0,0 +1,116 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import * as ReactDOM from 'react-dom';
|
||||||
|
import {observable, configure, action} from 'mobx';
|
||||||
|
import {observer} from 'mobx-react';
|
||||||
|
|
||||||
|
import { Radio, RadioChangeEvent, Divider, message } from "./CRE";
|
||||||
|
|
||||||
|
configure({enforceActions: 'always'});
|
||||||
|
|
||||||
|
|
||||||
|
enum HF {
|
||||||
|
LOVHF1 = 54,
|
||||||
|
LOVHF2 = 2,
|
||||||
|
HF1 = 5,
|
||||||
|
HF2 = 6,
|
||||||
|
HF3 = 7,
|
||||||
|
HF4 = 8,
|
||||||
|
HF5 = 9,
|
||||||
|
HF6 = 11
|
||||||
|
}
|
||||||
|
|
||||||
|
enum VHF {
|
||||||
|
VHF1 = 12,
|
||||||
|
VHF2 = 13,
|
||||||
|
VHF3 = 14,
|
||||||
|
VHF4 = 15,
|
||||||
|
VHF5 = 16,
|
||||||
|
VHF6 = 17
|
||||||
|
}
|
||||||
|
|
||||||
|
// const HFENABLEPIN = 5;
|
||||||
|
|
||||||
|
class AppState {
|
||||||
|
|
||||||
|
@observable hfSelection: HF;
|
||||||
|
@observable vhfSelection: VHF;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@action.bound
|
||||||
|
setHF(selection: HF) {
|
||||||
|
this.hfSelection = selection;
|
||||||
|
}
|
||||||
|
|
||||||
|
@action.bound
|
||||||
|
setVHF(selection: VHF) {
|
||||||
|
this.vhfSelection = selection;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@observer
|
||||||
|
class TimerView extends React.Component<{appState: AppState}, {}> {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Divider>LoVHF / HF selection</Divider>
|
||||||
|
<Radio.Group buttonStyle="solid" onChange={this.changeHF}>
|
||||||
|
<Radio.Button value={HF.LOVHF1}>LoVHF1</Radio.Button>
|
||||||
|
<Radio.Button value={HF.LOVHF2}>LoVHF2</Radio.Button>
|
||||||
|
<Radio.Button value={HF.HF1}>HF1</Radio.Button>
|
||||||
|
<Radio.Button value={HF.HF2}>HF2</Radio.Button>
|
||||||
|
<Radio.Button value={HF.HF3}>HF3</Radio.Button>
|
||||||
|
<Radio.Button value={HF.HF4}>HF4</Radio.Button>
|
||||||
|
<Radio.Button value={HF.HF5}>HF5</Radio.Button>
|
||||||
|
<Radio.Button value={HF.HF6}>HF6</Radio.Button>
|
||||||
|
</Radio.Group>
|
||||||
|
|
||||||
|
<Divider>VHF selection</Divider>
|
||||||
|
<Radio.Group buttonStyle="solid" onChange={this.changeVHF}>
|
||||||
|
<Radio.Button value={VHF.VHF1}>VHF1</Radio.Button>
|
||||||
|
<Radio.Button value={VHF.VHF2}>VHF2</Radio.Button>
|
||||||
|
<Radio.Button value={VHF.VHF3}>VHF3</Radio.Button>
|
||||||
|
<Radio.Button value={VHF.VHF4}>VHF4</Radio.Button>
|
||||||
|
<Radio.Button value={VHF.VHF5}>VHF5</Radio.Button>
|
||||||
|
<Radio.Button value={VHF.VHF6}>VHF6</Radio.Button>
|
||||||
|
</Radio.Group>
|
||||||
|
<br></br>
|
||||||
|
<br></br>
|
||||||
|
<br></br>
|
||||||
|
HF: {this.props.appState.hfSelection}
|
||||||
|
<br></br>
|
||||||
|
VHF: {this.props.appState.vhfSelection}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@action.bound
|
||||||
|
async changeHF(e: RadioChangeEvent) {
|
||||||
|
this.props.appState.setHF(e.target.value);
|
||||||
|
const res = await fetch(`http://192.168.9.4/`, {
|
||||||
|
method: "POST",
|
||||||
|
headers: {},
|
||||||
|
body: String.fromCharCode(Number(e.target.value) + 65)
|
||||||
|
});
|
||||||
|
if (res.ok) {
|
||||||
|
message.success("HF change sent!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@action.bound
|
||||||
|
async changeVHF(e: RadioChangeEvent) {
|
||||||
|
this.props.appState.setVHF(e.target.value);
|
||||||
|
const res = await fetch(`http://192.168.9.4/`, {
|
||||||
|
method: "POST",
|
||||||
|
headers: {},
|
||||||
|
body: String.fromCharCode(Number(e.target.value) + 65)
|
||||||
|
});
|
||||||
|
if (res.ok) {
|
||||||
|
message.success("VHF change sent!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const appState = new AppState();
|
||||||
|
ReactDOM.render(<TimerView appState={appState} />, document.getElementById('root'));
|
||||||
14
fe/tsconfig.json
Normal file
14
fe/tsconfig.json
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es5",
|
||||||
|
"removeComments": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"jsx": "react",
|
||||||
|
"outDir": "dist",
|
||||||
|
"lib": ["dom", "es2015"]
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"node_modules",
|
||||||
|
"static"
|
||||||
|
]
|
||||||
|
}
|
||||||
59
fe/webpack.config.js
Normal file
59
fe/webpack.config.js
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
var path = require('path');
|
||||||
|
var webpack = require('webpack');
|
||||||
|
|
||||||
|
const ExtractCssChunks = require('extract-css-chunks-webpack-plugin');
|
||||||
|
// const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
// devtool: 'eval',
|
||||||
|
// mode: 'development',
|
||||||
|
mode: 'production',
|
||||||
|
entry: [
|
||||||
|
// 'webpack-dev-server/client?http://localhost:3000',
|
||||||
|
'./src/index'
|
||||||
|
],
|
||||||
|
output: {
|
||||||
|
path: path.join(__dirname, 'dist'),
|
||||||
|
filename: 'bundle.js',
|
||||||
|
publicPath: '/static/'
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
extensions: ['.js', '.ts', '.tsx'],
|
||||||
|
alias: { mobx: __dirname + "/node_modules/mobx/lib/mobx.es6.js" }
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new ExtractCssChunks({
|
||||||
|
filename: '[name].css',
|
||||||
|
chunkFilename: '[id].css',
|
||||||
|
})
|
||||||
|
],
|
||||||
|
module: {
|
||||||
|
rules: [{
|
||||||
|
test: /\.tsx?$/,
|
||||||
|
loader: "ts-loader",
|
||||||
|
include: path.join(__dirname, 'src')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.less$/,
|
||||||
|
use: [
|
||||||
|
{
|
||||||
|
loader: ExtractCssChunks.loader
|
||||||
|
},
|
||||||
|
{
|
||||||
|
loader: 'css-loader'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
loader: 'less-loader',
|
||||||
|
options: {
|
||||||
|
javascriptEnabled: true
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.css$/i,
|
||||||
|
use: [ExtractCssChunks.loader, 'css-loader'],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
};
|
||||||
5503
fe/yarn.lock
Normal file
5503
fe/yarn.lock
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue