Merge pull request #1 from she11sh0cked/master

Port to typescript
This commit is contained in:
Aria Moradi 2020-12-24 19:40:21 +03:30 committed by GitHub
commit 666c982936
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 762 additions and 739 deletions

View File

@ -0,0 +1 @@
.eslintrc.js

View File

@ -1,33 +1,17 @@
module.exports = {
env: {
browser: true,
es2021: true,
},
extends: [
'plugin:react/recommended',
'airbnb',
],
extends: ['airbnb-typescript'],
plugins: ['@typescript-eslint'],
parserOptions: {
ecmaFeatures: {
jsx: true,
},
ecmaVersion: 12,
sourceType: 'module',
project: './tsconfig.json',
},
plugins: [
'react',
],
rules: {
// Indent with 4 spaces
indent: ['error', 4],
'@typescript-eslint/indent': ['error', 4],
// Indent JSX with 4 spaces
'react/jsx-indent': ['error', 4],
// Indent props with 4 spaces
'react/jsx-indent-props': ['error', 4],
// allow JSX in both js and jsx files
'react/jsx-filename-extension': [1, { extensions: ['.js', '.jsx'] }],
},
};

View File

@ -34,11 +34,17 @@
]
},
"devDependencies": {
"@types/react": "^17.0.0",
"@types/react-dom": "^17.0.0",
"@types/react-router-dom": "^5.1.6",
"@typescript-eslint/eslint-plugin": "^4.11.0",
"@typescript-eslint/parser": "4.11.0",
"eslint": "^7.16.0",
"eslint-config-airbnb": "^18.2.1",
"eslint-config-airbnb-typescript": "^12.0.0",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-jsx-a11y": "^6.4.1",
"eslint-plugin-react": "^7.21.5",
"eslint-plugin-react-hooks": "^4.2.0"
"eslint-plugin-react-hooks": "^4.2.0",
"typescript": "^4.1.0"
}
}
}

View File

