diff --git a/.env.docker-compose-dist b/.env.docker-compose-dist
new file mode 100644
index 0000000..55d214f
--- /dev/null
+++ b/.env.docker-compose-dist
@@ -0,0 +1,4 @@
+POSTGRES_USER=postgres
+POSTGRES_PASSWORD=
+POSTGRES_DB=postgres
+
diff --git a/.gitignore b/.gitignore
index 48d43e5..69df68a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,12 +1,86 @@
-.vs
+### Node ###
+# 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
+
+# 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 output
+.vuepress/dist
+
+# Serverless directories
+.serverless/
+
+# FuseBox cache
+.fusebox/
+
+# DynamoDB Local files
+.dynamodb/
+
+# Custom
+.vs*
.idea
__generated__
build
-node_modules
docker-compose.override.yml
-npm-error.log*
-npm-debug.log*
-yarn-error.log*
-yarn-debug.log*
-lerna-debug.log*
backup.sql
diff --git a/.vscode/settings.json b/.vscode/settings.json
deleted file mode 100644
index f108e7f..0000000
--- a/.vscode/settings.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "editor.formatOnSave": true,
- "flow.useNPMPackagedFlow": true,
- "javascript.format.enable": false,
- "javascript.validate.enable": false,
- "search.exclude": {
- "**/build": true,
- "**/node_modules": true,
- "**/yarn.lock": true,
- "**/__generated__": true
- },
- "typescript.tsdk": "./node_modules/typescript/lib"
-}
diff --git a/api/.env b/api/.env
deleted file mode 100644
index dc665f7..0000000
--- a/api/.env
+++ /dev/null
@@ -1,19 +0,0 @@
-# CORS
-
-API_ORIGIN=http://localhost:8080
-CORS_ORIGIN=http://localhost
-CRM_ORIGIN=http://localhost:3001
-
-# https://www.postgresql.org/docs/current/static/libpq-envars.html
-
-PGHOST=localhost
-PGPORT=5432
-PGUSER=postgres
-PGPASSWORD=
-PGDATABASE=database
-PGAPP=api
-PGDEBUG=false
-
-
-
-
diff --git a/api/.env.dist b/api/.env.dist
new file mode 100644
index 0000000..1f4e677
--- /dev/null
+++ b/api/.env.dist
@@ -0,0 +1,13 @@
+PORT=8080
+
+# DB
+PG_LISTINGS_HOST=
+PG_LISTINGS_USER=
+PG_LISTINGS_PASSWORD=
+PG_LISTINGS_DATABASE=
+
+# CORS
+API_ORIGIN=http://localhost:8080
+CORS_ORIGIN=http://localhost
+CRM_ORIGIN=http://localhost:3001
+
diff --git a/api/.vscode/launch.json b/api/.vscode/launch.json
deleted file mode 100644
index c7646c0..0000000
--- a/api/.vscode/launch.json
+++ /dev/null
@@ -1,34 +0,0 @@
-{
- // Use IntelliSense to learn about possible Node.js debug attributes.
- // Hover to view descriptions of existing attributes.
- // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
- "version": "0.2.0",
- "configurations": [
- {
- "name": "Run",
- "type": "node",
- "request": "attach",
- "port": 9229,
- "protocol": "inspector",
- "localRoot": "${workspaceRoot}",
- "remoteRoot": "/usr/src/app"
- },
- {
- "name": "Server",
- "type": "node",
- "request": "attach",
- "port": 9230,
- "protocol": "inspector",
- "sourceMaps": true,
- "localRoot": "${workspaceRoot}",
- "remoteRoot": "/usr/src/app",
- "restart": true
- }
- ],
- "compounds": [
- {
- "name": "Run/Server",
- "configurations": ["Run", "Server"]
- }
- ]
-}
diff --git a/api/.vscode/settings.json b/api/.vscode/settings.json
deleted file mode 100644
index 2cfbc4e..0000000
--- a/api/.vscode/settings.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "editor.formatOnSave": true,
- "flow.useNPMPackagedFlow": true,
- "javascript.format.enable": false,
- "javascript.validate.enable": false,
- "vsicons.presets.angular": false,
- "search.exclude": {
- "**/.idea": true,
- "**/build": true,
- "**/node_modules": true,
- "**/yarn-error.log": true,
- "**/yarn.lock": true
- }
-}
diff --git a/api/.vscode/snippets/javascript.json b/api/.vscode/snippets/javascript.json
deleted file mode 100644
index a435856..0000000
--- a/api/.vscode/snippets/javascript.json
+++ /dev/null
@@ -1,47 +0,0 @@
-{
- "GraphQL Type": {
- "prefix": "type",
- "body": [
- "/* @flow */",
- "",
- "import { GraphQLObjectType, GraphQLString } from 'graphql';",
- "import { globalIdField } from 'graphql-relay';",
- "",
- "export default new GraphQLObjectType({",
- " name: '${1:name}',",
- " fields: {",
- " id: globalIdField(),",
- " ${2:field}",
- " },",
- "});",
- ""
- ],
- "description": "GraphQL Type"
- },
- "GraphQL Field": {
- "prefix": "field",
- "body": [
- "${1:field}: {",
- " type: ${2:type},",
- " resolve(${3:parent}, args, { ${4:loader} }) {",
- " return ${4:loader}.load(${3:parent}.id);",
- " },",
- "},"
- ],
- "description": "GraphQL Field"
- },
- "Test": {
- "prefix": "test",
- "body": [
- "/* eslint-env jest */",
- "",
- "describe('${1:namespace}', () => {",
- " test('${2:test}', () => {",
- " expect(${3:expect})$0;",
- " });",
- "});",
- ""
- ],
- "description": "Test Script"
- }
-}
diff --git a/api/Dockerfile b/api/Dockerfile
new file mode 100644
index 0000000..f0b3e37
--- /dev/null
+++ b/api/Dockerfile
@@ -0,0 +1,14 @@
+FROM node:8-alpine
+
+WORKDIR /app
+
+COPY package*.json ./
+COPY yarn.lock ./
+
+RUN apk update \
+ && apk add --no-cache curl bash \
+ && sh -c "curl -o- -L https://yarnpkg.com/install.sh | bash" \
+ && yarn install
+
+EXPOSE 8080
+CMD [ "yarn", "dev" ]
diff --git a/api/docker-compose.yml b/api/docker-compose.yml
deleted file mode 100644
index 9ca2787..0000000
--- a/api/docker-compose.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-# Docker Compose settings for launching PostgreSQL and Redis databases
-# You can override these settings in docker-compose.override.yml
-# https://docs.docker.com/compose/compose-file/
-
-version: '3'
-
-volumes:
- ? db
-
-services:
- # SQL and document data store
- db:
- image: db
- build:
- context: ./images/db
- volumes:
- - db:/var/lib/postgresql/data
- - ./postgres-initdb.sh:/docker-entrypoint-initdb.d/initdb.sh
- ports:
- - '127.0.0.1:5432:5432'
diff --git a/api/images/db/Dockerfile b/api/images/db/Dockerfile
deleted file mode 100644
index 1795a72..0000000
--- a/api/images/db/Dockerfile
+++ /dev/null
@@ -1,2 +0,0 @@
-FROM postgres:9.6.9-alpine
-
diff --git a/api/knexfile.js b/api/knexfile.js
index f73474e..a2d3c4d 100644
--- a/api/knexfile.js
+++ b/api/knexfile.js
@@ -9,7 +9,12 @@ dotenv.config({ path: '.env' });
module.exports = {
client: 'pg',
- connection: {},
+ connection: {
+ host: process.env.PG_LISTINGS_HOST,
+ user: process.env.PG_LISTINGS_USER,
+ password: process.env.PG_LISTINGS_PASSWORD,
+ database: process.env.PG_LISTINGS_DATABASE,
+ },
migrations: {
tableName: 'migrations',
},
diff --git a/api/migrations/201902252336_properties_alter.js b/api/migrations/201902252336_properties_alter.js
new file mode 100644
index 0000000..05f0cb1
--- /dev/null
+++ b/api/migrations/201902252336_properties_alter.js
@@ -0,0 +1,23 @@
+/* prettier-ignore */
+
+module.exports.up = async db => {
+ console.log('append land_surface, number_of_rooms, number_of_parkings to properties table');
+
+ await db.schema.alterTable('properties', table => {
+ table.float('land_surface');
+ table.float('number_of_rooms');
+ table.integer('number_of_parkings');
+ });
+};
+
+module.exports.down = async db => {
+ console.log('drop land_surface, number_of_rooms, number_of_parkings to properties table');
+
+ await db.schema.alterTable('properties', table => {
+ table.dropColumn('land_surface');
+ table.dropColumn('number_of_rooms');
+ table.dropColumn('number_of_parkings');
+ });
+};
+
+module.exports.config = { transaction: true };
diff --git a/api/package.json b/api/package.json
index d20f04b..633cec3 100755
--- a/api/package.json
+++ b/api/package.json
@@ -23,7 +23,7 @@
"graphql-relay": "^0.5.5",
"graphql-type-json": "^0.2.1",
"idx": "^2.2.0",
- "knex": "^0.15.2",
+ "knex": "^0.16.3",
"lodash": "^4.17.4",
"lru-cache": "^4.1.1",
"morgan": "^1.9.0",
@@ -77,6 +77,7 @@
"db-seed": "node scripts/db.js seed",
"db-restore": "./scripts/db-restore.sh",
"update-schema": "node scripts/update-schema.js",
- "start": "node --icu-data-dir=`yarn -s run node-full-icu-path` ./server.js"
+ "start": "node --icu-data-dir=`yarn -s run node-full-icu-path` ./server.js",
+ "dev": "npm run db-migrate && npm run start"
}
}
diff --git a/api/postgres-initdb.sh b/api/postgres-initdb.sh
index 8e3baf3..34a5723 100644
--- a/api/postgres-initdb.sh
+++ b/api/postgres-initdb.sh
@@ -1,10 +1,6 @@
#!/bin/sh -e
-psql --variable=ON_ERROR_STOP=1 --username "$POSTGRES_USER" <<-EOSQL
- CREATE DATABASE "database";
-EOSQL
-
-psql --variable=ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname=database <<-EOSQL
+psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
CREATE EXTENSION "uuid-ossp";
EOSQL
diff --git a/api/schema.graphql b/api/schema.graphql
index 3fb90e7..ee3e71c 100644
--- a/api/schema.graphql
+++ b/api/schema.graphql
@@ -44,6 +44,9 @@ type Property implements Node {
# The ID of an object
id: ID!
livingSurface: Float
+ landSurface: Float
+ numberOfRooms: Float
+ numberOfParkings: Int
createdAt: DateTime
updatedAt: DateTime
}
@@ -75,6 +78,9 @@ input PropertyFilters {
input PropertyInput {
id: ID
livingSurface: Float
+ landSurface: Float
+ numberOfRooms: Float
+ numberOfParkings: Int
}
type Query {
diff --git a/api/server.js b/api/server.js
index c68e736..15ca7f7 100644
--- a/api/server.js
+++ b/api/server.js
@@ -10,10 +10,8 @@ if (process.env.NODE_ENV === 'production') {
// Otherwise, built it from source and launch
// on http://localhost:8080/ with "live reload"
require('source-map-support').install();
- const cp = require('child_process');
const restart = require('restart');
const build = require('./scripts/build');
- cp.spawnSync('docker-compose', ['up', '-d'], { stdio: 'inherit' });
build({
watch: true,
onComplete: () => restart('./build/server'),
diff --git a/api/src/db_.js b/api/src/db_.js
index 8f91c4d..f3721af 100644
--- a/api/src/db_.js
+++ b/api/src/db_.js
@@ -11,7 +11,12 @@ import knex from 'knex';
const db = knex({
client: 'pg',
- connection: {},
+ connection: {
+ host: process.env.PG_LISTINGS_HOST,
+ user: process.env.PG_LISTINGS_USER,
+ password: process.env.PG_LISTINGS_PASSWORD,
+ database: process.env.PG_LISTINGS_DATABASE,
+ },
migrations: {
tableName: 'migrations',
},
diff --git a/api/src/schema/PropertyInputType.js b/api/src/schema/PropertyInputType.js
index ec106b8..3e06371 100644
--- a/api/src/schema/PropertyInputType.js
+++ b/api/src/schema/PropertyInputType.js
@@ -1,8 +1,11 @@
-import { GraphQLID, GraphQLInputObjectType, GraphQLFloat } from 'graphql';
+import { GraphQLID, GraphQLInputObjectType, GraphQLFloat, GraphQLInt } from 'graphql';
export const fields = {
id: { type: GraphQLID },
livingSurface: { type: GraphQLFloat },
+ landSurface: { type: GraphQLFloat },
+ numberOfRooms: { type: GraphQLFloat },
+ numberOfParkings: { type: GraphQLInt }
};
export const PropertyInputType = new GraphQLInputObjectType({
diff --git a/api/src/schema/PropertyType.js b/api/src/schema/PropertyType.js
index f861c96..c4ddb74 100644
--- a/api/src/schema/PropertyType.js
+++ b/api/src/schema/PropertyType.js
@@ -1,6 +1,6 @@
/* @flow */
-import { GraphQLObjectType, GraphQLFloat } from 'graphql';
+import { GraphQLObjectType, GraphQLFloat, GraphQLInt } from 'graphql';
import { GraphQLDateTime } from 'graphql-iso-date';
import { globalIdField } from 'graphql-relay';
@@ -17,6 +17,21 @@ export const PropertyType = new GraphQLObjectType({
resolve: parent => parent.living_surface,
},
+ landSurface: {
+ type: GraphQLFloat,
+ resolve: parent => parent.land_surface,
+ },
+
+ numberOfRooms: {
+ type: GraphQLFloat,
+ resolve: parent => parent.number_of_rooms,
+ },
+
+ numberOfParkings: {
+ type: GraphQLInt,
+ resolve: parent => parent.number_of_parkings,
+ },
+
createdAt: {
type: GraphQLDateTime,
resolve: parent => parent.created_at,
diff --git a/api/src/schema/property/validate.js b/api/src/schema/property/validate.js
index 89e5803..aec680e 100644
--- a/api/src/schema/property/validate.js
+++ b/api/src/schema/property/validate.js
@@ -9,7 +9,14 @@ export default async function(input: any, ctx: Context) {
.field('id')
.fromGlobalId('Property')
.field('livingSurface', { as: 'living_surface' })
- .isFloat({ min: 20, max: 5000 }),
+ .isFloat({ min: 20, max: 5000 })
+ .field('landSurface', { as: 'land_surface' })
+ .isFloat({ min: 20, max: 5000 })
+ .field('numberOfRooms', { as: 'number_of_rooms' })
+ .isFloat({ min: 1, max: 10 })
+ .field('numberOfParkings', { as: 'number_of_parkings' })
+ .isInt({ min: 1, max: 5 })
+ .field('createdAt', { as: 'created_at' })
);
return data;
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..e1a98f5
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,43 @@
+version: '3'
+
+services:
+ web:
+ build:
+ context: ./web
+ volumes:
+ - ./web:/app
+ - ./api:/api
+ ports:
+ - '3000:3000'
+ networks:
+ - default
+ links:
+ - api
+ api:
+ build:
+ context: ./api
+ volumes:
+ - ./api:/app
+ ports:
+ - '8080:8080'
+ networks:
+ - default
+ links:
+ - db
+ db:
+ image: postgres:9.6.9-alpine
+ volumes:
+ - db-data:/var/lib/postgresql/data
+ - ./api/postgres-initdb.sh:/docker-entrypoint-initdb.d/init-api.sh
+ expose:
+ - '5432'
+ networks:
+ - default
+
+volumes:
+ db-data:
+ driver: local
+
+networks:
+ default:
+ driver: bridge
diff --git a/web/.env.dist b/web/.env.dist
new file mode 100644
index 0000000..a7b0ed2
--- /dev/null
+++ b/web/.env.dist
@@ -0,0 +1 @@
+API_ENDPOINT=http://api:8080/graphql
diff --git a/web/Dockerfile b/web/Dockerfile
new file mode 100644
index 0000000..6f3c94a
--- /dev/null
+++ b/web/Dockerfile
@@ -0,0 +1,14 @@
+FROM node:8-alpine
+
+WORKDIR /app
+
+COPY package*.json ./
+COPY yarn.lock ./
+
+RUN apk update \
+ && apk add --no-cache curl bash \
+ && sh -c "curl -o- -L https://yarnpkg.com/install.sh | bash" \
+ && yarn install
+
+EXPOSE 3000
+CMD [ "yarn", "dev" ]
diff --git a/web/controls/relay/mutation.js b/web/controls/relay/mutation.js
index c120de4..0396c9a 100644
--- a/web/controls/relay/mutation.js
+++ b/web/controls/relay/mutation.js
@@ -88,12 +88,14 @@ export function createMutation<
const rootField = getRootFieldName(environment, mutation);
if (!rootField) {
+ console.log('root field with errors!')
return;
}
const payload = store.getRootField(rootField);
if (!payload) {
// mutation contains errors
+ console.log('mutation commited with errors!')
return;
}
diff --git a/web/package.json b/web/package.json
index 1421a47..4f2e822 100644
--- a/web/package.json
+++ b/web/package.json
@@ -5,6 +5,7 @@
"license": "CC-BY-4.0",
"dependencies": {
"@material-ui/core": "^3.4.0",
+ "@material-ui/icons": "^3.0.2",
"@material-ui/lab": "^3.0.0-alpha.23",
"@rebass/components": "^4.0.0-1",
"@rebass/grid": "^6.0.0-4",
@@ -18,9 +19,11 @@
"esm": "^3.0.82",
"fast-memoize": "^2.5.1",
"flow-remove-types": "^1.2.3",
+ "formik": "^1.5.1",
"full-icu": "^1.2.1",
"i18next": "^11.5.0",
"jss": "^9.8.7",
+ "momentjs": "^2.0.0",
"next": "^7.0.1",
"path-to-regexp": "^2.2.1",
"polished": "^2.0.3",
@@ -117,7 +120,6 @@
"node": "8"
},
"config": {
- "API_ENDPOINT": "http://localhost:8080/graphql",
"descr": [
"SCRIPTS description",
"test - pregenerate files and run tests",
@@ -131,11 +133,11 @@
},
"scripts": {
"test": "yarn relay && eslint ./ && flow && jest",
- "start": "API_ENDPOINT=$npm_package_config_API_ENDPOINT NODE_ENV=production node --icu-data-dir=`yarn -s run node-full-icu-path` server/index.js",
+ "start": "NODE_ENV=production node server/index.js",
"build": "yarn relay && next build",
"dev": "yarn relay && yarn dev:raw",
- "dev:raw": "API_ENDPOINT=$npm_package_config_API_ENDPOINT node --icu-data-dir=`yarn -s run node-full-icu-path` server/index.js",
- "relay": "relay-compiler --src . --schema ../api/schema.graphql",
+ "dev:raw": "node --icu-data-dir=`yarn -s run node-full-icu-path` server/index.js",
+ "relay": "relay-compiler --src . --schema /api/schema.graphql",
"relay:clean": "rimraf $TMPDIR/* && rimraf ./**/__generated__/*.graphql.js"
}
}
diff --git a/web/pages/_document.js b/web/pages/_document.js
index e99947f..d406c34 100644
--- a/web/pages/_document.js
+++ b/web/pages/_document.js
@@ -32,9 +32,9 @@ export default class MyDocument extends Document {
const styles = extractCritical(initialProps.html);
const muiCss = pageContext ? pageContext.sheetsRegistry.toString() : '';
- if (ctx.res.statusCode < 200 || ctx.res.statusCode >= 400) {
- return { ...initialProps, ...styles, muiCss, headTags };
- }
+ // if (ctx.res.statusCode < 200 || ctx.res.statusCode >= 400) {
+ // return { ...initialProps, ...styles, muiCss, headTags };
+ // }
return {
...initialProps,
diff --git a/web/pages/index.js b/web/pages/index.js
index a0ca893..ddf3b55 100644
--- a/web/pages/index.js
+++ b/web/pages/index.js
@@ -28,9 +28,9 @@ export default () => (
Hello, Welcome to Total React Starter:
-
+