From 4b1af5788d549985825b989154fc5e7dca163b32 Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Sun, 12 May 2019 00:26:55 +0900 Subject: [PATCH 01/50] no-console, no-empty is false --- frontend/tslint.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontend/tslint.json b/frontend/tslint.json index 9920293e2..62d49eb49 100644 --- a/frontend/tslint.json +++ b/frontend/tslint.json @@ -12,6 +12,8 @@ true, "ignore-same-line" ], + "no-console": false, + "no-empty": false, "no-unused-expression": [ true, "allow-fast-null-checks" From 22b60722a74eddb402e8875411b9473c47d4b374 Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Sun, 12 May 2019 09:04:40 +0900 Subject: [PATCH 02/50] refactor: replace es6 --- frontend/src/api/RestClient.ts | 57 +++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/frontend/src/api/RestClient.ts b/frontend/src/api/RestClient.ts index bdd3bac48..54834dd74 100644 --- a/frontend/src/api/RestClient.ts +++ b/frontend/src/api/RestClient.ts @@ -1,80 +1,87 @@ +import axios, { AxiosInstance, AxiosResponse, AxiosError } from "axios"; + export default class RestClient { - axios: any; + public axios: AxiosInstance; constructor(baseUrl: string) { - const axiosBase = require("axios"); - const csrfToken = (document.querySelector("meta[name=csrf-token]")).content; + const csrfToken = (document.querySelector("meta[name=csrf-token]") as HTMLMetaElement).content; - this.axios = axiosBase.create({ + this.axios = axios.create({ baseURL: baseUrl, timeout: 1000, headers: { "Content-Type": "application/json", - "X-CSRF-TOKEN": csrfToken, - }, + "X-CSRF-TOKEN": csrfToken + } }); } - get( + public get( path: string, params: object, successed: (res: object) => void, errored: (res: object) => void, - always = () => {} + always: () => any = () => {} ) { return this.axios - .get(path, { params: params }) - .then((result: object) => { - console.log(`GET ${this.axios.baseURL}/${path}`); + .get(path, { params }) + .then((result: AxiosResponse) => { + console.log(`GET ${result.config.url}`); + if (params) console.log(`Params: ${JSON.stringify(params)}`); console.log(`result: ${JSON.stringify(result)}`); successed(result); }) - .catch((error: object) => { - console.log(`ERROR! GET ${this.axios.baseURL}/${path}`); + .catch((error: AxiosError) => { + console.log(`ERROR! GET ${error.config.url}`); + if (params) console.log(`ERROR! Params: ${JSON.stringify(params)}`); console.log(`error: ${JSON.stringify(error)}`); errored(error); }) .then(always()); } - post( + public post( path: string, params: object, successed: (res: object) => void, errored: (res: object) => void, - always = () => {} + always: () => any = () => {} ) { return this.axios .post(path, params) - .then((result: object) => { - console.log(`POST ${this.axios.baseURL}/${path}`); + .then((result: AxiosResponse) => { + console.log(`POST ${result.config.url}`); + if (params) console.log(`Params: ${JSON.stringify(params)}`); console.log(`result: ${result}`); successed(result); }) - .catch((error: object) => { - console.log(`ERROR! POST ${this.axios.baseURL}/${path}`); + .catch((error: AxiosError) => { + console.log(`ERROR! POST ${error.config.url}`); + if (params) console.log(`ERROR! Params: ${JSON.stringify(params)}`); console.log(`error: ${error}`); errored(error); }) .then(always()); } - delete( + public delete( path: string, params: object, successed: (res: object) => void, errored: (res: object) => void, - always = () => {} + always: () => any = () => {} ) { return this.axios .delete(path, { data: { params } }) - .then((result: object) => { - console.log(`DELETE ${this.axios.baseURL}/${path}`); + .then((result: AxiosResponse) => { + console.log(`DELETE ${result.config.url}`); + if (params) console.log(`Params: ${JSON.stringify(params)}`); console.log(`result: ${result}`); successed(result); }) - .catch((error: object) => { - console.log(`ERROR! DELETE ${this.axios.baseURL}/${path}`); + .catch((error: AxiosError) => { + console.log(`ERROR! DELETE ${error.config.url}`); + if (params) console.log(`ERROR! Params: ${JSON.stringify(params)}`); console.log(`error: ${error}`); errored(error); }) From 35698a218cbcc5bb4e4fbff9c0a602c5db9e0f20 Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Sun, 12 May 2019 09:13:48 +0900 Subject: [PATCH 03/50] set class property as public --- frontend/src/api/ContactApi.ts | 9 +++++-- frontend/src/models/ContactModel.ts | 41 +++++++++++++++-------------- frontend/src/stores/ContactStore.ts | 4 +-- frontend/src/stores/RootStore.ts | 2 +- 4 files changed, 31 insertions(+), 25 deletions(-) diff --git a/frontend/src/api/ContactApi.ts b/frontend/src/api/ContactApi.ts index 0105fb520..73e410379 100644 --- a/frontend/src/api/ContactApi.ts +++ b/frontend/src/api/ContactApi.ts @@ -1,13 +1,18 @@ import RestClient from "./RestClient"; export default class ContactApi { - restClient: RestClient; + public restClient: RestClient; constructor(restClient: RestClient) { this.restClient = restClient; } - saveContact(json: object, succussed: (res: object) => void, errored: (err: object) => void, always = () => {}) { + public saveContact( + json: object, + succussed: (res: object) => void, + errored: (err: object) => void, + always = () => {} + ) { return this.restClient.post("/api/v1/contacts", json, succussed, errored, always); } } diff --git a/frontend/src/models/ContactModel.ts b/frontend/src/models/ContactModel.ts index 098273c48..12987dd36 100644 --- a/frontend/src/models/ContactModel.ts +++ b/frontend/src/models/ContactModel.ts @@ -2,17 +2,17 @@ import { computed } from "mobx"; import ContactStore from "../stores/ContactStore"; export default class ContactModel { - store: ContactStore; + public store: ContactStore; - id: number; - readable: boolean; - corner: number; - message: string; - nickname?: string; - name?: string; - email: string; - department: number; - grade: number; + public id: number; + public readable: boolean; + public corner: number; + public message: string; + public nickname?: string; + public name?: string; + public email: string; + public department: number; + public grade: number; constructor(store: ContactStore, json: any) { this.store = store; @@ -29,23 +29,24 @@ export default class ContactModel { this.grade = grade; } - save(successed: (res: object) => void, failed: (res: object) => void) { + public save(successed: (res: object) => void, failed: (res: object) => void) { console.log(this.toJson); return this.store.transportLayer.saveContact(this.toJson, successed, failed); } @computed get toJson() { + const { id, readable, corner, message, nickname, name, email, department, grade } = this; return { - id: this.id, - readable: this.readable, - corner: this.corner, - message: this.message, - nickname: this.nickname, - name: this.name, - email: this.email, - department: this.department, - grade: this.grade, + id, + readable, + corner, + message, + nickname, + name, + email, + department, + grade }; } } diff --git a/frontend/src/stores/ContactStore.ts b/frontend/src/stores/ContactStore.ts index 1ad536d00..0648be0c7 100644 --- a/frontend/src/stores/ContactStore.ts +++ b/frontend/src/stores/ContactStore.ts @@ -2,13 +2,13 @@ import ContactApi from "../api/ContactApi"; import ContactModel from "../models/ContactModel"; export default class ContactStore { - transportLayer: ContactApi; + public transportLayer: ContactApi; constructor(transportLayer: ContactApi) { this.transportLayer = transportLayer; } - createContact(json: object) { + public createContact(json: object) { return new ContactModel(this, json); } } diff --git a/frontend/src/stores/RootStore.ts b/frontend/src/stores/RootStore.ts index 25812464c..a610cbbbc 100644 --- a/frontend/src/stores/RootStore.ts +++ b/frontend/src/stores/RootStore.ts @@ -3,7 +3,7 @@ import ContactApi from "../api/ContactApi"; import RestClient from "../api/RestClient"; export default class RootStore { - contactStore: ContactStore; + public contactStore: ContactStore; constructor(baseUrl: string) { const restClient = new RestClient(baseUrl); From 4df6b2a8098fa316fa673e81872a6d3e4a019640 Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Sun, 12 May 2019 09:26:25 +0900 Subject: [PATCH 04/50] add props: onClick --- frontend/src/commons/ChkButtonBase.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/frontend/src/commons/ChkButtonBase.tsx b/frontend/src/commons/ChkButtonBase.tsx index 20c37f5f4..aed913edf 100644 --- a/frontend/src/commons/ChkButtonBase.tsx +++ b/frontend/src/commons/ChkButtonBase.tsx @@ -14,29 +14,29 @@ interface IPropsChkButtonBase extends IPropsCss { to?: string; text: string | React.ReactNode; name?: string; + onClick?: (e: any) => any; } const ChkButtonBase = (props: IPropsChkButtonBase) => { - const { to, text, name } = props; - const { color, bgcolor, border } = props; + const { to, text, name, color, bgcolor, border, onClick, ...otherProps } = props; if (to) { if (to.startsWith("http")) { return ( - + {text} ); } else { return ( - + {text} ); } } else { return ( - + {text} ); From b93317046b739e98216efca12d93736d226e81aa Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Sun, 12 May 2019 09:29:43 +0900 Subject: [PATCH 05/50] refactoring --- frontend/src/components/ContactForm.tsx | 48 ++++++++++++------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/frontend/src/components/ContactForm.tsx b/frontend/src/components/ContactForm.tsx index 29f0d94ad..d47e39c18 100644 --- a/frontend/src/components/ContactForm.tsx +++ b/frontend/src/components/ContactForm.tsx @@ -1,16 +1,15 @@ import * as React from "react"; import styled from "styled-components"; -import { ChkButtonBase } from "../commons/ChkButtonBase"; -import { chkColors } from "../commons/color"; import ContactStore from "../stores/ContactStore"; +import ChkButtonBase from "../commons/ChkButtonBase"; -type Prop = { +interface IProp { contactStore: ContactStore; successed: (res: object) => void; failed: (res: object) => void; -}; +} -type State = { +interface IState { name: string; corner?: number; department?: number; @@ -19,10 +18,10 @@ type State = { nickname: string; message: string; readable: boolean; -}; +} -export default class ContactForm extends React.Component { - constructor(props: Prop) { +export default class ContactForm extends React.Component { + constructor(props: IProp) { super(props); this.state = { name: "", @@ -32,15 +31,15 @@ export default class ContactForm extends React.Component { email: "", nickname: "", message: "", - readable: false, + readable: false }; this.createContact = this.createContact.bind(this); } - render() { + public render() { return ( -
+ { this.setState({ corner: e.target.value })} + onChange={(e: any) => + this.setState({ + corner: e.target.value + }) + } required > @@ -82,7 +85,11 @@ export default class ContactForm extends React.Component { this.setState({ grade: e.target.value })} + onChange={(e: any) => + this.setState({ + grade: e.target.value + }) + } required > @@ -136,12 +143,12 @@ export default class ContactForm extends React.Component { ラジオ内でメッセージを読み上げてもいい場合はチェックをつけてください - 送信 + ); } - createContact(e: any) { + public createContact(e: any) { e.preventDefault(); const { contactStore } = this.props; @@ -190,7 +197,7 @@ const ContactFormSelect = styled.select` color: #00afec; `; -const ContactFormSelectHalf = ContactFormSelect.extend` +const ContactFormSelectHalf = styled(ContactFormSelect)` width: 50%; `; @@ -219,11 +226,4 @@ const ContactFormCheckbox = styled.input` margin-right: 10px; `; -const ContactFormButton = ChkButtonBase.extend` - background-color: ${chkColors.orange}; - width: 30%; - margin-top: 40px; - margin-left: auto; - margin-right: auto; - border-radius: 20px; -`; +const ContactFormButton = styled(ChkButtonBase)``; From 869c389af418bc9961b5497c4c5972602d9e8469 Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Fri, 17 May 2019 20:27:03 +0900 Subject: [PATCH 06/50] upgrade --- frontend/yarn.lock | 78 ++++++++++++++++++++++++++++------------------ 1 file changed, 48 insertions(+), 30 deletions(-) diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 143df6b3b..abca3c141 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -66,26 +66,26 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.18.tgz#1d3ca764718915584fcd9f6344621b7672665c67" "@types/prop-types@*": - version "15.5.8" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.5.8.tgz#8ae4e0ea205fe95c3901a5a1df7f66495e3a56ce" + version "15.7.1" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.1.tgz#f1a11e7babb0c3cad68100be381d1e064c68f1f6" "@types/react-dom@^16.0.5": - version "16.0.11" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.0.11.tgz#bd10ccb0d9260343f4b9a49d4f7a8330a5c1f081" + version "16.8.4" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.8.4.tgz#7fb7ba368857c7aa0f4e4511c4710ca2c5a12a88" dependencies: "@types/react" "*" "@types/react-router-dom@^4.2.7": - version "4.3.1" - resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-4.3.1.tgz#71fe2918f8f60474a891520def40a63997dafe04" + version "4.3.3" + resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-4.3.3.tgz#7837e3e9fefbc84a8f6c8a51dca004f4e83e94e3" dependencies: "@types/history" "*" "@types/react" "*" "@types/react-router" "*" "@types/react-router@*": - version "4.4.3" - resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-4.4.3.tgz#ea68b4021cb576866f83365b2201411537423d50" + version "5.0.0" + resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.0.0.tgz#22ae8f55d8af770ea1f755218936f01bfe1bfe27" dependencies: "@types/history" "*" "@types/react" "*" @@ -97,8 +97,8 @@ "@types/react" "*" "@types/react@*", "@types/react@^16.3.16": - version "16.7.20" - resolved "https://registry.yarnpkg.com/@types/react/-/react-16.7.20.tgz#13ae752c012710d0fa800985ca809814b51d3b58" + version "16.8.17" + resolved "https://registry.yarnpkg.com/@types/react/-/react-16.8.17.tgz#f287b76a5badb93bc9aa3f54521a3eb53d6c2374" dependencies: "@types/prop-types" "*" csstype "^2.2.0" @@ -1943,8 +1943,8 @@ csso@~2.3.1: source-map "^0.5.3" csstype@^2.2.0: - version "2.6.1" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.1.tgz#4cfbf637a577497036ebcd7e32647ef19a0b8076" + version "2.6.4" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.4.tgz#d585a6062096e324e7187f80e04f92bd0f00e37f" cyclist@~0.2.2: version "0.2.2" @@ -3015,8 +3015,14 @@ hmac-drbg@^1.0.0: minimalistic-crypto-utils "^1.0.1" hoist-non-react-statics@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.0.tgz#d2ca2dfc19c5a91c5a6615ce8e564ef0347e2a40" + version "2.5.5" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz#c5903cf409c0dfd908f388e619d86b9c1174cb47" + +hoist-non-react-statics@^3.0.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.0.tgz#b09178f0122184fb95acf525daaecb4d8f45958b" + dependencies: + react-is "^16.7.0" home-or-tmp@^2.0.0: version "2.0.0" @@ -3848,7 +3854,7 @@ long@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/long/-/long-3.2.0.tgz#d821b7138ca1cb581c172990ef14db200b5c474b" -loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1: +loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" dependencies: @@ -4122,15 +4128,15 @@ mkdirp@0.5.x, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: minimist "0.0.8" mobx-react@^5.2.3: - version "5.2.3" - resolved "https://registry.yarnpkg.com/mobx-react/-/mobx-react-5.2.3.tgz#cdf6141c2fe63377c5813cbd254e8ce0d4676631" + version "5.4.4" + resolved "https://registry.yarnpkg.com/mobx-react/-/mobx-react-5.4.4.tgz#b3de9c6eabcd0ed8a40036888cb0221ab9568b80" dependencies: - hoist-non-react-statics "^2.5.0" + hoist-non-react-statics "^3.0.0" react-lifecycles-compat "^3.0.2" mobx@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/mobx/-/mobx-5.0.3.tgz#53b97f2a0f9b0dd7774c96249f81bf2d513d8e1c" + version "5.9.4" + resolved "https://registry.yarnpkg.com/mobx/-/mobx-5.9.4.tgz#1dee92aba33f67b7baeeb679e3bd376a12e55812" move-concurrently@^1.0.1: version "1.0.1" @@ -5014,7 +5020,7 @@ promise@^7.1.1: dependencies: asap "~2.0.3" -prop-types@^15.3.0, prop-types@^15.6.2: +prop-types@^15.3.0: version "15.6.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102" dependencies: @@ -5029,6 +5035,14 @@ prop-types@^15.5.4, prop-types@^15.6.1: loose-envify "^1.3.1" object-assign "^4.1.1" +prop-types@^15.6.2: + version "15.7.2" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" + dependencies: + loose-envify "^1.4.0" + object-assign "^4.1.1" + react-is "^16.8.1" + proxy-addr@~2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.4.tgz#ecfc733bf22ff8c6f407fa275327b9ab67e48b93" @@ -5160,18 +5174,22 @@ rc@^1.1.7: strip-json-comments "~2.0.1" react-dom@^16.4.0: - version "16.7.0" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.7.0.tgz#a17b2a7ca89ee7390bc1ed5eb81783c7461748b8" + version "16.8.6" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.8.6.tgz#71d6303f631e8b0097f56165ef608f051ff6e10f" dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" prop-types "^15.6.2" - scheduler "^0.12.0" + scheduler "^0.13.6" react-is@^16.6.0: version "16.7.0" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.7.0.tgz#c1bd21c64f1f1364c6f70695ec02d69392f41bfa" +react-is@^16.7.0, react-is@^16.8.1: + version "16.8.6" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16" + react-lifecycles-compat@^3.0.2: version "3.0.4" resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" @@ -5219,13 +5237,13 @@ react-twitter-widgets@^1.7.1: scriptjs "^2.5.8" react@^16.4.0: - version "16.7.0" - resolved "https://registry.yarnpkg.com/react/-/react-16.7.0.tgz#b674ec396b0a5715873b350446f7ea0802ab6381" + version "16.8.6" + resolved "https://registry.yarnpkg.com/react/-/react-16.8.6.tgz#ad6c3a9614fd3a4e9ef51117f54d888da01f2bbe" dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" prop-types "^15.6.2" - scheduler "^0.12.0" + scheduler "^0.13.6" read-chunk@^2.1.0: version "2.1.0" @@ -5530,9 +5548,9 @@ sax@^1.2.4, sax@~1.2.1: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" -scheduler@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.12.0.tgz#8ab17699939c0aedc5a196a657743c496538647b" +scheduler@^0.13.6: + version "0.13.6" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.13.6.tgz#466a4ec332467b31a91b9bf74e5347072e4cd889" dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" From 0d60e53596a0e4123f7ac45452222783abe6528d Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Sun, 19 May 2019 16:12:15 +0900 Subject: [PATCH 07/50] upgrade --- frontend/package.json | 44 ++++++++-------- frontend/yarn.lock | 114 ++++++++++++++++++++++++------------------ 2 files changed, 88 insertions(+), 70 deletions(-) diff --git a/frontend/package.json b/frontend/package.json index e4c09a9c9..d5a490688 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -12,44 +12,44 @@ "lint": "npx tslint --fix -c ./tslint.json 'src/**/*{.ts,.tsx}'" }, "devDependencies": { + "@types/react": "^16.8.17", + "@types/react-dom": "^16.8.4", + "@types/react-router-dom": "^4.3.3", + "@types/react-slick": "^0.23.4", + "@types/styled-components": "^4.1.6", "awesome-typescript-loader": "^5.0.0", "babel-loader": "^7.1.4", "babel-preset-es2015": "^6.24.1", "babel-preset-react": "^6.24.1", + "clean-webpack-plugin": "^1.0.0", "css-loader": "^0.28.11", + "file-loader": "^1.1.11", + "prettier": "^1.15.3", "source-map-loader": "^0.2.3", "style-loader": "^0.21.0", + "tslint": "^5.11.0", + "tslint-config-prettier": "^1.17.0", + "tslint-plugin-prettier": "^2.0.1", "typescript": "^3.4.5", + "url-loader": "^1.0.1", "webpack": "^4.10.2", - "webpack-cli": "^2.1.4" + "webpack-cli": "^2.1.4", + "webpack-dev-server": "^3.1.10", + "webpack-manifest-plugin": "^2.0.4", + "webpack-merge": "^4.1.4" }, "dependencies": { - "@types/react": "^16.3.16", - "@types/react-dom": "^16.0.5", - "@types/react-router-dom": "^4.2.7", - "@types/react-slick": "^0.23.4", - "@types/styled-components": "^4.1.6", "axios": "^0.18.0", "babel-polyfill": "^6.26.0", - "clean-webpack-plugin": "^1.0.0", - "file-loader": "^1.1.11", - "mobx": "^5.0.3", - "mobx-react": "^5.2.3", + "mobx": "^5.9.4", + "mobx-react": "^5.4.4", "normalize.css": "^8.0.0", - "prettier": "^1.15.3", - "react": "^16.4.0", - "react-dom": "^16.4.0", - "react-router-dom": "^4.3.1", + "react": "^16.8.6", + "react-dom": "^16.8.6", + "react-router-dom": "^5.0.0", "react-slick": "^0.24.0", "react-twitter-widgets": "^1.7.1", "slick-carousel": "^1.8.1", - "styled-components": "^4.1.3", - "tslint": "^5.11.0", - "tslint-config-prettier": "^1.17.0", - "tslint-plugin-prettier": "^2.0.1", - "url-loader": "^1.0.1", - "webpack-dev-server": "^3.1.10", - "webpack-manifest-plugin": "^2.0.4", - "webpack-merge": "^4.1.4" + "styled-components": "^4.1.3" } } diff --git a/frontend/yarn.lock b/frontend/yarn.lock index abca3c141..7082fd349 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -14,6 +14,12 @@ dependencies: "@babel/types" "^7.0.0" +"@babel/runtime@^7.1.2": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.4.4.tgz#dc2e34982eb236803aa27a07fea6857af1b9171d" + dependencies: + regenerator-runtime "^0.13.2" + "@babel/types@^7.0.0": version "7.3.0" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.3.0.tgz#61dc0b336a93badc02bf5f69c4cd8e1353f2ffc0" @@ -69,13 +75,13 @@ version "15.7.1" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.1.tgz#f1a11e7babb0c3cad68100be381d1e064c68f1f6" -"@types/react-dom@^16.0.5": +"@types/react-dom@^16.8.4": version "16.8.4" resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.8.4.tgz#7fb7ba368857c7aa0f4e4511c4710ca2c5a12a88" dependencies: "@types/react" "*" -"@types/react-router-dom@^4.2.7": +"@types/react-router-dom@^4.3.3": version "4.3.3" resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-4.3.3.tgz#7837e3e9fefbc84a8f6c8a51dca004f4e83e94e3" dependencies: @@ -96,7 +102,7 @@ dependencies: "@types/react" "*" -"@types/react@*", "@types/react@^16.3.16": +"@types/react@*", "@types/react@^16.8.17": version "16.8.17" resolved "https://registry.yarnpkg.com/@types/react/-/react-16.8.17.tgz#f287b76a5badb93bc9aa3f54521a3eb53d6c2374" dependencies: @@ -1817,6 +1823,13 @@ 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" + dependencies: + fbjs "^0.8.0" + gud "^1.0.0" + cross-spawn@^5.0.1: version "5.1.0" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" @@ -2518,7 +2531,7 @@ faye-websocket@~0.11.1: dependencies: websocket-driver ">=0.5.1" -fbjs@^0.8.16: +fbjs@^0.8.0, fbjs@^0.8.16: version "0.8.17" resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.17.tgz#c4d598ead6949112653d6588b01a5cdcd9f90fdd" dependencies: @@ -2909,6 +2922,10 @@ grouped-queue@^0.3.3: dependencies: lodash "^4.17.2" +gud@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/gud/-/gud-1.0.0.tgz#a489581b17e6a70beca9abe3ae57de7a499852c0" + handle-thing@^1.2.5: version "1.2.5" resolved "http://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz#fd7aad726bf1a5fd16dfc29b2f7a6601d27139c4" @@ -2996,15 +3013,16 @@ hash.js@^1.0.0, hash.js@^1.0.3: inherits "^2.0.3" minimalistic-assert "^1.0.0" -history@^4.7.2: - version "4.7.2" - resolved "https://registry.yarnpkg.com/history/-/history-4.7.2.tgz#22b5c7f31633c5b8021c7f4a8a954ac139ee8d5b" +history@^4.9.0: + version "4.9.0" + resolved "https://registry.yarnpkg.com/history/-/history-4.9.0.tgz#84587c2068039ead8af769e9d6a6860a14fa1bca" dependencies: - invariant "^2.2.1" + "@babel/runtime" "^7.1.2" loose-envify "^1.2.0" resolve-pathname "^2.2.0" + tiny-invariant "^1.0.2" + tiny-warning "^1.0.0" value-equal "^0.4.0" - warning "^3.0.0" hmac-drbg@^1.0.0: version "1.0.1" @@ -3014,11 +3032,7 @@ hmac-drbg@^1.0.0: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -hoist-non-react-statics@^2.5.0: - version "2.5.5" - resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz#c5903cf409c0dfd908f388e619d86b9c1174cb47" - -hoist-non-react-statics@^3.0.0: +hoist-non-react-statics@^3.0.0, hoist-non-react-statics@^3.1.0: version "3.3.0" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.0.tgz#b09178f0122184fb95acf525daaecb4d8f45958b" dependencies: @@ -3231,7 +3245,7 @@ into-stream@^3.1.0: from2 "^2.1.1" p-is-promise "^1.1.0" -invariant@^2.2.1, invariant@^2.2.2, invariant@^2.2.4: +invariant@^2.2.2: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" dependencies: @@ -4127,14 +4141,14 @@ mkdirp@0.5.x, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: dependencies: minimist "0.0.8" -mobx-react@^5.2.3: +mobx-react@^5.4.4: version "5.4.4" resolved "https://registry.yarnpkg.com/mobx-react/-/mobx-react-5.4.4.tgz#b3de9c6eabcd0ed8a40036888cb0221ab9568b80" dependencies: hoist-non-react-statics "^3.0.0" react-lifecycles-compat "^3.0.2" -mobx@^5.0.3: +mobx@^5.9.4: version "5.9.4" resolved "https://registry.yarnpkg.com/mobx/-/mobx-5.9.4.tgz#1dee92aba33f67b7baeeb679e3bd376a12e55812" @@ -5027,7 +5041,7 @@ prop-types@^15.3.0: loose-envify "^1.3.1" object-assign "^4.1.1" -prop-types@^15.5.4, prop-types@^15.6.1: +prop-types@^15.5.4: version "15.6.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.1.tgz#36644453564255ddda391191fb3a125cbdf654ca" dependencies: @@ -5173,7 +5187,7 @@ rc@^1.1.7: minimist "^1.2.0" strip-json-comments "~2.0.1" -react-dom@^16.4.0: +react-dom@^16.8.6: version "16.8.6" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.8.6.tgz#71d6303f631e8b0097f56165ef608f051ff6e10f" dependencies: @@ -5194,28 +5208,32 @@ react-lifecycles-compat@^3.0.2: version "3.0.4" resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" -react-router-dom@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-4.3.1.tgz#4c2619fc24c4fa87c9fd18f4fb4a43fe63fbd5c6" +react-router-dom@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.0.0.tgz#542a9b86af269a37f0b87218c4c25ea8dcf0c073" dependencies: - history "^4.7.2" - invariant "^2.2.4" + "@babel/runtime" "^7.1.2" + history "^4.9.0" loose-envify "^1.3.1" - prop-types "^15.6.1" - react-router "^4.3.1" - warning "^4.0.1" + prop-types "^15.6.2" + react-router "5.0.0" + tiny-invariant "^1.0.2" + tiny-warning "^1.0.0" -react-router@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/react-router/-/react-router-4.3.1.tgz#aada4aef14c809cb2e686b05cee4742234506c4e" +react-router@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.0.0.tgz#349863f769ffc2fa10ee7331a4296e86bc12879d" dependencies: - history "^4.7.2" - hoist-non-react-statics "^2.5.0" - invariant "^2.2.4" + "@babel/runtime" "^7.1.2" + create-react-context "^0.2.2" + history "^4.9.0" + hoist-non-react-statics "^3.1.0" loose-envify "^1.3.1" path-to-regexp "^1.7.0" - prop-types "^15.6.1" - warning "^4.0.1" + prop-types "^15.6.2" + react-is "^16.6.0" + tiny-invariant "^1.0.2" + tiny-warning "^1.0.0" react-slick@^0.24.0: version "0.24.0" @@ -5236,7 +5254,7 @@ react-twitter-widgets@^1.7.1: prop-types "^15.3.0" scriptjs "^2.5.8" -react@^16.4.0: +react@^16.8.6: version "16.8.6" resolved "https://registry.yarnpkg.com/react/-/react-16.8.6.tgz#ad6c3a9614fd3a4e9ef51117f54d888da01f2bbe" dependencies: @@ -5339,6 +5357,10 @@ regenerator-runtime@^0.11.0: version "0.11.1" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" +regenerator-runtime@^0.13.2: + version "0.13.2" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz#32e59c9a6fb9b1a4aff09b4930ca2d4477343447" + regenerator-transform@^0.10.0: version "0.10.1" resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" @@ -6129,6 +6151,14 @@ timers-browserify@^2.0.4: dependencies: setimmediate "^1.0.4" +tiny-invariant@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.0.4.tgz#346b5415fd93cb696b0c4e8a96697ff590f92463" + +tiny-warning@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.2.tgz#1dfae771ee1a04396bdfde27a3adcebc6b648b28" + tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" @@ -6444,18 +6474,6 @@ vm-browserify@0.0.4: dependencies: indexof "0.0.1" -warning@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/warning/-/warning-3.0.0.tgz#32e5377cb572de4ab04753bdf8821c01ed605b7c" - dependencies: - loose-envify "^1.0.0" - -warning@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.1.tgz#66ce376b7fbfe8a887c22bdf0e7349d73d397745" - dependencies: - loose-envify "^1.0.0" - watchpack@^1.5.0: version "1.6.0" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00" From f301d59f1dbbab7ba3da6ea3143c6a2772ab16fa Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Sun, 19 May 2019 18:48:27 +0900 Subject: [PATCH 08/50] print params by table --- frontend/src/api/RestClient.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/frontend/src/api/RestClient.ts b/frontend/src/api/RestClient.ts index 54834dd74..2d26f41cd 100644 --- a/frontend/src/api/RestClient.ts +++ b/frontend/src/api/RestClient.ts @@ -27,13 +27,13 @@ export default class RestClient { .get(path, { params }) .then((result: AxiosResponse) => { console.log(`GET ${result.config.url}`); - if (params) console.log(`Params: ${JSON.stringify(params)}`); - console.log(`result: ${JSON.stringify(result)}`); + if (params) console.table(params); + console.log(`status: ${result.status}, statusText: ${result.statusText}`); successed(result); }) .catch((error: AxiosError) => { console.log(`ERROR! GET ${error.config.url}`); - if (params) console.log(`ERROR! Params: ${JSON.stringify(params)}`); + if (params) console.table(params); console.log(`error: ${JSON.stringify(error)}`); errored(error); }) @@ -51,13 +51,13 @@ export default class RestClient { .post(path, params) .then((result: AxiosResponse) => { console.log(`POST ${result.config.url}`); - if (params) console.log(`Params: ${JSON.stringify(params)}`); - console.log(`result: ${result}`); + if (params) console.table(params); + console.log(`status: ${result.status}, statusText: ${result.statusText}`); successed(result); }) .catch((error: AxiosError) => { console.log(`ERROR! POST ${error.config.url}`); - if (params) console.log(`ERROR! Params: ${JSON.stringify(params)}`); + if (params) console.table(params); console.log(`error: ${error}`); errored(error); }) @@ -75,13 +75,13 @@ export default class RestClient { .delete(path, { data: { params } }) .then((result: AxiosResponse) => { console.log(`DELETE ${result.config.url}`); - if (params) console.log(`Params: ${JSON.stringify(params)}`); - console.log(`result: ${result}`); + if (params) console.table(params); + console.log(`status: ${result.status}, statusText: ${result.statusText}`); successed(result); }) .catch((error: AxiosError) => { console.log(`ERROR! DELETE ${error.config.url}`); - if (params) console.log(`ERROR! Params: ${JSON.stringify(params)}`); + if (params) console.table(params); console.log(`error: ${error}`); errored(error); }) From 9c68a74560ddc3380ced23412f266688c4c70732 Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Sun, 19 May 2019 18:48:52 +0900 Subject: [PATCH 09/50] add TextInput --- frontend/src/components/Forms/TextInput.tsx | 89 +++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 frontend/src/components/Forms/TextInput.tsx diff --git a/frontend/src/components/Forms/TextInput.tsx b/frontend/src/components/Forms/TextInput.tsx new file mode 100644 index 000000000..f21703f55 --- /dev/null +++ b/frontend/src/components/Forms/TextInput.tsx @@ -0,0 +1,89 @@ +import * as React from "react"; +import styled, { css } from "styled-components"; + +type TextInputType = "text" | "password" | "email"; + +export interface ITextInputProps { + value?: string; + name?: string; + placeholder?: string; + type?: TextInputType; + multiLine?: boolean; + onChange?(value: string): void; +} + +export default ({ value, name, placeholder, multiLine, onChange, type = "text" }: ITextInputProps) => { + const [currentInputValue, setCurrentInputValue] = React.useState(""); + const [inFocus, setInFocus] = React.useState(false); + + const handleChange = React.useCallback((e: React.ChangeEvent) => { + const data = e.target.value; + setCurrentInputValue(data); + console.log(data); + + if (onChange) { + onChange(data); + } + }, []); + + const handleFocus = React.useCallback(() => { + setInFocus(true); + }, []); + + // call: did handleFoucus + const handleBlur = React.useCallback(() => { + console.log(inFocus); + setInFocus(false); + }, []); + + React.useEffect( + () => { + if (value != null) { + setCurrentInputValue(value); + } + }, + [value] + ); + + const props = { + type, + placeholder, + onFocus: handleFocus, + onBlur: handleBlur, + id: name, + value: currentInputValue, + onChange: handleChange, + styledFocus: inFocus ? true : false + }; + + return multiLine ? : ; +}; + +// TODO: focus時とそうでない時で背景かアウトラインのデザインを変える +const style = css` + margin: 5px; + margin-left: 0; + margin-right: 0; + padding: 5px; + padding-left: 30px; + line-height: 1.5rem; + width: 100%; + border: 2px solid #00afec; + border-radius: 1.5rem; + + ::placeholder { + color: #00afec; + opacity: 1; + } + ::-ms-input-placeholder { + color: #00afec; + } +`; + +const StyledInput = styled.input` + ${style}; +`; + +const StyledTextarea = styled.textarea` + ${style} +`; From bc69f2ee379c1da1a148f0d532691fae01a82fdb Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Sun, 19 May 2019 19:06:27 +0900 Subject: [PATCH 10/50] remove console.log --- frontend/src/components/Forms/TextInput.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/src/components/Forms/TextInput.tsx b/frontend/src/components/Forms/TextInput.tsx index f21703f55..2af1ffecf 100644 --- a/frontend/src/components/Forms/TextInput.tsx +++ b/frontend/src/components/Forms/TextInput.tsx @@ -32,7 +32,6 @@ export default ({ value, name, placeholder, multiLine, onChange, type = "text" } // call: did handleFoucus const handleBlur = React.useCallback(() => { - console.log(inFocus); setInFocus(false); }, []); From c3d22ec8b3a5594cdb220afd88d2b5050cf79efb Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Sun, 19 May 2019 19:29:22 +0900 Subject: [PATCH 11/50] upgrade styled-components --- frontend/package.json | 4 ++-- frontend/yarn.lock | 33 ++++++++++++++++++--------------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/frontend/package.json b/frontend/package.json index d5a490688..49f14dc29 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -16,7 +16,7 @@ "@types/react-dom": "^16.8.4", "@types/react-router-dom": "^4.3.3", "@types/react-slick": "^0.23.4", - "@types/styled-components": "^4.1.6", + "@types/styled-components": "^4.1.15", "awesome-typescript-loader": "^5.0.0", "babel-loader": "^7.1.4", "babel-preset-es2015": "^6.24.1", @@ -50,6 +50,6 @@ "react-slick": "^0.24.0", "react-twitter-widgets": "^1.7.1", "slick-carousel": "^1.8.1", - "styled-components": "^4.1.3" + "styled-components": "^4.2.0" } } diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 7082fd349..eac4b0815 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -67,10 +67,6 @@ version "4.7.2" resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.2.tgz#0e670ea254d559241b6eeb3894f8754991e73220" -"@types/node@*": - version "10.12.18" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.18.tgz#1d3ca764718915584fcd9f6344621b7672665c67" - "@types/prop-types@*": version "15.7.1" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.1.tgz#f1a11e7babb0c3cad68100be381d1e064c68f1f6" @@ -81,6 +77,13 @@ dependencies: "@types/react" "*" +"@types/react-native@*": + version "0.57.57" + resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.57.57.tgz#4b59068acf6e542ac8e1e02e8a639b47e3e02c02" + dependencies: + "@types/prop-types" "*" + "@types/react" "*" + "@types/react-router-dom@^4.3.3": version "4.3.3" resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-4.3.3.tgz#7837e3e9fefbc84a8f6c8a51dca004f4e83e94e3" @@ -109,12 +112,12 @@ "@types/prop-types" "*" csstype "^2.2.0" -"@types/styled-components@^4.1.6": - version "4.1.6" - resolved "https://registry.yarnpkg.com/@types/styled-components/-/styled-components-4.1.6.tgz#9aa1d47dbc6bae540083869bcc6c639c6e9af0fe" +"@types/styled-components@^4.1.15": + version "4.1.15" + resolved "https://registry.yarnpkg.com/@types/styled-components/-/styled-components-4.1.15.tgz#532b6738ec633b2911e0470522c23e3c658952f2" dependencies: - "@types/node" "*" "@types/react" "*" + "@types/react-native" "*" csstype "^2.2.0" "@webassemblyjs/ast@1.5.9": @@ -3978,9 +3981,9 @@ mem@^4.0.0: mimic-fn "^1.0.0" p-is-promise "^1.1.0" -memoize-one@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-4.1.0.tgz#a2387c58c03fff27ca390c31b764a79addf3f906" +memoize-one@^5.0.0: + version "5.0.4" + resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.0.4.tgz#005928aced5c43d890a4dfab18ca908b0ec92cbc" memory-fs@^0.4.0, memory-fs@~0.4.1: version "0.4.1" @@ -6029,16 +6032,16 @@ style-loader@^0.21.0: loader-utils "^1.1.0" schema-utils "^0.4.5" -styled-components@^4.1.3: - version "4.1.3" - resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-4.1.3.tgz#4472447208e618b57e84deaaeb6acd34a5e0fe9b" +styled-components@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-4.2.0.tgz#811fbbec4d64c7189f6c7482b9eb6fefa7fefef7" dependencies: "@babel/helper-module-imports" "^7.0.0" "@emotion/is-prop-valid" "^0.7.3" "@emotion/unitless" "^0.7.0" babel-plugin-styled-components ">= 1" css-to-react-native "^2.2.2" - memoize-one "^4.0.0" + memoize-one "^5.0.0" prop-types "^15.5.4" react-is "^16.6.0" stylis "^3.5.0" From 08db1afce129a9a6e2ef9a361a6adef3a8897c8f Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Sun, 19 May 2019 19:40:56 +0900 Subject: [PATCH 12/50] add Select --- frontend/src/components/Forms/Select.tsx | 71 ++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 frontend/src/components/Forms/Select.tsx diff --git a/frontend/src/components/Forms/Select.tsx b/frontend/src/components/Forms/Select.tsx new file mode 100644 index 000000000..e10451287 --- /dev/null +++ b/frontend/src/components/Forms/Select.tsx @@ -0,0 +1,71 @@ +import * as React from "react"; +import styled from "styled-components"; + +// TODO: childrenの型が分からない +export interface ITextInputProps { + children: any; + value?: string; + name?: string; + onChange?(value: string): void; +} + +export default ({ value, name, onChange, children }: ITextInputProps) => { + console.log(typeof children); + const [currentValue, setCurrentValue] = React.useState(value); + const [inFocus, setInFocus] = React.useState(false); + + const handleChange = React.useCallback((e: React.ChangeEvent) => { + const data = e.target.value; + setCurrentValue(data); + console.log(data); + + if (onChange) { + onChange(data); + } + }, []); + + const handleFocus = React.useCallback(() => { + setInFocus(true); + }, []); + + // call: did handleFoucus + const handleBlur = React.useCallback(() => { + setInFocus(false); + }, []); + + React.useEffect( + () => { + if (value != null) { + setCurrentValue(value); + } + }, + [value] + ); + + const props = { + onFocus: handleFocus, + onBlur: handleBlur, + id: name, + value: currentValue, + onChange: handleChange, + styledFocus: inFocus ? true : false + }; + + return {children}; +}; + +// TODO: focus時とそうでない時で背景かアウトラインのデザインを変える +const StyledSelect = styled.select` + -moz-appearance: none; + -webkit-appearance: none; + appearance: none; + width: 100%; + line-height: 1.5rem; + padding: 5px; + padding-left: 30px; + border: 2px solid #00afec; + border-radius: 1.5rem; + background: none transparent; + vertical-align: middle; + color: #00afec; +`; From 942ff62b6833ee324dc20fba840ec522036d688f Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Mon, 20 May 2019 01:05:59 +0900 Subject: [PATCH 13/50] add rows to textarea --- frontend/src/components/ContactForm2.tsx | 117 ++++++++++++++++++++ frontend/src/components/Forms/CheckBox.tsx | 70 ++++++++++++ frontend/src/components/Forms/TextInput.tsx | 2 +- 3 files changed, 188 insertions(+), 1 deletion(-) create mode 100644 frontend/src/components/ContactForm2.tsx create mode 100644 frontend/src/components/Forms/CheckBox.tsx diff --git a/frontend/src/components/ContactForm2.tsx b/frontend/src/components/ContactForm2.tsx new file mode 100644 index 000000000..8af7ccb34 --- /dev/null +++ b/frontend/src/components/ContactForm2.tsx @@ -0,0 +1,117 @@ +import * as React from "react"; +import styled from "styled-components"; + +// import ContactStore from "../stores/ContactStore"; + +// import ChkButtonBase from "../commons/ChkButtonBase"; + +import TextInput from "./Forms/TextInput"; +import Select from "./Forms/Select"; + +// interface IProp { +// contactStore: ContactStore; +// successed: (res: object) => void; +// failed: (res: object) => void; +// } + +// message: string; +// readable: boolean; + +// props: IProp + +export default () => { + // this.createContact = this.createContact.bind(this); + const [name, setName] = React.useState(""); + const [corner, setCorner] = React.useState(""); + const [department, setDepartment] = React.useState(""); + const [grade, setGrade] = React.useState(""); + const [email, setEmail] = React.useState(""); + const [nickname, setNickname] = React.useState(""); + + const [message, setMessage] = React.useState(""); + // const [nickname, setNickname] = React.useState(""); + + return ( +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {/* */} + + ); +}; + +// public createContact(e: any) { +// e.preventDefault(); + +// const { contactStore } = this.props; +// const contact = contactStore.createContact(this.state); + +// contact.save(this.props.successed, this.props.failed); +// } +// } + +// const ContactFormCheckbox = styled.input` +// margin-left: 20px; +// margin-right: 10px; +// `; + +// const ContactFormButton = styled(ChkButtonBase)``; + +const InlineWrapper = styled.div` + margin: 20px; +`; + +const InlineHalfWrapper = styled.div` + width: 50%; + display: inline-block; +`; diff --git a/frontend/src/components/Forms/CheckBox.tsx b/frontend/src/components/Forms/CheckBox.tsx new file mode 100644 index 000000000..a60b528cd --- /dev/null +++ b/frontend/src/components/Forms/CheckBox.tsx @@ -0,0 +1,70 @@ +import * as React from "react"; +import styled from "styled-components"; + +// TODO: childrenの型が分からない +export interface ITextInputProps { + children: any; + value?: string; + name?: string; + onChange?(value: string): void; +} + +export default ({ value, name, onChange, children }: ITextInputProps) => { + const [currentValue, setCurrentValue] = React.useState(value); + const [inFocus, setInFocus] = React.useState(false); + + const handleChange = React.useCallback((e: React.ChangeEvent) => { + const data = e.target.value; + setCurrentValue(data); + console.log(data); + + if (onChange) { + onChange(data); + } + }, []); + + const handleFocus = React.useCallback(() => { + setInFocus(true); + }, []); + + // call: did handleFoucus + const handleBlur = React.useCallback(() => { + setInFocus(false); + }, []); + + React.useEffect( + () => { + if (value != null) { + setCurrentValue(value); + } + }, + [value] + ); + + const props = { + onFocus: handleFocus, + onBlur: handleBlur, + id: name, + value: currentValue, + onChange: handleChange, + styledFocus: inFocus ? true : false + }; + + return {children}; +}; + +// TODO: focus時とそうでない時で背景かアウトラインのデザインを変える +const StyledSelect = styled.select` + -moz-appearance: none; + -webkit-appearance: none; + appearance: none; + width: 100%; + line-height: 1.5rem; + padding: 5px; + padding-left: 30px; + border: 2px solid #00afec; + border-radius: 1.5rem; + background: none transparent; + vertical-align: middle; + color: #00afec; +`; diff --git a/frontend/src/components/Forms/TextInput.tsx b/frontend/src/components/Forms/TextInput.tsx index 2af1ffecf..060c6705c 100644 --- a/frontend/src/components/Forms/TextInput.tsx +++ b/frontend/src/components/Forms/TextInput.tsx @@ -55,7 +55,7 @@ export default ({ value, name, placeholder, multiLine, onChange, type = "text" } styledFocus: inFocus ? true : false }; - return multiLine ? : ; + return multiLine ? : ; }; // TODO: focus時とそうでない時で背景かアウトラインのデザインを変える From 4bc302159df17c152bf9870ed7d0a85b45332476 Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Mon, 20 May 2019 01:22:05 +0900 Subject: [PATCH 14/50] remove console.log --- frontend/src/components/Forms/Select.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/frontend/src/components/Forms/Select.tsx b/frontend/src/components/Forms/Select.tsx index e10451287..432735f5d 100644 --- a/frontend/src/components/Forms/Select.tsx +++ b/frontend/src/components/Forms/Select.tsx @@ -10,14 +10,12 @@ export interface ITextInputProps { } export default ({ value, name, onChange, children }: ITextInputProps) => { - console.log(typeof children); const [currentValue, setCurrentValue] = React.useState(value); const [inFocus, setInFocus] = React.useState(false); const handleChange = React.useCallback((e: React.ChangeEvent) => { const data = e.target.value; setCurrentValue(data); - console.log(data); if (onChange) { onChange(data); From 383c812c7f8f305ec5378b2e736b5b8a9e083a2b Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Mon, 20 May 2019 01:22:25 +0900 Subject: [PATCH 15/50] fix --- frontend/src/components/Forms/CheckBox.tsx | 49 ++++++++++------------ 1 file changed, 21 insertions(+), 28 deletions(-) diff --git a/frontend/src/components/Forms/CheckBox.tsx b/frontend/src/components/Forms/CheckBox.tsx index a60b528cd..2fffa8155 100644 --- a/frontend/src/components/Forms/CheckBox.tsx +++ b/frontend/src/components/Forms/CheckBox.tsx @@ -1,22 +1,20 @@ import * as React from "react"; import styled from "styled-components"; -// TODO: childrenの型が分からない export interface ITextInputProps { - children: any; - value?: string; + children: string; + checked: boolean; name?: string; - onChange?(value: string): void; + onChange?(value: boolean): void; } -export default ({ value, name, onChange, children }: ITextInputProps) => { - const [currentValue, setCurrentValue] = React.useState(value); +export default ({ checked, name, onChange, children }: ITextInputProps) => { + const [currentChecked, setCurrentChecked] = React.useState(checked); const [inFocus, setInFocus] = React.useState(false); - const handleChange = React.useCallback((e: React.ChangeEvent) => { - const data = e.target.value; - setCurrentValue(data); - console.log(data); + const handleChange = React.useCallback((e: React.ChangeEvent) => { + const data = e.target.checked; + setCurrentChecked(data); if (onChange) { onChange(data); @@ -34,37 +32,32 @@ export default ({ value, name, onChange, children }: ITextInputProps) => { React.useEffect( () => { - if (value != null) { - setCurrentValue(value); + if (checked !== null) { + setCurrentChecked(checked); } }, - [value] + [checked] ); const props = { onFocus: handleFocus, onBlur: handleBlur, id: name, - value: currentValue, + checked: currentChecked, onChange: handleChange, styledFocus: inFocus ? true : false }; - return {children}; + return ( + + ); }; // TODO: focus時とそうでない時で背景かアウトラインのデザインを変える -const StyledSelect = styled.select` - -moz-appearance: none; - -webkit-appearance: none; - appearance: none; - width: 100%; - line-height: 1.5rem; - padding: 5px; - padding-left: 30px; - border: 2px solid #00afec; - border-radius: 1.5rem; - background: none transparent; - vertical-align: middle; - color: #00afec; +const StyledCheckBox = styled.input` + margin-left: 20px; + margin-right: 10px; `; From 6edda7d5f366ef9ded4b42a381fd6845b5c38aa0 Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Mon, 20 May 2019 01:23:28 +0900 Subject: [PATCH 16/50] fix rule --- frontend/tsconfig.json | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index 82d18fc02..ce9d4f5d6 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -12,6 +12,7 @@ "noImplicitReturns": true, "noFallthroughCasesInSwitch": true, "forceConsistentCasingInFileNames": true, + "skipLibCheck": true, "experimentalDecorators": true, "newLine": "LF" }, From c529ffa36f24d8e95ee1c6af710621a4be487b52 Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Mon, 20 May 2019 01:31:33 +0900 Subject: [PATCH 17/50] remove console.log --- frontend/src/components/Forms/TextInput.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/src/components/Forms/TextInput.tsx b/frontend/src/components/Forms/TextInput.tsx index 060c6705c..1f3ce85ef 100644 --- a/frontend/src/components/Forms/TextInput.tsx +++ b/frontend/src/components/Forms/TextInput.tsx @@ -19,7 +19,6 @@ export default ({ value, name, placeholder, multiLine, onChange, type = "text" } const handleChange = React.useCallback((e: React.ChangeEvent) => { const data = e.target.value; setCurrentInputValue(data); - console.log(data); if (onChange) { onChange(data); From d99c618654c70b0284a21226b5c58ade825a284a Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Mon, 20 May 2019 01:31:45 +0900 Subject: [PATCH 18/50] remove id --- frontend/src/models/ContactModel.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/frontend/src/models/ContactModel.ts b/frontend/src/models/ContactModel.ts index 12987dd36..8834be5c8 100644 --- a/frontend/src/models/ContactModel.ts +++ b/frontend/src/models/ContactModel.ts @@ -4,7 +4,6 @@ import ContactStore from "../stores/ContactStore"; export default class ContactModel { public store: ContactStore; - public id: number; public readable: boolean; public corner: number; public message: string; @@ -17,8 +16,7 @@ export default class ContactModel { constructor(store: ContactStore, json: any) { this.store = store; - const { id, readable, corner, message, nickname, name, email, department, grade } = json; - this.id = id; + const { readable, corner, message, nickname, name, email, department, grade } = json; this.readable = readable; this.corner = corner; this.message = message; @@ -36,9 +34,8 @@ export default class ContactModel { @computed get toJson() { - const { id, readable, corner, message, nickname, name, email, department, grade } = this; + const { readable, corner, message, nickname, name, email, department, grade } = this; return { - id, readable, corner, message, From a7b484141267ed1b510706067b1b9c689d4a6d66 Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Mon, 20 May 2019 01:33:02 +0900 Subject: [PATCH 19/50] fix --- frontend/src/components/ContactForm.tsx | 282 +++++++---------------- frontend/src/components/ContactForm2.tsx | 117 ---------- frontend/src/entries/Contact.tsx | 19 +- 3 files changed, 99 insertions(+), 319 deletions(-) delete mode 100644 frontend/src/components/ContactForm2.tsx diff --git a/frontend/src/components/ContactForm.tsx b/frontend/src/components/ContactForm.tsx index d47e39c18..da318b19f 100644 --- a/frontend/src/components/ContactForm.tsx +++ b/frontend/src/components/ContactForm.tsx @@ -1,79 +1,68 @@ import * as React from "react"; import styled from "styled-components"; + import ContactStore from "../stores/ContactStore"; + import ChkButtonBase from "../commons/ChkButtonBase"; +import TextInput from "./Forms/TextInput"; +import Select from "./Forms/Select"; +import CheckBox from "./Forms/CheckBox"; + interface IProp { contactStore: ContactStore; successed: (res: object) => void; failed: (res: object) => void; } -interface IState { - name: string; - corner?: number; - department?: number; - grade?: number; - email: string; - nickname: string; - message: string; - readable: boolean; -} +export default (props: IProp) => { + const [name, setName] = React.useState(""); + const [corner, setCorner] = React.useState(""); + const [department, setDepartment] = React.useState(""); + const [grade, setGrade] = React.useState(""); + const [email, setEmail] = React.useState(""); + const [nickname, setNickname] = React.useState(""); + + const [message, setMessage] = React.useState(""); + const [readable, setReadable] = React.useState(false); -export default class ContactForm extends React.Component { - constructor(props: IProp) { - super(props); - this.state = { - name: "", - corner: undefined, - department: undefined, - grade: undefined, - email: "", - nickname: "", - message: "", - readable: false - }; - - this.createContact = this.createContact.bind(this); - } - - public render() { - return ( -
- - this.setState({ name: e.target.value })} - /> - - - - this.setState({ - corner: e.target.value - }) - } - required - > - - - - - - - - - this.setState({ department: e.target.value })} - required - > + const createContact = (e: any) => { + e.preventDefault(); + + const { contactStore } = props; + const contact = contactStore.createContact({ + name, + corner, + department, + grade, + email, + nickname, + message, + readable + }); + + contact.save(props.successed, props.failed); + }; + + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ラジオ内でメッセージを読み上げてもいい場合はチェックをつけてください + + + + + + ); +}; + +const InlineWrapper = styled.div` margin: 20px; `; -const ContactFormInput = styled.input` - margin: 5px; - margin-left: 0; - margin-right: 0; - padding: 5px; - padding-left: 30px; - line-height: 1.5rem; - width: 100%; - border: 2px solid #00afec; - border-radius: 1.5rem; - - ::placeholder { - color: #00afec; - opacity: 1; - } - ::-ms-input-placeholder { - color: #00afec; - } -`; - -const ContactFormSelect = styled.select` - -moz-appearance: none; - -webkit-appearance: none; - appearance: none; - width: 100%; - line-height: 1.5rem; - padding: 5px; - padding-left: 30px; - border: 2px solid #00afec; - border-radius: 1.5rem; - background: none transparent; - vertical-align: middle; - color: #00afec; -`; - -const ContactFormSelectHalf = styled(ContactFormSelect)` +const InlineHalfWrapper = styled.div` width: 50%; -`; - -const ContactFormTextarea = styled.textarea` - margin: 5px; - margin-left: 0; - margin-right: 0; - padding: 5px; - padding-left: 30px; - line-height: 1.5rem; - width: 100%; - border: 2px solid #00afec; - border-radius: 1.5rem; - - ::placeholder { - color: #00afec; - opacity: 1; - } - ::-ms-input-placeholder { - color: #00afec; - } -`; - -const ContactFormCheckbox = styled.input` - margin-left: 20px; - margin-right: 10px; + display: inline-block; `; const ContactFormButton = styled(ChkButtonBase)``; diff --git a/frontend/src/components/ContactForm2.tsx b/frontend/src/components/ContactForm2.tsx deleted file mode 100644 index 8af7ccb34..000000000 --- a/frontend/src/components/ContactForm2.tsx +++ /dev/null @@ -1,117 +0,0 @@ -import * as React from "react"; -import styled from "styled-components"; - -// import ContactStore from "../stores/ContactStore"; - -// import ChkButtonBase from "../commons/ChkButtonBase"; - -import TextInput from "./Forms/TextInput"; -import Select from "./Forms/Select"; - -// interface IProp { -// contactStore: ContactStore; -// successed: (res: object) => void; -// failed: (res: object) => void; -// } - -// message: string; -// readable: boolean; - -// props: IProp - -export default () => { - // this.createContact = this.createContact.bind(this); - const [name, setName] = React.useState(""); - const [corner, setCorner] = React.useState(""); - const [department, setDepartment] = React.useState(""); - const [grade, setGrade] = React.useState(""); - const [email, setEmail] = React.useState(""); - const [nickname, setNickname] = React.useState(""); - - const [message, setMessage] = React.useState(""); - // const [nickname, setNickname] = React.useState(""); - - return ( -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {/* */} - - ); -}; - -// public createContact(e: any) { -// e.preventDefault(); - -// const { contactStore } = this.props; -// const contact = contactStore.createContact(this.state); - -// contact.save(this.props.successed, this.props.failed); -// } -// } - -// const ContactFormCheckbox = styled.input` -// margin-left: 20px; -// margin-right: 10px; -// `; - -// const ContactFormButton = styled(ChkButtonBase)``; - -const InlineWrapper = styled.div` - margin: 20px; -`; - -const InlineHalfWrapper = styled.div` - width: 50%; - display: inline-block; -`; diff --git a/frontend/src/entries/Contact.tsx b/frontend/src/entries/Contact.tsx index d17b58aeb..3afecce80 100644 --- a/frontend/src/entries/Contact.tsx +++ b/frontend/src/entries/Contact.tsx @@ -7,12 +7,13 @@ import { HeroArea } from "../components/HeroArea"; import { ContactHeroContent } from "../components/ContactHeroContent"; import { inject } from "../../node_modules/mobx-react"; import RootStore from "../stores/RootStore"; -import ContactForm from "../components/ContactForm"; +import ContactForm from "../components/ContactForm2"; -interface Prop { +interface IProp { rootStore?: RootStore; } -interface State { + +interface IState { alert: { message: string; status?: string; @@ -20,8 +21,8 @@ interface State { } @inject("rootStore") -export default class Contact extends React.Component { - constructor(props: Prop) { +export default class Contact extends React.Component { + constructor(props: any) { super(props); this.state = { alert: { @@ -57,11 +58,15 @@ export default class Contact extends React.Component { } public successSendContact(_: object) { - this.setState({ alert: { status: "successed", message: "おたよりを送信しました。" } }); + this.setState({ + alert: { status: "successed", message: "おたよりを送信しました。" } + }); } public failSendContact(_: object) { - this.setState({ alert: { status: "failed", message: "おたよりの送信に失敗しました。" } }); + this.setState({ + alert: { status: "failed", message: "おたよりの送信に失敗しました。" } + }); } } From 5917d9ab9120fee329edf6417cfbbb6d2ce3b31d Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Mon, 20 May 2019 01:34:09 +0900 Subject: [PATCH 20/50] fix --- frontend/src/components/ContactForm.tsx | 1 + frontend/src/entries/Contact.tsx | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/frontend/src/components/ContactForm.tsx b/frontend/src/components/ContactForm.tsx index da318b19f..bc2b4078a 100644 --- a/frontend/src/components/ContactForm.tsx +++ b/frontend/src/components/ContactForm.tsx @@ -44,6 +44,7 @@ export default (props: IProp) => { contact.save(props.successed, props.failed); }; + // TODO(euglena1215): requiredの*をべた書きで書かなくてもいいようにする return (
diff --git a/frontend/src/entries/Contact.tsx b/frontend/src/entries/Contact.tsx index 3afecce80..fa74cd172 100644 --- a/frontend/src/entries/Contact.tsx +++ b/frontend/src/entries/Contact.tsx @@ -1,13 +1,14 @@ import * as React from "react"; import styled from "styled-components"; +import { inject } from "mobx-react"; + +import RootStore from "../stores/RootStore"; import { media } from "../commons/style"; import { HeroArea } from "../components/HeroArea"; import { ContactHeroContent } from "../components/ContactHeroContent"; -import { inject } from "../../node_modules/mobx-react"; -import RootStore from "../stores/RootStore"; -import ContactForm from "../components/ContactForm2"; +import ContactForm from "../components/ContactForm"; interface IProp { rootStore?: RootStore; @@ -38,7 +39,6 @@ export default class Contact extends React.Component { public render() { const rootStore = this.props.rootStore!; - // TODO(euglena1215): requiredの*をべた書きで書かなくてもいいようにする return (
} /> From 5c21bdd7cc7a26917950330be37d8fb584662c07 Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Mon, 20 May 2019 02:15:34 +0900 Subject: [PATCH 21/50] add message --- frontend/src/components/ContactForm.tsx | 155 +++++++++++++++--------- frontend/src/entries/Contact.tsx | 9 +- 2 files changed, 102 insertions(+), 62 deletions(-) diff --git a/frontend/src/components/ContactForm.tsx b/frontend/src/components/ContactForm.tsx index bc2b4078a..427312e2a 100644 --- a/frontend/src/components/ContactForm.tsx +++ b/frontend/src/components/ContactForm.tsx @@ -13,6 +13,10 @@ interface IProp { contactStore: ContactStore; successed: (res: object) => void; failed: (res: object) => void; + alert: { + message: string; + status?: string; + }; } export default (props: IProp) => { @@ -46,67 +50,80 @@ export default (props: IProp) => { // TODO(euglena1215): requiredの*をべた書きで書かなくてもいいようにする return ( - - - - - - - - - - - - - - - + + + + + - - - - - - - - - - - - - - - - - - ラジオ内でメッセージを読み上げてもいい場合はチェックをつけてください - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + ラジオ内でメッセージを読み上げてもいい場合はチェックをつけてください + + + + + + ); }; @@ -120,3 +137,21 @@ const InlineHalfWrapper = styled.div` `; const ContactFormButton = styled(ChkButtonBase)``; + +const AlertBar = styled.div` + width: 80%; + margin: 10px auto; + line-height: 1.5rem; + padding: 5px; + border-radius: 1.5rem; + vertical-align: middle; + text-align: center; +`; + +const SuccessedAlertBar = styled(AlertBar)` + background-color: #c9ecd4; +`; + +const FailedAlertBar = styled(AlertBar)` + background-color: #ff9494; +`; diff --git a/frontend/src/entries/Contact.tsx b/frontend/src/entries/Contact.tsx index fa74cd172..e6bc4d23a 100644 --- a/frontend/src/entries/Contact.tsx +++ b/frontend/src/entries/Contact.tsx @@ -1,5 +1,6 @@ import * as React from "react"; import styled from "styled-components"; +import { withRouter, RouteComponentProps } from "react-router-dom"; import { inject } from "mobx-react"; import RootStore from "../stores/RootStore"; @@ -22,7 +23,7 @@ interface IState { } @inject("rootStore") -export default class Contact extends React.Component { +class Contact extends React.Component { constructor(props: any) { super(props); this.state = { @@ -50,6 +51,7 @@ export default class Contact extends React.Component { contactStore={rootStore.contactStore} successed={this.successSendContact} failed={this.failSendContact} + alert={this.state.alert} />
@@ -59,8 +61,9 @@ export default class Contact extends React.Component { public successSendContact(_: object) { this.setState({ - alert: { status: "successed", message: "おたよりを送信しました。" } + alert: { status: "successed", message: "おたよりを送信しました。 5秒後に自動でトップページに戻ります。" } }); + setTimeout(() => console.log(this.props.history.push("/")), 5000); } public failSendContact(_: object) { @@ -94,3 +97,5 @@ const ContactFormTitle = styled.div` text-align: center; color: #00afec; `; + +export default withRouter(Contact); From 00a26a5a037b8123f9ab2ea2b48740bae52b6a0f Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Mon, 20 May 2019 18:11:18 +0900 Subject: [PATCH 22/50] fix successed & failed design --- frontend/src/components/ContactForm.tsx | 18 ++++++++++++------ frontend/src/entries/Contact.tsx | 5 ++++- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/frontend/src/components/ContactForm.tsx b/frontend/src/components/ContactForm.tsx index 427312e2a..e63861795 100644 --- a/frontend/src/components/ContactForm.tsx +++ b/frontend/src/components/ContactForm.tsx @@ -136,22 +136,28 @@ const InlineHalfWrapper = styled.div` display: inline-block; `; -const ContactFormButton = styled(ChkButtonBase)``; +const ContactFormButton = styled(ChkButtonBase)` + width: 40%; + margin: 0 auto; +`; const AlertBar = styled.div` - width: 80%; + width: 100%; margin: 10px auto; - line-height: 1.5rem; + line-height: 1rem; padding: 5px; - border-radius: 1.5rem; vertical-align: middle; + border: 3px solid #000; + color: #000; text-align: center; `; const SuccessedAlertBar = styled(AlertBar)` - background-color: #c9ecd4; + border: 3px solid #3ed986; + color: #000; `; const FailedAlertBar = styled(AlertBar)` - background-color: #ff9494; + border: 3px solid #d95f3f; + color: #d95f3f; `; diff --git a/frontend/src/entries/Contact.tsx b/frontend/src/entries/Contact.tsx index e6bc4d23a..189c77d06 100644 --- a/frontend/src/entries/Contact.tsx +++ b/frontend/src/entries/Contact.tsx @@ -68,7 +68,10 @@ class Contact extends React.Component { public failSendContact(_: object) { this.setState({ - alert: { status: "failed", message: "おたよりの送信に失敗しました。" } + alert: { + status: "failed", + message: "おたよりの送信に失敗しました。 * がついている項目は全て記入して再送信してください。" + } }); } } From ce242056d70b2ab26b2e11d04d15d0e7473b1fd5 Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Mon, 20 May 2019 18:28:15 +0900 Subject: [PATCH 23/50] fix props no always needed --- frontend/src/api/RestClient.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/frontend/src/api/RestClient.ts b/frontend/src/api/RestClient.ts index 2d26f41cd..eb11bf5fc 100644 --- a/frontend/src/api/RestClient.ts +++ b/frontend/src/api/RestClient.ts @@ -18,9 +18,9 @@ export default class RestClient { public get( path: string, - params: object, - successed: (res: object) => void, - errored: (res: object) => void, + params?: object, + successed?: (res: object) => void, + errored?: (res: object) => void, always: () => any = () => {} ) { return this.axios @@ -29,13 +29,13 @@ export default class RestClient { console.log(`GET ${result.config.url}`); if (params) console.table(params); console.log(`status: ${result.status}, statusText: ${result.statusText}`); - successed(result); + if (successed) successed(result); }) .catch((error: AxiosError) => { console.log(`ERROR! GET ${error.config.url}`); if (params) console.table(params); console.log(`error: ${JSON.stringify(error)}`); - errored(error); + if (errored) errored(error); }) .then(always()); } From 821969ece6ac9013de49ac1c11a2c84992a56d80 Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Mon, 20 May 2019 18:28:32 +0900 Subject: [PATCH 24/50] add fetchContactEnum --- frontend/src/api/ContactApi.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frontend/src/api/ContactApi.ts b/frontend/src/api/ContactApi.ts index 73e410379..bdcb697d0 100644 --- a/frontend/src/api/ContactApi.ts +++ b/frontend/src/api/ContactApi.ts @@ -15,4 +15,8 @@ export default class ContactApi { ) { return this.restClient.post("/api/v1/contacts", json, succussed, errored, always); } + + public fetchContactEnum() { + return this.restClient.get("/api/v1/contacts/enum"); + } } From 5e4173cc54031957cc4bd8eb0c0f1810171931a7 Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Tue, 21 May 2019 03:07:09 +0900 Subject: [PATCH 25/50] use axios.interceptors.response --- frontend/src/api/RestClient.ts | 47 +++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/frontend/src/api/RestClient.ts b/frontend/src/api/RestClient.ts index eb11bf5fc..c9809c248 100644 --- a/frontend/src/api/RestClient.ts +++ b/frontend/src/api/RestClient.ts @@ -14,9 +14,27 @@ export default class RestClient { "X-CSRF-TOKEN": csrfToken } }); + + this.axios.interceptors.response.use( + response => { + const { config, data, status } = response; + const { method, params, url } = config; + + console.group(`${method ? method.toUpperCase() : "undefined method"}:${status} - ${url}`); + if (params) console.table(params); + console.log(data); + console.groupEnd(); + + return response; + }, + error => { + console.log(error); + return Promise.reject(error); + } + ); } - public get( + public get( path: string, params?: object, successed?: (res: object) => void, @@ -25,19 +43,18 @@ export default class RestClient { ) { return this.axios .get(path, { params }) - .then((result: AxiosResponse) => { - console.log(`GET ${result.config.url}`); - if (params) console.table(params); - console.log(`status: ${result.status}, statusText: ${result.statusText}`); + .then((result: AxiosResponse) => { if (successed) successed(result); + return result; }) .catch((error: AxiosError) => { - console.log(`ERROR! GET ${error.config.url}`); - if (params) console.table(params); - console.log(`error: ${JSON.stringify(error)}`); if (errored) errored(error); }) - .then(always()); + .then(result => { + always(); + if (result) return result.data; + return result; + }); } public post( @@ -50,15 +67,9 @@ export default class RestClient { return this.axios .post(path, params) .then((result: AxiosResponse) => { - console.log(`POST ${result.config.url}`); - if (params) console.table(params); - console.log(`status: ${result.status}, statusText: ${result.statusText}`); successed(result); }) .catch((error: AxiosError) => { - console.log(`ERROR! POST ${error.config.url}`); - if (params) console.table(params); - console.log(`error: ${error}`); errored(error); }) .then(always()); @@ -74,15 +85,9 @@ export default class RestClient { return this.axios .delete(path, { data: { params } }) .then((result: AxiosResponse) => { - console.log(`DELETE ${result.config.url}`); - if (params) console.table(params); - console.log(`status: ${result.status}, statusText: ${result.statusText}`); successed(result); }) .catch((error: AxiosError) => { - console.log(`ERROR! DELETE ${error.config.url}`); - if (params) console.table(params); - console.log(`error: ${error}`); errored(error); }) .then(always()); From a44a6e567fe82bfc19b043d45d1d0370426123e7 Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Tue, 21 May 2019 03:07:33 +0900 Subject: [PATCH 26/50] add type --- frontend/src/api/ContactApi.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/frontend/src/api/ContactApi.ts b/frontend/src/api/ContactApi.ts index bdcb697d0..5bdd9338b 100644 --- a/frontend/src/api/ContactApi.ts +++ b/frontend/src/api/ContactApi.ts @@ -1,5 +1,11 @@ import RestClient from "./RestClient"; +export interface IContactEnum { + corners: { [key: string]: number }; + departments: { [key: string]: number }; + grades: { [key: string]: number }; +} + export default class ContactApi { public restClient: RestClient; @@ -17,6 +23,6 @@ export default class ContactApi { } public fetchContactEnum() { - return this.restClient.get("/api/v1/contacts/enum"); + return this.restClient.get("/api/v1/contacts/enum"); } } From c6cdd39760de62aa9bb3645fcdfca6913535bd8e Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Thu, 23 May 2019 15:40:47 +0900 Subject: [PATCH 27/50] add mobx-react-lite --- frontend/package.json | 1 + frontend/yarn.lock | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/frontend/package.json b/frontend/package.json index 49f14dc29..edcfb9018 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -43,6 +43,7 @@ "babel-polyfill": "^6.26.0", "mobx": "^5.9.4", "mobx-react": "^5.4.4", + "mobx-react-lite": "^1.3.2", "normalize.css": "^8.0.0", "react": "^16.8.6", "react-dom": "^16.8.6", diff --git a/frontend/yarn.lock b/frontend/yarn.lock index eac4b0815..3905a8a84 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -4144,6 +4144,10 @@ mkdirp@0.5.x, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: dependencies: minimist "0.0.8" +mobx-react-lite@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/mobx-react-lite/-/mobx-react-lite-1.3.2.tgz#4366048b5d283d12a82053367638b5d79281951f" + mobx-react@^5.4.4: version "5.4.4" resolved "https://registry.yarnpkg.com/mobx-react/-/mobx-react-5.4.4.tgz#b3de9c6eabcd0ed8a40036888cb0221ab9568b80" From 6f1a8d239fee11c9464e166f816cca951db1e9a3 Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Thu, 23 May 2019 23:28:02 +0900 Subject: [PATCH 28/50] add CircleSpinner --- .../src/components/Spinners/CircleSpinner.tsx | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 frontend/src/components/Spinners/CircleSpinner.tsx diff --git a/frontend/src/components/Spinners/CircleSpinner.tsx b/frontend/src/components/Spinners/CircleSpinner.tsx new file mode 100644 index 000000000..4e3d92cff --- /dev/null +++ b/frontend/src/components/Spinners/CircleSpinner.tsx @@ -0,0 +1,46 @@ +import * as React from "react"; +import styled, { keyframes } from "styled-components"; + +import { chkColors } from "../../commons/color"; + +interface IProps { + size?: number; + color?: string; + isLoading?: boolean; +} + +export default ({ size = 35, color = chkColors.blue, isLoading = true }: IProps) => { + console.log(size); + console.log(color); + + return isLoading ? ( + + + + ) : null; +}; + +const Wrapper = styled.div` + display: flex; + justify-content: center; + align-items: center; +`; + +const clip = keyframes` + 0% {transform: rotate(0deg) scale(1)} + 50% {transform: rotate(180deg) scale(0.8)} + 100% {transform: rotate(360deg) scale(1)} +`; + +const StyledSpinner = styled.div` + background: transparent !important; + width: ${(props: IProps) => `${props.size}px`}; + height: ${(props: IProps) => `${props.size}px`}; + border-radius: 100%; + border: 2px solid; + border-color: ${(props: IProps) => props.color}; + border-bottom-color: transparent; + display: inline-block; + animation: ${clip} 1.3s 0s infinite linear; + animation-fill-mode: both; +`; From fd558584ba2a1c2397831e1d34aa6abe0d8ca516 Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Thu, 23 May 2019 23:35:57 +0900 Subject: [PATCH 29/50] remove commnet --- frontend/src/components/Spinners/CircleSpinner.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/frontend/src/components/Spinners/CircleSpinner.tsx b/frontend/src/components/Spinners/CircleSpinner.tsx index 4e3d92cff..1cf3a064d 100644 --- a/frontend/src/components/Spinners/CircleSpinner.tsx +++ b/frontend/src/components/Spinners/CircleSpinner.tsx @@ -10,9 +10,6 @@ interface IProps { } export default ({ size = 35, color = chkColors.blue, isLoading = true }: IProps) => { - console.log(size); - console.log(color); - return isLoading ? ( From 01405c49fa6da656de417ae783ddb5f31587d1f8 Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Thu, 23 May 2019 23:37:44 +0900 Subject: [PATCH 30/50] add optionsElements --- frontend/src/components/Forms/Select.tsx | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/frontend/src/components/Forms/Select.tsx b/frontend/src/components/Forms/Select.tsx index 432735f5d..5e77e3b64 100644 --- a/frontend/src/components/Forms/Select.tsx +++ b/frontend/src/components/Forms/Select.tsx @@ -3,13 +3,14 @@ import styled from "styled-components"; // TODO: childrenの型が分からない export interface ITextInputProps { - children: any; + children?: any; value?: string; name?: string; + optionElements?: { [key: string]: string | number }; onChange?(value: string): void; } -export default ({ value, name, onChange, children }: ITextInputProps) => { +export default ({ value, name, optionElements, onChange, children }: ITextInputProps) => { const [currentValue, setCurrentValue] = React.useState(value); const [inFocus, setInFocus] = React.useState(false); @@ -49,7 +50,12 @@ export default ({ value, name, onChange, children }: ITextInputProps) => { styledFocus: inFocus ? true : false }; - return {children}; + return ( + + {children && children} + {optionElements && Object.keys(optionElements).map(v => )} + + ); }; // TODO: focus時とそうでない時で背景かアウトラインのデザインを変える From a128a17ea49e467ee5413bdbfbcd9c422d555a2a Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Thu, 23 May 2019 23:51:31 +0900 Subject: [PATCH 31/50] set key for map --- frontend/src/components/Forms/Select.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/Forms/Select.tsx b/frontend/src/components/Forms/Select.tsx index 5e77e3b64..b69abe94b 100644 --- a/frontend/src/components/Forms/Select.tsx +++ b/frontend/src/components/Forms/Select.tsx @@ -53,7 +53,12 @@ export default ({ value, name, optionElements, onChange, children }: ITextInputP return ( {children && children} - {optionElements && Object.keys(optionElements).map(v => )} + {optionElements && + Object.keys(optionElements).map(v => ( + + ))} ); }; From 050dba4d7c09c414e4eea991c3f805b17ad227c4 Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Thu, 23 May 2019 23:52:25 +0900 Subject: [PATCH 32/50] rewrite by react hooks --- frontend/src/components/ContactForm.tsx | 55 ++++++++++++++----------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/frontend/src/components/ContactForm.tsx b/frontend/src/components/ContactForm.tsx index e63861795..c668570f1 100644 --- a/frontend/src/components/ContactForm.tsx +++ b/frontend/src/components/ContactForm.tsx @@ -1,5 +1,6 @@ import * as React from "react"; import styled from "styled-components"; +import { observer } from "mobx-react-lite"; import ContactStore from "../stores/ContactStore"; @@ -9,6 +10,8 @@ import TextInput from "./Forms/TextInput"; import Select from "./Forms/Select"; import CheckBox from "./Forms/CheckBox"; +import CircleSpinner from "./Spinners/CircleSpinner"; + interface IProp { contactStore: ContactStore; successed: (res: object) => void; @@ -19,7 +22,14 @@ interface IProp { }; } -export default (props: IProp) => { +export default observer((props: IProp) => { + const { contactStore } = props; + const { contactEnum } = contactStore; + + React.useEffect(() => { + contactStore.fetchContactEnum(); + }, []); + const [name, setName] = React.useState(""); const [corner, setCorner] = React.useState(""); const [department, setDepartment] = React.useState(""); @@ -33,7 +43,6 @@ export default (props: IProp) => { const createContact = (e: any) => { e.preventDefault(); - const { contactStore } = props; const contact = contactStore.createContact({ name, corner, @@ -49,7 +58,7 @@ export default (props: IProp) => { }; // TODO(euglena1215): requiredの*をべた書きで書かなくてもいいようにする - return ( + return contactEnum ? ( <> {props.alert.status === "successed" && ( @@ -68,37 +77,25 @@ export default (props: IProp) => {
- - - - - - - - - - - - - - - - - - - - @@ -112,7 +109,13 @@ export default (props: IProp) => { - + @@ -124,8 +127,10 @@ export default (props: IProp) => { + ) : ( + ); -}; +}); const InlineWrapper = styled.div` margin: 20px; From da05e1644df146e18fae999437afe98266d23eb4 Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Fri, 24 May 2019 00:07:08 +0900 Subject: [PATCH 33/50] fix --- frontend/package.json | 2 +- frontend/src/api/RestClient.ts | 83 +++++++++++++++++----------------- frontend/yarn.lock | 24 ++++++---- 3 files changed, 56 insertions(+), 53 deletions(-) diff --git a/frontend/package.json b/frontend/package.json index edcfb9018..e237458d8 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -39,7 +39,7 @@ "webpack-merge": "^4.1.4" }, "dependencies": { - "axios": "^0.18.0", + "axios": "0.19.0-beta.1", "babel-polyfill": "^6.26.0", "mobx": "^5.9.4", "mobx-react": "^5.4.4", diff --git a/frontend/src/api/RestClient.ts b/frontend/src/api/RestClient.ts index c9809c248..0092f26a4 100644 --- a/frontend/src/api/RestClient.ts +++ b/frontend/src/api/RestClient.ts @@ -1,4 +1,4 @@ -import axios, { AxiosInstance, AxiosResponse, AxiosError } from "axios"; +import axios, { AxiosInstance } from "axios"; export default class RestClient { public axios: AxiosInstance; @@ -15,6 +15,7 @@ export default class RestClient { } }); + // TODO: Productionではログを流さないようにする this.axios.interceptors.response.use( response => { const { config, data, status } = response; @@ -34,62 +35,60 @@ export default class RestClient { ); } - public get( + public async get( path: string, params?: object, successed?: (res: object) => void, errored?: (res: object) => void, always: () => any = () => {} ) { - return this.axios - .get(path, { params }) - .then((result: AxiosResponse) => { - if (successed) successed(result); - return result; - }) - .catch((error: AxiosError) => { - if (errored) errored(error); - }) - .then(result => { - always(); - if (result) return result.data; - return result; - }); + try { + const response = await this.axios.get(path, { params }); + if (successed) successed(response); + return response; + } catch (error) { + if (errored) errored(error); + throw error; + } finally { + always(); + } } - public post( + public async post( path: string, - params: object, - successed: (res: object) => void, - errored: (res: object) => void, + params?: object, + successed?: (res: object) => void, + errored?: (res: object) => void, always: () => any = () => {} ) { - return this.axios - .post(path, params) - .then((result: AxiosResponse) => { - successed(result); - }) - .catch((error: AxiosError) => { - errored(error); - }) - .then(always()); + try { + const response = await this.axios.post(path, params); + if (successed) successed(response); + return response; + } catch (error) { + if (errored) errored(error); + throw error; + } finally { + always(); + } } - public delete( + public async delete( path: string, - params: object, - successed: (res: object) => void, - errored: (res: object) => void, + params?: object, + successed?: (res: object) => void, + errored?: (res: object) => void, always: () => any = () => {} ) { - return this.axios - .delete(path, { data: { params } }) - .then((result: AxiosResponse) => { - successed(result); - }) - .catch((error: AxiosError) => { - errored(error); - }) - .then(always()); + try { + const response = await this.axios.delete(path, { data: { params } }); + if (successed) successed(response); + return response; + } catch (error) { + if (errored) errored(error); + throw error; + } finally { + always(); + } } } diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 3905a8a84..b9ccf8e4a 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -480,12 +480,12 @@ awesome-typescript-loader@^5.0.0: source-map-support "^0.5.3" webpack-log "^1.2.0" -axios@^0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.18.0.tgz#32d53e4851efdc0a11993b6cd000789d70c05102" +axios@0.19.0-beta.1: + version "0.19.0-beta.1" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.0-beta.1.tgz#3d6a9ee75885d1fd39e108df9a4fb2e48e1af1e8" dependencies: - follow-redirects "^1.3.0" - is-buffer "^1.1.5" + follow-redirects "^1.4.1" + is-buffer "^2.0.2" babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: version "6.26.0" @@ -2000,7 +2000,7 @@ debug@=3.1.0, debug@^3.1.0: dependencies: ms "2.0.0" -debug@^3.2.5: +debug@^3.2.5, debug@^3.2.6: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" dependencies: @@ -2660,11 +2660,11 @@ follow-redirects@^1.0.0: dependencies: debug "=3.1.0" -follow-redirects@^1.3.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.1.tgz#67a8f14f5a1f67f962c2c46469c79eaec0a90291" +follow-redirects@^1.4.1: + version "1.7.0" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.7.0.tgz#489ebc198dc0e7f64167bd23b03c4c19b5784c76" dependencies: - debug "^3.1.0" + debug "^3.2.6" for-in@^1.0.1, for-in@^1.0.2: version "1.0.2" @@ -3308,6 +3308,10 @@ is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" +is-buffer@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725" + is-builtin-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" From 92cae4132ec5c54b38ba0d03b6cfb0bfdf1b2669 Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Fri, 24 May 2019 00:08:40 +0900 Subject: [PATCH 34/50] add ContactEnum --- frontend/src/stores/ContactStore.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/frontend/src/stores/ContactStore.ts b/frontend/src/stores/ContactStore.ts index 0648be0c7..3f9ebaf55 100644 --- a/frontend/src/stores/ContactStore.ts +++ b/frontend/src/stores/ContactStore.ts @@ -1,7 +1,11 @@ -import ContactApi from "../api/ContactApi"; +import { action, observable } from "mobx"; + +import ContactApi, { IContactEnum } from "../api/ContactApi"; import ContactModel from "../models/ContactModel"; export default class ContactStore { + @observable public contactEnum?: IContactEnum; + public transportLayer: ContactApi; constructor(transportLayer: ContactApi) { @@ -11,4 +15,13 @@ export default class ContactStore { public createContact(json: object) { return new ContactModel(this, json); } + + public async fetchContactEnum() { + const enums = await this.transportLayer.fetchContactEnum(); + this.setContactEnum(enums.data); + } + + @action public setContactEnum(enums: any) { + this.contactEnum = enums; + } } From 081ca80c9af835c331f435ab2454522bccb72c1c Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Fri, 24 May 2019 00:09:18 +0900 Subject: [PATCH 35/50] fix comment --- frontend/src/components/ContactForm.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/ContactForm.tsx b/frontend/src/components/ContactForm.tsx index c668570f1..295b05b76 100644 --- a/frontend/src/components/ContactForm.tsx +++ b/frontend/src/components/ContactForm.tsx @@ -57,7 +57,7 @@ export default observer((props: IProp) => { contact.save(props.successed, props.failed); }; - // TODO(euglena1215): requiredの*をべた書きで書かなくてもいいようにする + // TODO(euglena1215): validationをつける return contactEnum ? ( <> {props.alert.status === "successed" && ( From b9909b37c596c5278c87dc4bd941beccd97e120f Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Thu, 30 May 2019 21:58:22 +0900 Subject: [PATCH 36/50] create validation methods --- frontend/src/utils/validation.ts | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 frontend/src/utils/validation.ts diff --git a/frontend/src/utils/validation.ts b/frontend/src/utils/validation.ts new file mode 100644 index 000000000..c2157457e --- /dev/null +++ b/frontend/src/utils/validation.ts @@ -0,0 +1,30 @@ +const EMAIL_REGEXP = /^([\w])+([\w\._-])*@([\w_-])+\.([\w\._-]+)+$/; + +export interface IValidationResult { + validity: boolean; + errorMessage?: string; +} + +export const notValidate = (_?: any) => { + return { + validity: true + }; +}; + +export const validateEmail = (email: string): IValidationResult => { + if (!email) { + return { + validity: false, + errorMessage: "メールアドレスを入力してください。" + }; + } + if (!EMAIL_REGEXP.test(email)) { + return { + validity: false, + errorMessage: "有効なメールアドレスではありません。" + }; + } + return { validity: true }; +}; + +export type ValidationMethods = typeof validateEmail | typeof notValidate; From 74aa2916f38d2a14f61d44b22a66298c81c271e4 Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Thu, 30 May 2019 22:02:11 +0900 Subject: [PATCH 37/50] add error color --- frontend/src/commons/color.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frontend/src/commons/color.ts b/frontend/src/commons/color.ts index 7e3e19c6c..54a09b53b 100644 --- a/frontend/src/commons/color.ts +++ b/frontend/src/commons/color.ts @@ -12,5 +12,6 @@ export const chkColors: IColor = { white: "#ffffff", placeholder: "#b0bec5", aqua: "#b3dfe2", - darkenAqua: "#50AAB7" + darkenAqua: "#50AAB7", + error: "#ff4b42" }; From aef420723629d9306c34f0340ffef3b1a6552f11 Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Thu, 30 May 2019 22:03:10 +0900 Subject: [PATCH 38/50] add validation: email --- frontend/src/components/ContactForm.tsx | 10 ++++- frontend/src/components/Forms/TextInput.tsx | 50 +++++++++++++++++++-- 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/frontend/src/components/ContactForm.tsx b/frontend/src/components/ContactForm.tsx index 295b05b76..6990bacf3 100644 --- a/frontend/src/components/ContactForm.tsx +++ b/frontend/src/components/ContactForm.tsx @@ -6,6 +6,8 @@ import ContactStore from "../stores/ContactStore"; import ChkButtonBase from "../commons/ChkButtonBase"; +import { validateEmail } from "../utils/validation"; + import TextInput from "./Forms/TextInput"; import Select from "./Forms/Select"; import CheckBox from "./Forms/CheckBox"; @@ -101,7 +103,13 @@ export default observer((props: IProp) => { - + diff --git a/frontend/src/components/Forms/TextInput.tsx b/frontend/src/components/Forms/TextInput.tsx index 1f3ce85ef..a524ac967 100644 --- a/frontend/src/components/Forms/TextInput.tsx +++ b/frontend/src/components/Forms/TextInput.tsx @@ -1,6 +1,9 @@ import * as React from "react"; import styled, { css } from "styled-components"; +import { chkColors } from "../../commons/color"; +import { IValidationResult, ValidationMethods, notValidate } from "../../utils/validation"; + type TextInputType = "text" | "password" | "email"; export interface ITextInputProps { @@ -9,11 +12,21 @@ export interface ITextInputProps { placeholder?: string; type?: TextInputType; multiLine?: boolean; + validation?: ValidationMethods; onChange?(value: string): void; } -export default ({ value, name, placeholder, multiLine, onChange, type = "text" }: ITextInputProps) => { +export default ({ + value, + name, + placeholder, + multiLine, + onChange, + validation = notValidate, + type = "text" +}: ITextInputProps) => { const [currentInputValue, setCurrentInputValue] = React.useState(""); + const [validationResult, setValidationResult] = React.useState({ validity: true } as IValidationResult); const [inFocus, setInFocus] = React.useState(false); const handleChange = React.useCallback((e: React.ChangeEvent) => { @@ -25,6 +38,16 @@ export default ({ value, name, placeholder, multiLine, onChange, type = "text" } } }, []); + React.useEffect( + () => { + if (validation) { + if (!currentInputValue) return; + setValidationResult(validation(currentInputValue)); + } + }, + [currentInputValue] + ); + const handleFocus = React.useCallback(() => { setInFocus(true); }, []); @@ -51,10 +74,25 @@ export default ({ value, name, placeholder, multiLine, onChange, type = "text" } id: name, value: currentInputValue, onChange: handleChange, - styledFocus: inFocus ? true : false + styledFocus: inFocus ? true : false, + validationResult: validationResult.validity }; - return multiLine ? : ; + return ( +
+ {multiLine ? ( + <> + + {validationResult && validationResult.validity ? null : {validationResult.errorMessage}} + + ) : ( + <> + + {validationResult && validationResult.validity ? null : {validationResult.errorMessage}} + + )} +
+ ); }; // TODO: focus時とそうでない時で背景かアウトラインのデザインを変える @@ -66,7 +104,7 @@ const style = css` padding-left: 30px; line-height: 1.5rem; width: 100%; - border: 2px solid #00afec; + border: 2px solid ${(props: any) => (props.validationResult ? "#00afec" : chkColors.error)}; border-radius: 1.5rem; ::placeholder { @@ -76,6 +114,10 @@ const style = css` ::-ms-input-placeholder { color: #00afec; } + + &:-webkit-autofill { + box-shadow: 0 0 0 1000px #fff inset; + } `; const StyledInput = styled.input` From 182d42472eed278b6e73b022d523b0e75f6895e9 Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Thu, 30 May 2019 22:07:10 +0900 Subject: [PATCH 39/50] cannot select placefolder options --- frontend/src/components/ContactForm.tsx | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/frontend/src/components/ContactForm.tsx b/frontend/src/components/ContactForm.tsx index 6990bacf3..0ddd44ae9 100644 --- a/frontend/src/components/ContactForm.tsx +++ b/frontend/src/components/ContactForm.tsx @@ -80,7 +80,9 @@ export default observer((props: IProp) => { @@ -92,12 +94,16 @@ export default observer((props: IProp) => { value={department} optionElements={contactEnum.departments} > - +
From b7cd0f25632b685e41ab8cc631992f262e8aa6bb Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Thu, 30 May 2019 22:49:47 +0900 Subject: [PATCH 40/50] fix --- frontend/src/components/Forms/TextInput.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/Forms/TextInput.tsx b/frontend/src/components/Forms/TextInput.tsx index a524ac967..dc78d8e3f 100644 --- a/frontend/src/components/Forms/TextInput.tsx +++ b/frontend/src/components/Forms/TextInput.tsx @@ -45,7 +45,7 @@ export default ({ setValidationResult(validation(currentInputValue)); } }, - [currentInputValue] + [currentInputValue, inFocus] ); const handleFocus = React.useCallback(() => { From 84417e1e825bf390dcfc9dd3add051f5c8167732 Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Thu, 30 May 2019 23:12:13 +0900 Subject: [PATCH 41/50] solve error & add require --- frontend/src/components/ContactForm.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/frontend/src/components/ContactForm.tsx b/frontend/src/components/ContactForm.tsx index 0ddd44ae9..419ab7940 100644 --- a/frontend/src/components/ContactForm.tsx +++ b/frontend/src/components/ContactForm.tsx @@ -45,6 +45,8 @@ export default observer((props: IProp) => { const createContact = (e: any) => { e.preventDefault(); + if (!(corner && department && grade && validateEmail(email).validity)) return; + const contact = contactStore.createContact({ name, corner, @@ -80,7 +82,7 @@ export default observer((props: IProp) => { @@ -94,14 +96,14 @@ export default observer((props: IProp) => { value={department} optionElements={contactEnum.departments} > - From 73ee59350b047bc4d0c34ca4e25d687c65094165 Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Thu, 30 May 2019 23:35:49 +0900 Subject: [PATCH 42/50] change send button color --- frontend/src/commons/color.ts | 3 ++- frontend/src/components/ContactForm.tsx | 23 +++++++++++++++++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/frontend/src/commons/color.ts b/frontend/src/commons/color.ts index 54a09b53b..bbf43caac 100644 --- a/frontend/src/commons/color.ts +++ b/frontend/src/commons/color.ts @@ -13,5 +13,6 @@ export const chkColors: IColor = { placeholder: "#b0bec5", aqua: "#b3dfe2", darkenAqua: "#50AAB7", - error: "#ff4b42" + error: "#ff4b42", + disabled: "#cccccc" }; diff --git a/frontend/src/components/ContactForm.tsx b/frontend/src/components/ContactForm.tsx index 419ab7940..64ead8ea7 100644 --- a/frontend/src/components/ContactForm.tsx +++ b/frontend/src/components/ContactForm.tsx @@ -42,10 +42,23 @@ export default observer((props: IProp) => { const [message, setMessage] = React.useState(""); const [readable, setReadable] = React.useState(false); + const [sendable, setSendable] = React.useState(false); + + React.useEffect( + () => { + if (corner && department && grade && validateEmail(email).validity) { + setSendable(true); + } else { + setSendable(false); + } + }, + [corner, department, grade, email] + ); + const createContact = (e: any) => { e.preventDefault(); - if (!(corner && department && grade && validateEmail(email).validity)) return; + if (!sendable) return; const contact = contactStore.createContact({ name, @@ -140,7 +153,12 @@ export default observer((props: IProp) => { - + ) : ( @@ -160,6 +178,7 @@ const InlineHalfWrapper = styled.div` const ContactFormButton = styled(ChkButtonBase)` width: 40%; margin: 0 auto; + cursor: ${(props: { sendable: boolean }) => (props.sendable ? "pointer" : "default")}; `; const AlertBar = styled.div` From f08d4e82252c78736c82d9638beda04680f590e0 Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Fri, 31 May 2019 09:49:42 +0900 Subject: [PATCH 43/50] validity to isValid --- frontend/src/components/ContactForm.tsx | 2 +- frontend/src/components/Forms/TextInput.tsx | 8 ++++---- frontend/src/utils/validation.ts | 10 +++++----- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/frontend/src/components/ContactForm.tsx b/frontend/src/components/ContactForm.tsx index 64ead8ea7..955d33164 100644 --- a/frontend/src/components/ContactForm.tsx +++ b/frontend/src/components/ContactForm.tsx @@ -46,7 +46,7 @@ export default observer((props: IProp) => { React.useEffect( () => { - if (corner && department && grade && validateEmail(email).validity) { + if (corner && department && grade && validateEmail(email).isValid) { setSendable(true); } else { setSendable(false); diff --git a/frontend/src/components/Forms/TextInput.tsx b/frontend/src/components/Forms/TextInput.tsx index dc78d8e3f..305afe846 100644 --- a/frontend/src/components/Forms/TextInput.tsx +++ b/frontend/src/components/Forms/TextInput.tsx @@ -26,7 +26,7 @@ export default ({ type = "text" }: ITextInputProps) => { const [currentInputValue, setCurrentInputValue] = React.useState(""); - const [validationResult, setValidationResult] = React.useState({ validity: true } as IValidationResult); + const [validationResult, setValidationResult] = React.useState({ isValid: true } as IValidationResult); const [inFocus, setInFocus] = React.useState(false); const handleChange = React.useCallback((e: React.ChangeEvent) => { @@ -75,7 +75,7 @@ export default ({ value: currentInputValue, onChange: handleChange, styledFocus: inFocus ? true : false, - validationResult: validationResult.validity + validationResult: validationResult.isValid }; return ( @@ -83,12 +83,12 @@ export default ({ {multiLine ? ( <> - {validationResult && validationResult.validity ? null : {validationResult.errorMessage}} + {validationResult && validationResult.isValid ? null : {validationResult.errorMessage}} ) : ( <> - {validationResult && validationResult.validity ? null : {validationResult.errorMessage}} + {validationResult && validationResult.isValid ? null : {validationResult.errorMessage}} )} diff --git a/frontend/src/utils/validation.ts b/frontend/src/utils/validation.ts index c2157457e..3d5af54cb 100644 --- a/frontend/src/utils/validation.ts +++ b/frontend/src/utils/validation.ts @@ -1,30 +1,30 @@ const EMAIL_REGEXP = /^([\w])+([\w\._-])*@([\w_-])+\.([\w\._-]+)+$/; export interface IValidationResult { - validity: boolean; + isValid: boolean; errorMessage?: string; } export const notValidate = (_?: any) => { return { - validity: true + isValid: true }; }; export const validateEmail = (email: string): IValidationResult => { if (!email) { return { - validity: false, + isValid: false, errorMessage: "メールアドレスを入力してください。" }; } if (!EMAIL_REGEXP.test(email)) { return { - validity: false, + isValid: false, errorMessage: "有効なメールアドレスではありません。" }; } - return { validity: true }; + return { isValid: true }; }; export type ValidationMethods = typeof validateEmail | typeof notValidate; From 6ee245ae8c6c768fa95cd302a346b465b3e0d16a Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Fri, 31 May 2019 10:01:55 +0900 Subject: [PATCH 44/50] fix: show error message when exist --- frontend/src/components/Forms/TextInput.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/frontend/src/components/Forms/TextInput.tsx b/frontend/src/components/Forms/TextInput.tsx index 305afe846..afffa40a3 100644 --- a/frontend/src/components/Forms/TextInput.tsx +++ b/frontend/src/components/Forms/TextInput.tsx @@ -26,7 +26,7 @@ export default ({ type = "text" }: ITextInputProps) => { const [currentInputValue, setCurrentInputValue] = React.useState(""); - const [validationResult, setValidationResult] = React.useState({ isValid: true } as IValidationResult); + const [validationResult, setValidationResult] = React.useState({} as IValidationResult); const [inFocus, setInFocus] = React.useState(false); const handleChange = React.useCallback((e: React.ChangeEvent) => { @@ -75,7 +75,7 @@ export default ({ value: currentInputValue, onChange: handleChange, styledFocus: inFocus ? true : false, - validationResult: validationResult.isValid + validationResult: validationResult.isValid || !validationResult.errorMessage }; return ( @@ -83,12 +83,12 @@ export default ({ {multiLine ? ( <> - {validationResult && validationResult.isValid ? null : {validationResult.errorMessage}} + {validationResult && !validationResult.errorMessage ? null : {validationResult.errorMessage}} ) : ( <> - {validationResult && validationResult.isValid ? null : {validationResult.errorMessage}} + {validationResult && !validationResult.errorMessage ? null : {validationResult.errorMessage}} )} From 1be4d552a907e4df6f43f2c9fa59005f6e316ce2 Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Fri, 31 May 2019 10:10:23 +0900 Subject: [PATCH 45/50] fix --- frontend/src/utils/validation.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/utils/validation.ts b/frontend/src/utils/validation.ts index 3d5af54cb..686562e7c 100644 --- a/frontend/src/utils/validation.ts +++ b/frontend/src/utils/validation.ts @@ -5,7 +5,7 @@ export interface IValidationResult { errorMessage?: string; } -export const notValidate = (_?: any) => { +export const notValidate = (_: any) => { return { isValid: true }; From d827a41aa7d6e28c57bc808368bf58c4fd4ae799 Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Sat, 1 Jun 2019 09:05:13 +0900 Subject: [PATCH 46/50] remove property: isValid --- frontend/src/components/ContactForm.tsx | 2 +- frontend/src/components/Forms/TextInput.tsx | 2 +- frontend/src/utils/validation.ts | 11 ++++------- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/frontend/src/components/ContactForm.tsx b/frontend/src/components/ContactForm.tsx index 955d33164..af6eda463 100644 --- a/frontend/src/components/ContactForm.tsx +++ b/frontend/src/components/ContactForm.tsx @@ -46,7 +46,7 @@ export default observer((props: IProp) => { React.useEffect( () => { - if (corner && department && grade && validateEmail(email).isValid) { + if (corner && department && grade && validateEmail(email).errorMessage) { setSendable(true); } else { setSendable(false); diff --git a/frontend/src/components/Forms/TextInput.tsx b/frontend/src/components/Forms/TextInput.tsx index afffa40a3..84f872fb3 100644 --- a/frontend/src/components/Forms/TextInput.tsx +++ b/frontend/src/components/Forms/TextInput.tsx @@ -75,7 +75,7 @@ export default ({ value: currentInputValue, onChange: handleChange, styledFocus: inFocus ? true : false, - validationResult: validationResult.isValid || !validationResult.errorMessage + validationResult: !validationResult.errorMessage }; return ( diff --git a/frontend/src/utils/validation.ts b/frontend/src/utils/validation.ts index 686562e7c..81237065a 100644 --- a/frontend/src/utils/validation.ts +++ b/frontend/src/utils/validation.ts @@ -1,30 +1,27 @@ const EMAIL_REGEXP = /^([\w])+([\w\._-])*@([\w_-])+\.([\w\._-]+)+$/; export interface IValidationResult { - isValid: boolean; - errorMessage?: string; + errorMessage: string; } -export const notValidate = (_: any) => { +export const notValidate = (_: any): IValidationResult => { return { - isValid: true + errorMessage: "" }; }; export const validateEmail = (email: string): IValidationResult => { if (!email) { return { - isValid: false, errorMessage: "メールアドレスを入力してください。" }; } if (!EMAIL_REGEXP.test(email)) { return { - isValid: false, errorMessage: "有効なメールアドレスではありません。" }; } - return { isValid: true }; + return { errorMessage: "" }; }; export type ValidationMethods = typeof validateEmail | typeof notValidate; From 06b35fa9c4a85311981e070cf46c6eb02153c32e Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Sat, 1 Jun 2019 09:17:05 +0900 Subject: [PATCH 47/50] rename validationResult to validationError --- frontend/src/components/ContactForm.tsx | 2 +- frontend/src/components/Forms/TextInput.tsx | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/frontend/src/components/ContactForm.tsx b/frontend/src/components/ContactForm.tsx index af6eda463..55509a7a7 100644 --- a/frontend/src/components/ContactForm.tsx +++ b/frontend/src/components/ContactForm.tsx @@ -46,7 +46,7 @@ export default observer((props: IProp) => { React.useEffect( () => { - if (corner && department && grade && validateEmail(email).errorMessage) { + if (corner && department && grade && !validateEmail(email).errorMessage) { setSendable(true); } else { setSendable(false); diff --git a/frontend/src/components/Forms/TextInput.tsx b/frontend/src/components/Forms/TextInput.tsx index 84f872fb3..ed9b3ac34 100644 --- a/frontend/src/components/Forms/TextInput.tsx +++ b/frontend/src/components/Forms/TextInput.tsx @@ -26,7 +26,7 @@ export default ({ type = "text" }: ITextInputProps) => { const [currentInputValue, setCurrentInputValue] = React.useState(""); - const [validationResult, setValidationResult] = React.useState({} as IValidationResult); + const [validationError, setValidationError] = React.useState({} as IValidationResult); const [inFocus, setInFocus] = React.useState(false); const handleChange = React.useCallback((e: React.ChangeEvent) => { @@ -42,7 +42,7 @@ export default ({ () => { if (validation) { if (!currentInputValue) return; - setValidationResult(validation(currentInputValue)); + setValidationError(validation(currentInputValue)); } }, [currentInputValue, inFocus] @@ -75,7 +75,7 @@ export default ({ value: currentInputValue, onChange: handleChange, styledFocus: inFocus ? true : false, - validationResult: !validationResult.errorMessage + validationError: !validationError.errorMessage }; return ( @@ -83,12 +83,12 @@ export default ({ {multiLine ? ( <> - {validationResult && !validationResult.errorMessage ? null : {validationResult.errorMessage}} + {validationError && !validationError.errorMessage ? null : {validationError.errorMessage}} ) : ( <> - {validationResult && !validationResult.errorMessage ? null : {validationResult.errorMessage}} + {validationError && !validationError.errorMessage ? null : {validationError.errorMessage}} )} @@ -104,7 +104,7 @@ const style = css` padding-left: 30px; line-height: 1.5rem; width: 100%; - border: 2px solid ${(props: any) => (props.validationResult ? "#00afec" : chkColors.error)}; + border: 2px solid ${(props: any) => (props.validationError ? "#00afec" : chkColors.error)}; border-radius: 1.5rem; ::placeholder { From b8b7e8191aef375a74c33b26c7d3fad4cba06113 Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Sat, 1 Jun 2019 09:19:17 +0900 Subject: [PATCH 48/50] fix --- frontend/src/components/ContactForm.tsx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/frontend/src/components/ContactForm.tsx b/frontend/src/components/ContactForm.tsx index 55509a7a7..802180f8e 100644 --- a/frontend/src/components/ContactForm.tsx +++ b/frontend/src/components/ContactForm.tsx @@ -46,13 +46,13 @@ export default observer((props: IProp) => { React.useEffect( () => { - if (corner && department && grade && !validateEmail(email).errorMessage) { + if (corner && department && grade && !validateEmail(email).errorMessage && message) { setSendable(true); } else { setSendable(false); } }, - [corner, department, grade, email] + [corner, department, grade, email, message] ); const createContact = (e: any) => { @@ -96,7 +96,7 @@ export default observer((props: IProp) => { @@ -110,14 +110,14 @@ export default observer((props: IProp) => { optionElements={contactEnum.departments} > @@ -126,7 +126,7 @@ export default observer((props: IProp) => { { Date: Sat, 1 Jun 2019 19:10:30 +0900 Subject: [PATCH 49/50] be able to some validations --- frontend/src/components/ContactForm.tsx | 3 +- frontend/src/components/Forms/TextInput.tsx | 34 +++++++++------------ frontend/src/utils/validation.ts | 2 +- 3 files changed, 17 insertions(+), 22 deletions(-) diff --git a/frontend/src/components/ContactForm.tsx b/frontend/src/components/ContactForm.tsx index 802180f8e..0af3ef823 100644 --- a/frontend/src/components/ContactForm.tsx +++ b/frontend/src/components/ContactForm.tsx @@ -74,7 +74,6 @@ export default observer((props: IProp) => { contact.save(props.successed, props.failed); }; - // TODO(euglena1215): validationをつける return contactEnum ? ( <> {props.alert.status === "successed" && ( @@ -129,7 +128,7 @@ export default observer((props: IProp) => { placeholder="メールアドレス(必須)" onChange={setEmail} value={email} - validation={validateEmail} + validations={[validateEmail]} /> diff --git a/frontend/src/components/Forms/TextInput.tsx b/frontend/src/components/Forms/TextInput.tsx index ed9b3ac34..85c547d0a 100644 --- a/frontend/src/components/Forms/TextInput.tsx +++ b/frontend/src/components/Forms/TextInput.tsx @@ -2,7 +2,7 @@ import * as React from "react"; import styled, { css } from "styled-components"; import { chkColors } from "../../commons/color"; -import { IValidationResult, ValidationMethods, notValidate } from "../../utils/validation"; +import { IValidationResult, ValidationMethod } from "../../utils/validation"; type TextInputType = "text" | "password" | "email"; @@ -12,21 +12,13 @@ export interface ITextInputProps { placeholder?: string; type?: TextInputType; multiLine?: boolean; - validation?: ValidationMethods; + validations?: ValidationMethod[]; onChange?(value: string): void; } -export default ({ - value, - name, - placeholder, - multiLine, - onChange, - validation = notValidate, - type = "text" -}: ITextInputProps) => { +export default ({ value, name, placeholder, multiLine, onChange, validations, type = "text" }: ITextInputProps) => { const [currentInputValue, setCurrentInputValue] = React.useState(""); - const [validationError, setValidationError] = React.useState({} as IValidationResult); + const [validationErrors, setValidationErrors] = React.useState([] as IValidationResult[]); const [inFocus, setInFocus] = React.useState(false); const handleChange = React.useCallback((e: React.ChangeEvent) => { @@ -40,9 +32,14 @@ export default ({ React.useEffect( () => { - if (validation) { + if (validations) { if (!currentInputValue) return; - setValidationError(validation(currentInputValue)); + + const newErrors: IValidationResult[] = []; + validations.forEach(validation => { + newErrors.push(validation(currentInputValue)); + }); + setValidationErrors(newErrors); } }, [currentInputValue, inFocus] @@ -75,7 +72,7 @@ export default ({ value: currentInputValue, onChange: handleChange, styledFocus: inFocus ? true : false, - validationError: !validationError.errorMessage + validationError: validationErrors.filter(v => v.errorMessage).length > 0 ? true : false }; return ( @@ -83,19 +80,18 @@ export default ({ {multiLine ? ( <> - {validationError && !validationError.errorMessage ? null : {validationError.errorMessage}} + {validationErrors.length > 0 ? validationErrors.map((v, i) => {v.errorMessage}) : null} ) : ( <> - {validationError && !validationError.errorMessage ? null : {validationError.errorMessage}} + {validationErrors.length > 0 ? validationErrors.map((v, i) => {v.errorMessage}) : null} )} ); }; -// TODO: focus時とそうでない時で背景かアウトラインのデザインを変える const style = css` margin: 5px; margin-left: 0; @@ -104,7 +100,7 @@ const style = css` padding-left: 30px; line-height: 1.5rem; width: 100%; - border: 2px solid ${(props: any) => (props.validationError ? "#00afec" : chkColors.error)}; + border: 2px solid ${(props: any) => (props.validationError ? chkColors.error : "#00afec")}; border-radius: 1.5rem; ::placeholder { diff --git a/frontend/src/utils/validation.ts b/frontend/src/utils/validation.ts index 81237065a..a1f7ad756 100644 --- a/frontend/src/utils/validation.ts +++ b/frontend/src/utils/validation.ts @@ -24,4 +24,4 @@ export const validateEmail = (email: string): IValidationResult => { return { errorMessage: "" }; }; -export type ValidationMethods = typeof validateEmail | typeof notValidate; +export type ValidationMethod = typeof validateEmail | typeof notValidate; From 5741f2384fedb56ac281b1a605dc4fdde2632c64 Mon Sep 17 00:00:00 2001 From: kobakakzu0429 Date: Sun, 2 Jun 2019 10:44:20 +0900 Subject: [PATCH 50/50] remove notValidate --- frontend/src/utils/validation.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/frontend/src/utils/validation.ts b/frontend/src/utils/validation.ts index a1f7ad756..f5665e754 100644 --- a/frontend/src/utils/validation.ts +++ b/frontend/src/utils/validation.ts @@ -4,12 +4,6 @@ export interface IValidationResult { errorMessage: string; } -export const notValidate = (_: any): IValidationResult => { - return { - errorMessage: "" - }; -}; - export const validateEmail = (email: string): IValidationResult => { if (!email) { return { @@ -24,4 +18,4 @@ export const validateEmail = (email: string): IValidationResult => { return { errorMessage: "" }; }; -export type ValidationMethod = typeof validateEmail | typeof notValidate; +export type ValidationMethod = typeof validateEmail;