-
Notifications
You must be signed in to change notification settings - Fork 384
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add rescript example (#442) * Add rescript build configurations * Create rescript page components * Add rescript deps * Solve render comments issue * Refactor css transaction components React Hooks shouldn't be used in loops or if statement. * Ignore the rescript output js files from lint The rescript output js files from lint because it doesn't follow the lint rules. * Apply review requested changes * Remove unused tag * Add ROR binding * Apply review requested changes * remove action js file * Remove .mjs files * Compile rescript files before running js tests * Build recript files before test * minor change * remove react-on-rails binding * migrate to tailwind * remove bs.mjs files * remove unused scss files * fix rescript spec tests * build rescript before test * refactor rescript src * fix add commit fail bug * refactor the types * format rescript files * remove the types files * update error rescript page state design * refactor switch statements * move store comment state to the form component * format rescript * rename the saving state * empty commit
- Loading branch information
Showing
31 changed files
with
740 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,6 +36,8 @@ def no_router | |
|
||
def simple; end | ||
|
||
def rescript; end | ||
|
||
private | ||
|
||
def set_comments | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
<%= react_component "RescriptShow", prerender: true %> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
{ | ||
"name": "react-webpack-rails-tutorial", | ||
"sources": [ | ||
{ | ||
"dir": "client/app/bundles/comments/rescript", | ||
"subdirs": true | ||
} | ||
], | ||
"package-specs": [ | ||
{ | ||
"module": "es6", | ||
"in-source": true | ||
} | ||
], | ||
"bsc-flags": ["-open JsonCombinators", "-open Belt"], | ||
"suffix": ".bs.js", | ||
"bs-dependencies": [ | ||
"@rescript/react", | ||
"@rescript/core", | ||
"@glennsl/rescript-fetch", | ||
"@glennsl/rescript-json-combinators", | ||
"rescript-react-on-rails" | ||
], | ||
"jsx": { | ||
"version": 4, | ||
"mode": "automatic" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
export const ROUTER_PATH = '/'; | ||
export const REACT_ROUTER_PATH = '/react-router'; | ||
export const NO_ROUTER_PATH = '/no-router'; | ||
export const RESCRIPT_PATH = '/rescript'; | ||
export const SIMPLE_REACT_PATH = '/simple'; | ||
export const STIMULUS_PATH = '/stimulus'; | ||
export const RAILS_PATH = '/comments'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
// TODO : use only one way to make http requests either Axios or Fetch | ||
module Create = { | ||
type t = { | ||
author: string, | ||
text: string, | ||
} | ||
|
||
let storeComment = async (comment: t) => { | ||
let _ = await Axios.post( | ||
"comments.json", | ||
{ | ||
"author": comment.author, | ||
"text": comment.text, | ||
}, | ||
{ | ||
"responseType": "json", | ||
"headers": { | ||
// see https://github.com/shakacode/react_on_rails/blob/249c69812474e0f532df432581bf5e618df0e1ec/node_package/src/Authenticity.ts#L13C1-L18C1 | ||
"X-CSRF-Token": ReactOnRails.authenticityToken(), | ||
"X-Requested-With": "XMLHttpRequest", | ||
}, | ||
}, | ||
) | ||
} | ||
} | ||
|
||
module Fetch = { | ||
type t = { | ||
author: string, | ||
text: string, | ||
id: int, | ||
} | ||
|
||
type comments = array<t> | ||
|
||
type commentsRes = {comments: comments} | ||
|
||
let fetchComments = async (): result<comments, string> => { | ||
open Json.Decode | ||
|
||
let response = await Fetch.get("comments.json") | ||
let jsonRes = await response->Fetch.Response.json | ||
|
||
let jsonComment = Json.Decode.object(field => { | ||
author: field.required(. "author", string), | ||
text: field.required(. "text", string), | ||
id: field.required(. "id", int), | ||
}) | ||
|
||
let jsonComments = Json.Decode.object(field => { | ||
comments: field.required(. "comments", array(jsonComment)), | ||
}) | ||
|
||
switch jsonRes->Json.decode(jsonComments) { | ||
| Ok(decodedRes) => Ok(decodedRes.comments) | ||
| Error(e) => Error(e) | ||
} | ||
} | ||
} |
149 changes: 149 additions & 0 deletions
149
client/app/bundles/comments/rescript/CommentForm/CommentForm.res
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
type formDisplay = | ||
| Horizontal | ||
| Inline | ||
| Stacked | ||
|
||
type savingStatus = | ||
| Idle | ||
| Saving | ||
| Error | ||
|
||
type formData = { | ||
formName: string, | ||
formType: formDisplay, | ||
} | ||
|
||
type state = { | ||
author: string, | ||
text: string, | ||
form: formDisplay, | ||
savingStatus: savingStatus, | ||
} | ||
|
||
type action = | ||
| SetAuthor(string) | ||
| SetText(string) | ||
| SetFormType(formDisplay) | ||
| SetSavingError | ||
| ClearSavingError | ||
| SetStoreStatusSaving | ||
|
||
let reducer = (state: state, action: action): state => { | ||
switch action { | ||
| SetAuthor(author) => {...state, author} | ||
| SetText(text) => {...state, text} | ||
| SetFormType(form) => {...state, form} | ||
| SetSavingError => {...state, savingStatus: Error} | ||
| ClearSavingError => {...state, savingStatus: Idle} | ||
| SetStoreStatusSaving => {...state, savingStatus: Saving} | ||
} | ||
} | ||
|
||
@react.component | ||
let make = (~fetchData) => { | ||
let (state, dispatch) = React.useReducer( | ||
reducer, | ||
{ | ||
author: "", | ||
text: "", | ||
form: Horizontal, | ||
savingStatus: Idle, | ||
}, | ||
) | ||
|
||
let disabled = React.useMemo1(() => { | ||
switch state.savingStatus { | ||
| Saving => true | ||
| Idle | ||
| Error => false | ||
} | ||
}, [state.savingStatus]) | ||
|
||
let storeComment = (newComment: Actions.Create.t) => { | ||
SetStoreStatusSaving->dispatch | ||
let saveAndFetchComments = async () => { | ||
try { | ||
let _ = await Actions.Create.storeComment(newComment) | ||
ClearSavingError->dispatch | ||
|
||
await fetchData() | ||
} catch { | ||
| _ => SetSavingError->dispatch | ||
} | ||
} | ||
saveAndFetchComments()->ignore | ||
} | ||
|
||
let handleAuthorChange = event => { | ||
let value = ReactEvent.Form.currentTarget(event)["value"] | ||
SetAuthor(value)->dispatch | ||
} | ||
|
||
let handleTextChange = event => { | ||
let value = ReactEvent.Form.currentTarget(event)["value"] | ||
SetText(value)->dispatch | ||
} | ||
|
||
let handleSubmit = event => { | ||
ReactEvent.Form.preventDefault(event) | ||
storeComment({author: state.author, text: state.text}) | ||
} | ||
|
||
let forms: array<formData> = [ | ||
{formName: "Horizontal Form", formType: Horizontal}, | ||
{formName: "Inline Form", formType: Inline}, | ||
{formName: "Stacked Form", formType: Stacked}, | ||
] | ||
|
||
<div> | ||
<div className="flex gap-1 not-prose"> | ||
{forms | ||
->Array.map(form => | ||
<button | ||
key={`form_${form.formName}`} | ||
className={`px-6 py-2 font-semibold border-0 rounded ${state.form == form.formType | ||
? "text-sky-50 bg-sky-600" | ||
: "text-sky-600 hover:bg-gray-100"}`} | ||
onClick={event => SetFormType(form.formType)->dispatch}> | ||
{form.formName->React.string} | ||
</button> | ||
) | ||
->React.array} | ||
</div> | ||
<hr /> | ||
{switch state.form { | ||
| Horizontal => | ||
<HorizontalForm | ||
author={state.author} | ||
handleAuthorChange | ||
text={state.text} | ||
handleTextChange | ||
handleSubmit | ||
disabled | ||
/> | ||
| Stacked => | ||
<StackedFrom | ||
author={state.author} | ||
handleAuthorChange | ||
text={state.text} | ||
handleTextChange | ||
handleSubmit | ||
disabled | ||
/> | ||
| Inline => | ||
<InlineForm | ||
author={state.author} | ||
handleAuthorChange | ||
text={state.text} | ||
handleTextChange | ||
handleSubmit | ||
disabled | ||
/> | ||
}} | ||
{switch state.savingStatus { | ||
| Error => <AlertError errorMsg="Can't save the comment!" /> | ||
| Idle | ||
| Saving => React.null | ||
}} | ||
</div> | ||
} |
37 changes: 37 additions & 0 deletions
37
client/app/bundles/comments/rescript/CommentForm/forms/HorizontalForm.res
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
@react.component | ||
let make = (~author, ~handleAuthorChange, ~text, ~handleTextChange, ~handleSubmit, ~disabled) => { | ||
<form className="form-horizontal flex flex-col gap-4" onSubmit=handleSubmit disabled> | ||
<div className="flex flex-col gap-0 items-center lg:gap-4 lg:flex-row"> | ||
<label className="w-full lg:w-2/12 lg:text-end shrink-0"> {"Name"->React.string} </label> | ||
<input | ||
type_="text" | ||
className="px-3 py-1 leading-4 border border-gray-300 rounded w-full" | ||
placeholder="Your Name" | ||
name="comment_author" | ||
id="comment_author" | ||
onChange=handleAuthorChange | ||
value={author} | ||
/> | ||
</div> | ||
<div className="flex flex-col gap-0 items-center lg:gap-4 lg:flex-row"> | ||
<label className="w-full lg:w-2/12 lg:text-end shrink-0"> {"Text"->React.string} </label> | ||
<input | ||
type_="text" | ||
className="px-3 py-1 leading-4 border border-gray-300 rounded w-full" | ||
placeholder="Say something using markdown..." | ||
name="comment_text" | ||
id="comment_text" | ||
onChange=handleTextChange | ||
value={text} | ||
/> | ||
</div> | ||
<div className="flex flex-col gap-0 lg:gap-4 lg:flex-row"> | ||
<div className="hidden lg:block lg:w-2/12 grow-0" /> | ||
<input | ||
type_="submit" | ||
className="self-start px-3 py-1 font-semibold border-0 rounded text-sky-50 bg-sky-600 hover:bg-sky-800" | ||
value="Post" | ||
/> | ||
</div> | ||
</form> | ||
} |
40 changes: 40 additions & 0 deletions
40
client/app/bundles/comments/rescript/CommentForm/forms/InlineForm.res
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
@react.component | ||
let make = (~author, ~handleAuthorChange, ~text, ~handleTextChange, ~handleSubmit, ~disabled) => { | ||
<form | ||
className="form-inline flex flex-col lg:flex-row flex-wrap gap-4" | ||
onSubmit=handleSubmit | ||
disabled> | ||
<div className="flex gap-2 items-center"> | ||
<label> {"Name"->React.string} </label> | ||
<input | ||
type_="text" | ||
className="px-3 py-1 leading-4 border border-gray-300 rounded" | ||
placeholder="Your Name" | ||
name="comment_author" | ||
id="comment_author" | ||
value={author} | ||
onChange=handleAuthorChange | ||
/> | ||
</div> | ||
<div className="flex gap-2 items-center"> | ||
<label> {"Text"->React.string} </label> | ||
<input | ||
type_="text" | ||
className="px-3 py-1 leading-4 border border-gray-300 rounded" | ||
placeholder="Say something using markdown..." | ||
name="comment_text" | ||
id="comment_text" | ||
onChange=handleTextChange | ||
value={text} | ||
/> | ||
</div> | ||
<div className="flex gap-2"> | ||
<input | ||
type_="submit" | ||
className="self-start px-3 py-1 font-semibold border-0 rounded text-sky-50 bg-sky-600 hover:bg-sky-800" | ||
onSubmit=handleSubmit | ||
value="Post" | ||
/> | ||
</div> | ||
</form> | ||
} |
Oops, something went wrong.