Commit b63018c4 by jhrabal

work in progress

parent d8905263
......@@ -11,19 +11,13 @@
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry including="**/*.java" kind="src" output="target/test-classes" path="src/test/java">
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
<attributes>
<attribute name="maven.pomderived" value="true"/>
......
......@@ -15,6 +15,11 @@
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.springframework.ide.eclipse.boot.validation.springbootbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
......
boot.validation.initialized=true
eclipse.preferences.version=1
......@@ -67,11 +67,14 @@
</dependency>
<!-- db -->
<!-- <dependency> -->
<!-- <groupId>org.postgresql</groupId> -->
<!-- <artifactId>postgresql</artifactId> -->
<!-- </dependency> -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.5</version>
</dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<!-- testing -->
<dependency>
......
......@@ -8,6 +8,52 @@ public class Project {
private String sourceLanguage;
private String targetLanguage;
private String[] targetLanguages;
public Project() {
super();
}
public Project(String name, String status, String sourceLanguage, String[] targetLanguages) {
super();
this.name = name;
this.status = status;
this.sourceLanguage = sourceLanguage;
this.targetLanguages = targetLanguages;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getSourceLanguage() {
return sourceLanguage;
}
public void setSourceLanguage(String sourceLanguage) {
this.sourceLanguage = sourceLanguage;
}
public String[] getTargetLanguages() {
return targetLanguages;
}
public void setTargetLanguages(String[] targetLanguages) {
this.targetLanguages = targetLanguages;
}
}
......@@ -16,18 +16,14 @@ public class ProjectApiController {
@GetMapping("/projects")
public @ResponseBody List<ProjectDTO> getSettings() {
/*
public @ResponseBody List<Project> getSettings() {
List<Project> projects = service.getProjects();
if (projects == null) {
return Collections.emptyList();
}
//map to DTO
return projects.stream().map(p -> new ProjectDTO()).collect(Collectors.toList());
*/
return Collections.singletonList(new ProjectDTO("test", "done", "en", new String[] { "de" }));
return projects;
}
......
package com.jh.memsource.project;
public class ProjectDTO {
private String name;
private String status;
private String sourceLanguage;
private String[] targetLanguages;
public ProjectDTO() {
super();
}
public ProjectDTO(String name, String status, String sourceLanguage, String[] targetLanguages) {
super();
this.name = name;
this.status = status;
this.sourceLanguage = sourceLanguage;
this.targetLanguages = targetLanguages;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getSourceLanguage() {
return sourceLanguage;
}
public void setSourceLanguage(String sourceLanguage) {
this.sourceLanguage = sourceLanguage;
}
public String[] getTargetLanguages() {
return targetLanguages;
}
public void setTargetLanguages(String[] targetLanguages) {
this.targetLanguages = targetLanguages;
}
}
package com.jh.memsource.project;
import java.util.Collections;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Service;
......@@ -9,10 +9,12 @@ import org.springframework.stereotype.Service;
public class ProjectService {
public List<Project> getProjects() {
return Collections.emptyList();
List<Project> projects = new ArrayList<>();
for (int i = 1; i < 11; i++) {
projects.add(new Project(String.format("Project %s", i), null, null, null));
}
return projects;
}
......
package com.jh.memsource.project;
public class RemoteProject {
private String name;
private String status;
private String sourceLanguage;
private String targetLanguage;
}
......@@ -29,9 +29,10 @@ public class SettingsApiController {
@PutMapping("/settings")
@ResponseStatus
public void saveSettings(@RequestBody Settings settings) {
@ResponseStatus(HttpStatus.ACCEPTED)
public @ResponseBody String saveSettings(@RequestBody Settings settings) {
service.saveSettings(settings);
return "OK";
}
}
spring.datasource.jdbcUrl=jdbc:postgresql://localhost:5432/memsource
spring.datasource.username=postgres
spring.datasource.jdbcUrl=jdbc:h2:mem:testdb
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password
spring.datasource.driver-class-name=org.postgresql.Driver
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.open-in-view=false
spring.jpa.show-sql=false
spring.jpa.properties.hibernate.id.new_generator_mappings=true
spring.jpa.properties.hibernate.ddl-auto=none
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
\ No newline at end of file
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
CREATE SEQUENCE ID_GENERATOR;
CREATE SEQUENCE IF NOT EXISTS ID_GENERATOR;
CREATE TABLE SETTINGS (
CREATE TABLE IF NOT EXISTS SETTINGS (
ID INT8 NOT NULL,
USERNAME VARCHAR,
PASSWORD VARCHAR,
PRIMARY KEY (ID)
);
Manifest-Version: 1.0
Implementation-Title: memsource
Implementation-Version: 0.0.1
Build-Jdk-Spec: 1.8
Created-By: Maven Integration for Eclipse
#Generated by Maven Integration for Eclipse
#Mon Sep 16 11:44:07 CEST 2019
version=0.0.1
groupId=com.jh
m2e.projectName=memsource
m2e.projectLocation=C\:\\Users\\jh\\git\\memsource\\backend
artifactId=memsource
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.jh</groupId>
<artifactId>memsource</artifactId>
<version>0.0.1</version>
<packaging>jar</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
<relativePath />
</parent>
<properties>
<project.build.date>${maven.build.timestamp}</project.build.date>
<maven.build.timestamp.format>yyyy-MM-dd HH:mm</maven.build.timestamp.format>
<project.build.date>${maven.build.timestamp}</project.build.date>
<java.version>8</java.version>
</properties>
<dependencies>
<!-- Spring dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-hibernate5</artifactId>
</dependency>
<!-- db -->
<!-- <dependency> -->
<!-- <groupId>org.postgresql</groupId> -->
<!-- <artifactId>postgresql</artifactId> -->
<!-- </dependency> -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<!-- testing -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<filtering>false</filtering>
<directory>${basedir}/src/main/java</directory>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
<resource>
<filtering>false</filtering>
<directory>${basedir}/src/main/resources</directory>
</resource>
<resource>
<filtering>true</filtering>
<directory>${basedir}/src/main/resources</directory>
<includes>
<include>*.properties</include>
</includes>
</resource>
</resources>
<testResources>
<testResource>
<filtering>false</filtering>
<directory>${basedir}/src/test/java</directory>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</testResource>
<testResource>
<filtering>false</filtering>
<directory>${basedir}/src/test/resources</directory>
</testResource>
</testResources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.4.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<configuration>
<sourcepath>${basedir}/dummy</sourcepath>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version><!--$NO-MVN-MAN-VER$-->
<configuration>
<release>${java.version}</release>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>com.springsource.repository.maven.release</id>
<url>http://repo.springsource.org/release/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>com.springsource.repository.bundles.release</id>
<url>http://repository.springsource.com/maven/bundles/release</url>
</repository>
<repository>
<id>com.springsource.repository.bundles.external</id>
<url>http://repository.springsource.com/maven/bundles/external</url>
</repository>
</repositories>
</project>
spring.datasource.jdbcUrl=jdbc:postgresql://localhost:5432/memsource
spring.datasource.username=postgres
spring.datasource.jdbcUrl=jdbc:h2:mem:testdb
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password
spring.datasource.driver-class-name=org.postgresql.Driver
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.open-in-view=false
spring.jpa.show-sql=false
spring.jpa.properties.hibernate.id.new_generator_mappings=true
spring.jpa.properties.hibernate.ddl-auto=none
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
\ No newline at end of file
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
CREATE SEQUENCE IF NOT EXISTS ID_GENERATOR;
CREATE TABLE IF NOT EXISTS SETTINGS (
ID INT8 NOT NULL,
USERNAME VARCHAR,
PASSWORD VARCHAR,
PRIMARY KEY (ID)
);
CREATE DATABASE memsource
WITH
OWNER = postgres
ENCODING = 'utf8'
TABLESPACE = pg_default
CONNECTION LIMIT = -1;
......@@ -6,6 +6,7 @@
"dependencies": {
"@material-ui/core": "^4.4.2",
"@material-ui/icons": "^4.4.1",
"formik": "^1.5.8",
"react": "^16.9.0",
"react-dom": "^16.9.0",
"react-router-dom": "^5.0.1",
......
import React, { useState } from 'react';
import { BrowserRouter, Route, Switch, withRouter } from 'react-router-dom';
import { BrowserRouter, Route, IndexRoute, Switch, withRouter } from 'react-router-dom';
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 { createMuiTheme, MuiThemeProvider } from '@material-ui/core/styles';
import SwipeableDrawer from '@material-ui/core/SwipeableDrawer';
import List from '@material-ui/core/List';
import Divider from '@material-ui/core/Divider';
import ListItem from '@material-ui/core/ListItem';
import ListItemIcon from '@material-ui/core/ListItemIcon';
import ListItemText from '@material-ui/core/ListItemText';
import ListIcon from '@material-ui/icons/List';
import SettingsIcon from '@material-ui/icons/Settings';
import { CircularProgress } from '@material-ui/core';
import SettingsPage from 'pages/settings';
import ProjectsPage from 'pages/projects';
import WelcomePage from 'pages/welcome';
import Layout from 'components/layout';
import injectSettings from 'lib/settings';
/* *** layout *** */
const useStyles = makeStyles(theme => ({
root: {
flexGrow: 1,
},
menuButton: {
marginRight: theme.spacing(2),
},
title: {
flexGrow: 1,
},
list: {
width: 250,
},
fullList: {
width: 'auto',
},
}));
// layout copied from material-ui
const Layout = (props) => {
const classes = useStyles();
const [open, toggleDrawer] = useState(false);
return (
<div className={ classes.root }>
<AppBar position="static">
<Toolbar>
<IconButton edge="start" className={ classes.menuButton } color="inherit" aria-label="menu" onClick={ () => toggleDrawer(!open) }>
<MenuIcon />
</IconButton>
<Typography variant="h6" className={ classes.title }>
Settings
</Typography>
</Toolbar>
</AppBar>
{ props.children }
<SwipeableDrawer
open={ open }
onClose={ () => toggleDrawer(false) }
onOpen={ () => toggleDrawer(true) }
>
<List>
<ListItem button>
<ListItemIcon><ListIcon /></ListItemIcon>
<ListItemText primary="Projects" />
</ListItem>
</List>
<Divider/>
<List>
<ListItem button>
<ListItemIcon><SettingsIcon /></ListItemIcon>
<ListItemText primary="Settings" />
</ListItem>
</List>
</SwipeableDrawer>
</div>
);
}
/* *** routes - main app *** */
const App = injectSettings(({ settings, ...props }) => {
const App = injectSettings((props) => {
const settings = props.settings;
if (settings && settings.fetching) {
return <CircularProgress size={ 60 } />
}
return (
<BrowserRouter>
<Route path="/" render={ (props) => (
<Layout {...props}>
<Switch>
<Route path="*" render={ (props) => <p>Not implemented</p> } />
<Route path="/settings" exact component={ SettingsPage } />
<Route path="/projects" exact component={ ProjectsPage } />
<Route path="*" component={ WelcomePage } />
</Switch>
</Layout>
) }/>
......@@ -109,4 +36,26 @@ const App = injectSettings(({ settings, ...props }) => {
});
export default App;
/* *** main theme *** */
const theme = createMuiTheme({
palette: {
primary: {
main: '#17b7ff'
},
background: {
paper: '#FFFFFF',
default: '#FAFAFA'
},
type: 'light',
contrastThreshold: 2
},
shape: {
borderRadius: 0
}
});
export default () => (
<MuiThemeProvider theme={ theme }>
<App />
</MuiThemeProvider>
);
import React, { useState } from 'react';
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 SwipeableDrawer from '@material-ui/core/SwipeableDrawer';
import List from '@material-ui/core/List';
import Divider from '@material-ui/core/Divider';
import ListItem from '@material-ui/core/ListItem';
import ListItemIcon from '@material-ui/core/ListItemIcon';
import ListItemText from '@material-ui/core/ListItemText';
import HomeIcon from '@material-ui/icons/Home';
import ListIcon from '@material-ui/icons/List';
import SettingsIcon from '@material-ui/icons/Settings';
import { makeStyles, createMuiTheme, MuiThemeProvider } from '@material-ui/core/styles';
import { withRouter } from 'react-router-dom';
const useStyles = makeStyles(theme => ({
root: {
flexGrow: 1,
},
menuButton: {
marginRight: theme.spacing(2),
},
title: {
flexGrow: 1,
},
list: {
width: 250,
},
fullList: {
width: 'auto',
},
}));
// layout copied from material-ui
const Layout = withRouter(({ history, children, location }) => {
const classes = useStyles();
const [open, toggleDrawer] = useState(false);
function navigate(target) {
return () => {
toggleDrawer(false);
history.push(target);
}
}
let title = document.title;
if (location.pathname == "/projects") {
title = "Projects";
} else if (location.pathname == "/settings") {
title = "Settings";
}
return (
<div className={ classes.root }>
<AppBar position="static">
<Toolbar>
<IconButton edge="start" className={ classes.menuButton } color="inherit" aria-label="menu" onClick={ () => toggleDrawer(!open) }>
<MenuIcon />
</IconButton>
<Typography variant="h6" className={ classes.title }>
{ title }
</Typography>
</Toolbar>
</AppBar>
{ children }
<SwipeableDrawer
open={ open }
onClose={ () => toggleDrawer(false) }
onOpen={ () => toggleDrawer(true) }
>
<List>
<ListItem button onClick={ navigate("/") }>
<ListItemIcon><HomeIcon /></ListItemIcon>
<ListItemText primary="Home" />
</ListItem>
</List>
<List>
<ListItem button onClick={ navigate("/projects") }>
<ListItemIcon><ListIcon /></ListItemIcon>
<ListItemText primary="Projects" />
</ListItem>
</List>
<Divider/>
<List>
<ListItem button onClick={ navigate("/settings") }>
<ListItemIcon><SettingsIcon /></ListItemIcon>
<ListItemText primary="Settings" />
</ListItem>
</List>
</SwipeableDrawer>
</div>
);
});
export default Layout;
\ No newline at end of file
body {
body, html {
margin: 0;
font-family: "Roboto", "Helvetica Neue", sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
background-color: #f5f5f5;
}
......@@ -4,17 +4,22 @@
import React, { useState, useEffect, createContext } from 'react';
import backend from 'lib/backend';
export const fetchSettings = async () => {
return {
login: "login",
password: "password"
}
let response = await backend("/settings");
return response.body;
}
export const saveSettings = async () => {
export const saveSettings = async ({ username, password }) => {
await backend("/settings", "PUT", {
body: {
username,
password
}
});
}
......@@ -24,7 +29,7 @@ export const defaultCtxValue = {
saving: false,
login: null,
username: null,
password: null,
fetch: () => null,
......@@ -37,19 +42,24 @@ export const SettingsContext = createContext(defaultCtxValue);
// HoC component
export default (Wrapped) => (props) => {
const [settings, updateSettings] = useState({ ...defaultCtxValue, fetch, save });
const [settings, updateSettings] = useState(defaultCtxValue);
//wrapped backend calls
async function fetch() {
updateSettings({ ...settings, fetching: true });
let response = await fetchSettings();
updateSettings({ ...settings, fetching: false, fetched: true });
try {
let response = await fetchSettings();
updateSettings({ ...settings, ...response, fetching: false, fetched: true });
} catch (e) {
updateSettings({ ...settings, fetching: false, fetched: false });
}
}
async function save() {
async function save(values) {
updateSettings({ ...settings, saving: true });
let response = await saveSettings();
updateSettings({ ...settings, saving: false });
let response = await saveSettings(values);
updateSettings({ ...settings, ...values, saving: false });
}
//try to fetch settings once the component is mounted
......@@ -58,7 +68,7 @@ export default (Wrapped) => (props) => {
}, []);
return (
<SettingsContext.Provider value={ settings }>
<SettingsContext.Provider value={{ ...settings, fetch, save }}>
<Wrapped settings={ settings } {...props} />
</SettingsContext.Provider>
);
......
import React from 'react';
import React, { useState, useEffect } from 'react';
import { makeStyles } from '@material-ui/core/styles';
import List from '@material-ui/core/List';
......@@ -7,52 +7,102 @@ import Divider from '@material-ui/core/Divider';
import ListItemText from '@material-ui/core/ListItemText';
import ListItemAvatar from '@material-ui/core/ListItemAvatar';
import Avatar from '@material-ui/core/Avatar';
import WorkIcon from '@material-ui/icons/Work';
import Typography from '@material-ui/core/Typography';
import Container from '@material-ui/core/Container';
import Box from '@material-ui/core/Box';
import Paper from '@material-ui/core/Paper';
import backend from 'lib/backend';
const useStyles = makeStyles(theme => ({
root: {
width: '100%',
maxWidth: 360,
backgroundColor: theme.palette.background.paper,
},
inline: {
inline: {
display: 'inline',
},
}));
/*className={classes.inline}*/
const Project = (props) => {
return (
<ListItem alignItems="flex-start">
<ListItemAvatar>
<Avatar alt="Travis Howard" src="/static/images/avatar/2.jpg" />
<Avatar>
<WorkIcon />
</Avatar>
</ListItemAvatar>
<ListItemText
primary="Summer BBQ"
secondary={
<React.Fragment>
<Typography
component="span"
variant="body2"
className={classes.inline}
color="textPrimary"
>
to Scott, Alex, Jennifer
</Typography>
{" — Wish I could come, but I'm out of town this…"}
</React.Fragment>
}
/>
<ListItemText
primary={ props.name }
secondary={
<React.Fragment>
<Typography
component="span"
variant="body2"
color="textPrimary"
>
to Scott, Alex, Jennifer
</Typography>
<p>xxx</p>
</React.Fragment>
}
/>
</ListItem>
);
}
export default (props) => {
const classes = useStyles();
const [ projects, setProjects ] = useState([]);
const [ loading, setLoading ] = useState(true);
const fetchProjects = async () => {
setLoading(true);
try {
let response = await backend("/projects");
setProjects(response.body);
} catch (e) {
//TODO
setProjects(false);
}
setLoading(false);
};
useEffect(() => {
fetchProjects();
}, []);
if (!Array.isArray(projects)) {
//an error occured
return <div>error</div>
}
//construct list items
const list = [];
for (let i = 0; i < projects.length; i++) {
list.push(<Project key={ `project-${i}` } name={ projects[i].name } />);
if (i < projects.length - 1) {
list.push(<Divider key={ `divider-${i}` } />);
}
}
return (
<div>
</div>
<Container maxWidth="md">
<Box m={ 2 } className={ classes.root }>
<Paper>
<List>
{ list }
</List>
</Paper>
</Box>
</Container>
);
}
\ No newline at end of file
import React, { useContext } from 'react';
import { makeStyles } from '@material-ui/core/styles';
import { Container, Box, Paper, Button, TextField } from '@material-ui/core';
import { Formik } from 'formik';
import { SettingsContext } from 'lib/settings';
const useStyles = makeStyles(theme => ({
root: {
width: '100%',
maxWidth: 360,
backgroundColor: theme.palette.background.paper,
},
inline: {
display: 'inline',
},
button: {
margin: theme.spacing(1),
},
textField: {
marginLeft: theme.spacing(1),
marginRight: theme.spacing(1),
},
}));
export default (props) => {
const classes = useStyles();
const settings = useContext(SettingsContext);
console.info(settings);
return (
<Formik
initialValues={{ username: settings.username || "", password: settings.password || "" }}
validate={ values => {
let errors = {};
if (!values.username) {
errors.username = 'Required';
}
if (!values.password) {
errors.password = 'Required';
}
return errors;
}}
onSubmit={ async (values, { setSubmitting }) => {
setSubmitting(true);
try {
await settings.save(values);
} catch (err) {
//TODO
}
setSubmitting(false);
}}
>
{({
values,
errors,
touched,
handleChange,
handleBlur,
handleSubmit,
isSubmitting,
}) => (
<Container maxWidth="md">
<Box m={ 2 }>
<Paper>
<form onSubmit={ handleSubmit }>
<TextField
label="Username"
className={ classes.textField }
name="username"
value={ values.username }
onChange={ handleChange }
margin="normal"
disabled={ isSubmitting }
helperText={ errors.username }
error={ !!errors.username }
/>
<TextField
label="Password"
className={ classes.textField }
name="password"
value={ values.password }
onChange={ handleChange }
margin="normal"
disabled={ isSubmitting }
helperText={ errors.email && touched.email && errors.email }
/>
<Button className={ classes.button } disabled={ isSubmitting }>
Cancel
</Button>
<Button type="submit" variant="contained" color="primary" className={classes.button} disabled={ isSubmitting }>
Ok
</Button>
</form>
</Paper>
</Box>
</Container>
) }
</Formik>
);
}
\ No newline at end of file
import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import { Container, Box, Paper } from '@material-ui/core';
const useStyles = makeStyles(theme => ({
root: {
width: '100%',
backgroundColor: theme.palette.background.paper,
},
}));
export default () => {
const classes = useStyles();
return (
<Container maxWidth="md">
<Box m={ 2 } className={ classes.root }>
<Paper>
XXX
</Paper>
</Box>
</Container>
);
};
\ No newline at end of file
......@@ -1851,7 +1851,7 @@ arrify@^1.0.1:
resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=
asap@~2.0.6:
asap@~2.0.3, asap@~2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=
......@@ -2892,6 +2892,11 @@ core-js@3.1.4:
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.1.4.tgz#3a2837fc48e582e1ae25907afcd6cf03b0cc7a07"
integrity sha512-YNZN8lt82XIMLnLirj9MhKDFZHalwzzrL9YLt6eb0T5D0EDl4IQ90IGkua8mHbnxNrkj1d8hbdizMc0Qmg1WnQ==
core-js@^1.0.0:
version "1.2.7"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636"
integrity sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=
core-js@^2.4.0:
version "2.6.9"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2"
......@@ -2943,6 +2948,14 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4:
safe-buffer "^5.0.1"
sha.js "^2.4.8"
create-react-context@^0.2.2:
version "0.2.3"
resolved "https://registry.yarnpkg.com/create-react-context/-/create-react-context-0.2.3.tgz#9ec140a6914a22ef04b8b09b7771de89567cb6f3"
integrity sha512-CQBmD0+QGgTaxDL3OX1IDXYqjkp2It4RIbcb99jS6AEg27Ga+a9G3JtK6SIu0HBwPLZlmwt9F7UwWA4Bn92Rag==
dependencies:
fbjs "^0.8.0"
gud "^1.0.0"
cross-spawn@6.0.5, cross-spawn@^6.0.0, cross-spawn@^6.0.5:
version "6.0.5"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
......@@ -3298,6 +3311,11 @@ deep-is@~0.1.3:
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
deepmerge@^2.1.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.2.1.tgz#5d3ff22a01c00f645405a2fbc17d0778a1801170"
integrity sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==
deepmerge@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.0.0.tgz#3e3110ca29205f120d7cb064960a39c3d2087c09"
......@@ -3613,6 +3631,13 @@ encodeurl@~1.0.2:
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=
encoding@^0.1.11:
version "0.1.12"
resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb"
integrity sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=
dependencies:
iconv-lite "~0.4.13"
end-of-stream@^1.0.0, end-of-stream@^1.1.0:
version "1.4.1"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43"
......@@ -4156,6 +4181,19 @@ fb-watchman@^2.0.0:
dependencies:
bser "^2.0.0"
fbjs@^0.8.0:
version "0.8.17"
resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.17.tgz#c4d598ead6949112653d6588b01a5cdcd9f90fdd"
integrity sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=
dependencies:
core-js "^1.0.0"
isomorphic-fetch "^2.1.1"
loose-envify "^1.0.0"
object-assign "^4.1.0"
promise "^7.1.1"
setimmediate "^1.0.5"
ua-parser-js "^0.7.18"
figgy-pudding@^3.5.1:
version "3.5.1"
resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790"
......@@ -4337,6 +4375,21 @@ form-data@~2.3.2:
combined-stream "^1.0.6"
mime-types "^2.1.12"
formik@^1.5.8:
version "1.5.8"
resolved "https://registry.yarnpkg.com/formik/-/formik-1.5.8.tgz#eee8cd345effe46839bc748c7f920486f12f14b0"
integrity sha512-fNvPe+ddbh+7xiByT25vuso2p2hseG/Yvuj211fV1DbCjljUEG9OpgRpcb7g7O3kxHX/q31cbZDzMxJXPWSNwA==
dependencies:
create-react-context "^0.2.2"
deepmerge "^2.1.1"
hoist-non-react-statics "^3.3.0"
lodash "^4.17.14"
lodash-es "^4.17.14"
prop-types "^15.6.1"
react-fast-compare "^2.0.1"
tiny-warning "^1.0.2"
tslib "^1.9.3"
forwarded@~0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84"
......@@ -4714,7 +4767,7 @@ hmac-drbg@^1.0.0:
minimalistic-assert "^1.0.0"
minimalistic-crypto-utils "^1.0.1"
hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.2.1:
hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.2.1, hoist-non-react-statics@^3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.0.tgz#b09178f0122184fb95acf525daaecb4d8f45958b"
integrity sha512-0XsbTXxgiaCDYDIWFcwkmerZPSwywfUqYmwT4jzewKTQSWoE6FCMoUVOeBJWK3E/CrWbxRG3m5GzY4lnIwGRBA==
......@@ -4880,7 +4933,7 @@ hyphenate-style-name@^1.0.3:
resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.3.tgz#097bb7fa0b8f1a9cf0bd5c734cf95899981a9b48"
integrity sha512-EcuixamT82oplpoJ2XU4pDtKGWQ7b00CD9f1ug9IaQ3p1bkHMiKCZ9ut9QDI6qsa6cpUuB+A/I+zLtdNK4n2DQ==
iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4:
iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13:
version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
......@@ -5346,7 +5399,7 @@ is-root@2.1.0:
resolved "https://registry.yarnpkg.com/is-root/-/is-root-2.1.0.tgz#809e18129cf1129644302a4f8544035d51984a9c"
integrity sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==
is-stream@^1.1.0:
is-stream@^1.0.1, is-stream@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
......@@ -5412,6 +5465,14 @@ isobject@^4.0.0:
resolved "https://registry.yarnpkg.com/isobject/-/isobject-4.0.0.tgz#3f1c9155e73b192022a80819bacd0343711697b0"
integrity sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA==
isomorphic-fetch@^2.1.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9"
integrity sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=
dependencies:
node-fetch "^1.0.1"
whatwg-fetch ">=0.10.0"
isstream@~0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
......@@ -6242,6 +6303,11 @@ locate-path@^3.0.0:
p-locate "^3.0.0"
path-exists "^3.0.0"
lodash-es@^4.17.14:
version "4.17.15"
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.15.tgz#21bd96839354412f23d7a10340e5eac6ee455d78"
integrity sha512-rlrc3yU3+JNOpZ9zj5pQtxnx2THmvRykwL4Xlxoa8I9lHBlVbbyPhgyPMioxVZ4NqyxaVVtaJnzsyOidQIhyyQ==
lodash._reinterpolate@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
......@@ -6701,6 +6767,14 @@ no-case@^2.2.0:
dependencies:
lower-case "^1.1.1"
node-fetch@^1.0.1:
version "1.7.3"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef"
integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==
dependencies:
encoding "^0.1.11"
is-stream "^1.0.1"
node-forge@0.8.2:
version "0.8.2"
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.8.2.tgz#b4bcc59fb12ce77a8825fc6a783dfe3182499c5a"
......@@ -8141,6 +8215,13 @@ promise@8.0.3:
dependencies:
asap "~2.0.6"
promise@^7.1.1:
version "7.3.1"
resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf"
integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==
dependencies:
asap "~2.0.3"
prompts@^2.0.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.2.1.tgz#f901dd2a2dfee080359c0e20059b24188d75ad35"
......@@ -8149,7 +8230,7 @@ prompts@^2.0.1:
kleur "^3.0.3"
sisteransi "^1.0.3"
prop-types@^15.6.2, prop-types@^15.7.2:
prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2:
version "15.7.2"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
......@@ -8363,6 +8444,11 @@ react-error-overlay@^6.0.1:
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.1.tgz#b8d3cf9bb991c02883225c48044cb3ee20413e0f"
integrity sha512-V9yoTr6MeZXPPd4nV/05eCBvGH9cGzc52FN8fs0O0TVQ3HYYf1n7EgZVtHbldRq5xU9zEzoXIITjYNIfxDDdUw==
react-fast-compare@^2.0.1:
version "2.0.4"
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9"
integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==
react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.8.6:
version "16.9.0"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.9.0.tgz#21ca9561399aad0ff1a7701c01683e8ca981edcb"
......@@ -9059,7 +9145,7 @@ set-value@^2.0.0, set-value@^2.0.1:
is-plain-object "^2.0.3"
split-string "^3.0.1"
setimmediate@^1.0.4:
setimmediate@^1.0.4, setimmediate@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=
......@@ -9790,7 +9876,7 @@ ts-pnp@^1.1.2:
resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.1.4.tgz#ae27126960ebaefb874c6d7fa4729729ab200d90"
integrity sha512-1J/vefLC+BWSo+qe8OnJQfWTYRS6ingxjwqmHMqaMxXMj7kFtKLgAaYW3JeX3mktjgUL+etlU8/B4VUAUI9QGw==
tslib@^1.8.1, tslib@^1.9.0:
tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
version "1.10.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a"
integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==
......@@ -9844,6 +9930,11 @@ typedarray@^0.0.6:
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
ua-parser-js@^0.7.18:
version "0.7.20"
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.20.tgz#7527178b82f6a62a0f243d1f94fd30e3e3c21098"
integrity sha512-8OaIKfzL5cpx8eCMAhhvTlft8GYF8b2eQr6JkCyVdrgjcytyOmPCXrqXFcUnhonRpLlh5yxEZVohm6mzaowUOw==
uglify-js@3.4.x:
version "3.4.10"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.10.tgz#9ad9563d8eb3acdfb8d38597d2af1d815f6a755f"
......@@ -10249,7 +10340,7 @@ whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3, whatwg-encoding@^1.0.5:
dependencies:
iconv-lite "0.4.24"
whatwg-fetch@3.0.0:
whatwg-fetch@3.0.0, whatwg-fetch@>=0.10.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb"
integrity sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==
......
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