Commit b63018c4 by jhrabal

work in progress

parent d8905263
...@@ -11,19 +11,13 @@ ...@@ -11,19 +11,13 @@
<attribute name="maven.pomderived" value="true"/> <attribute name="maven.pomderived" value="true"/>
</attributes> </attributes>
</classpathentry> </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> <attributes>
<attribute name="optional" value="true"/> <attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/> <attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/> <attribute name="test" value="true"/>
</attributes> </attributes>
</classpathentry> </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"> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
<attributes> <attributes>
<attribute name="maven.pomderived" value="true"/> <attribute name="maven.pomderived" value="true"/>
......
...@@ -15,6 +15,11 @@ ...@@ -15,6 +15,11 @@
<arguments> <arguments>
</arguments> </arguments>
</buildCommand> </buildCommand>
<buildCommand>
<name>org.springframework.ide.eclipse.boot.validation.springbootbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec> </buildSpec>
<natures> <natures>
<nature>org.eclipse.jdt.core.javanature</nature> <nature>org.eclipse.jdt.core.javanature</nature>
......
boot.validation.initialized=true
eclipse.preferences.version=1
...@@ -67,10 +67,13 @@ ...@@ -67,10 +67,13 @@
</dependency> </dependency>
<!-- db --> <!-- db -->
<!-- <dependency> -->
<!-- <groupId>org.postgresql</groupId> -->
<!-- <artifactId>postgresql</artifactId> -->
<!-- </dependency> -->
<dependency> <dependency>
<groupId>org.postgresql</groupId> <groupId>com.h2database</groupId>
<artifactId>postgresql</artifactId> <artifactId>h2</artifactId>
<version>42.2.5</version>
</dependency> </dependency>
<!-- testing --> <!-- testing -->
......
...@@ -8,6 +8,52 @@ public class Project { ...@@ -8,6 +8,52 @@ public class Project {
private String sourceLanguage; 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 { ...@@ -16,18 +16,14 @@ public class ProjectApiController {
@GetMapping("/projects") @GetMapping("/projects")
public @ResponseBody List<ProjectDTO> getSettings() { public @ResponseBody List<Project> getSettings() {
/*
List<Project> projects = service.getProjects(); List<Project> projects = service.getProjects();
if (projects == null) { if (projects == null) {
return Collections.emptyList(); return Collections.emptyList();
} }
//map to DTO //map to DTO
return projects.stream().map(p -> new ProjectDTO()).collect(Collectors.toList()); return projects;
*/
return Collections.singletonList(new ProjectDTO("test", "done", "en", new String[] { "de" }));
} }
......
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; package com.jh.memsource.project;
import java.util.Collections; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
...@@ -9,10 +9,12 @@ import org.springframework.stereotype.Service; ...@@ -9,10 +9,12 @@ import org.springframework.stereotype.Service;
public class ProjectService { public class ProjectService {
public List<Project> getProjects() { 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 { ...@@ -29,9 +29,10 @@ public class SettingsApiController {
@PutMapping("/settings") @PutMapping("/settings")
@ResponseStatus @ResponseStatus(HttpStatus.ACCEPTED)
public void saveSettings(@RequestBody Settings settings) { public @ResponseBody String saveSettings(@RequestBody Settings settings) {
service.saveSettings(settings); service.saveSettings(settings);
return "OK";
} }
} }
spring.datasource.jdbcUrl=jdbc:postgresql://localhost:5432/memsource spring.datasource.jdbcUrl=jdbc:h2:mem:testdb
spring.datasource.username=postgres spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password 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.open-in-view=false
spring.jpa.show-sql=false spring.jpa.show-sql=false
...@@ -9,3 +10,4 @@ spring.jpa.properties.hibernate.id.new_generator_mappings=true ...@@ -9,3 +10,4 @@ spring.jpa.properties.hibernate.id.new_generator_mappings=true
spring.jpa.properties.hibernate.ddl-auto=none spring.jpa.properties.hibernate.ddl-auto=none
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true 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, ID INT8 NOT NULL,
USERNAME VARCHAR, USERNAME VARCHAR,
PASSWORD VARCHAR, PASSWORD VARCHAR,
PRIMARY KEY (ID) 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.jdbcUrl=jdbc:h2:mem:testdb
spring.datasource.username=postgres spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password 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.open-in-view=false
spring.jpa.show-sql=false spring.jpa.show-sql=false
...@@ -9,3 +10,4 @@ spring.jpa.properties.hibernate.id.new_generator_mappings=true ...@@ -9,3 +10,4 @@ spring.jpa.properties.hibernate.id.new_generator_mappings=true
spring.jpa.properties.hibernate.ddl-auto=none spring.jpa.properties.hibernate.ddl-auto=none
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true 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 @@ ...@@ -6,6 +6,7 @@
"dependencies": { "dependencies": {
"@material-ui/core": "^4.4.2", "@material-ui/core": "^4.4.2",
"@material-ui/icons": "^4.4.1", "@material-ui/icons": "^4.4.1",
"formik": "^1.5.8",
"react": "^16.9.0", "react": "^16.9.0",
"react-dom": "^16.9.0", "react-dom": "^16.9.0",
"react-router-dom": "^5.0.1", "react-router-dom": "^5.0.1",
......
import React, { useState } from 'react'; 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 { createMuiTheme, MuiThemeProvider } 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 SwipeableDrawer from '@material-ui/core/SwipeableDrawer'; import { CircularProgress } from '@material-ui/core';
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 SettingsPage from 'pages/settings';
import ProjectsPage from 'pages/projects';
import WelcomePage from 'pages/welcome';
import Layout from 'components/layout';
import injectSettings from 'lib/settings'; 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 *** */ /* *** 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 ( return (
<BrowserRouter> <BrowserRouter>
<Route path="/" render={ (props) => ( <Route path="/" render={ (props) => (
<Layout {...props}> <Layout {...props}>
<Switch> <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> </Switch>
</Layout> </Layout>
) }/> ) }/>
...@@ -109,4 +36,26 @@ const App = injectSettings(({ settings, ...props }) => { ...@@ -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; margin: 0;
font-family: "Roboto", "Helvetica Neue", sans-serif; font-family: "Roboto", "Helvetica Neue", sans-serif;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
background-color: #f5f5f5;
} }
...@@ -4,17 +4,22 @@ ...@@ -4,17 +4,22 @@
import React, { useState, useEffect, createContext } from 'react'; import React, { useState, useEffect, createContext } from 'react';
import backend from 'lib/backend';
export const fetchSettings = async () => { export const fetchSettings = async () => {
return { let response = await backend("/settings");
login: "login", return response.body;
password: "password"
}
} }
export const saveSettings = async () => { export const saveSettings = async ({ username, password }) => {
await backend("/settings", "PUT", {
body: {
username,
password
}
});
} }
...@@ -24,7 +29,7 @@ export const defaultCtxValue = { ...@@ -24,7 +29,7 @@ export const defaultCtxValue = {
saving: false, saving: false,
login: null, username: null,
password: null, password: null,
fetch: () => null, fetch: () => null,
...@@ -37,19 +42,24 @@ export const SettingsContext = createContext(defaultCtxValue); ...@@ -37,19 +42,24 @@ export const SettingsContext = createContext(defaultCtxValue);
// HoC component // HoC component
export default (Wrapped) => (props) => { export default (Wrapped) => (props) => {
const [settings, updateSettings] = useState({ ...defaultCtxValue, fetch, save }); const [settings, updateSettings] = useState(defaultCtxValue);
//wrapped backend calls //wrapped backend calls
async function fetch() { async function fetch() {
updateSettings({ ...settings, fetching: true }); updateSettings({ ...settings, fetching: true });
try {
let response = await fetchSettings(); let response = await fetchSettings();
updateSettings({ ...settings, fetching: false, fetched: true }); 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 }); updateSettings({ ...settings, saving: true });
let response = await saveSettings(); let response = await saveSettings(values);
updateSettings({ ...settings, saving: false }); updateSettings({ ...settings, ...values, saving: false });
} }
//try to fetch settings once the component is mounted //try to fetch settings once the component is mounted
...@@ -58,7 +68,7 @@ export default (Wrapped) => (props) => { ...@@ -58,7 +68,7 @@ export default (Wrapped) => (props) => {
}, []); }, []);
return ( return (
<SettingsContext.Provider value={ settings }> <SettingsContext.Provider value={{ ...settings, fetch, save }}>
<Wrapped settings={ settings } {...props} /> <Wrapped settings={ settings } {...props} />
</SettingsContext.Provider> </SettingsContext.Provider>
); );
......
import React from 'react'; import React, { useState, useEffect } from 'react';
import { makeStyles } from '@material-ui/core/styles'; import { makeStyles } from '@material-ui/core/styles';
import List from '@material-ui/core/List'; import List from '@material-ui/core/List';
...@@ -7,14 +7,19 @@ import Divider from '@material-ui/core/Divider'; ...@@ -7,14 +7,19 @@ import Divider from '@material-ui/core/Divider';
import ListItemText from '@material-ui/core/ListItemText'; import ListItemText from '@material-ui/core/ListItemText';
import ListItemAvatar from '@material-ui/core/ListItemAvatar'; import ListItemAvatar from '@material-ui/core/ListItemAvatar';
import Avatar from '@material-ui/core/Avatar'; import Avatar from '@material-ui/core/Avatar';
import WorkIcon from '@material-ui/icons/Work';
import Typography from '@material-ui/core/Typography'; 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 => ({ const useStyles = makeStyles(theme => ({
root: { root: {
width: '100%', width: '100%',
maxWidth: 360,
backgroundColor: theme.palette.background.paper, backgroundColor: theme.palette.background.paper,
}, },
inline: { inline: {
...@@ -23,25 +28,29 @@ const useStyles = makeStyles(theme => ({ ...@@ -23,25 +28,29 @@ const useStyles = makeStyles(theme => ({
})); }));
/*className={classes.inline}*/
const Project = (props) => { const Project = (props) => {
return ( return (
<ListItem alignItems="flex-start"> <ListItem alignItems="flex-start">
<ListItemAvatar> <ListItemAvatar>
<Avatar alt="Travis Howard" src="/static/images/avatar/2.jpg" /> <Avatar>
<WorkIcon />
</Avatar>
</ListItemAvatar> </ListItemAvatar>
<ListItemText <ListItemText
primary="Summer BBQ" primary={ props.name }
secondary={ secondary={
<React.Fragment> <React.Fragment>
<Typography <Typography
component="span" component="span"
variant="body2" variant="body2"
className={classes.inline}
color="textPrimary" color="textPrimary"
> >
to Scott, Alex, Jennifer to Scott, Alex, Jennifer
</Typography> </Typography>
{" — Wish I could come, but I'm out of town this…"} <p>xxx</p>
</React.Fragment> </React.Fragment>
} }
/> />
...@@ -51,8 +60,49 @@ const Project = (props) => { ...@@ -51,8 +60,49 @@ const Project = (props) => {
export default (props) => { 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 ( return (
<div> <Container maxWidth="md">
</div> <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
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