@ -8,6 +8,34 @@ import Button from '@material-ui/core/Button';
import NavBar from './components/NavBar';
import ExtensionCard from './components/ExtensionCard';
function Extensions() {
let mapped;
const [extensions, setExtensions] = useState<IExtension[]>([]);
if (extensions.length === 0) {
mapped = <h3>wait</h3>;
fetch('http://127.0.0.1:4567/api/v1/extensions')
.then((response) => response.json())
.then((data) => setExtensions(data));
} else {
mapped = extensions.map((it) => <ExtensionCard extension={it} />);
}
return <h2>{mapped}</h2>;
}
function Home() {
return (
<Button variant="contained" color="primary">
Hello World
</Button>
);
}
function Users() {
return <h2>Users</h2>;
}
export default function App() {
return (
<Router>
@ -28,31 +56,3 @@ export default function App() {
</Router>
);
}
function Extensions() {
let mapped;
const [extensions, setExtensions] = useState([]);
if (extensions.length === 0) {
mapped = <h3>wait</h3>;
fetch('http://127.0.0.1:4567/api/v1/extensions')
.then((response) => response.json())
.then((data) => setExtensions(data));
} else {
mapped = extensions.map((it) => <ExtensionCard {...it} />);
}
return <h2>{mapped}</h2>;
}
function Home() {
return (
<Button variant="contained" color="primary">
Hello World
</Button>
);
}
function Users() {
return <h2>Users</h2>;
}

View File

@ -1,65 +0,0 @@
import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import Card from "@material-ui/core/Card";
import CardContent from "@material-ui/core/CardContent";
import Button from "@material-ui/core/Button";
import Avatar from "@material-ui/core/Avatar";
import Typography from "@material-ui/core/Typography";
const useStyles = makeStyles((theme) => ({
root: {
display: "flex",
justifyContent: "space-between",
alignItems: "center",
padding: 16
},
bullet: {
display: "inline-block",
margin: "0 2px",
transform: "scale(0.8)"
},
title: {
fontSize: 14
},
pos: {
marginBottom: 12
},
icon: {
width: theme.spacing(7),
height: theme.spacing(7),
flex: "0 0 auto",
marginRight: 16
}
}));
export default function ExtensionCard(props) {
const classes = useStyles();
const bull = <span className={classes.bullet}></span>;
const {name, lang, versionName, iconUrl} = props
const langPress = lang === "all"? "All": lang.toUpperCase()
return (
<Card>
<CardContent className={classes.root}>
<div style={{display:"flex"}}>
<Avatar
variant="rounded"
className={classes.icon}
alt={name}
src={iconUrl}
/>
<div style={{display:"flex", flexDirection:"column"}}>
<Typography variant="h5" component="h2">
{name}
</Typography>
<Typography variant="caption" display="block" gutterBottom>
{langPress} {versionName}
</Typography>
</div>
</div>
<Button variant="outlined" >install</Button>
</CardContent>
</Card>
);
}

View File

@ -0,0 +1,75 @@
import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import Card from '@material-ui/core/Card';
import CardContent from '@material-ui/core/CardContent';
import Button from '@material-ui/core/Button';
import Avatar from '@material-ui/core/Avatar';
import Typography from '@material-ui/core/Typography';
const useStyles = makeStyles((theme) => ({
root: {
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
padding: 16,
},
bullet: {
display: 'inline-block',
margin: '0 2px',
transform: 'scale(0.8)',
},
title: {
fontSize: 14,
},
pos: {
marginBottom: 12,
},
icon: {
width: theme.spacing(7),
height: theme.spacing(7),
flex: '0 0 auto',
marginRight: 16,
},
}));
interface IProps {
extension: IExtension
}
export default function ExtensionCard({
extension: {
name, lang, versionName, iconUrl,
},
}: IProps) {
const classes = useStyles();
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const bull = <span className={classes.bullet}></span>;
const langPress = lang === 'all' ? 'All' : lang.toUpperCase();
return (
<Card>
<CardContent className={classes.root}>
<div style={{ display: 'flex' }}>
<Avatar
variant="rounded"
className={classes.icon}
alt={name}
src={iconUrl}
/>
<div style={{ display: 'flex', flexDirection: 'column' }}>
<Typography variant="h5" component="h2">
{name}
</Typography>
<Typography variant="caption" display="block" gutterBottom>
{langPress}
{' '}
{versionName}
</Typography>
</div>
</div>
<Button variant="outlined">install</Button>
</CardContent>
</Card>
);
}

View File

@ -1,12 +1,11 @@
import React, {useState} from 'react';
import {makeStyles} from '@material-ui/core/styles';
import React, { useState } from 'react';
import { makeStyles } from '@material-ui/core/styles';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import Typography from '@material-ui/core/Typography';
import Button from '@material-ui/core/Button';
import IconButton from '@material-ui/core/IconButton';
import MenuIcon from '@material-ui/icons/Menu';
import TemporaryDrawer from "./TemporaryDrawer";
import TemporaryDrawer from './TemporaryDrawer';
const useStyles = makeStyles((theme) => ({
root: {
@ -22,22 +21,28 @@ const useStyles = makeStyles((theme) => ({
export default function NavBar() {
const classes = useStyles();
const [drawerOpen, setDrawerOpen] = useState(false)
const [drawerOpen, setDrawerOpen] = useState(false);
return (
<div className={classes.root}>
<AppBar position="static">
<Toolbar>
<IconButton edge="start" className={classes.menuButton} color="inherit" aria-label="menu" disableRipple
onClick={() => setDrawerOpen(true)}>
<MenuIcon/>
<IconButton
edge="start"
className={classes.menuButton}
color="inherit"
aria-label="menu"
disableRipple
onClick={() => setDrawerOpen(true)}
>
<MenuIcon />
</IconButton>
<Typography variant="h6" className={classes.title}>
Tachidesk
</Typography>
</Toolbar>
</AppBar>
<TemporaryDrawer drawerOpen={drawerOpen} setDrawerOpen={setDrawerOpen}/>
<TemporaryDrawer drawerOpen={drawerOpen} setDrawerOpen={setDrawerOpen} />
</div>
);
}

View File

@ -1,55 +0,0 @@
import React from "react";
import {makeStyles} from "@material-ui/core/styles";
import Drawer from "@material-ui/core/Drawer";
import Button from "@material-ui/core/Button";
import List from "@material-ui/core/List";
import ListItem from "@material-ui/core/ListItem";
import ListItemIcon from "@material-ui/core/ListItemIcon";
import ListItemText from "@material-ui/core/ListItemText";
import InboxIcon from "@material-ui/icons/MoveToInbox";
import MailIcon from "@material-ui/icons/Mail";
import {Link} from "react-router-dom";
const useStyles = makeStyles({
list: {
width: 250
}
});
export default function TemporaryDrawer(props) {
const classes = useStyles();
const {drawerOpen, setDrawerOpen} = props
const sideList = side => (
<div
className={classes.list}
role="presentation"
onClick={() => setDrawerOpen(false)}
onKeyDown={() => setDrawerOpen(false)}
>
<List>
<Link to="/extensions" style={{color: "inherit", textDecoration: "none"}}>
<ListItem button key="Extensions">
<ListItemIcon>
<InboxIcon/>
</ListItemIcon>
<ListItemText primary="Extensions"/>
</ListItem>
</Link>
</List>
</div>
);
return (
<div>
<Drawer
BackdropProps={{invisible: true}}
open={drawerOpen}
anchor={"left"}
onClose={() => setDrawerOpen(false)}
>
{sideList("left")}
</Drawer>
</div>
);
}

View File

@ -0,0 +1,58 @@
import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import Drawer from '@material-ui/core/Drawer';
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import ListItemIcon from '@material-ui/core/ListItemIcon';
import ListItemText from '@material-ui/core/ListItemText';
import InboxIcon from '@material-ui/icons/MoveToInbox';
import { Link } from 'react-router-dom';
const useStyles = makeStyles({
list: {
width: 250,
},
});
interface IProps {
drawerOpen: boolean
setDrawerOpen(state: boolean): void
}
export default function TemporaryDrawer({ drawerOpen, setDrawerOpen }: IProps) {
const classes = useStyles();
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const sideList = (side: 'left') => (
<div
className={classes.list}
role="presentation"
onClick={() => setDrawerOpen(false)}
onKeyDown={() => setDrawerOpen(false)}
>
<List>
<Link to="/extensions" style={{ color: 'inherit', textDecoration: 'none' }}>
<ListItem button key="Extensions">
<ListItemIcon>
<InboxIcon />
</ListItemIcon>
<ListItemText primary="Extensions" />
</ListItem>
</Link>
</List>
</div>
);
return (
<div>
<Drawer
BackdropProps={{ invisible: true }}
open={drawerOpen}
anchor="left"
onClose={() => setDrawerOpen(false)}
>
{sideList('left')}
</Drawer>
</div>
);
}

View File

@ -6,12 +6,11 @@ import './index.css';
// roboto font
import 'fontsource-roboto';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root'),
);
// If you want to start measuring performance in your app, pass a function

1
webUI/react/src/react-app-env.d.ts vendored Normal file
View File

@ -0,0 +1 @@
/// <reference types="react-scripts" />

View File

@ -1,13 +0,0 @@
const reportWebVitals = onPerfEntry => {
if (onPerfEntry && onPerfEntry instanceof Function) {
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
getCLS(onPerfEntry);
getFID(onPerfEntry);
getFCP(onPerfEntry);
getLCP(onPerfEntry);
getTTFB(onPerfEntry);
});
}
};
export default reportWebVitals;

View File

@ -0,0 +1,17 @@
import { ReportHandler } from 'web-vitals';
const reportWebVitals = (onPerfEntry?: ReportHandler) => {
if (onPerfEntry) {
import('web-vitals').then(({
getCLS, getFID, getFCP, getLCP, getTTFB,
}) => {
getCLS(onPerfEntry);
getFID(onPerfEntry);
getFCP(onPerfEntry);
getLCP(onPerfEntry);
getTTFB(onPerfEntry);
});
}
};
export default reportWebVitals;

6
webUI/react/src/typings.d.ts vendored Normal file
View File

@ -0,0 +1,6 @@
interface IExtension {
name: string
lang: string
versionName: string
iconUrl: string
}

26
webUI/react/tsconfig.json Normal file
View File

@ -0,0 +1,26 @@
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": [
"src"
]
}

File diff suppressed because it is too large Load Diff