Commit 282d009a authored by Fence's avatar Fence 🌈

init admin-fe, only really has a login page

parent 22881d6d
{
"presets": ["@babel/preset-env", "@babel/preset-react"]
}
\ No newline at end of file
mocha.opts
*.json
*.scss
*.css
module.exports = {
"parser": "@typescript-eslint/parser",
"parserOptions": {
ecmaVersion: 2018, // Allows for the parsing of modern ECMAScript features
sourceType: 'module', // Allows for the use of imports
ecmaFeatures: {
jsx: true, // Allows for the parsing of JSX
},
},
"plugins": [
"import"
],
"env": {
"browser": true,
},
"extends": [
"eslint:recommended",
'plugin:@typescript-eslint/recommended',
"airbnb"
],
"rules": {
"indent": [2, 4, {SwitchCase: 1}],
"quotes": [2, "double"],
"react/jsx-indent": [2, 4, {checkAttributes: true}],
"react/jsx-indent-props": [2, 4],
"react/jsx-filename-extension": [1, { "extensions": [".jsx", ".tsx"] }],
"react/jsx-no-bind": [2, {allowBind: true}],
"jsx-a11y/label-has-for": [0], // Deprecated since october 2018
"jsx-a11y/media-has-caption": [0]
},
"settings": {
"import/resolver": {
node: {
extensions: [
".js",
".jsx",
".ts",
".tsx",
]
}
}
}
};
\ No newline at end of file
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.test
# parcel-bundler cache (https://parceljs.org/)
.cache
# next.js build output
.next
# nuxt.js build output
.nuxt
# vuepress build outputdist
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
build/
package-lock.json
*.sqlite
key
key.pub
config.private.js
dist/
\ No newline at end of file
{
"diff": true,
"extension": ["ts", "js"],
"opts": "./test/mocha.opts",
"package": "./package.json",
"reporter": "spec",
"slow": 75,
"timeout": 2000,
"ui": "bdd"
}
\ No newline at end of file
if [ ! -d "./dist" ] ; then
yarn build
fi
yarn dev-server
{
"name": "minor-admin",
"version": "0.0.1",
"main": "index.js",
"author": "fence",
"license": "AGPL3",
"private": true,
"scripts": {
"test": "mocha",
"dev": "./dev.sh",
"dev-server": "webpack-dev-server --mode development",
"build": "webpack --mode development",
"build:prod": "webpack --mode production",
"lint": "eslint './src/**' './test/**'"
},
"devDependencies": {
"@babel/core": "^7.3.4",
"@babel/preset-env": "^7.3.4",
"@babel/preset-react": "^7.0.0",
"@types/chai": "^4.1.7",
"@types/mocha": "^5.2.7",
"@typescript-eslint/eslint-plugin": "^1.4.2",
"@typescript-eslint/parser": "2.2.0",
"awesome-typescript-loader": "^5.2.1",
"babel-loader": "^8.0.5",
"chai": "^4.2.0",
"css-loader": "^2.1.0",
"error-overlay-webpack-plugin": "^0.1.6",
"eslint": "^5.15.1",
"eslint-config-airbnb": "^17.1.0",
"eslint-import-resolver-node": "^0.3.2",
"eslint-import-resolver-webpack": "^0.11.0",
"eslint-plugin-import": "^2.16.0",
"eslint-plugin-jsx-a11y": "^6.2.1",
"eslint-plugin-react": "^7.12.4",
"file-loader": "^4.2.0",
"html-webpack-plugin": "^3.2.0",
"image-webpack-loader": "^6.0.0",
"jsdom": "^15.1.1",
"jsdom-global": "^3.0.2",
"mini-css-extract-plugin": "^0.8.0",
"mocha": "^6.2.0",
"node-sass": "^4.11.0",
"purgecss-webpack-plugin": "^1.5.0",
"sass-loader": "^7.1.0",
"style-loader": "^0.23.1",
"typescript": "3.6.2",
"url-loader": "^2.1.0",
"webpack": "^4.29.3",
"webpack-cli": "^3.2.3",
"webpack-dev-server": "^3.1.14"
},
"dependencies": {
"@babel/polyfill": "^7.2.5",
"@marcj/marshal": "^0.9.0",
"@types/prop-types": "^15.7.0",
"@types/react": "^16.8.7",
"classnames": "^2.2.6",
"prop-types": "^15.7.2",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"react-router-dom": "^4.3.1",
"reflect-metadata": "^0.1.13",
"semantic-ui-css": "^2.4.1",
"semantic-ui-react": "^0.88.1"
}
}
import React from "react";
import {
BrowserRouter as Router,
Route,
Switch,
} from "react-router-dom";
import Navbar from "./navbar";
import HomePage from "../pages/home";
import SongListPage from "../pages/songs";
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (
<div>
<Navbar />
<Router>
<Switch>
<Route path="/" component={HomePage} />
<Route path="/" component={SongListPage} />
</Switch>
</Router>
</div>
);
}
}
import React from "react";
import PropTypes from "prop-types";
import {
Button,
Form,
Grid,
Header,
Segment,
} from "semantic-ui-react";
const LoginForm = ({
email, password, onChange, submit,
}) => {
const onInputChange = (e, { name, value }) => {
const values = {};
values[name] = value;
onChange(values);
};
return (
<Grid textAlign="center" style={{ height: "100vh" }} verticalAlign="middle">
<Grid.Column style={{ maxWidth: 450 }}>
<Header as="h2" color="teal" textAlign="center">
Minor Admin Frontend
</Header>
<Form size="large">
<Segment stacked>
<Form.Input
fluid
name="email"
icon="user"
iconPosition="left"
placeholder="E-mail address"
value={email}
onChange={onInputChange}
/>
<Form.Input
fluid
name="password"
icon="lock"
iconPosition="left"
placeholder="Password"
type="password"
value={password}
onChange={onInputChange}
/>
<Button
color="teal"
fluid
size="large"
onClick={submit}
>
Login
</Button>
</Segment>
</Form>
</Grid.Column>
</Grid>
);
};
LoginForm.propTypes = {
email: PropTypes.string.isRequired,
password: PropTypes.string.isRequired,
onChange: PropTypes.func.isRequired,
submit: PropTypes.func.isRequired,
};
export default LoginForm;
import React from "react";
const Navbar = () => (
<p>nav</p>
);
export default Navbar;
import React from "react";
export default class Test extends React.Component {
public render(): JSX.Element {
return <h1>This is a Typescript Component!!!</h1>;
}
}
import React from "react";
import LoginForm from "../components/login";
export default class LoginContainer extends React.Component {
constructor(props) {
super(props);
this.state = {
email: "",
password: "",
};
}
onChange({ email, password }) {
const state = { ...this.state };
if (email) {
state.email = email;
}
if (password) {
state.password = password;
}
this.setState(state);
}
login() {
const { email, password } = this.state;
if (email && password) {
fetch("/auth/login", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ email, password }),
}).then(resp => resp.json()).then((data) => {
if (data.code === 200) {
localStorage.setItem("token", data.value);
// TODO redirect to other page
}
});
}
}
render() {
return (
<LoginForm
onChange={this.onChange.bind(this)}
submit={this.login.bind(this)}
/>
);
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" >
<title>Minor Admin Frontend</title>
</head>
<body id="index">
</body>
</html>
import "semantic-ui-css/semantic.min.css";
import "@babel/polyfill";
import "reflect-metadata";
import React from "react";
import ReactDOM from "react-dom";
import App from "./components/app";
ReactDOM.render(React.createElement(App), document.getElementById("index"));
import React from "react";
import LoginContainer from "../containers/LoginContainer";
export default class HomePage extends React.PureComponent {
render() {
return (
<div className="page-home">
<LoginContainer />
</div>
);
}
}
import React from "react";
export default class HomePage extends React.PureComponent {
render() {
return (
<div className="page-song-list" />
);
}
}
--require jsdom-global/register
--require ts-node/register
--require source-map-support/register
--recursive
test/**/*.js
test/**/*.ts
\ No newline at end of file
{
"compilerOptions": {
"outDir": "./dist/",
"sourceMap": true,
"noImplicitAny": true,
"module": "commonjs",
"target": "es5",
"jsx": "react",
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"allowJs": true,
"lib": [ "es2017", "dom", "dom.iterable" ],
"typeRoots": [
"./types"
],
"experimentalDecorators": true,
"emitDecoratorMetadata": true
},
"include": [
"./src/**/*",
]
}
/* eslint-env node, mocha */
const path = require("path");
const glob = require("glob");
const HtmlWebPackPlugin = require("html-webpack-plugin");
const ErrorOverlayPlugin = require("error-overlay-webpack-plugin");
const ExtractCssPlugin = require("mini-css-extract-plugin");
const PurgecssPlugin = require("purgecss-webpack-plugin");
module.exports = (env, options) => {
const devMode = options.mode !== "production";
const PATHS = {
src: path.join(__dirname, "src"),
};
const plugins = [
new HtmlWebPackPlugin({
template: "./src/index.html",
filename: "./index.html",
}),
new ErrorOverlayPlugin(),
new ExtractCssPlugin(),
];
if (!devMode) {
plugins.push(
new PurgecssPlugin({
paths: glob.sync(`${PATHS.src}/**/*`, { nodir: true }),
whitelist: ["whitelisted"],
}),
);
}
return {
entry: ["./src/main.js"],
output: {
path: path.resolve(__dirname, "dist"),
filename: "bundle.js",
publicPath: "/dist",
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
},
},
{
test: /\.tsx?$/,
loader: "awesome-typescript-loader",
},
{
test: /\.(sa|sc|c)ss$/,
use: [
{
loader: ExtractCssPlugin.loader,
options: {
sourceMap: true,
url: false,
},
},
"css-loader",
{
loader: "sass-loader",
options: {
sourceMap: true,
url: false,
},
},
],
},
{ test: /\.(png|woff|woff2|eot|ttf|svg)$/, loader: "url-loader?limit=100000" },
],
},
resolve: {
extensions: [".ts", ".tsx", ".js", ".jsx"],
},
devServer: {
contentBase: "./dist",
open: false,
historyApiFallback: {
index: "index.html",
},
proxy: {
"/api": "http://localhost:5000",
"/auth": "http://localhost:5000",
},
},
plugins,
devtool: "cheap-module-source-map",
};
};
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment